import * as assert from "assert"; import * as path from "path"; import * as vscode from "vscode"; import type { CowritingApi } from "../../../src/extension"; const WS = process.env.E2E_WORKSPACE!; const DOC_REL = "docs/preview.md"; const docUri = () => vscode.Uri.file(path.join(WS, DOC_REL)).toString(); async function openDoc(rel = DOC_REL): Promise { const uri = vscode.Uri.file(path.join(WS, rel)); const doc = await vscode.workspace.openTextDocument(uri); await vscode.window.showTextDocument(doc); return doc; } async function getApi(): Promise { const ext = vscode.extensions.getExtension("benstull.vscode-cowriting-plugin")!; const api = (await ext.activate()) as CowritingApi; assert.ok(api?.trackChangesPreviewController, "extension exports trackChangesPreviewController"); return api; } const settle = () => new Promise((r) => setTimeout(r, 400)); const kinds = (api: CowritingApi) => (api.trackChangesPreviewController.getLastModel(docUri()) ?? []).map((o) => o.kind); // Order-dependent (F2–F6 pattern): later tests consume earlier state. suite("F7 track-changes preview (host E2E — markdown only, programmatic seam, no LLM)", () => { const TARGET = "A target sentence Claude will rewrite via the seam."; const REPLACEMENT = "A SENTENCE CLAUDE REWROTE via the seam."; test("open on a markdown doc → panel open, opened baseline shows no changes (PUC-1)", async () => { const doc = await openDoc(); const api = await getApi(); assert.strictEqual(api.trackChangesPreviewController.isOpen(docUri()), false, "no panel yet"); await vscode.commands.executeCommand("cowriting.showTrackChangesPreview"); await settle(); assert.strictEqual(api.trackChangesPreviewController.isOpen(docUri()), true, "panel open"); const model = api.trackChangesPreviewController.getLastModel(docUri()); assert.ok(model && model.length > 0, "a model was computed"); assert.ok( model!.every((o) => o.kind === "unchanged"), "baseline == buffer at open → every block unchanged", ); void doc; }); test("typing produces a changed/added block (PUC-2)", async () => { const doc = await openDoc(); const api = await getApi(); const edit = new vscode.WorkspaceEdit(); const end = doc.positionAt(doc.getText().length); edit.insert(doc.uri, end, "\n\nA freshly typed paragraph.\n"); assert.ok(await vscode.workspace.applyEdit(edit), "operator edit applied"); await settle(); assert.ok( kinds(api).some((k) => k === "added" || k === "changed"), "an added/changed block appears after typing", ); }); test("accepting a proposal advances the baseline; the landed block goes unchanged (PUC-3, INV-18)", async () => { const doc = await openDoc(); const api = await getApi(); const start = doc.getText().indexOf(TARGET); assert.ok(start >= 0, "fixture contains the target sentence"); const id = await vscode.commands.executeCommand("cowriting.proposeAgentEdit", { uri: doc.uri.toString(), start, end: start + TARGET.length, newText: REPLACEMENT, model: "sonnet", sessionId: "e2e-f7", turnId: "turn-f7-1", }); assert.ok(id, "propose returns an id"); assert.ok(await api.proposalController.acceptById(DOC_REL, id!), "accept applies via the seam"); await settle(); // The baseline advanced to include REPLACEMENT, so the buffer == baseline for // that block → it is NOT marked. Confirm the replacement is not flagged as a change. const model = api.trackChangesPreviewController.getLastModel(docUri()) ?? []; const replacementMarked = model.some( (o) => o.kind !== "unchanged" && o.block.raw.includes("CLAUDE REWROTE"), ); assert.ok(!replacementMarked, "the just-landed text renders unmarked (baseline advanced)"); }); test("pin resets the baseline to now → preview shows no marks (PUC-4)", async () => { const doc = await openDoc(); const api = await getApi(); await vscode.commands.executeCommand("cowriting.pinDiffBaseline"); await settle(); assert.ok( kinds(api).every((k) => k === "unchanged"), "after pin, every block is unchanged (baseline == buffer)", ); void doc; }); test("a non-markdown doc → command warns and opens no panel (PUC-6, markdown-only)", async () => { const txt = await openDoc("docs/notes.txt"); const api = await getApi(); const key = txt.uri.toString(); assert.notStrictEqual(txt.languageId, "markdown", "fixture is not markdown"); await vscode.commands.executeCommand("cowriting.showTrackChangesPreview"); await settle(); assert.strictEqual(api.trackChangesPreviewController.isOpen(key), false, "no panel for non-markdown"); }); });