From 069e0f777d8138099adaa8460992e4cab53487fd Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 17 Mar 2026 20:00:40 +0100 Subject: [PATCH 1/2] test: fix column test in rolldown (#9892) --- test/cli/test/static-collect.test.ts | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/test/cli/test/static-collect.test.ts b/test/cli/test/static-collect.test.ts index 9b128edf751c..423172c0a26c 100644 --- a/test/cli/test/static-collect.test.ts +++ b/test/cli/test/static-collect.test.ts @@ -1415,7 +1415,7 @@ test('collects tests with runIf modifier', async () => { test.runIf(true)('runs conditionally', () => {}) test.runIf(false)('also conditional', () => {}) }) -`) +`, { fnFn: true }) expect(testModule).toMatchInlineSnapshot(` { "runIf tests": { @@ -1448,7 +1448,7 @@ test('collects tests with skipIf modifier', async () => { test.skipIf(true)('skips conditionally', () => {}) test.skipIf(false)('also conditional skip', () => {}) }) -`) +`, { fnFn: true }) expect(testModule).toMatchInlineSnapshot(` { "skipIf tests": { @@ -1593,28 +1593,34 @@ async function collectTestModule(code: string, options?: CliOptions) { ) } -async function collectTests(code: string, options?: CliOptions) { - return testTree(await collectTestModule(code, options)) +async function collectTests(code: string, options?: CliOptions & { fnFn?: boolean }) { + return testTree(await collectTestModule(code, options), {}, options?.fnFn) } -function testTree(module: TestModule | TestSuite, tree: any = {}) { +function testTree(module: TestModule | TestSuite, tree: any = {}, fnFn?: boolean) { for (const item of module.children) { if (item.type === 'test') { - tree[item.name] = testItem(item) + tree[item.name] = testItem(item, fnFn) } else { tree[item.name] ??= {} - testTree(item, tree[item.name]) + testTree(item, tree[item.name], fnFn) } } return tree } -function testItem(testCase: TestCase) { +function testItem( + testCase: TestCase, + // A function returning a function (like test.runIf()('name')) + // rolldown's column is moved by 1 in that case + fnFn?: boolean, +) { let location: string | undefined + const state = testCase.result().state if (testCase.location) { // rolldown's column is moved by 1 when using test.each/test.for - const column = rolldownVersion && testCase.options.each + const column = rolldownVersion && (testCase.options.each || fnFn) ? testCase.location.column - 1 : testCase.location.column location = `${testCase.location.line}:${column}` @@ -1624,7 +1630,7 @@ function testItem(testCase: TestCase) { location, mode: testCase.options.mode, fullName: testCase.fullName, - state: testCase.result().state, + state, errors: testCase.result().errors || [], ...(testCase.task.dynamic ? { dynamic: true } : {}), ...(testCase.options.each ? { each: true } : {}), From ed27080103b2c96c3d482e68ba56e06d1fcf1a25 Mon Sep 17 00:00:00 2001 From: NoiseFan Date: Wed, 18 Mar 2026 03:04:40 +0800 Subject: [PATCH 2/2] docs(lifecycle): update lifecycle document format (#9866) --- docs/guide/lifecycle.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/guide/lifecycle.md b/docs/guide/lifecycle.md index 48da13c9f779..aa98886f9c5e 100644 --- a/docs/guide/lifecycle.md +++ b/docs/guide/lifecycle.md @@ -11,13 +11,13 @@ Understanding the test run lifecycle is essential for writing effective tests, d A typical Vitest test run goes through these main phases: -1. **Initialization** - Configuration loading and project setup -2. **Global Setup** - One-time setup before any tests run -3. **Worker Creation** - Test workers are spawned based on the [pool](/config/pool) configuration -4. **Test File Collection** - Test files are discovered and organized -5. **Test Execution** - Tests run with their hooks and assertions -6. **Reporting** - Results are collected and reported -7. **Global Teardown** - Final cleanup after all tests complete +1. **Initialization:** Configuration loading and project setup +2. **Global Setup:** One-time setup before any tests run +3. **Worker Creation:** Test workers are spawned based on the [pool](/config/pool) configuration +4. **Test File Collection:** Test files are discovered and organized +5. **Test Execution:** Tests run with their hooks and assertions +6. **Reporting:** Results are collected and reported +7. **Global Teardown:** Final cleanup after all tests complete Phases 4–6 run once for each test file, so across your test suite they will execute multiple times and may also run in parallel across different files when you use more than [1 worker](/config/maxworkers). @@ -124,10 +124,10 @@ Test files are executed based on your configuration: The execution follows this order: -1. **File-level code** - All code outside `describe` blocks runs immediately -2. **Test collection** - `describe` blocks are processed, and tests are registered as side effects of importing the test file -3. **[`aroundAll`](/api/hooks#aroundall) hooks** - Wrap around all tests in the suite (must call `runSuite()`) -4. **[`beforeAll`](/api/hooks#beforeall) hooks** - Run once before any tests in the suite +1. **File-level code:** All code outside `describe` blocks runs immediately +2. **Test collection:** `describe` blocks are processed, and tests are registered as side effects of importing the test file +3. **[`aroundAll`](/api/hooks#aroundall) hooks:** Wrap around all tests in the suite (must call `runSuite()`) +4. **[`beforeAll`](/api/hooks#beforeall) hooks:** Run once before any tests in the suite 5. **For each test:** - [`aroundEach`](/api/hooks#aroundeach) hooks wrap around the test (must call `runTest()`) - `beforeEach` hooks execute (in order defined, or based on [`sequence.hooks`](/config/sequence#sequence-hooks)) @@ -136,7 +136,7 @@ The execution follows this order: - [`onTestFinished`](/api/hooks#ontestfinished) callbacks run (always in reverse order) - If test failed: [`onTestFailed`](/api/hooks#ontestfailed) callbacks run - Note: if `repeats` or `retry` are set, all of these steps are executed again -6. **[`afterAll`](/api/hooks#afterall) hooks** - Run once after all tests in the suite complete +6. **[`afterAll`](/api/hooks#afterall) hooks:** Run once after all tests in the suite complete **Example execution flow:** @@ -347,7 +347,7 @@ Understanding where code executes is crucial for avoiding common pitfalls: In watch mode, the lifecycle repeats with some differences: -1. **Initial run** - Full lifecycle as described above +1. **Initial run:** Full lifecycle as described above 2. **On file change:** - New [test run](/api/advanced/reporters#ontestrunstart) starts - Only affected test files are re-run