fix(e2e): persist the winning A1 body snippet for post-restart

UI-13b already made A1 the durable document, but phase-state still expected the UI-06 marker. Record successful saves as the latest snippet, ignore conflict drafts, and write that final value at UI-15-pre without relaxing the restore assertion.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-09-13 23:28:17 +00:00
co-authored by Cursor
parent eb85b8a068
commit 5db2d9a3b1
3 changed files with 77 additions and 1 deletions
+18 -1
View File
@@ -28,6 +28,7 @@ import {
SHARED_PHASE_STATE_FILE,
playwrightResultsFileName,
} from '../src/lib/playwrightPhaseArtifacts';
import { nextDurableBodySnippet } from '../src/lib/durableBodySnippet';
/**
* Document revision runtime — real UI acceptance (UI-01..UI-16).
@@ -670,6 +671,8 @@ test.describe.serial('document-revision-runtime UI acceptance', () => {
let secondDocTitle = '';
let secondDocId = '';
let uploadedDocId = '';
/** Latest server-durable body marker; UI-15-pre writes this as bodySnippet. */
let latestDurableBodySnippet = '';
test.beforeAll(async ({ browser }) => {
context = await browser.newContext();
@@ -1047,8 +1050,12 @@ test.describe.serial('document-revision-runtime UI acceptance', () => {
timeout: 30_000,
});
await shot(page, 'UI-06-after-refresh.png');
latestDurableBodySnippet = nextDurableBodySnippet(latestDurableBodySnippet, {
kind: 'persisted',
snippet: marker,
}) || marker;
const st = readPhaseState();
writePhaseState({ ...st, bodySnippet: marker, revisionText: r1 });
writePhaseState({ ...st, bodySnippet: latestDurableBodySnippet, revisionText: r1 });
recordPass({
id: 'UI-06',
name: 'save + hard refresh',
@@ -1386,6 +1393,15 @@ test.describe.serial('document-revision-runtime UI acceptance', () => {
await expect(page.getByText(markerA2)).toHaveCount(0);
await shot(pageA2, 'UI-13b-conflict-A2.png');
await ctxA2.close();
latestDurableBodySnippet = nextDurableBodySnippet(latestDurableBodySnippet, {
kind: 'persisted',
snippet: markerA1,
}) || markerA1;
latestDurableBodySnippet = nextDurableBodySnippet(latestDurableBodySnippet, {
kind: 'conflict_draft',
snippet: markerA2,
}) || latestDurableBodySnippet;
writePhaseState({ ...readPhaseState(), bodySnippet: latestDurableBodySnippet });
recordPass({
id: 'UI-13b',
name: 'author A/A head conflict',
@@ -1448,6 +1464,7 @@ test.describe.serial('document-revision-runtime UI acceptance', () => {
controlledDocId,
versionText: v,
revisionText: r,
bodySnippet: latestDurableBodySnippet || st.bodySnippet,
userA: USER_A,
userB: USER_B,
userC: USER_C,
+33
View File
@@ -0,0 +1,33 @@
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { nextDurableBodySnippet, requireDurableSnippet } from './durableBodySnippet';
describe('durableBodySnippet', () => {
it('rejects empty persisted snippets', () => {
assert.throws(() => requireDurableSnippet(' '), /empty_durable_body_snippet/);
assert.throws(
() => nextDurableBodySnippet('UI06-old', { kind: 'persisted', snippet: ' ' }),
/empty_durable_body_snippet/,
);
});
it('lets a later successful revision replace the old snippet', () => {
const afterUi06 = nextDurableBodySnippet(undefined, { kind: 'persisted', snippet: ' UI06-mu0eq020 ' });
assert.equal(afterUi06, 'UI06-mu0eq020');
const afterA1 = nextDurableBodySnippet(afterUi06, { kind: 'persisted', snippet: 'A1-win-mu0eq020' });
assert.equal(afterA1, 'A1-win-mu0eq020');
assert.notEqual(afterA1, afterUi06);
});
it('does not promote a conflict-failed draft to the expected body', () => {
const afterUi06 = nextDurableBodySnippet(undefined, { kind: 'persisted', snippet: 'UI06-mu0eq020' });
const afterA1 = nextDurableBodySnippet(afterUi06, { kind: 'persisted', snippet: 'A1-win-mu0eq020' });
const afterA2Conflict = nextDurableBodySnippet(afterA1, {
kind: 'conflict_draft',
snippet: 'A2-conflict-mu0eq020',
});
assert.equal(afterA2Conflict, 'A1-win-mu0eq020');
assert.notEqual(afterA2Conflict, 'A2-conflict-mu0eq020');
assert.notEqual(afterA2Conflict, 'UI06-mu0eq020');
});
});
+26
View File
@@ -0,0 +1,26 @@
export type DurableBodyEvent =
| { kind: 'persisted'; snippet: string }
| { kind: 'conflict_draft'; snippet: string };
export function requireDurableSnippet(snippet: string): string {
const next = snippet.trim();
if (!next) {
throw new Error('empty_durable_body_snippet');
}
return next;
}
/**
* Latest server-durable body snippet for post-restart.
* A later successful save replaces the previous snippet.
* A conflict-failed editor draft never becomes the expected body.
*/
export function nextDurableBodySnippet(
current: string | undefined,
event: DurableBodyEvent,
): string | undefined {
if (event.kind === 'conflict_draft') {
return current;
}
return requireDurableSnippet(event.snippet);
}