diff --git a/cases/base-share/a-duplicated-base-in-the-recent-list.case.ts b/cases/base-share/a-duplicated-base-in-the-recent-list.case.ts index d6e129e..de61cc5 100644 --- a/cases/base-share/a-duplicated-base-in-the-recent-list.case.ts +++ b/cases/base-share/a-duplicated-base-in-the-recent-list.case.ts @@ -11,6 +11,10 @@ export default defineBugCase({ title: "A freshly duplicated base is in the recent list", runner: "duplicate-base-recent-list", timeoutMs: 240_000, + // Recent bases are user-global state. Another concurrent case may visit its + // own base after this copy and correctly move ahead of it, invalidating this + // checkpoint without reproducing T2571. + serial: true, bug: { issue: "T2571", status: "fixed", diff --git a/e2e-lab.e2e-spec.ts b/e2e-lab.e2e-spec.ts index ac89d15..93b3047 100644 --- a/e2e-lab.e2e-spec.ts +++ b/e2e-lab.e2e-spec.ts @@ -78,18 +78,22 @@ describe("e2e-lab bug regression runner (e2e)", () => { }); for (const bugCase of bugCases) { - it.concurrent( - `observes ${bugCase.id} [${bugCase.bug.issue}]`, - { timeout: bugCase.timeoutMs }, - async () => { - logPhase("case:start", { caseId: bugCase.id }); - const caseStarted = performance.now(); - await runBugCase(bugCase, { app, appUrl, cookie }); - logPhase("case:done", { - caseId: bugCase.id, - caseMs: Math.round(performance.now() - caseStarted), - }); - }, - ); + const name = `observes ${bugCase.id} [${bugCase.bug.issue}]`; + const options = { timeout: bugCase.timeoutMs }; + const run = async () => { + logPhase("case:start", { caseId: bugCase.id }); + const caseStarted = performance.now(); + await runBugCase(bugCase, { app, appUrl, cookie }); + logPhase("case:done", { + caseId: bugCase.id, + caseMs: Math.round(performance.now() - caseStarted), + }); + }; + + if (bugCase.serial) { + it(name, options, run); + } else { + it.concurrent(name, options, run); + } } }); diff --git a/framework/types.ts b/framework/types.ts index 972755e..58aad40 100644 --- a/framework/types.ts +++ b/framework/types.ts @@ -169,6 +169,12 @@ interface BugCaseBase { id: string; title: string; bug: BugRef; + /** + * Run without overlapping any concurrent case. Use only when the checkpoint + * intentionally observes user-global state that per-case bases cannot + * isolate (for example, the current user's recent-base ordering). + */ + serial?: boolean; timeoutMs: number; }