fix(e2e): write post-restart results to a separate ledger

A successful post-restart recordPass would overwrite the main 18-case ui-acceptance-results.json. Keep that historical name for main and write ui-acceptance-results-post-restart.json after restart, while still sharing phase-state and secrets.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-09-13 23:23:27 +00:00
co-authored by Cursor
parent 8907b61745
commit 0936a94fdf
3 changed files with 48 additions and 4 deletions
+8 -3
View File
@@ -23,6 +23,11 @@ import {
currentProjectBannerName,
visibleProjectEntry,
} from '../src/lib/currentProjectRestore';
import {
SHARED_PHASE_SECRETS_FILE,
SHARED_PHASE_STATE_FILE,
playwrightResultsFileName,
} from '../src/lib/playwrightPhaseArtifacts';
/**
* Document revision runtime — real UI acceptance (UI-01..UI-16).
@@ -45,10 +50,10 @@ const ASSETS = path.resolve(
const SCREENSHOTS = path.join(ASSETS, 'screenshots');
const TRACES = path.join(ASSETS, 'traces');
const VIDEOS = path.join(ASSETS, 'videos');
const RESULTS_FILE = path.join(ASSETS, 'ui-acceptance-results.json');
const PHASE_STATE_FILE = path.join(ASSETS, 'phase-state.json');
const RESULTS_FILE = path.join(ASSETS, playwrightResultsFileName(uiPhase));
const PHASE_STATE_FILE = path.join(ASSETS, SHARED_PHASE_STATE_FILE);
/** Local-only secrets for post-restart login — never copied into results JSON. */
const PHASE_SECRETS_FILE = path.join(ASSETS, 'phase-secrets.local.json');
const PHASE_SECRETS_FILE = path.join(ASSETS, SHARED_PHASE_SECRETS_FILE);
for (const d of [SCREENSHOTS, TRACES, VIDEOS]) {
fs.mkdirSync(d, { recursive: true });
+26 -1
View File
@@ -1,6 +1,14 @@
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { playwrightArtifactDirNames, playwrightPhaseSlug } from './playwrightPhaseArtifacts';
import {
MAIN_RESULTS_FILE,
POST_RESTART_RESULTS_FILE,
SHARED_PHASE_SECRETS_FILE,
SHARED_PHASE_STATE_FILE,
playwrightArtifactDirNames,
playwrightPhaseSlug,
playwrightResultsFileName,
} from './playwrightPhaseArtifacts';
describe('playwrightPhaseArtifacts', () => {
it('defaults unknown or empty UI_PHASE to main', () => {
@@ -19,4 +27,21 @@ describe('playwrightPhaseArtifacts', () => {
assert.notEqual(main.outputDirName, restart.outputDirName);
assert.notEqual(main.reportDirName, restart.reportDirName);
});
it('keeps main results at the historical filename and isolates post-restart recordPass', () => {
assert.equal(playwrightResultsFileName('main'), MAIN_RESULTS_FILE);
assert.equal(playwrightResultsFileName(undefined), 'ui-acceptance-results.json');
assert.equal(playwrightResultsFileName('post-restart'), POST_RESTART_RESULTS_FILE);
assert.equal(playwrightArtifactDirNames('main').resultsFileName, 'ui-acceptance-results.json');
assert.equal(
playwrightArtifactDirNames('post-restart').resultsFileName,
'ui-acceptance-results-post-restart.json',
);
assert.notEqual(playwrightResultsFileName('main'), playwrightResultsFileName('post-restart'));
});
it('shares phase-state and secrets across phases', () => {
assert.equal(SHARED_PHASE_STATE_FILE, 'phase-state.json');
assert.equal(SHARED_PHASE_SECRETS_FILE, 'phase-secrets.local.json');
});
});
+14
View File
@@ -1,18 +1,32 @@
export type PlaywrightUiPhase = 'main' | 'post-restart';
/** Shared across phases so post-restart can resume the main project/login. */
export const SHARED_PHASE_STATE_FILE = 'phase-state.json';
export const SHARED_PHASE_SECRETS_FILE = 'phase-secrets.local.json';
/** Main keeps the historical ledger name so existing evidence/docs stay valid. */
export const MAIN_RESULTS_FILE = 'ui-acceptance-results.json';
export const POST_RESTART_RESULTS_FILE = 'ui-acceptance-results-post-restart.json';
export function playwrightPhaseSlug(uiPhase?: string): PlaywrightUiPhase {
return uiPhase?.trim() === 'post-restart' ? 'post-restart' : 'main';
}
export function playwrightResultsFileName(uiPhase?: string): string {
return playwrightPhaseSlug(uiPhase) === 'post-restart' ? POST_RESTART_RESULTS_FILE : MAIN_RESULTS_FILE;
}
export function playwrightArtifactDirNames(uiPhase?: string): {
outputDirName: string;
reportDirName: string;
resultsFileName: string;
slug: PlaywrightUiPhase;
} {
const slug = playwrightPhaseSlug(uiPhase);
return {
outputDirName: `playwright-output-${slug}`,
reportDirName: `playwright-report-${slug}`,
resultsFileName: playwrightResultsFileName(uiPhase),
slug,
};
}