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 all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 run -c vitest.config.e2e.ts",
"test-build": "cross-env VITE_TEST_BUILD=1 vitest run -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 vitest run -c vitest.config.e2e.ts",
"debug-build": "cross-env VITE_TEST_BUILD=1 VITE_PRESERVE_BUILD_ARTIFACTS=1 vitest run -c vitest.config.e2e.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.4"
},
"simple-git-hooks": {
"pre-commit": "pnpm exec lint-staged --concurrent false",
Expand Down
38 changes: 18 additions & 20 deletions packages/vite/src/node/__tests__/plugins/css.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,31 +179,29 @@ describe('hoist @ rules', () => {

test('dont hoist @import and @charset in comments', async () => {
const css = `
.foo{color:red;}
/*
@import "bla";
*/
@charset "utf-8";
/*
@charset "utf-8";
@import "bar";
*/
@import "baz";
`
.foo{color:red;}
/*
@import "bla";
*/
@charset "utf-8";
/*
@charset "utf-8";
@import "bar";
*/
@import "baz";`
const result = await hoistAtRules(css)
expect(result).toBe(
`@charset "utf-8";@import "baz";
expect(result).toMatchInlineSnapshot(`
"@charset \\"utf-8\\";@import \\"baz\\";
.foo{color:red;}
/*
@import "bla";
@import \\"bla\\";
*/

/*
@charset "utf-8";
@import "bar";
@charset \\"utf-8\\";
@import \\"bar\\";
*/

`
)
"
`)
})
})
2 changes: 1 addition & 1 deletion packages/vite/src/node/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,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
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,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
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,9 @@ export const multilineCommentsRE = /\/\*(.|[\r\n])*?\*\//gm
export const singlelineCommentsRE = /\/\/.*/g
export const requestQuerySplitRE = /\?(?!.*[\/|\}])/

// @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
100 changes: 43 additions & 57 deletions playground/assets/__tests__/assets.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,9 @@ describe('css url() references', () => {
expect(bg).toMatch(assetMatch)
})

if (isBuild) {
test('preserve postfix query/hash', () => {
expect(findAssetFile(/\.css$/, 'foo')).toMatch(`woff2?#iefix`)
})
}
test.runIf(isBuild)('preserve postfix query/hash', () => {
expect(findAssetFile(/\.css$/, 'foo')).toMatch(`woff2?#iefix`)
})
})

describe('image', () => {
Expand Down Expand Up @@ -254,17 +252,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 All @@ -286,51 +280,43 @@ test('new URL(`non-existent`, import.meta.url)', async () => {
)
})

if (isBuild) {
test('manifest', async () => {
const manifest = readManifest('foo')
const entry = manifest['index.html']

for (const file of listAssets('foo')) {
if (file.endsWith('.css')) {
expect(entry.css).toContain(`assets/${file}`)
} else if (!file.endsWith('.js')) {
expect(entry.assets).toContain(`assets/${file}`)
}
test.runIf(isBuild)('manifest', async () => {
const manifest = readManifest('foo')
const entry = manifest['index.html']

for (const file of listAssets('foo')) {
if (file.endsWith('.css')) {
expect(entry.css).toContain(`assets/${file}`)
} else if (!file.endsWith('.js')) {
expect(entry.assets).toContain(`assets/${file}`)
}
})
}
}
})

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
Loading