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

fix: use Vitest for unit testing, clean regex bug #8040

Merged
merged 6 commits into from
May 6, 2022
Merged
Show file tree
Hide file tree
Changes from 5 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
4 changes: 2 additions & 2 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ module.exports = defineConfig({
'node/no-extraneous-import': [
'error',
{
allowModules: ['vite', 'less', 'sass']
allowModules: ['vite', 'less', 'sass', 'vitest']
}
],
'node/no-extraneous-require': [
Expand Down Expand Up @@ -103,7 +103,7 @@ module.exports = defineConfig({
}
},
{
files: ['packages/vite/types/**'],
files: ['packages/vite/types/**', '*.spec.ts'],
rules: {
'node/no-extraneous-import': 'off'
}
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ jobs:
- name: Build plugin-react
run: pnpm run build-plugin-react

- name: Test unit
run: pnpm run test-unit

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

Expand Down
14 changes: 12 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,15 @@ And re-run `pnpm install` to link the package.

## Running Tests

### Integration Tests

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.

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 test can be run under either dev server mode or build mode.
Each integration test can be run under either dev server mode or build mode.

- `pnpm test` by default runs every test in both serve and build mode.
- `pnpm test` by default runs every intergartion test in both serve and build mode, and also unit tests.
patak-dev marked this conversation as resolved.
Show resolved Hide resolved

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

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

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

### Unit Tests

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.

- `pnpm run test-unit` runs unit tests under each package.

- You can also use `pnpm run test-unit -- [match]` to run related tests.

### Test Env and Helpers

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:
Expand Down
4 changes: 1 addition & 3 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import type { Config } from '@jest/types'

const config: Config.InitialOptions = {
preset: 'ts-jest',
testMatch: process.env.VITE_TEST_BUILD
? ['**/playground/**/*.spec.[jt]s?(x)']
: ['**/*.spec.[jt]s?(x)'],
testMatch: ['**/playground/**/*.spec.[jt]s?(x)'],
testTimeout: process.env.CI ? 50000 : 20000,
globalSetup: './scripts/jestGlobalSetup.cjs',
globalTeardown: './scripts/jestGlobalTeardown.cjs',
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
"preinstall": "npx only-allow pnpm",
"format": "prettier --write .",
"lint": "eslint packages/*/{src,types}/**",
"test": "run-s test-serve test-build",
"test": "run-s test-serve test-build test-unit",
"test-serve": "jest",
"debug-serve": "cross-env VITE_DEBUG_SERVE=1 node --inspect-brk ./node_modules/.bin/jest",
"test-build": "cross-env VITE_TEST_BUILD=1 jest",
"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",
"docs": "vitepress dev docs",
"build-docs": "vitepress build docs",
Expand Down Expand Up @@ -68,7 +69,8 @@
"ts-node": "^10.4.0",
"typescript": "~4.5.4",
"vite": "workspace:*",
"vitepress": "^0.22.3"
"vitepress": "^0.22.3",
"vitest": "^0.10.4"
},
"simple-git-hooks": {
"pre-commit": "pnpm exec lint-staged --concurrent false",
Expand Down
1 change: 1 addition & 0 deletions packages/create-vite/__tests__/cli.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { ExecaSyncReturnValue, SyncOptions } from 'execa'
import { commandSync } from 'execa'
import { mkdirpSync, readdirSync, remove, writeFileSync } from 'fs-extra'
import { join } from 'path'
import { test, expect, beforeAll, afterEach } from 'vitest'

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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import babelRestoreJSX from './babel-restore-jsx'
import * as babel from '@babel/core'
import { describe, it, expect } from 'vitest'

function jsx(code: string) {
return babel.transform(code, {
Expand Down
1 change: 1 addition & 0 deletions packages/plugin-react/src/jsx-runtime/restore-jsx.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { restoreJSX } from './restore-jsx'
import * as babel from '@babel/core'
import { describe, it, expect } from 'vitest'

async function jsx(sourceCode: string) {
const [ast] = await restoreJSX(babel, sourceCode, 'test.js')
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/__tests__/asset.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { describe, test, expect } from 'vitest'
import { assetFileNamesToFileName, getAssetHash } from '../plugins/asset'

describe('getAssetHash', () => {
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/__tests__/build.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { LibraryFormats, LibraryOptions } from '../build'
import { resolveLibFilename } from '../build'
import { resolve } from 'path'
import { describe, test, expect } from 'vitest'

type FormatsToFileNames = [LibraryFormats, string][]
const baseLibOptions: LibraryOptions = {
Expand Down
Binary file modified packages/vite/src/node/__tests__/cleanString.spec.ts
Binary file not shown.
1 change: 1 addition & 0 deletions packages/vite/src/node/__tests__/config.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { InlineConfig } from '..'
import type { UserConfigExport, UserConfig } from '../config'
import { mergeConfig, resolveConfig, resolveEnvPrefix } from '../config'
import { describe, test, expect } from 'vitest'

describe('mergeConfig', () => {
test('handles configs with different alias schemas', () => {
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/__tests__/dev.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { resolveConfig } from '..'
import { describe, test, expect } from 'vitest'

describe('resolveBuildOptions in dev', () => {
test('build.rollupOptions should not have input in lib', async () => {
Expand Down
3 changes: 2 additions & 1 deletion packages/vite/src/node/__tests__/plugins/css.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { cssUrlRE, cssPlugin, hoistAtRules } from '../../plugins/css'
import { resolveConfig } from '../../config'
import fs from 'fs'
import path from 'path'
import { describe, vi, test, expect } from 'vitest'

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

await buildStart.call({})

const mockFs = jest
const mockFs = vi
.spyOn(fs, 'readFile')
// @ts-ignore jest.spyOn not recognize overrided `fs.readFile` definition.
.mockImplementationOnce((p, encoding, callback) => {
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/__tests__/plugins/define.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { describe, test, expect } from 'vitest'
import { definePlugin } from '../../plugins/define'
import { resolveConfig } from '../../config'

Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/__tests__/plugins/import.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { describe, test, expect } from 'vitest'
import { transformCjsImport } from '../../plugins/importAnalysis'

describe('transformCjsImport', () => {
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/__tests__/scan.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { scriptRE, commentRE, importsRE } from '../optimizer/scan'
import { multilineCommentsRE, singlelineCommentsRE } from '../utils'
import { describe, test, expect } from 'vitest'

describe('optimizer-scan:script-test', () => {
const scriptContent = `import { defineComponent } from 'vue'
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/__tests__/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
isWindows,
resolveHostname
} from '../utils'
import { describe, test, expect } from 'vitest'

describe('injectQuery', () => {
if (isWindows) {
Expand Down
9 changes: 6 additions & 3 deletions packages/vite/src/node/cleanString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { multilineCommentsRE, singlelineCommentsRE } from './utils'
// /`([^`\$\{\}]|\$\{(`|\g<1>)*\})*`/g can match nested string template
// but js not support match expression(\g<0>). so clean string template(`...`) in other ways.
const stringsRE = /"([^"\r\n]|(?<=\\)")*"|'([^'\r\n]|(?<=\\)')*'/g
const regexRE = /\/.*?(?<!\\)\/[gimsuy]*/g
const cleanerRE = new RegExp(
`${stringsRE.source}|${multilineCommentsRE.source}|${singlelineCommentsRE.source}`,
'g'
Expand All @@ -15,9 +16,11 @@ const stringBlankReplacer = (s: string) =>
`${s[0]}${'\0'.repeat(s.length - 2)}${s[0]}`

export function emptyString(raw: string): string {
let res = raw.replace(cleanerRE, (s: string) =>
s[0] === '/' ? blankReplacer(s) : stringBlankReplacer(s)
)
let res = raw
.replace(cleanerRE, (s: string) =>
s[0] === '/' ? blankReplacer(s) : stringBlankReplacer(s)
)
.replace(regexRE, (s) => stringBlankReplacer(s))

let lastEnd = 0
let start = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { Plugin } from '../../plugin'
import { ModuleGraph } from '../moduleGraph'
import type { PluginContainer } from '../pluginContainer'
import { createPluginContainer } from '../pluginContainer'
import { describe, it, expect, beforeEach } from 'vitest'

let resolveId: (id: string) => any
let moduleGraph: ModuleGraph
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { searchForWorkspaceRoot } from '../searchRoot'
import { resolve } from 'path'
import { describe, test, expect } from 'vitest'

describe('searchForWorkspaceRoot', () => {
test('lerna', () => {
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/ssr/__tests__/ssrExternal.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { stripNesting } from '../ssrExternal'
import { test, expect } from 'vitest'

test('stripNesting', async () => {
expect(stripNesting(['c', 'p1>c1', 'p2 > c2'])).toEqual(['c', 'c1', 'c2'])
Expand Down
3 changes: 2 additions & 1 deletion packages/vite/src/node/ssr/__tests__/ssrModuleLoader.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { resolve } from 'path'
import { createServer } from '../../index'
import { test, vi, expect } from 'vitest'

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

test('always throw error when evaluating an wrong SSR module', async () => {
const viteServer = await createServer()
const spy = jest.spyOn(console, 'error').mockImplementation(() => {})
const spy = vi.spyOn(console, 'error').mockImplementation(() => {})
const expectedErrors = []
for (const i of [0, 1]) {
try {
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { transformWithEsbuild } from '../../plugins/esbuild'
import { traverseHtml } from '../../plugins/html'
import { ssrTransform } from '../ssrTransform'
import { test, expect } from 'vitest'

test('default import', async () => {
expect(
Expand Down
Loading