Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: migrate to vitest #8076

Merged
merged 28 commits into from May 11, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 1 addition & 8 deletions .eslintrc.cjs
Expand Up @@ -29,14 +29,7 @@ module.exports = defineConfig({
'node/no-missing-import': [
'error',
{
allowModules: [
'types',
'estree',
'testUtils',
'less',
'sass',
'stylus'
],
allowModules: ['types', 'estree', 'less', 'sass', 'stylus'],
tryExtensions: ['.ts', '.js', '.jsx', '.tsx', '.d.ts']
}
],
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Expand Up @@ -72,10 +72,10 @@ jobs:
run: pnpm run test-unit

- name: Test serve
run: pnpm run test-serve -- --runInBand
run: pnpm run test-serve

- name: Test build
run: pnpm run test-build -- --runInBand
run: pnpm run test-build

lint:
timeout-minutes: 10
Expand Down
12 changes: 6 additions & 6 deletions CONTRIBUTING.md
Expand Up @@ -30,11 +30,11 @@ If you want to use break point and explore code execution you can use the ["Run

5. The execution will stop and you'll use the [Debug toolbar](https://code.visualstudio.com/docs/editor/debugging#_debug-actions) to continue, step over, restart the process...

### Debugging errors in Jest tests using Playwright (Chromium)
### Debugging errors in Vitest tests using Playwright (Chromium)

Some errors are masked and hidden away because of the layers of abstraction and sandboxed nature added by Jest, Playwright, and Chromium. In order to see what's actually going wrong and the contents of the devtools console in those instances, follow this setup:
Some errors are masked and hidden away because of the layers of abstraction and sandboxed nature added by Vitest, Playwright, and Chromium. In order to see what's actually going wrong and the contents of the devtools console in those instances, follow this setup:

1. Add a `debugger` statement to the `scripts/jestPerTestSetup.ts` -> `afterAll` hook. This will pause execution before the tests quit and the Playwright browser instance exits.
1. Add a `debugger` statement to the `scripts/vitestSetup.ts` -> `afterAll` hook. This will pause execution before the tests quit and the Playwright browser instance exits.

1. Run the tests with the `debug-serve` script command which will enable remote debugging: `pnpm run debug-serve -- --runInBand resolve`.

Expand Down Expand Up @@ -69,15 +69,15 @@ And re-run `pnpm install` to link the package.

### Integration Tests

Each package under `playground/` contains a `__tests__` directory. The tests are run using [Jest](https://jestjs.io/) + [Playwright](https://playwright.dev/) with custom integrations to make writing tests simple. The detailed setup is inside `jest.config.js` and `scripts/jest*` files.
Each package under `playground/` contains a `__tests__` directory. The tests are run using [Vitest](https://vitest.dev/) + [Playwright](https://playwright.dev/) with custom integrations to make writing tests simple. The detailed setup is inside `vitest.config.e2e.js` and `scripts/vitest*` files.

Before running the tests, make sure that [Vite has been built](#repo-setup). On Windows, you may want to [activate Developer Mode](https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development) to solve [issues with symlink creation for non-admins](https://github.com/vitejs/vite/issues/7390). Also you may want to [set git `core.symlinks` to `true` to solve issues with symlinks in git](https://github.com/vitejs/vite/issues/5242).

Each integration test can be run under either dev server mode or build mode.

- `pnpm test` by default runs every integration test in both serve and build mode, and also unit tests.

- `pnpm run test-serve` runs tests only under serve mode. This is just calling `jest` so you can pass any Jest flags to this command. Since Jest will attempt to run tests in parallel, if your machine has many cores this may cause flaky test failures with multiple Playwright instances running at the same time. You can force the tests to run in series with `pnpm run test-serve -- --runInBand`.
- `pnpm run test-serve` runs tests only under serve mode.

- `pnpm run test-build` runs tests only under build mode.

Expand Down Expand Up @@ -105,7 +105,7 @@ test('should work', async () => {

Some common test helpers, e.g. `testDir`, `isBuild` or `editFile` are available in `playground/testUtils.ts`.

Note: The test build environment uses a [different default set of Vite config](https://github.com/vitejs/vite/blob/9c6501d9c363eaa3c1e7708d531fb2a92b633db6/scripts/jestPerTestSetup.ts#L102-L122) to skip transpilation during tests to make it faster. This may produce a different result compared to the default production build.
Note: The test build environment uses a [different default set of Vite config](https://github.com/vitejs/vite/blob/9c6501d9c363eaa3c1e7708d531fb2a92b633db6/scripts/vitestSetup.ts#L102-L122) to skip transpilation during tests to make it faster. This may produce a different result compared to the default production build.

### Extending the Test Suite

Expand Down
24 changes: 0 additions & 24 deletions jest.config.ts

This file was deleted.

15 changes: 7 additions & 8 deletions package.json
Expand Up @@ -17,11 +17,11 @@
"format": "prettier --write .",
"lint": "eslint packages/*/{src,types}/**",
"test": "run-s test-unit test-serve test-build",
"test-serve": "jest",
"test-build": "cross-env VITE_TEST_BUILD=1 jest",
"test-serve": "vitest -c vitest.config.e2e.ts",
"test-build": "cross-env VITE_TEST_BUILD=1 vitest -c vitest.config.e2e.ts",
"test-unit": "vitest run",
"debug-serve": "cross-env VITE_DEBUG_SERVE=1 node --inspect-brk ./node_modules/.bin/jest",
"debug-build": "cross-env VITE_TEST_BUILD=1 VITE_PRESERVE_BUILD_ARTIFACTS=1 node --inspect-brk ./node_modules/.bin/jest",
"debug-serve": "cross-env VITE_DEBUG_SERVE=1 node --inspect-brk ./node_modules/.bin/vitest -- -c vitest.e2e.config.ts",
"debug-build": "cross-env VITE_TEST_BUILD=1 VITE_PRESERVE_BUILD_ARTIFACTS=1 node --inspect-brk ./node_modules/.bin/vitest -- -c vitest.e2e.config.ts",
"docs": "vitepress dev docs",
"build-docs": "vitepress build docs",
"serve-docs": "vitepress serve docs",
Expand All @@ -36,8 +36,8 @@
},
"devDependencies": {
"@microsoft/api-extractor": "^7.23.1",
"@types/babel__core": "^7.1.19",
"@types/fs-extra": "^9.0.13",
"@types/jest": "^27.5.0",
"@types/node": "^17.0.31",
"@types/prompts": "^2.4.0",
"@types/semver": "^7.3.9",
Expand All @@ -51,7 +51,7 @@
"eslint-plugin-node": "^11.1.0",
"execa": "^5.1.1",
"fs-extra": "^10.1.0",
"jest": "^27.5.1",
"kill-port": "^1.6.1",
"lint-staged": "^12.4.1",
"minimist": "^1.2.6",
"node-fetch": "^2.6.7",
Expand All @@ -65,12 +65,11 @@
"semver": "^7.3.7",
"simple-git-hooks": "^2.7.0",
"sirv": "^2.0.2",
"ts-jest": "^27.1.4",
"ts-node": "^10.7.0",
"typescript": "^4.6.4",
"vite": "workspace:*",
"vitepress": "^0.22.4",
"vitest": "^0.10.5"
"vitest": "^0.12.3"
},
"simple-git-hooks": {
"pre-commit": "pnpm exec lint-staged --concurrent false",
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/server/index.ts
Expand Up @@ -405,7 +405,7 @@ export async function createServer(
try {
await server.close()
} finally {
process.exit(0)
process.exit()
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/ssr/ssrModuleLoader.ts
Expand Up @@ -287,6 +287,7 @@ async function nodeImport(
importer,
// Non-external modules can import ESM-only modules, but only outside
// of test runs, because we use Node `require` in Jest to avoid segfault.
// @ts-expect-error
antfu marked this conversation as resolved.
Show resolved Hide resolved
typeof jest === 'undefined'
? { ...resolveOptions, tryEsmOnly: true }
: resolveOptions
Expand Down
2 changes: 2 additions & 0 deletions packages/vite/src/node/utils.ts
Expand Up @@ -724,7 +724,9 @@ export function toUpperCaseDriveLetter(pathName: string): string {
export const multilineCommentsRE = /\/\*(.|[\r\n])*?\*\//gm
export const singlelineCommentsRE = /\/\/.*/g

// @ts-expect-error
export const usingDynamicImport = typeof jest === 'undefined'

/**
* Dynamically import files. It will make sure it's not being compiled away by TS/Rollup.
*
Expand Down
68 changes: 29 additions & 39 deletions playground/assets/__tests__/assets.spec.ts
Expand Up @@ -239,17 +239,13 @@ describe('unicode url', () => {
})
})

describe('encodeURI', () => {
if (isBuild) {
test('img src with encodeURI', async () => {
const img = await page.$('.encodeURI')
expect(
await (
await img.getAttribute('src')
).startsWith('data:image/png;base64')
).toBe(true)
})
}
describe.runIf(isBuild)('encodeURI', () => {
test('img src with encodeURI', async () => {
const img = await page.$('.encodeURI')
expect(
await (await img.getAttribute('src')).startsWith('data:image/png;base64')
).toBe(true)
})
})

test('new URL(..., import.meta.url)', async () => {
Expand Down Expand Up @@ -286,36 +282,30 @@ if (isBuild) {
})
}

describe('css and assets in css in build watch', () => {
if (isBuild) {
test('css will not be lost and css does not contain undefined', async () => {
editFile('index.html', (code) => code.replace('Assets', 'assets'), true)
await notifyRebuildComplete(watcher)
const cssFile = findAssetFile(/index\.\w+\.css$/, 'foo')
expect(cssFile).not.toBe('')
expect(cssFile).not.toMatch(/undefined/)
})
describe.runIf(isBuild)('css and assets in css in build watch', () => {
test('css will not be lost and css does not contain undefined', async () => {
editFile('index.html', (code) => code.replace('Assets', 'assets'), true)
await notifyRebuildComplete(watcher)
const cssFile = findAssetFile(/index\.\w+\.css$/, 'foo')
expect(cssFile).not.toBe('')
expect(cssFile).not.toMatch(/undefined/)
})

test('import module.css', async () => {
expect(await getColor('#foo')).toBe('red')
editFile(
'css/foo.module.css',
(code) => code.replace('red', 'blue'),
true
)
await notifyRebuildComplete(watcher)
await page.reload()
expect(await getColor('#foo')).toBe('blue')
})
test('import module.css', async () => {
expect(await getColor('#foo')).toBe('red')
editFile('css/foo.module.css', (code) => code.replace('red', 'blue'), true)
await notifyRebuildComplete(watcher)
await page.reload()
expect(await getColor('#foo')).toBe('blue')
})

test('import with raw query', async () => {
expect(await page.textContent('.raw-query')).toBe('foo')
editFile('static/foo.txt', (code) => code.replace('foo', 'zoo'), true)
await notifyRebuildComplete(watcher)
await page.reload()
expect(await page.textContent('.raw-query')).toBe('zoo')
})
}
test('import with raw query', async () => {
expect(await page.textContent('.raw-query')).toBe('foo')
editFile('static/foo.txt', (code) => code.replace('foo', 'zoo'), true)
await notifyRebuildComplete(watcher)
await page.reload()
expect(await page.textContent('.raw-query')).toBe('zoo')
})
})

test('inline style test', async () => {
Expand Down
@@ -1,21 +1,16 @@
// @ts-check
// this is automtically detected by scripts/jestPerTestSetup.ts and will replace
// this is automatically detected by scripts/vitestSetup.ts and will replace
// the default e2e test serve behavior

const path = require('path')
// eslint-disable-next-line node/no-restricted-require
const execa = require('execa')
const { workspaceRoot, ports } = require('../../testUtils')
import path from 'path'
import execa from 'execa'
import { workspaceRoot, ports } from '../../testUtils'
import kill from 'kill-port'

const isWindows = process.platform === 'win32'
const port = (exports.port = ports['cli-module'])
export const port = ports['cli-module']
const viteBin = path.join(workspaceRoot, 'packages', 'vite', 'bin', 'vite.js')

/**
* @param {string} root
* @param {boolean} isProd
*/
exports.serve = async function serve(root, isProd) {
export async function serve(root: string, isProd: boolean) {
// collect stdout and stderr streams from child processes here to avoid interfering with regular jest output
const streams = {
build: { out: [], err: [] },
Expand Down Expand Up @@ -60,6 +55,8 @@ exports.serve = async function serve(root, isProd) {
}
}

await kill(port)

// run `vite --port x` or `vite preview --port x` to start server
const viteServerArgs = ['--port', `${port}`, '--strict-port']
if (isProd) {
Expand Down Expand Up @@ -113,7 +110,7 @@ exports.serve = async function serve(root, isProd) {
// helper to validate that server was started on the correct port
async function startedOnPort(serverProcess, port, timeout) {
let checkPort
const startedPromise = new Promise((resolve, reject) => {
const startedPromise = new Promise<void>((resolve, reject) => {
checkPort = (data) => {
const str = data.toString()
// hack, console output may contain color code gibberish
Expand Down
@@ -1,21 +1,17 @@
// @ts-check
// this is automtically detected by scripts/jestPerTestSetup.ts and will replace
// this is automatically detected by scripts/vitestSetup.ts and will replace
// the default e2e test serve behavior

const path = require('path')
// eslint-disable-next-line node/no-restricted-require
const execa = require('execa')
const { workspaceRoot, ports } = require('../../testUtils')
import path from 'path'
import execa from 'execa'
import { workspaceRoot, ports } from '../../testUtils'
import kill from 'kill-port'

const isWindows = process.platform === 'win32'
const port = (exports.port = ports.cli)
const viteBin = path.join(workspaceRoot, 'packages', 'vite', 'bin', 'vite.js')

/**
* @param {string} root
* @param {boolean} isProd
*/
exports.serve = async function serve(root, isProd) {
export async function serve(root: string, isProd: boolean) {
// collect stdout and stderr streams from child processes here to avoid interfering with regular jest output
const streams = {
build: { out: [], err: [] },
Expand Down Expand Up @@ -60,6 +56,8 @@ exports.serve = async function serve(root, isProd) {
}
}

await kill(port)

// run `vite --port x` or `vite preview --port x` to start server
const viteServerArgs = ['--port', `${port}`, '--strict-port']
if (isProd) {
Expand Down Expand Up @@ -113,7 +111,7 @@ exports.serve = async function serve(root, isProd) {
// helper to validate that server was started on the correct port
async function startedOnPort(serverProcess, port, timeout) {
let checkPort
const startedPromise = new Promise((resolve, reject) => {
const startedPromise = new Promise<void>((resolve, reject) => {
checkPort = (data) => {
const str = data.toString()
// hack, console output may contain color code gibberish
Expand Down
16 changes: 5 additions & 11 deletions playground/css-sourcemap/__tests__/build.spec.ts
@@ -1,13 +1,7 @@
import { isBuild } from 'testUtils'
import { isBuild } from '../../testUtils'

if (isBuild) {
test('should not output sourcemap warning (#4939)', () => {
serverLogs.forEach((log) => {
expect(log).not.toMatch('Sourcemap is likely to be incorrect')
})
test.runIf(isBuild)('should not output sourcemap warning (#4939)', () => {
serverLogs.forEach((log) => {
expect(log).not.toMatch('Sourcemap is likely to be incorrect')
})
} else {
test('this file only includes test for build', () => {
expect(true).toBe(true)
})
}
})