Skip to content

Commit 63cd53d

Browse files
authored
fix: use Vitest for unit testing, clean regex bug (#8040)
1 parent c7eeb8d commit 63cd53d

26 files changed

+160
-15
lines changed

.eslintrc.cjs

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ module.exports = defineConfig({
6363
'node/no-extraneous-import': [
6464
'error',
6565
{
66-
allowModules: ['vite', 'less', 'sass']
66+
allowModules: ['vite', 'less', 'sass', 'vitest']
6767
}
6868
],
6969
'node/no-extraneous-require': [
@@ -103,7 +103,7 @@ module.exports = defineConfig({
103103
}
104104
},
105105
{
106-
files: ['packages/vite/types/**'],
106+
files: ['packages/vite/types/**', '*.spec.ts'],
107107
rules: {
108108
'node/no-extraneous-import': 'off'
109109
}

.github/workflows/ci.yml

+3
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ jobs:
6666
- name: Build plugin-react
6767
run: pnpm run build-plugin-react
6868

69+
- name: Test unit
70+
run: pnpm run test-unit
71+
6972
- name: Test serve
7073
run: pnpm run test-serve -- --runInBand
7174

CONTRIBUTING.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,15 @@ And re-run `pnpm install` to link the package.
6767

6868
## Running Tests
6969

70+
### Integration Tests
71+
7072
Each package under `packages/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.
7173

7274
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).
7375

74-
Each test can be run under either dev server mode or build mode.
76+
Each integration test can be run under either dev server mode or build mode.
7577

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

7880
- `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`.
7981

@@ -83,6 +85,14 @@ Each test can be run under either dev server mode or build mode.
8385

8486
Note package matching is not available for the `pnpm test` script, which always runs all tests.
8587

88+
### Unit Tests
89+
90+
Other than tests under `packages/playground/` for integration tests, packages might contains unit tests under their `__tests__` directory. Unit tests are powered by [Vitest](https://vitest.dev/). The detailed config is inside `vitest.config.ts` files.
91+
92+
- `pnpm run test-unit` runs unit tests under each package.
93+
94+
- You can also use `pnpm run test-unit -- [match]` to run related tests.
95+
8696
### Test Env and Helpers
8797

8898
Inside playground tests, a global `page` object is automatically available, which is a Playwright [`Page`](https://playwright.dev/docs/api/class-page) instance that has already navigated to the served page of the current playground. So writing a test is as simple as:

jest.config.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ import type { Config } from '@jest/types'
33

44
const config: Config.InitialOptions = {
55
preset: 'ts-jest',
6-
testMatch: process.env.VITE_TEST_BUILD
7-
? ['**/playground/**/*.spec.[jt]s?(x)']
8-
: ['**/*.spec.[jt]s?(x)'],
6+
testMatch: ['**/playground/**/*.spec.[jt]s?(x)'],
97
testTimeout: process.env.CI ? 50000 : 20000,
108
globalSetup: './scripts/jestGlobalSetup.cjs',
119
globalTeardown: './scripts/jestGlobalTeardown.cjs',

package.json

+5-3
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616
"preinstall": "npx only-allow pnpm",
1717
"format": "prettier --write .",
1818
"lint": "eslint packages/*/{src,types}/**",
19-
"test": "run-s test-serve test-build",
19+
"test": "run-s test-serve test-build test-unit",
2020
"test-serve": "jest",
21-
"debug-serve": "cross-env VITE_DEBUG_SERVE=1 node --inspect-brk ./node_modules/.bin/jest",
2221
"test-build": "cross-env VITE_TEST_BUILD=1 jest",
22+
"test-unit": "vitest run",
23+
"debug-serve": "cross-env VITE_DEBUG_SERVE=1 node --inspect-brk ./node_modules/.bin/jest",
2324
"debug-build": "cross-env VITE_TEST_BUILD=1 VITE_PRESERVE_BUILD_ARTIFACTS=1 node --inspect-brk ./node_modules/.bin/jest",
2425
"docs": "vitepress dev docs",
2526
"build-docs": "vitepress build docs",
@@ -68,7 +69,8 @@
6869
"ts-node": "^10.4.0",
6970
"typescript": "~4.5.4",
7071
"vite": "workspace:*",
71-
"vitepress": "^0.22.3"
72+
"vitepress": "^0.22.3",
73+
"vitest": "^0.10.4"
7274
},
7375
"simple-git-hooks": {
7476
"pre-commit": "pnpm exec lint-staged --concurrent false",

packages/create-vite/__tests__/cli.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { ExecaSyncReturnValue, SyncOptions } from 'execa'
33
import { commandSync } from 'execa'
44
import { mkdirpSync, readdirSync, remove, writeFileSync } from 'fs-extra'
55
import { join } from 'path'
6+
import { test, expect, beforeAll, afterEach } from 'vitest'
67

78
const CLI_PATH = join(__dirname, '..')
89

packages/plugin-react/src/jsx-runtime/babel-restore-jsx.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import babelRestoreJSX from './babel-restore-jsx'
22
import * as babel from '@babel/core'
3+
import { describe, it, expect } from 'vitest'
34

45
function jsx(code: string) {
56
return babel.transform(code, {

packages/plugin-react/src/jsx-runtime/restore-jsx.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { restoreJSX } from './restore-jsx'
22
import * as babel from '@babel/core'
3+
import { describe, it, expect } from 'vitest'
34

45
async function jsx(sourceCode: string) {
56
const [ast] = await restoreJSX(babel, sourceCode, 'test.js')

packages/vite/src/node/__tests__/asset.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { describe, test, expect } from 'vitest'
12
import { assetFileNamesToFileName, getAssetHash } from '../plugins/asset'
23

34
describe('getAssetHash', () => {

packages/vite/src/node/__tests__/build.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { LibraryFormats, LibraryOptions } from '../build'
22
import { resolveLibFilename } from '../build'
33
import { resolve } from 'path'
4+
import { describe, test, expect } from 'vitest'
45

56
type FormatsToFileNames = [LibraryFormats, string][]
67
const baseLibOptions: LibraryOptions = {
Binary file not shown.

packages/vite/src/node/__tests__/config.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { InlineConfig } from '..'
22
import type { UserConfigExport, UserConfig } from '../config'
33
import { mergeConfig, resolveConfig, resolveEnvPrefix } from '../config'
4+
import { describe, test, expect } from 'vitest'
45

56
describe('mergeConfig', () => {
67
test('handles configs with different alias schemas', () => {

packages/vite/src/node/__tests__/dev.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { resolveConfig } from '..'
2+
import { describe, test, expect } from 'vitest'
23

34
describe('resolveBuildOptions in dev', () => {
45
test('build.rollupOptions should not have input in lib', async () => {

packages/vite/src/node/__tests__/plugins/css.spec.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { cssUrlRE, cssPlugin, hoistAtRules } from '../../plugins/css'
22
import { resolveConfig } from '../../config'
33
import fs from 'fs'
44
import path from 'path'
5+
import { describe, vi, test, expect } from 'vitest'
56

67
describe('search css url function', () => {
78
test('some spaces before it', () => {
@@ -69,7 +70,7 @@ describe('css path resolutions', () => {
6970

7071
await buildStart.call({})
7172

72-
const mockFs = jest
73+
const mockFs = vi
7374
.spyOn(fs, 'readFile')
7475
// @ts-ignore jest.spyOn not recognize overrided `fs.readFile` definition.
7576
.mockImplementationOnce((p, encoding, callback) => {

packages/vite/src/node/__tests__/plugins/define.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { describe, test, expect } from 'vitest'
12
import { definePlugin } from '../../plugins/define'
23
import { resolveConfig } from '../../config'
34

packages/vite/src/node/__tests__/plugins/import.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { describe, test, expect } from 'vitest'
12
import { transformCjsImport } from '../../plugins/importAnalysis'
23

34
describe('transformCjsImport', () => {

packages/vite/src/node/__tests__/scan.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { scriptRE, commentRE, importsRE } from '../optimizer/scan'
22
import { multilineCommentsRE, singlelineCommentsRE } from '../utils'
3+
import { describe, test, expect } from 'vitest'
34

45
describe('optimizer-scan:script-test', () => {
56
const scriptContent = `import { defineComponent } from 'vue'

packages/vite/src/node/__tests__/utils.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
isWindows,
55
resolveHostname
66
} from '../utils'
7+
import { describe, test, expect } from 'vitest'
78

89
describe('injectQuery', () => {
910
if (isWindows) {

packages/vite/src/node/cleanString.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { multilineCommentsRE, singlelineCommentsRE } from './utils'
55
// /`([^`\$\{\}]|\$\{(`|\g<1>)*\})*`/g can match nested string template
66
// but js not support match expression(\g<0>). so clean string template(`...`) in other ways.
77
const stringsRE = /"([^"\r\n]|(?<=\\)")*"|'([^'\r\n]|(?<=\\)')*'/g
8+
const regexRE = /\/.*?(?<!\\)\/[gimsuy]*/g
89
const cleanerRE = new RegExp(
910
`${stringsRE.source}|${multilineCommentsRE.source}|${singlelineCommentsRE.source}`,
1011
'g'
@@ -15,9 +16,11 @@ const stringBlankReplacer = (s: string) =>
1516
`${s[0]}${'\0'.repeat(s.length - 2)}${s[0]}`
1617

1718
export function emptyString(raw: string): string {
18-
let res = raw.replace(cleanerRE, (s: string) =>
19-
s[0] === '/' ? blankReplacer(s) : stringBlankReplacer(s)
20-
)
19+
let res = raw
20+
.replace(cleanerRE, (s: string) =>
21+
s[0] === '/' ? blankReplacer(s) : stringBlankReplacer(s)
22+
)
23+
.replace(regexRE, (s) => stringBlankReplacer(s))
2124

2225
let lastEnd = 0
2326
let start = 0

packages/vite/src/node/server/__tests__/pluginContainer.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { Plugin } from '../../plugin'
44
import { ModuleGraph } from '../moduleGraph'
55
import type { PluginContainer } from '../pluginContainer'
66
import { createPluginContainer } from '../pluginContainer'
7+
import { describe, it, expect, beforeEach } from 'vitest'
78

89
let resolveId: (id: string) => any
910
let moduleGraph: ModuleGraph

packages/vite/src/node/server/__tests__/search-root.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { searchForWorkspaceRoot } from '../searchRoot'
22
import { resolve } from 'path'
3+
import { describe, test, expect } from 'vitest'
34

45
describe('searchForWorkspaceRoot', () => {
56
test('lerna', () => {

packages/vite/src/node/ssr/__tests__/ssrExternal.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { stripNesting } from '../ssrExternal'
2+
import { test, expect } from 'vitest'
23

34
test('stripNesting', async () => {
45
expect(stripNesting(['c', 'p1>c1', 'p2 > c2'])).toEqual(['c', 'c1', 'c2'])

packages/vite/src/node/ssr/__tests__/ssrModuleLoader.spec.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { resolve } from 'path'
22
import { createServer } from '../../index'
3+
import { test, vi, expect } from 'vitest'
34

45
const badjs = resolve(__dirname, './fixtures/ssrModuleLoader-bad.js')
56
const THROW_MESSAGE = 'it is an expected error'
67

78
test('always throw error when evaluating an wrong SSR module', async () => {
89
const viteServer = await createServer()
9-
const spy = jest.spyOn(console, 'error').mockImplementation(() => {})
10+
const spy = vi.spyOn(console, 'error').mockImplementation(() => {})
1011
const expectedErrors = []
1112
for (const i of [0, 1]) {
1213
try {

packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { transformWithEsbuild } from '../../plugins/esbuild'
22
import { traverseHtml } from '../../plugins/html'
33
import { ssrTransform } from '../ssrTransform'
4+
import { test, expect } from 'vitest'
45

56
test('default import', async () => {
67
expect(

0 commit comments

Comments
 (0)