mirror of
https://github.com/vitest-dev/vitest.git
synced 2025-12-08 18:26:03 +00:00
1261 lines
40 KiB
TypeScript
1261 lines
40 KiB
TypeScript
import type { UserConsoleLog } from 'vitest'
|
|
import type {
|
|
ReportedHookContext,
|
|
Reporter,
|
|
SerializedError,
|
|
TestCase,
|
|
TestModule,
|
|
TestRunEndReason,
|
|
TestSpecification,
|
|
TestSuite,
|
|
TestUserConfig,
|
|
Vitest,
|
|
} from 'vitest/node'
|
|
import { rmSync } from 'node:fs'
|
|
import { resolve, sep } from 'node:path'
|
|
import { describe, expect, onTestFinished, test } from 'vitest'
|
|
import { runInlineTests, ts } from '../../test-utils'
|
|
|
|
describe('TestRun', () => {
|
|
test('pass test run without files (no-watch)', async () => {
|
|
const report = await run(
|
|
{},
|
|
{
|
|
passWithNoTests: true,
|
|
watch: false,
|
|
},
|
|
{
|
|
printTestRunEvents: true,
|
|
failed: true,
|
|
},
|
|
)
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestRunStart (0 specifications)
|
|
onTestRunEnd (passed, 0 modules, 0 errors)"
|
|
`)
|
|
})
|
|
|
|
test('pass test run without files (watch)', async () => {
|
|
const report = await run(
|
|
{},
|
|
{
|
|
passWithNoTests: true,
|
|
watch: true,
|
|
},
|
|
{
|
|
printTestRunEvents: true,
|
|
failed: true,
|
|
},
|
|
)
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestRunStart (0 specifications)
|
|
onTestRunEnd (passed, 0 modules, 0 errors)"
|
|
`)
|
|
})
|
|
|
|
test('fail test run without files (no-watch)', async () => {
|
|
const report = await run(
|
|
{},
|
|
{
|
|
passWithNoTests: false,
|
|
watch: false,
|
|
},
|
|
{
|
|
printTestRunEvents: true,
|
|
failed: true,
|
|
},
|
|
)
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestRunStart (0 specifications)
|
|
onTestRunEnd (failed, 0 modules, 0 errors)"
|
|
`)
|
|
})
|
|
})
|
|
|
|
describe('TestModule', () => {
|
|
test('single test module', async () => {
|
|
const report = await run({
|
|
'test-module.test.ts': ts`
|
|
test('example', () => {});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (test-module.test.ts)
|
|
onTestModuleCollected (test-module.test.ts)
|
|
onTestModuleStart (test-module.test.ts)
|
|
onTestCaseReady (test-module.test.ts) |example|
|
|
onTestCaseResult (test-module.test.ts) |example|
|
|
onTestModuleEnd (test-module.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('multiple test modules', async () => {
|
|
const report = await run({
|
|
'first.test.ts': ts`
|
|
test('first test case', () => {});
|
|
`,
|
|
'second.test.ts': ts`
|
|
test('second test case', () => {});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (first.test.ts)
|
|
onTestModuleCollected (first.test.ts)
|
|
onTestModuleStart (first.test.ts)
|
|
onTestCaseReady (first.test.ts) |first test case|
|
|
onTestCaseResult (first.test.ts) |first test case|
|
|
onTestModuleEnd (first.test.ts)
|
|
|
|
onTestModuleQueued (second.test.ts)
|
|
onTestModuleCollected (second.test.ts)
|
|
onTestModuleStart (second.test.ts)
|
|
onTestCaseReady (second.test.ts) |second test case|
|
|
onTestCaseResult (second.test.ts) |second test case|
|
|
onTestModuleEnd (second.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('test modules with delay', async () => {
|
|
const report = await run({
|
|
'first.test.ts': ts`
|
|
${delay()}
|
|
test('first test case', async () => { ${delay()} });
|
|
`,
|
|
'second.test.ts': ts`
|
|
${delay()}
|
|
test('second test case', async () => { ${delay()} });
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (first.test.ts)
|
|
onTestModuleCollected (first.test.ts)
|
|
onTestModuleStart (first.test.ts)
|
|
onTestCaseReady (first.test.ts) |first test case|
|
|
onTestCaseResult (first.test.ts) |first test case|
|
|
onTestModuleEnd (first.test.ts)
|
|
|
|
onTestModuleQueued (second.test.ts)
|
|
onTestModuleCollected (second.test.ts)
|
|
onTestModuleStart (second.test.ts)
|
|
onTestCaseReady (second.test.ts) |second test case|
|
|
onTestCaseResult (second.test.ts) |second test case|
|
|
onTestModuleEnd (second.test.ts)"
|
|
`)
|
|
})
|
|
})
|
|
|
|
describe('TestCase', () => {
|
|
test('single test case', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
test('single test case', async () => {
|
|
await new Promise(resolve => setTimeout(resolve, 300))
|
|
console.log("Test running!")
|
|
});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestCaseReady (example.test.ts) |single test case|
|
|
onUserConsoleLog (example.test.ts) |single test case| > Test running!
|
|
onTestCaseResult (example.test.ts) |single test case|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('multiple test cases', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
test('first', () => {});
|
|
test('second', () => {});
|
|
test('third', () => {});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestCaseReady (example.test.ts) |first|
|
|
onTestCaseResult (example.test.ts) |first|
|
|
onTestCaseReady (example.test.ts) |second|
|
|
onTestCaseResult (example.test.ts) |second|
|
|
onTestCaseReady (example.test.ts) |third|
|
|
onTestCaseResult (example.test.ts) |third|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('multiple test cases with delay', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
${delay()}
|
|
test('first', async () => { ${delay()} });
|
|
test('second', async () => { ${delay()} });
|
|
test('third', async () => { ${delay()} });
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestCaseReady (example.test.ts) |first|
|
|
onTestCaseResult (example.test.ts) |first|
|
|
onTestCaseReady (example.test.ts) |second|
|
|
onTestCaseResult (example.test.ts) |second|
|
|
onTestCaseReady (example.test.ts) |third|
|
|
onTestCaseResult (example.test.ts) |third|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('failing test case', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
test('failing test case', () => {
|
|
expect(1).toBe(2)
|
|
});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestCaseReady (example.test.ts) |failing test case|
|
|
onTestCaseResult (example.test.ts) |failing test case|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('skipped test case', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
test('running', () => {});
|
|
test.skip('skipped', () => {});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestCaseReady (example.test.ts) |running|
|
|
onTestCaseResult (example.test.ts) |running|
|
|
onTestCaseReady (example.test.ts) |skipped|
|
|
onTestCaseResult (example.test.ts) |skipped|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('skipped test case in a different order', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
test.skip('skipped', () => {});
|
|
test('running', () => {});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestCaseReady (example.test.ts) |skipped|
|
|
onTestCaseResult (example.test.ts) |skipped|
|
|
onTestCaseReady (example.test.ts) |running|
|
|
onTestCaseResult (example.test.ts) |running|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('skipped test case in a suite with a different order', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
describe('suite', () => {
|
|
test.skip('skipped', () => {});
|
|
test('running', () => {});
|
|
})
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestSuiteReady (example.test.ts) |suite|
|
|
onTestCaseReady (example.test.ts) |skipped|
|
|
onTestCaseResult (example.test.ts) |skipped|
|
|
onTestCaseReady (example.test.ts) |running|
|
|
onTestCaseResult (example.test.ts) |running|
|
|
onTestSuiteResult (example.test.ts) |suite|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('dynamically skipped test case', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
test('running', () => {});
|
|
test('skipped', (ctx) => { ctx.skip() });
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestCaseReady (example.test.ts) |running|
|
|
onTestCaseResult (example.test.ts) |running|
|
|
onTestCaseReady (example.test.ts) |skipped|
|
|
onTestCaseResult (example.test.ts) |skipped|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('skipped all test cases', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
test.skip('first', () => {});
|
|
test.skip('second', () => {});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestCaseReady (example.test.ts) |first|
|
|
onTestCaseResult (example.test.ts) |first|
|
|
onTestCaseReady (example.test.ts) |second|
|
|
onTestCaseResult (example.test.ts) |second|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
})
|
|
|
|
describe('TestSuite', () => {
|
|
test('single test suite', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
describe("example suite", () => {
|
|
test('first test case', () => {});
|
|
});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestSuiteReady (example.test.ts) |example suite|
|
|
onTestCaseReady (example.test.ts) |first test case|
|
|
onTestCaseResult (example.test.ts) |first test case|
|
|
onTestSuiteResult (example.test.ts) |example suite|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('multiple test suites', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
describe("first suite", () => {
|
|
test('first test case', () => {});
|
|
});
|
|
|
|
describe("second suite", () => {
|
|
test('second test case', () => {});
|
|
});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestSuiteReady (example.test.ts) |first suite|
|
|
onTestCaseReady (example.test.ts) |first test case|
|
|
onTestCaseResult (example.test.ts) |first test case|
|
|
onTestSuiteResult (example.test.ts) |first suite|
|
|
onTestSuiteReady (example.test.ts) |second suite|
|
|
onTestCaseReady (example.test.ts) |second test case|
|
|
onTestCaseResult (example.test.ts) |second test case|
|
|
onTestSuiteResult (example.test.ts) |second suite|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('multiple test suites with delay', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
${delay()}
|
|
describe("first suite", async () => {
|
|
${delay()}
|
|
test('first test case', async () => { ${delay()} });
|
|
});
|
|
|
|
describe("second suite", async () => {
|
|
${delay()}
|
|
test('second test case', async () => { ${delay()} });
|
|
});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestSuiteReady (example.test.ts) |first suite|
|
|
onTestCaseReady (example.test.ts) |first test case|
|
|
onTestCaseResult (example.test.ts) |first test case|
|
|
onTestSuiteResult (example.test.ts) |first suite|
|
|
onTestSuiteReady (example.test.ts) |second suite|
|
|
onTestCaseReady (example.test.ts) |second test case|
|
|
onTestCaseResult (example.test.ts) |second test case|
|
|
onTestSuiteResult (example.test.ts) |second suite|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('nested test suites', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
describe("first suite", () => {
|
|
test('first test case', () => {});
|
|
|
|
describe("second suite", () => {
|
|
test('second test case', () => {});
|
|
|
|
describe("third suite", () => {
|
|
test('third test case', () => {});
|
|
});
|
|
});
|
|
});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestSuiteReady (example.test.ts) |first suite|
|
|
onTestCaseReady (example.test.ts) |first test case|
|
|
onTestCaseResult (example.test.ts) |first test case|
|
|
onTestSuiteReady (example.test.ts) |second suite|
|
|
onTestCaseReady (example.test.ts) |second test case|
|
|
onTestCaseResult (example.test.ts) |second test case|
|
|
onTestSuiteReady (example.test.ts) |third suite|
|
|
onTestCaseReady (example.test.ts) |third test case|
|
|
onTestCaseResult (example.test.ts) |third test case|
|
|
onTestSuiteResult (example.test.ts) |third suite|
|
|
onTestSuiteResult (example.test.ts) |second suite|
|
|
onTestSuiteResult (example.test.ts) |first suite|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('skipped test suite', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
describe.skip("skipped suite", () => {
|
|
test('first test case', () => {});
|
|
});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestSuiteReady (example.test.ts) |skipped suite|
|
|
onTestCaseReady (example.test.ts) |first test case|
|
|
onTestCaseResult (example.test.ts) |first test case|
|
|
onTestSuiteResult (example.test.ts) |skipped suite|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('skipped double nested test suite', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
describe.skip("skipped suite", () => {
|
|
describe.skip("nested skipped suite", () => {
|
|
test('first nested case', () => {});
|
|
})
|
|
});
|
|
|
|
test('first test case', () => {});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestSuiteReady (example.test.ts) |skipped suite|
|
|
onTestSuiteReady (example.test.ts) |nested skipped suite|
|
|
onTestCaseReady (example.test.ts) |first nested case|
|
|
onTestCaseResult (example.test.ts) |first nested case|
|
|
onTestSuiteResult (example.test.ts) |nested skipped suite|
|
|
onTestSuiteResult (example.test.ts) |skipped suite|
|
|
onTestCaseReady (example.test.ts) |first test case|
|
|
onTestCaseResult (example.test.ts) |first test case|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('skipped nested test suite', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
describe("first suite", () => {
|
|
test('first test case', () => {});
|
|
|
|
describe.skip("skipped suite", () => {
|
|
test('second test case', () => {});
|
|
});
|
|
});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestSuiteReady (example.test.ts) |first suite|
|
|
onTestCaseReady (example.test.ts) |first test case|
|
|
onTestCaseResult (example.test.ts) |first test case|
|
|
onTestSuiteReady (example.test.ts) |skipped suite|
|
|
onTestCaseReady (example.test.ts) |second test case|
|
|
onTestCaseResult (example.test.ts) |second test case|
|
|
onTestSuiteResult (example.test.ts) |skipped suite|
|
|
onTestSuiteResult (example.test.ts) |first suite|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
})
|
|
|
|
describe('hooks', () => {
|
|
test('beforeEach', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
beforeEach(() => {});
|
|
|
|
test('first', () => {});
|
|
test('second', () => {});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestCaseReady (example.test.ts) |first|
|
|
onHookStart (example.test.ts) |first| [beforeEach]
|
|
onHookEnd (example.test.ts) |first| [beforeEach]
|
|
onTestCaseResult (example.test.ts) |first|
|
|
onTestCaseReady (example.test.ts) |second|
|
|
onHookStart (example.test.ts) |second| [beforeEach]
|
|
onHookEnd (example.test.ts) |second| [beforeEach]
|
|
onTestCaseResult (example.test.ts) |second|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('afterEach', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
afterEach(() => {});
|
|
|
|
test('first', () => {});
|
|
test('second', () => {});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestCaseReady (example.test.ts) |first|
|
|
onHookStart (example.test.ts) |first| [afterEach]
|
|
onHookEnd (example.test.ts) |first| [afterEach]
|
|
onTestCaseResult (example.test.ts) |first|
|
|
onTestCaseReady (example.test.ts) |second|
|
|
onHookStart (example.test.ts) |second| [afterEach]
|
|
onHookEnd (example.test.ts) |second| [afterEach]
|
|
onTestCaseResult (example.test.ts) |second|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('beforeEach and afterEach', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
beforeEach(() => {});
|
|
afterEach(() => {});
|
|
|
|
test('first', () => {});
|
|
test('second', () => {});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestCaseReady (example.test.ts) |first|
|
|
onHookStart (example.test.ts) |first| [beforeEach]
|
|
onHookEnd (example.test.ts) |first| [beforeEach]
|
|
onHookStart (example.test.ts) |first| [afterEach]
|
|
onHookEnd (example.test.ts) |first| [afterEach]
|
|
onTestCaseResult (example.test.ts) |first|
|
|
onTestCaseReady (example.test.ts) |second|
|
|
onHookStart (example.test.ts) |second| [beforeEach]
|
|
onHookEnd (example.test.ts) |second| [beforeEach]
|
|
onHookStart (example.test.ts) |second| [afterEach]
|
|
onHookEnd (example.test.ts) |second| [afterEach]
|
|
onTestCaseResult (example.test.ts) |second|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('beforeAll', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
beforeAll(() => {});
|
|
|
|
test('first', () => {});
|
|
test('second', () => {});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onHookStart (example.test.ts) [beforeAll]
|
|
onHookEnd (example.test.ts) [beforeAll]
|
|
onTestCaseReady (example.test.ts) |first|
|
|
onTestCaseResult (example.test.ts) |first|
|
|
onTestCaseReady (example.test.ts) |second|
|
|
onTestCaseResult (example.test.ts) |second|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('afterAll', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
afterAll(() => {});
|
|
|
|
test('first', () => {});
|
|
test('second', () => {});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestCaseReady (example.test.ts) |first|
|
|
onTestCaseResult (example.test.ts) |first|
|
|
onTestCaseReady (example.test.ts) |second|
|
|
onTestCaseResult (example.test.ts) |second|
|
|
onHookStart (example.test.ts) [afterAll]
|
|
onHookEnd (example.test.ts) [afterAll]
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('beforeAll and afterAll', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
beforeAll(() => {});
|
|
afterAll(() => {});
|
|
|
|
test('first', () => {});
|
|
test('second', () => {});
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onHookStart (example.test.ts) [beforeAll]
|
|
onHookEnd (example.test.ts) [beforeAll]
|
|
onTestCaseReady (example.test.ts) |first|
|
|
onTestCaseResult (example.test.ts) |first|
|
|
onTestCaseReady (example.test.ts) |second|
|
|
onTestCaseResult (example.test.ts) |second|
|
|
onHookStart (example.test.ts) [afterAll]
|
|
onHookEnd (example.test.ts) [afterAll]
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('all hooks with delay', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
${delay()}
|
|
beforeAll(async () => { ${delay()} });
|
|
afterAll(async () => { ${delay()} });
|
|
beforeEach(async () => { ${delay()} });
|
|
afterEach(async () => { ${delay()} });
|
|
|
|
test('first', async () => { ${delay()} });
|
|
test('second', async () => { ${delay()} });
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onHookStart (example.test.ts) [beforeAll]
|
|
onHookEnd (example.test.ts) [beforeAll]
|
|
onTestCaseReady (example.test.ts) |first|
|
|
onHookStart (example.test.ts) |first| [beforeEach]
|
|
onHookEnd (example.test.ts) |first| [beforeEach]
|
|
onHookStart (example.test.ts) |first| [afterEach]
|
|
onHookEnd (example.test.ts) |first| [afterEach]
|
|
onTestCaseResult (example.test.ts) |first|
|
|
onTestCaseReady (example.test.ts) |second|
|
|
onHookStart (example.test.ts) |second| [beforeEach]
|
|
onHookEnd (example.test.ts) |second| [beforeEach]
|
|
onHookStart (example.test.ts) |second| [afterEach]
|
|
onHookEnd (example.test.ts) |second| [afterEach]
|
|
onTestCaseResult (example.test.ts) |second|
|
|
onHookStart (example.test.ts) [afterAll]
|
|
onHookEnd (example.test.ts) [afterAll]
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('beforeAll on suite', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
describe("example", () => {
|
|
beforeAll(() => {});
|
|
|
|
test('first', () => {});
|
|
test('second', () => {});
|
|
})
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestSuiteReady (example.test.ts) |example|
|
|
onHookStart (example.test.ts) |example| [beforeAll]
|
|
onHookEnd (example.test.ts) |example| [beforeAll]
|
|
onTestCaseReady (example.test.ts) |first|
|
|
onTestCaseResult (example.test.ts) |first|
|
|
onTestCaseReady (example.test.ts) |second|
|
|
onTestCaseResult (example.test.ts) |second|
|
|
onTestSuiteResult (example.test.ts) |example|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('afterAll on suite', async () => {
|
|
const report = await run({
|
|
'example.test.ts': ts`
|
|
describe("example", () => {
|
|
afterAll(() => {});
|
|
|
|
test('first', () => {});
|
|
test('second', () => {});
|
|
})
|
|
`,
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestSuiteReady (example.test.ts) |example|
|
|
onTestCaseReady (example.test.ts) |first|
|
|
onTestCaseResult (example.test.ts) |first|
|
|
onTestCaseReady (example.test.ts) |second|
|
|
onTestCaseResult (example.test.ts) |second|
|
|
onHookStart (example.test.ts) |example| [afterAll]
|
|
onHookEnd (example.test.ts) |example| [afterAll]
|
|
onTestSuiteResult (example.test.ts) |example|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
})
|
|
|
|
describe('merge reports', () => {
|
|
test('correctly reports events for a single test module', async () => {
|
|
const blobsOutputDirectory = resolve(import.meta.dirname, 'fixtures-blobs')
|
|
const blobOutputFile = resolve(blobsOutputDirectory, 'blob.json')
|
|
onTestFinished(() => {
|
|
rmSync(blobOutputFile)
|
|
})
|
|
|
|
const { root } = await runInlineTests({
|
|
'example.test.ts': ts`
|
|
test('first', () => {});
|
|
describe('suite', () => {
|
|
test('second', () => {});
|
|
});
|
|
`,
|
|
}, {
|
|
globals: true,
|
|
reporters: [['blob', { outputFile: blobOutputFile }]],
|
|
})
|
|
|
|
const report = await run(
|
|
{},
|
|
{
|
|
mergeReports: blobsOutputDirectory,
|
|
},
|
|
{
|
|
roots: [root],
|
|
},
|
|
)
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example.test.ts)
|
|
onTestModuleCollected (example.test.ts)
|
|
onTestModuleStart (example.test.ts)
|
|
onTestCaseReady (example.test.ts) |first|
|
|
onTestCaseResult (example.test.ts) |first|
|
|
onTestSuiteReady (example.test.ts) |suite|
|
|
onTestCaseReady (example.test.ts) |second|
|
|
onTestCaseResult (example.test.ts) |second|
|
|
onTestSuiteResult (example.test.ts) |suite|
|
|
onTestModuleEnd (example.test.ts)"
|
|
`)
|
|
})
|
|
|
|
test('correctly reports multiple test modules', async () => {
|
|
const blobsOutputDirectory = resolve(import.meta.dirname, 'fixtures-blobs')
|
|
const blobOutputFile1 = resolve(blobsOutputDirectory, 'blob-1.json')
|
|
const blobOutputFile2 = resolve(blobsOutputDirectory, 'blob-2.json')
|
|
onTestFinished(() => {
|
|
rmSync(blobOutputFile1)
|
|
rmSync(blobOutputFile2)
|
|
})
|
|
|
|
const { root: root1 } = await runInlineTests({
|
|
'example-1.test.ts': ts`
|
|
test('first', () => {});
|
|
describe('suite', () => {
|
|
test('second', () => {});
|
|
});
|
|
`,
|
|
}, {
|
|
globals: true,
|
|
reporters: [['blob', { outputFile: blobOutputFile1 }]],
|
|
watch: false,
|
|
})
|
|
|
|
const { root: root2 } = await runInlineTests({
|
|
'example-2.test.ts': ts`
|
|
test('first', () => {});
|
|
describe.skip('suite', () => {
|
|
test('second', () => {});
|
|
test('third', () => {});
|
|
});
|
|
test.skip('fourth', () => {});
|
|
test('fifth', () => {});
|
|
`,
|
|
}, {
|
|
globals: true,
|
|
reporters: [['blob', { outputFile: blobOutputFile2 }]],
|
|
watch: false,
|
|
})
|
|
|
|
const report = await run({}, {
|
|
mergeReports: blobsOutputDirectory,
|
|
watch: false,
|
|
}, {
|
|
roots: [root1, root2],
|
|
})
|
|
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestModuleQueued (example-1.test.ts)
|
|
onTestModuleCollected (example-1.test.ts)
|
|
onTestModuleStart (example-1.test.ts)
|
|
onTestCaseReady (example-1.test.ts) |first|
|
|
onTestCaseResult (example-1.test.ts) |first|
|
|
onTestSuiteReady (example-1.test.ts) |suite|
|
|
onTestCaseReady (example-1.test.ts) |second|
|
|
onTestCaseResult (example-1.test.ts) |second|
|
|
onTestSuiteResult (example-1.test.ts) |suite|
|
|
onTestModuleEnd (example-1.test.ts)
|
|
|
|
onTestModuleQueued (example-2.test.ts)
|
|
onTestModuleCollected (example-2.test.ts)
|
|
onTestModuleStart (example-2.test.ts)
|
|
onTestCaseReady (example-2.test.ts) |first|
|
|
onTestCaseResult (example-2.test.ts) |first|
|
|
onTestSuiteReady (example-2.test.ts) |suite|
|
|
onTestCaseReady (example-2.test.ts) |second|
|
|
onTestCaseResult (example-2.test.ts) |second|
|
|
onTestCaseReady (example-2.test.ts) |third|
|
|
onTestCaseResult (example-2.test.ts) |third|
|
|
onTestSuiteResult (example-2.test.ts) |suite|
|
|
onTestCaseReady (example-2.test.ts) |fourth|
|
|
onTestCaseResult (example-2.test.ts) |fourth|
|
|
onTestCaseReady (example-2.test.ts) |fifth|
|
|
onTestCaseResult (example-2.test.ts) |fifth|
|
|
onTestModuleEnd (example-2.test.ts)"
|
|
`)
|
|
})
|
|
})
|
|
|
|
describe('type checking', () => {
|
|
test('typechecking is reported correctly', async () => {
|
|
const report = await run({
|
|
'example-1.test-d.ts': ts`
|
|
test('first', () => {});
|
|
describe('suite', () => {
|
|
test('second', () => {});
|
|
});
|
|
`,
|
|
'example-2.test-d.ts': ts`
|
|
test('first', () => {});
|
|
describe.skip('suite', () => {
|
|
test('second', () => {});
|
|
test('third', () => {});
|
|
});
|
|
test.skip('fourth', () => {});
|
|
test('fifth', () => {});
|
|
`,
|
|
'tsconfig.json': JSON.stringify({
|
|
compilerOptions: {
|
|
strict: true,
|
|
},
|
|
include: ['./*.test-d.ts'],
|
|
}),
|
|
}, {
|
|
typecheck: {
|
|
enabled: true,
|
|
},
|
|
}, { printTestRunEvents: true })
|
|
|
|
// NOTE: typechecker reports test modules in bulk, so the order of queued and collect
|
|
// is different from the normal test run, this is because the typechecker runs everything together
|
|
// this _might_ need to be changed in the future
|
|
expect(report).toMatchInlineSnapshot(`
|
|
"
|
|
onTestRunStart (2 specifications)
|
|
onTestModuleQueued (example-1.test-d.ts)
|
|
onTestModuleQueued (example-2.test-d.ts)
|
|
onTestModuleCollected (example-1.test-d.ts)
|
|
onTestModuleCollected (example-2.test-d.ts)
|
|
onTestModuleStart (example-1.test-d.ts)
|
|
onTestCaseReady (example-1.test-d.ts) |first|
|
|
onTestCaseResult (example-1.test-d.ts) |first|
|
|
onTestSuiteReady (example-1.test-d.ts) |suite|
|
|
onTestCaseReady (example-1.test-d.ts) |second|
|
|
onTestCaseResult (example-1.test-d.ts) |second|
|
|
onTestSuiteResult (example-1.test-d.ts) |suite|
|
|
onTestModuleEnd (example-1.test-d.ts)
|
|
|
|
onTestModuleStart (example-2.test-d.ts)
|
|
onTestCaseReady (example-2.test-d.ts) |first|
|
|
onTestCaseResult (example-2.test-d.ts) |first|
|
|
onTestSuiteReady (example-2.test-d.ts) |suite|
|
|
onTestCaseReady (example-2.test-d.ts) |second|
|
|
onTestCaseResult (example-2.test-d.ts) |second|
|
|
onTestCaseReady (example-2.test-d.ts) |third|
|
|
onTestCaseResult (example-2.test-d.ts) |third|
|
|
onTestSuiteResult (example-2.test-d.ts) |suite|
|
|
onTestCaseReady (example-2.test-d.ts) |fourth|
|
|
onTestCaseResult (example-2.test-d.ts) |fourth|
|
|
onTestCaseReady (example-2.test-d.ts) |fifth|
|
|
onTestCaseResult (example-2.test-d.ts) |fifth|
|
|
onTestModuleEnd (example-2.test-d.ts)
|
|
|
|
onTestRunEnd (failed, 2 modules, 0 errors)"
|
|
`)
|
|
})
|
|
})
|
|
|
|
describe('test run result', () => {
|
|
test('test run is interrupted', async () => {
|
|
let vitest: Vitest
|
|
let reason: TestRunEndReason | undefined
|
|
|
|
await runInlineTests({
|
|
'example.test.js': `
|
|
test('basic', () => new Promise(() => {}))
|
|
`,
|
|
}, {
|
|
globals: true,
|
|
reporters: [
|
|
{
|
|
onInit(ctx) {
|
|
vitest = ctx
|
|
},
|
|
async onTestModuleCollected() {
|
|
await vitest.cancelCurrentRun('keyboard-input')
|
|
},
|
|
onTestRunEnd(_, __, reason_) {
|
|
reason = reason_
|
|
},
|
|
},
|
|
],
|
|
})
|
|
|
|
expect(reason).toBe('interrupted')
|
|
})
|
|
|
|
test('test run failed, but passed afterwards', async () => {
|
|
let reason: TestRunEndReason | undefined
|
|
|
|
const { fs } = await runInlineTests({
|
|
'example.test.js': `
|
|
test('basic', () => {
|
|
expect(1).toBe(2)
|
|
})
|
|
`,
|
|
}, {
|
|
globals: true,
|
|
watch: true,
|
|
reporters: [
|
|
{
|
|
onTestRunEnd(_, __, reason_) {
|
|
reason = reason_
|
|
},
|
|
},
|
|
],
|
|
})
|
|
|
|
expect(reason).toBe('failed')
|
|
|
|
fs.editFile('./example.test.js', c => c.replace('toBe(2)', 'toBe(1)'))
|
|
|
|
await expect.poll(() => reason).toBe('passed')
|
|
})
|
|
|
|
test('test run passed', async () => {
|
|
let reason: TestRunEndReason | undefined
|
|
|
|
await runInlineTests({
|
|
'example.test.js': `
|
|
test('basic', () => {
|
|
expect(1).toBe(1)
|
|
})
|
|
`,
|
|
}, {
|
|
globals: true,
|
|
watch: true,
|
|
reporters: [
|
|
{
|
|
onTestRunEnd(_, __, reason_) {
|
|
reason = reason_
|
|
},
|
|
},
|
|
],
|
|
})
|
|
|
|
expect(reason).toBe('passed')
|
|
})
|
|
})
|
|
|
|
interface ReporterOptions {
|
|
printTestRunEvents?: boolean
|
|
roots?: string[]
|
|
failed?: boolean
|
|
}
|
|
|
|
async function run(
|
|
structure: Parameters<typeof runInlineTests>[0],
|
|
customConfig?: TestUserConfig,
|
|
reporterOptions?: ReporterOptions,
|
|
) {
|
|
const reporter = new CustomReporter(reporterOptions)
|
|
|
|
const config: TestUserConfig = {
|
|
config: false,
|
|
fileParallelism: false,
|
|
globals: true,
|
|
reporters: [reporter],
|
|
sequence: {
|
|
sequencer: class Sorter {
|
|
sort(files: TestSpecification[]) {
|
|
return files.sort((a, b) => a.moduleId.localeCompare(b.moduleId))
|
|
}
|
|
|
|
shard(files: TestSpecification[]) {
|
|
return files
|
|
}
|
|
},
|
|
},
|
|
...customConfig,
|
|
}
|
|
|
|
const { stdout, stderr } = await runInlineTests(structure, config)
|
|
|
|
if (!reporterOptions?.printTestRunEvents && !reporterOptions?.failed) {
|
|
expect(stdout).toBe('')
|
|
expect(stderr).toBe('')
|
|
}
|
|
|
|
return `\n${reporter.calls.join('\n').trim()}`
|
|
}
|
|
|
|
class CustomReporter implements Reporter {
|
|
calls: string[] = []
|
|
ctx!: Vitest
|
|
|
|
constructor(private options: ReporterOptions = {}) {}
|
|
|
|
onInit(ctx: Vitest) {
|
|
this.ctx = ctx
|
|
}
|
|
|
|
onTestRunStart(specifications: ReadonlyArray<TestSpecification>) {
|
|
if (this.options.printTestRunEvents) {
|
|
this.calls.push(`onTestRunStart (${specifications.length} specifications)`)
|
|
}
|
|
}
|
|
|
|
onTestRunEnd(modules: ReadonlyArray<TestModule>, errors: ReadonlyArray<SerializedError>, state: TestRunEndReason) {
|
|
if (this.options.printTestRunEvents) {
|
|
this.calls.push(`onTestRunEnd (${state}, ${modules.length} modules, ${errors.length} errors)`)
|
|
}
|
|
}
|
|
|
|
onTestModuleQueued(module: TestModule) {
|
|
this.calls.push(`onTestModuleQueued (${this.normalizeFilename(module)})`)
|
|
}
|
|
|
|
onTestModuleCollected(module: TestModule) {
|
|
this.calls.push(`onTestModuleCollected (${this.normalizeFilename(module)})`)
|
|
}
|
|
|
|
onTestSuiteReady(testSuite: TestSuite) {
|
|
this.calls.push(`${padded(testSuite, 'onTestSuiteReady')} (${this.normalizeFilename(testSuite.module)}) |${testSuite.name}|`)
|
|
}
|
|
|
|
onTestSuiteResult(testSuite: TestSuite) {
|
|
this.calls.push(`${padded(testSuite, 'onTestSuiteResult')} (${this.normalizeFilename(testSuite.module)}) |${testSuite.name}|`)
|
|
}
|
|
|
|
onTestModuleStart(module: TestModule) {
|
|
this.calls.push(`onTestModuleStart (${this.normalizeFilename(module)})`)
|
|
}
|
|
|
|
onTestModuleEnd(module: TestModule) {
|
|
this.calls.push(`onTestModuleEnd (${this.normalizeFilename(module)})\n`)
|
|
}
|
|
|
|
onTestCaseReady(test: TestCase) {
|
|
this.calls.push(`${padded(test, 'onTestCaseReady')} (${this.normalizeFilename(test.module)}) |${test.name}|`)
|
|
}
|
|
|
|
onTestCaseResult(test: TestCase) {
|
|
this.calls.push(`${padded(test, 'onTestCaseResult')} (${this.normalizeFilename(test.module)}) |${test.name}|`)
|
|
}
|
|
|
|
onUserConsoleLog(log: UserConsoleLog) {
|
|
const task = this.ctx.state.idMap.get(log.taskId!)
|
|
const test = task && this.ctx.state.getReportedEntity(task) as TestCase
|
|
|
|
this.calls.push(`${padded(test!, 'onUserConsoleLog')} (${this.normalizeFilename(test!.module)}) |${test!.name}| > ${log.content.replaceAll('\n', '')}`)
|
|
}
|
|
|
|
onHookStart(hook: ReportedHookContext) {
|
|
const module = hook.entity.type === 'module' ? hook.entity : hook.entity.module
|
|
const name = hook.entity.type !== 'module' ? ` |${hook.entity.name}|` : ''
|
|
this.calls.push(` ${padded(hook.entity, 'onHookStart', 19)} (${this.normalizeFilename(module)})${name} [${hook.name}]`)
|
|
}
|
|
|
|
onHookEnd(hook: ReportedHookContext) {
|
|
const module = hook.entity.type === 'module' ? hook.entity : hook.entity.module
|
|
const name = hook.entity.type !== 'module' ? ` |${hook.entity.name}|` : ''
|
|
this.calls.push(` ${padded(hook.entity, 'onHookEnd', 19)} (${this.normalizeFilename(module)})${name} [${hook.name}]`)
|
|
}
|
|
|
|
normalizeFilename(module: TestModule) {
|
|
return normalizeFilename(module, this.options.roots)
|
|
}
|
|
}
|
|
|
|
function normalizeFilename(module: TestModule, roots?: string[]) {
|
|
const relative = (roots || [module.project.config.root]).reduce((acc, root) => {
|
|
return acc.replace(root, '')
|
|
}, module.moduleId)
|
|
return relative.replaceAll(sep, '/')
|
|
.substring(1)
|
|
}
|
|
|
|
function padded(entity: TestSuite | TestCase | TestModule, name: string, pad = 21) {
|
|
return (' '.repeat(getDepth(entity)) + name).padEnd(pad)
|
|
}
|
|
|
|
function getDepth(entity: TestSuite | TestCase | TestModule) {
|
|
if (entity.type === 'module') {
|
|
return 0
|
|
}
|
|
|
|
let depth = 0
|
|
let parent = entity.parent
|
|
|
|
while (parent) {
|
|
depth += 2
|
|
if (parent.type !== 'module') {
|
|
parent = parent.parent
|
|
}
|
|
else {
|
|
break
|
|
}
|
|
}
|
|
|
|
return depth
|
|
}
|
|
|
|
function delay() {
|
|
return `await new Promise(resolve => setTimeout(resolve, 100));`
|
|
}
|