From 7a17cd1fdc28b127f4660b9fbd365e295ba10373 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 15 Aug 2026 01:28:19 +0000 Subject: [PATCH 1/5] bun test: fix error for snapshot matchers on an expect() from a finished test or describe body get_snapshot_name mapped every case where the captured execution entry could not be resolved to SnapshotInConcurrentGroup, so an expect() created in a test that has since finished (for example one that timed out) or in a describe callback reported "Snapshot matchers are not supported in concurrent tests". Classify by the state captured when expect() was called: a captured entry that is no longer active is TestNotActive, a concurrent group (no entry captured) stays SnapshotInConcurrentGroup, and the collection/done phases are NoTest, which Expect::snapshot now reports as "Snapshot matchers cannot be used outside of a test". --- src/runtime/test_runner/expect.rs | 20 +++- .../test/snapshot-tests/bun-snapshots.test.ts | 108 ++++++++++++++++++ 2 files changed, 124 insertions(+), 4 deletions(-) diff --git a/src/runtime/test_runner/expect.rs b/src/runtime/test_runner/expect.rs index e7b3471e39c0..49dbc88514ee 100644 --- a/src/runtime/test_runner/expect.rs +++ b/src/runtime/test_runner/expect.rs @@ -623,10 +623,19 @@ impl Expect { let parent = self.parent.as_ref().ok_or(crate::Error::NoTest)?; let buntest_strong = parent.bun_test().ok_or(crate::Error::TestNotActive)?; let buntest = buntest_strong.get(); - let execution_entry = parent - .phase - .entry(buntest) - .ok_or(crate::Error::SnapshotInConcurrentGroup)?; + let execution_entry = match &parent.phase { + // `entry()` is None once the runner has advanced past the entry that was + // running when this expect() was created. + bun_test::RefDataValue::Execution { entry_data: Some(_), .. } => { + parent.phase.entry(buntest).ok_or(crate::Error::TestNotActive)? + } + bun_test::RefDataValue::Execution { entry_data: None, .. } => { + return Err(crate::Error::SnapshotInConcurrentGroup); + } + bun_test::RefDataValue::Start + | bun_test::RefDataValue::Collection { .. } + | bun_test::RefDataValue::Done => return Err(crate::Error::NoTest), + }; let test_name: &[u8] = execution_entry.base.name.as_deref().unwrap_or(b"(unnamed)"); @@ -1253,6 +1262,9 @@ impl Expect { crate::Error::TestNotActive => { global_this.throw(format_args!("Snapshot matchers are not supported after the test has finished executing")) } + crate::Error::NoTest => { + global_this.throw(format_args!("Snapshot matchers cannot be used outside of a test")) + } _ => { let mut formatter = ConsoleObject::Formatter::new(global_this); global_this.throw(format_args!("Failed to snapshot value: {}", value.to_fmt(&mut formatter))) diff --git a/test/js/bun/test/snapshot-tests/bun-snapshots.test.ts b/test/js/bun/test/snapshot-tests/bun-snapshots.test.ts index e670e343921f..b3047e52bcc0 100644 --- a/test/js/bun/test/snapshot-tests/bun-snapshots.test.ts +++ b/test/js/bun/test/snapshot-tests/bun-snapshots.test.ts @@ -1,4 +1,6 @@ import { describe, expect, it, test } from "bun:test"; +import { bunEnv, bunExe, normalizeBunSnapshot, tempDir } from "harness"; +import { join } from "node:path"; test("it will create a snapshot file if it doesn't exist", () => { expect({ a: { b: { c: false } }, c: 2, jkfje: 99238 }).toMatchSnapshot({ a: { b: { c: expect.any(Boolean) } } }); @@ -62,3 +64,109 @@ describe("toMatchSnapshot errors", () => { }).toThrow(); }); }); + +// A snapshot's name comes from the test that was running when expect() was called. +// These cover the cases where that test cannot name a snapshot by the time the matcher runs. +describe("snapshot matchers on an expect() created outside of a running test", () => { + const finishedMessage = "Snapshot matchers are not supported after the test has finished executing"; + const outsideTestMessage = "Snapshot matchers cannot be used outside of a test"; + const concurrentMessage = "Snapshot matchers are not supported in concurrent tests"; + + describe("expect() created in a describe callback", () => { + let error: unknown; + try { + expect("described").toMatchSnapshot(); + } catch (e) { + error = e; + } + + it("throws the outside-of-a-test error", () => { + expect((error as Error).message).toBe(outsideTestMessage); + }); + }); + + describe("expect() created in a test that has since finished", () => { + let value: ReturnType; + let thrower: ReturnType; + let inline: ReturnType; + + it("creates the expect() objects", () => { + value = expect({ created: "in the previous test" }); + thrower = expect(() => { + throw new Error("created in the previous test"); + }); + inline = expect("created in the previous test"); + }); + + it("toMatchSnapshot throws the finished-test error", () => { + expect(() => value.toMatchSnapshot()).toThrow(finishedMessage); + expect(() => value.toMatchSnapshot("with hint")).toThrow(finishedMessage); + }); + + it("toThrowErrorMatchingSnapshot throws the finished-test error", () => { + expect(() => thrower.toThrowErrorMatchingSnapshot()).toThrow(finishedMessage); + }); + + it("inline snapshots are keyed by source location and still work", () => { + inline.toMatchInlineSnapshot(`"created in the previous test"`); + }); + }); + + describe.concurrent("expect() created in a concurrent group", () => { + for (const name of ["first", "second"]) { + it(`${name} test throws the concurrent error`, async () => { + expect(() => expect(name).toMatchSnapshot()).toThrow(concurrentMessage); + }); + } + }); + + it("expect() created in a test that timed out throws the finished-test error and writes nothing", async () => { + using dir = tempDir("snapshot-after-timeout", { + "timeout.test.ts": ` + import { expect, test } from "bun:test"; + + const nextTestStarted = Promise.withResolvers(); + const lateMatcherRan = Promise.withResolvers(); + + test("times out", async () => { + const captured = expect({ from: "times out" }); + // Only "next" resolves this, so this test has always timed out by the time it continues. + await nextTestStarted.promise; + try { + captured.toMatchSnapshot(); + console.log("late toMatchSnapshot: did not throw"); + } catch (error) { + console.log("late toMatchSnapshot:", (error as Error).message); + } + lateMatcherRan.resolve(); + }, 1); + + test("next", async () => { + nextTestStarted.resolve(); + await lateMatcherRan.promise; + expect({ from: "next" }).toMatchSnapshot(); + }); + `, + }); + + await using proc = Bun.spawn({ + cmd: [bunExe(), "test", "timeout.test.ts"], + cwd: String(dir), + env: { ...bunEnv, CI: "false" }, + stdout: "pipe", + stderr: "pipe", + }); + const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + + expect(normalizeBunSnapshot(stdout)).toBe( + `bun test ()\nlate toMatchSnapshot: ${finishedMessage}`, + ); + expect(stderr).toContain("this test timed out after 1ms"); + expect(stderr).toContain("(pass) next"); + expect(stderr).toContain("snapshots: +1 added"); + expect(await Bun.file(join(String(dir), "__snapshots__", "timeout.test.ts.snap")).text()).toBe( + '// Bun Snapshot v1, https://bun.sh/docs/test/snapshots\n\nexports[`next 1`] = `\n{\n "from": "next",\n}\n`;\n', + ); + expect(exitCode).toBe(1); + }); +}); From 16f71952fbab3f9e7a733bd6afacb9d6cc8f72a1 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 15 Aug 2026 05:08:39 +0000 Subject: [PATCH 2/5] ci: retrigger From f2b8e1f373f476f3e1d2d1a7bcca761e84fde4c7 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 15 Aug 2026 05:12:38 +0000 Subject: [PATCH 3/5] test_runner: shorten the get_snapshot_name comment --- src/runtime/test_runner/expect.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/runtime/test_runner/expect.rs b/src/runtime/test_runner/expect.rs index 49dbc88514ee..5eb46a786859 100644 --- a/src/runtime/test_runner/expect.rs +++ b/src/runtime/test_runner/expect.rs @@ -624,8 +624,7 @@ impl Expect { let buntest_strong = parent.bun_test().ok_or(crate::Error::TestNotActive)?; let buntest = buntest_strong.get(); let execution_entry = match &parent.phase { - // `entry()` is None once the runner has advanced past the entry that was - // running when this expect() was created. + // `entry()` only resolves while the captured entry is still the one running. bun_test::RefDataValue::Execution { entry_data: Some(_), .. } => { parent.phase.entry(buntest).ok_or(crate::Error::TestNotActive)? } From 90ca6a26eb406404d392dca860e47a4c940792ce Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 15 Aug 2026 08:00:36 +0000 Subject: [PATCH 4/5] test_runner: classify snapshot context errors in one place, including the finished-file case SnapshotContextError derives the reason from the RefDataValue captured by expect() and renders the message; get_snapshot_name, Expect::snapshot and the new check_snapshot_context pre-check used by toMatchSnapshot and toThrowErrorMatchingSnapshot all go through it. The pre-check replaces the two inlined guards, which reported an expect() whose test file had already finished as "outside of a test" under a ".not." signature. Tests: the in-process finished case now captures in beforeAll so it holds under -t and --randomize, and a two-file fixture covers the finished-file form for both matchers. --- src/runtime/test_runner/expect.rs | 110 ++++++++++++++---- .../test_runner/expect/toMatchSnapshot.rs | 11 +- .../expect/toThrowErrorMatchingSnapshot.rs | 11 +- test/js/bun/test/bun_test.test.ts | 4 +- .../test/snapshot-tests/bun-snapshots.test.ts | 95 ++++++++++++--- 5 files changed, 173 insertions(+), 58 deletions(-) diff --git a/src/runtime/test_runner/expect.rs b/src/runtime/test_runner/expect.rs index 5eb46a786859..117f09cce86f 100644 --- a/src/runtime/test_runner/expect.rs +++ b/src/runtime/test_runner/expect.rs @@ -175,6 +175,56 @@ impl Flags { } } +/// Why a snapshot cannot be named after the test an `expect()` was created in. +#[derive(Clone, Copy)] +enum SnapshotContextError { + TestFinished, + ConcurrentGroup, + NoTest, +} + +impl SnapshotContextError { + /// Judged from the runner state `expect()` captured: once that state no longer resolves to + /// a running entry, a captured entry means its test has finished, a concurrent group never + /// captures an entry, and the other phases have no test at all. + fn from_phase(phase: &bun_test::RefDataValue) -> Self { + match phase { + bun_test::RefDataValue::Execution { entry_data: Some(_), .. } => Self::TestFinished, + bun_test::RefDataValue::Execution { entry_data: None, .. } => Self::ConcurrentGroup, + bun_test::RefDataValue::Start + | bun_test::RefDataValue::Collection { .. } + | bun_test::RefDataValue::Done => Self::NoTest, + } + } + + fn from_error(err: &crate::Error) -> Option { + match err { + crate::Error::TestNotActive => Some(Self::TestFinished), + crate::Error::SnapshotInConcurrentGroup => Some(Self::ConcurrentGroup), + crate::Error::NoTest => Some(Self::NoTest), + _ => None, + } + } + + fn message(self) -> &'static str { + match self { + Self::TestFinished => "Snapshot matchers are not supported after the test has finished executing", + Self::ConcurrentGroup => "Snapshot matchers are not supported in concurrent tests", + Self::NoTest => "Snapshot matchers cannot be used outside of a test", + } + } +} + +impl From for crate::Error { + fn from(err: SnapshotContextError) -> Self { + match err { + SnapshotContextError::TestFinished => Self::TestNotActive, + SnapshotContextError::ConcurrentGroup => Self::SnapshotInConcurrentGroup, + SnapshotContextError::NoTest => Self::NoTest, + } + } +} + impl Expect { /// R-2 helper: read-modify-write the packed `Cell` through `&self`. #[inline] @@ -210,6 +260,36 @@ impl Expect { parent.bun_test() } + /// Only meaningful once `bun_test()` is None: the file this `expect()` was created in has + /// finished (or there was none), so the captured state is all that is left to report from. + fn snapshot_context_error(&self) -> SnapshotContextError { + match self.parent.as_ref() { + Some(parent) => SnapshotContextError::from_phase(&parent.phase), + None => SnapshotContextError::NoTest, + } + } + + /// Throws unless the test file this `expect()` was created in is still running. The file + /// snapshot matchers call this before looking at their arguments. + pub(crate) fn check_snapshot_context( + &self, + global_this: &JSGlobalObject, + matcher_name: &'static str, + ) -> JsResult<()> { + if self.bun_test().is_some() { + return Ok(()); + } + let signature = Self::get_signature(matcher_name, "", false); + throw!( + self, + global_this, + signature, + "\n\nMatcher error: {}\n", + self.snapshot_context_error().message(), + ) + .map(drop) + } + pub(crate) fn get_signature( matcher_name: &'static str, args: &'static str, @@ -621,20 +701,10 @@ impl Expect { pub(crate) fn get_snapshot_name(&self, hint: &[u8]) -> crate::Result> { let parent = self.parent.as_ref().ok_or(crate::Error::NoTest)?; - let buntest_strong = parent.bun_test().ok_or(crate::Error::TestNotActive)?; + let context_error = || crate::Error::from(SnapshotContextError::from_phase(&parent.phase)); + let buntest_strong = parent.bun_test().ok_or_else(context_error)?; let buntest = buntest_strong.get(); - let execution_entry = match &parent.phase { - // `entry()` only resolves while the captured entry is still the one running. - bun_test::RefDataValue::Execution { entry_data: Some(_), .. } => { - parent.phase.entry(buntest).ok_or(crate::Error::TestNotActive)? - } - bun_test::RefDataValue::Execution { entry_data: None, .. } => { - return Err(crate::Error::SnapshotInConcurrentGroup); - } - bun_test::RefDataValue::Start - | bun_test::RefDataValue::Collection { .. } - | bun_test::RefDataValue::Done => return Err(crate::Error::NoTest), - }; + let execution_entry = parent.phase.entry(buntest).ok_or_else(context_error)?; let test_name: &[u8] = execution_entry.base.name.as_deref().unwrap_or(b"(unnamed)"); @@ -1220,8 +1290,11 @@ impl Expect { let existing_value = match runner.snapshots.get_or_put(this, &pretty_value, hint) { Ok(v) => v, Err(err) => { + if let Some(reason) = SnapshotContextError::from_error(&err) { + return Err(global_this.throw(format_args!("{}", reason.message()))); + } let Some(buntest_strong) = this.bun_test() else { - return Err(global_this.throw(format_args!("Snapshot matchers cannot be used outside of a test"))); + return Err(global_this.throw(format_args!("{}", this.snapshot_context_error().message()))); }; let buntest = buntest_strong.get(); // MultiArrayList::get requires MultiArrayElement (derive pending); use column accessor. @@ -1255,15 +1328,6 @@ impl Expect { )) } } - crate::Error::SnapshotInConcurrentGroup => { - global_this.throw(format_args!("Snapshot matchers are not supported in concurrent tests")) - } - crate::Error::TestNotActive => { - global_this.throw(format_args!("Snapshot matchers are not supported after the test has finished executing")) - } - crate::Error::NoTest => { - global_this.throw(format_args!("Snapshot matchers cannot be used outside of a test")) - } _ => { let mut formatter = ConsoleObject::Formatter::new(global_this); global_this.throw(format_args!("Failed to snapshot value: {}", value.to_fmt(&mut formatter))) diff --git a/src/runtime/test_runner/expect/toMatchSnapshot.rs b/src/runtime/test_runner/expect/toMatchSnapshot.rs index b3953555441a..5cb96ec3821f 100644 --- a/src/runtime/test_runner/expect/toMatchSnapshot.rs +++ b/src/runtime/test_runner/expect/toMatchSnapshot.rs @@ -31,16 +31,7 @@ pub(crate) fn to_match_snapshot( ); } - let Some(buntest_strong) = this.bun_test() else { - let signature = get_signature("toMatchSnapshot", "", true); - return throw!( - this, - global, - signature, - "\n\nMatcher error: Snapshot matchers cannot be used outside of a test\n", - ); - }; - let _ = buntest_strong; // released by Drop at scope exit. + this.check_snapshot_context(global, "toMatchSnapshot")?; let mut hint_string: ZigString = ZigString::EMPTY; let mut property_matchers: Option = None; diff --git a/src/runtime/test_runner/expect/toThrowErrorMatchingSnapshot.rs b/src/runtime/test_runner/expect/toThrowErrorMatchingSnapshot.rs index 7c26e8e2c9b0..e2c26c633e05 100644 --- a/src/runtime/test_runner/expect/toThrowErrorMatchingSnapshot.rs +++ b/src/runtime/test_runner/expect/toThrowErrorMatchingSnapshot.rs @@ -30,16 +30,7 @@ pub(crate) fn to_throw_error_matching_snapshot( ); } - let Some(bun_test_strong) = this.bun_test() else { - let signature = get_signature("toThrowErrorMatchingSnapshot", "", true); - return throw!( - this, - global, - signature, - "\n\nMatcher error: Snapshot matchers cannot be used outside of a test\n", - ); - }; - let _ = &bun_test_strong; + this.check_snapshot_context(global, "toThrowErrorMatchingSnapshot")?; let mut hint_string: ZigString = ZigString::EMPTY; match arguments.len() { diff --git a/test/js/bun/test/bun_test.test.ts b/test/js/bun/test/bun_test.test.ts index 9659d9c18322..772a1aef14e0 100644 --- a/test/js/bun/test/bun_test.test.ts +++ b/test/js/bun/test/bun_test.test.ts @@ -232,7 +232,9 @@ test("cross-file safety", async () => { const exitCode = await result.exited; const stdout = await result.stdout.text(); const stderr = await result.stderr.text(); - expect(stderr).toInclude("Snapshot matchers cannot be used outside of a test"); + expect(normalizeBunSnapshot(stderr)).toInclude( + "error: expect(received).toMatchSnapshot()\n\nMatcher error: Snapshot matchers are not supported after the test has finished executing", + ); expect(exitCode).toBe(1); }); diff --git a/test/js/bun/test/snapshot-tests/bun-snapshots.test.ts b/test/js/bun/test/snapshot-tests/bun-snapshots.test.ts index b3047e52bcc0..42d2650c75f7 100644 --- a/test/js/bun/test/snapshot-tests/bun-snapshots.test.ts +++ b/test/js/bun/test/snapshot-tests/bun-snapshots.test.ts @@ -1,5 +1,6 @@ -import { describe, expect, it, test } from "bun:test"; +import { beforeAll, describe, expect, it, test } from "bun:test"; import { bunEnv, bunExe, normalizeBunSnapshot, tempDir } from "harness"; +import { readdirSync } from "node:fs"; import { join } from "node:path"; test("it will create a snapshot file if it doesn't exist", () => { @@ -65,9 +66,9 @@ describe("toMatchSnapshot errors", () => { }); }); -// A snapshot's name comes from the test that was running when expect() was called. -// These cover the cases where that test cannot name a snapshot by the time the matcher runs. -describe("snapshot matchers on an expect() created outside of a running test", () => { +// A snapshot is named after the test that was running when expect() was called. These cover +// the error reported when that test cannot name a snapshot by the time the matcher runs. +describe("snapshot matchers on an expect() that has no running test", () => { const finishedMessage = "Snapshot matchers are not supported after the test has finished executing"; const outsideTestMessage = "Snapshot matchers cannot be used outside of a test"; const concurrentMessage = "Snapshot matchers are not supported in concurrent tests"; @@ -85,17 +86,17 @@ describe("snapshot matchers on an expect() created outside of a running test", ( }); }); - describe("expect() created in a test that has since finished", () => { + describe("expect() created in a beforeAll that has since finished", () => { let value: ReturnType; let thrower: ReturnType; let inline: ReturnType; - it("creates the expect() objects", () => { - value = expect({ created: "in the previous test" }); + beforeAll(() => { + value = expect({ created: "in beforeAll" }); thrower = expect(() => { - throw new Error("created in the previous test"); + throw new Error("created in beforeAll"); }); - inline = expect("created in the previous test"); + inline = expect("created in beforeAll"); }); it("toMatchSnapshot throws the finished-test error", () => { @@ -108,7 +109,7 @@ describe("snapshot matchers on an expect() created outside of a running test", ( }); it("inline snapshots are keyed by source location and still work", () => { - inline.toMatchInlineSnapshot(`"created in the previous test"`); + inline.toMatchInlineSnapshot(`"created in beforeAll"`); }); }); @@ -120,7 +121,7 @@ describe("snapshot matchers on an expect() created outside of a running test", ( } }); - it("expect() created in a test that timed out throws the finished-test error and writes nothing", async () => { + it.concurrent("expect() from a timed out test throws the finished-test error and writes nothing", async () => { using dir = tempDir("snapshot-after-timeout", { "timeout.test.ts": ` import { expect, test } from "bun:test"; @@ -158,9 +159,10 @@ describe("snapshot matchers on an expect() created outside of a running test", ( }); const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); - expect(normalizeBunSnapshot(stdout)).toBe( - `bun test ()\nlate toMatchSnapshot: ${finishedMessage}`, - ); + expect(normalizeBunSnapshot(stdout)).toMatchInlineSnapshot(` + "bun test () + late toMatchSnapshot: Snapshot matchers are not supported after the test has finished executing" + `); expect(stderr).toContain("this test timed out after 1ms"); expect(stderr).toContain("(pass) next"); expect(stderr).toContain("snapshots: +1 added"); @@ -169,4 +171,69 @@ describe("snapshot matchers on an expect() created outside of a running test", ( ); expect(exitCode).toBe(1); }); + + it.concurrent("expect() created in a test file that has finished throws the finished-test error", async () => { + using dir = tempDir("snapshot-after-file", { + "shared.ts": ` + import type { expect } from "bun:test"; + export const captured: { value?: ReturnType; thrower?: ReturnType } = {}; + `, + "1-create.test.ts": ` + import { expect, test } from "bun:test"; + import { captured } from "./shared"; + + test("creates", () => { + captured.value = expect({ from: "1-create" }); + captured.thrower = expect(() => { + throw new Error("from 1-create"); + }); + }); + `, + "2-use.test.ts": ` + import { expect, test } from "bun:test"; + import { captured } from "./shared"; + + test("uses", () => { + for (const [name, matcher] of [ + ["toMatchSnapshot", () => captured.value!.toMatchSnapshot()], + ["toThrowErrorMatchingSnapshot", () => captured.thrower!.toThrowErrorMatchingSnapshot()], + ] as const) { + try { + matcher(); + console.log(name + ": did not throw"); + } catch (error) { + console.log(name + ": " + (error as Error).message); + } + } + expect({ from: "2-use" }).toMatchSnapshot(); + }); + `, + }); + + await using proc = Bun.spawn({ + cmd: [bunExe(), "test", "./1-create.test.ts", "./2-use.test.ts"], + cwd: String(dir), + env: { ...bunEnv, CI: "false" }, + stdout: "pipe", + stderr: "pipe", + }); + const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + + expect(normalizeBunSnapshot(stdout)).toMatchInlineSnapshot(` + "bun test () + toMatchSnapshot: expect(received).toMatchSnapshot() + + Matcher error: Snapshot matchers are not supported after the test has finished executing + + toThrowErrorMatchingSnapshot: expect(received).toThrowErrorMatchingSnapshot() + + Matcher error: Snapshot matchers are not supported after the test has finished executing" + `); + expect(stderr).toContain("snapshots: +1 added"); + expect(readdirSync(join(String(dir), "__snapshots__"))).toEqual(["2-use.test.ts.snap"]); + expect(await Bun.file(join(String(dir), "__snapshots__", "2-use.test.ts.snap")).text()).toBe( + '// Bun Snapshot v1, https://bun.sh/docs/test/snapshots\n\nexports[`uses 1`] = `\n{\n "from": "2-use",\n}\n`;\n', + ); + expect(exitCode).toBe(0); + }); }); From e46b2c1633f385ccce8d6c79a26b1efc5be17039 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sat, 15 Aug 2026 08:05:26 +0000 Subject: [PATCH 5/5] test_runner: trim SnapshotContextError doc comments --- src/runtime/test_runner/expect.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/runtime/test_runner/expect.rs b/src/runtime/test_runner/expect.rs index 117f09cce86f..13413e5e2154 100644 --- a/src/runtime/test_runner/expect.rs +++ b/src/runtime/test_runner/expect.rs @@ -184,12 +184,11 @@ enum SnapshotContextError { } impl SnapshotContextError { - /// Judged from the runner state `expect()` captured: once that state no longer resolves to - /// a running entry, a captured entry means its test has finished, a concurrent group never - /// captures an entry, and the other phases have no test at all. + /// For a state captured by `expect()` that no longer resolves to a running entry. fn from_phase(phase: &bun_test::RefDataValue) -> Self { match phase { bun_test::RefDataValue::Execution { entry_data: Some(_), .. } => Self::TestFinished, + // `get_current_state_data` records no entry only while a concurrent group runs. bun_test::RefDataValue::Execution { entry_data: None, .. } => Self::ConcurrentGroup, bun_test::RefDataValue::Start | bun_test::RefDataValue::Collection { .. } @@ -260,8 +259,7 @@ impl Expect { parent.bun_test() } - /// Only meaningful once `bun_test()` is None: the file this `expect()` was created in has - /// finished (or there was none), so the captured state is all that is left to report from. + /// Only valid once `bun_test()` is None; a live file is classified by `get_snapshot_name`. fn snapshot_context_error(&self) -> SnapshotContextError { match self.parent.as_ref() { Some(parent) => SnapshotContextError::from_phase(&parent.phase), @@ -269,8 +267,7 @@ impl Expect { } } - /// Throws unless the test file this `expect()` was created in is still running. The file - /// snapshot matchers call this before looking at their arguments. + /// Throws unless the test file this `expect()` was created in is still running. pub(crate) fn check_snapshot_context( &self, global_this: &JSGlobalObject,