Skip to content

Commit

Permalink
perf: simplify code
Browse files Browse the repository at this point in the history
  • Loading branch information
hemengke1997 committed Oct 26, 2023
1 parent 70d8782 commit 4c58386
Show file tree
Hide file tree
Showing 14 changed files with 41 additions and 911 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ concurrency:
cancel-in-progress: true

jobs:
main:
deploy:
if: "contains(github.event.head_commit.message, 'deploy')"

runs-on: ubuntu-latest
steps:
- name: Checkout
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ jobs:
key: ${{ runner.os }}-playwright-bin-v1
path: ${{ env.PLAYWRIGHT_BROWSERS_PATH }}

- name: Install Playwright
# does not need to explicitly set chromium after https://github.com/microsoft/playwright/issues/14862 is solved
run: pnpm playwright install chromium

- name: Build
run: pnpm run build

Expand Down
Empty file added CHANGELOG.md
Empty file.
15 changes: 4 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,14 @@
}
},
"scripts": {
"dev": "tsup --watch",
"dev": "simple-git-hooks && tsup --watch",
"build": "tsup",
"build:pages": "pnpm run build && cd playground/spa && pnpm run build",
"test": "run-s test:unit test:serve test:build",
"test:unit": "vitest run",
"test:serve": "vitest run -c vitest.config.e2e.ts",
"test:build": "cross-env VITE_TEST_BUILD=1 vitest run -c vitest.config.e2e.ts",
"preinstall": "npx only-allow pnpm",
"postinstall": "simple-git-hooks",
"lint": "eslint .",
"up": "taze -I -w -r",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
Expand All @@ -48,27 +47,21 @@
"@minko-fe/commitlint-config": "^2.0.2",
"@minko-fe/eslint-config": "^2.0.2",
"@minko-fe/tsconfig": "^2.0.2",
"@types/fs-extra": "^11.0.3",
"bumpp": "^9.2.0",
"conventional-changelog-cli": "^4.1.0",
"cross-env": "^7.0.3",
"eslint": "8.50.0",
"execa": "^8.0.1",
"fs-extra": "^11.1.1",
"npm-run-all": "^4.1.5",
"playwright-chromium": "^1.39.0",
"pnpm": "^8.7.6",
"rollup": "^4.1.4",
"simple-git-hooks": "^2.9.0",
"taze": "^0.11.2",
"tsup": "^7.2.0",
"typescript": "^5.2.2",
"vite": "^4.4.9",
"vitest": "^0.34.5"
"vitest": "^0.34.5",
"vitest-e2e": "^0.0.8"
},
"engines": {
"pnpm": ">=8.6.2",
"node": ">=18.0.0"
"node": ">=16.0.0"
},
"simple-git-hooks": {
"commit-msg": "pnpm exec commitlint -e"
Expand Down
7 changes: 1 addition & 6 deletions playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,5 @@
"name": "@ts-starter/vite-playground",
"version": "1.0.0",
"private": true,
"devDependencies": {
"kill-port": "^1.6.1",
"node-fetch": "^3.3.2",
"sirv": "^2.0.3",
"tree-kill": "^1.2.2"
}
"devDependencies": {}
}
4 changes: 0 additions & 4 deletions playground/shims.d.ts

This file was deleted.

239 changes: 1 addition & 238 deletions playground/test-utils.ts
Original file line number Diff line number Diff line change
@@ -1,238 +1 @@
// test utils used in e2e tests for playgrounds.
// `import { getColor } from '~utils'`

import { type ExecaChildProcess } from 'execa'
import fs from 'fs-extra'
import path from 'node:path'
import { type ConsoleMessage } from 'playwright-chromium'
import { type Manifest, normalizePath } from 'vite'
import { expect } from 'vitest'
import { isBuild, isWindows, page, testDir } from './vitestSetup'

export * from './vitestSetup'

// make sure these ports are unique
export const ports = {
spa: 9524,
ssr: 9525,
}
export const hmrPorts = {
spa: 24680,
ssr: 24681,
}

const timeout = (n: number) => new Promise((r) => setTimeout(r, n))

export function readFile(filename: string): string {
return fs.readFileSync(path.resolve(testDir, filename), 'utf-8')
}

export function editFile(filename: string, replacer: (str: string) => string, runInBuild: boolean = false) {
if (isBuild && !runInBuild) return
filename = path.resolve(testDir, filename)
const content = fs.readFileSync(filename, 'utf-8')
const modified = replacer(content)
fs.writeFileSync(filename, modified)
}

export function addFile(filename: string, content: string): void {
fs.writeFileSync(path.resolve(testDir, filename), content)
}

export function renameDir(dirname: string, to: string) {
fs.renameSync(path.resolve(testDir, dirname), path.resolve(testDir, to))
}

export function removeFile(filename: string): void {
fs.unlinkSync(path.resolve(testDir, filename))
}

export function removeDir(dirname: string) {
fs.rmSync(path.resolve(testDir, dirname), { force: true, recursive: true })
}

export function listFiles(dir = ''): string[] {
const filesDir = path.join(testDir, dir)
return fs.readdirSync(filesDir)
}

export function listAssets(base = '', assets = 'assets'): string[] {
const assetsDir = path.join(testDir, 'dist', base, assets)
return fs.readdirSync(assetsDir)
}

export function findAssetFile(match: string | RegExp, base = '', assets = 'assets'): string {
const assetsDir = path.join(testDir, 'dist', base, assets)
let files: string[]
try {
files = fs.readdirSync(assetsDir)
} catch (e) {
if (e.code === 'ENOENT') {
return ''
}
throw e
}
const file = files.find((file) => {
return file.match(match)
})
return file ? fs.readFileSync(path.resolve(assetsDir, file), 'utf-8') : ''
}

export function readManifest(base = ''): Manifest {
return JSON.parse(fs.readFileSync(path.join(testDir, 'dist', base, 'manifest.json'), 'utf-8'))
}

/**
* Poll a getter until the value it returns includes the expected value.
*/
export async function untilUpdated(
poll: () => string | Promise<string>,
expected: string,
runInBuild = false,
): Promise<void> {
if (isBuild && !runInBuild) return
const maxTries = process.env.CI ? 200 : 50
for (let tries = 0; tries < maxTries; tries++) {
const actual = (await poll()) ?? ''
if (actual.includes(expected) || tries === maxTries - 1) {
expect(actual).toMatch(expected)
break
} else {
await timeout(50)
}
}
}

/**
* Retry `func` until it does not throw error.
*/
export async function withRetry(func: () => Promise<void>, runInBuild = false): Promise<void> {
if (isBuild && !runInBuild) return
const maxTries = process.env.CI ? 200 : 50
for (let tries = 0; tries < maxTries; tries++) {
try {
await func()
return
} catch {}
await timeout(50)
}
await func()
}

type UntilBrowserLogAfterCallback = (logs: string[]) => PromiseLike<void> | void

export async function untilBrowserLogAfter(
operation: () => any,
target: string | RegExp | (string | RegExp)[],
expectOrder?: boolean,
callback?: UntilBrowserLogAfterCallback,
): Promise<string[]>
export async function untilBrowserLogAfter(
operation: () => any,
target: string | RegExp | (string | RegExp)[],
callback?: UntilBrowserLogAfterCallback,
): Promise<string[]>
export async function untilBrowserLogAfter(
operation: () => any,
target: string | RegExp | (string | RegExp)[],
arg3?: boolean | UntilBrowserLogAfterCallback,
arg4?: UntilBrowserLogAfterCallback,
): Promise<string[]> {
const expectOrder = typeof arg3 === 'boolean' ? arg3 : false
const callback = typeof arg3 === 'boolean' ? arg4 : arg3

const promise = untilBrowserLog(target, expectOrder)
await operation()
const logs = await promise
if (callback) {
await callback(logs)
}
return logs
}

async function untilBrowserLog(target?: string | RegExp | (string | RegExp)[], expectOrder = true): Promise<string[]> {
let resolve: () => void
let reject: (reason: any) => void
const promise = new Promise<void>((_resolve, _reject) => {
resolve = _resolve
reject = _reject
})

const logs = []

try {
const isMatch = (matcher: string | RegExp) => (text: string) =>
typeof matcher === 'string' ? text === matcher : matcher.test(text)

let processMsg: (text: string) => boolean

if (!target) {
processMsg = () => true
} else if (Array.isArray(target)) {
if (expectOrder) {
const remainingTargets = [...target]
processMsg = (text: string) => {
const nextTarget = remainingTargets.shift()
expect(text).toMatch(nextTarget)
return remainingTargets.length === 0
}
} else {
const remainingMatchers = target.map((element) => isMatch(element))
processMsg = (text: string) => {
const nextIndex = remainingMatchers.findIndex((matcher) => matcher(text))
if (nextIndex >= 0) {
remainingMatchers.splice(nextIndex, 1)
}
return remainingMatchers.length === 0
}
}
} else {
processMsg = isMatch(target)
}

const handleMsg = (msg: ConsoleMessage) => {
try {
const text = msg.text()
if (msg.text().includes('React DevTools')) return
logs.push(text)
const done = processMsg(text)
if (done) {
resolve()
}
} catch (err) {
reject(err)
}
}

page.on('console', handleMsg)
} catch (err) {
reject(err)
}

await promise

return logs
}

export const formatSourcemapForSnapshot = (map: any): any => {
const root = normalizePath(testDir)
const m = { ...map }
delete m.file
delete m.names
m.sources = m.sources.map((source) => source.replace(root, '/root'))
return m
}

// helper function to kill process, uses taskkill on windows to ensure child process is killed too
export async function killProcess(serverProcess: ExecaChildProcess): Promise<void> {
if (isWindows) {
try {
const { execaCommandSync } = await import('execa')
execaCommandSync(`taskkill /pid ${serverProcess.pid} /T /F`)
} catch (e) {
console.error('failed to taskkill:', e)
}
} else {
serverProcess.kill('SIGTERM', { forceKillAfterTimeout: 2000 })
}
}
export * from 'vitest-e2e/test-utils'
13 changes: 2 additions & 11 deletions playground/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"target": "ES2020",
"jsx": "preserve",
"module": "ESNext",
"moduleResolution": "Node",
"baseUrl": ".",
"paths": {
"~utils": ["./test-utils.ts"]
},
"types": ["vite/client"],
"resolveJsonModule": true,
"allowJs": true,
"outDir": "dist",
"esModuleInterop": true,
"noUnusedLocals": true,
"skipLibCheck": true
"types": ["vite/client"]
},
"include": ["."],
"exclude": ["**/dist/**"]
Expand Down
49 changes: 1 addition & 48 deletions playground/vitestGlobalSetup.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1 @@
import fs from 'fs-extra'
import os from 'node:os'
import path from 'node:path'
import { type BrowserServer, chromium } from 'playwright-chromium'

const DIR = path.join(os.tmpdir(), 'vitest_playwright_global_setup')

let browserServer: BrowserServer | undefined

export async function setup(): Promise<void> {
process.env.NODE_ENV = process.env.VITE_TEST_BUILD ? 'production' : 'development'

browserServer = await chromium.launchServer({
headless: !process.env.VITE_DEBUG_SERVE,
args: process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox'] : undefined,
})

await fs.mkdirp(DIR)
await fs.writeFile(path.join(DIR, 'wsEndpoint'), browserServer.wsEndpoint())

const tempDir = path.resolve(__dirname, '../playground-temp')
await fs.ensureDir(tempDir)
await fs.emptyDir(tempDir)
await fs
.copy(path.resolve(__dirname, '../playground'), tempDir, {
dereference: false,
filter(file) {
file = file.replace(/\\/g, '/')
return !file.includes('__tests__') && !/dist(\/|$)/.test(file)
},
})
.catch(async (error) => {
if (error.code === 'EPERM' && error.syscall === 'symlink') {
throw new Error(
'Could not create symlinks. On Windows, consider activating Developer Mode to allow non-admin users to create symlinks by following the instructions at https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development.',
)
} else {
throw error
}
})
}

export async function teardown(): Promise<void> {
await browserServer?.close()
if (!process.env.VITE_PRESERVE_BUILD_ARTIFACTS) {
fs.removeSync(path.resolve(__dirname, '../playground-temp'))
}
}
export * from 'vitest-e2e/vitestGlobalSetup'
Loading

0 comments on commit 4c58386

Please sign in to comment.