/** * Shared host-E2E helpers (native-surfaces migration, Task 2). NEW suites use * these; existing suites keep their own local copies (out of scope to * refactor them onto this shared file — see the Task 2 brief). */ import * as assert from "node:assert"; import * as vscode from "vscode"; import type { CowritingApi } from "../../../src/extension"; import { renderReview } from "../../../src/trackChangesModel"; /** Activate the extension and return its exported API (asserts it is real). */ export async function activateApi(): Promise { const ext = vscode.extensions.getExtension("benstull.vscode-cowriting-plugin")!; const api = (await ext.activate()) as CowritingApi; assert.ok(api?.diffViewController, "extension exports diffViewController"); return api; } /** * Task 8: the pure render probe the deleted TrackChangesPreviewController used * to wrap (`renderHtmlFor`) — the sunset webview was a thin shell around this * exact call (F6 baseline + F3 spans + F4 pending proposals -> `renderReview`). * Suites that used to read `controller.renderHtmlFor(key)` now call this * directly against the surviving controllers; no webview involved. */ export function renderHtmlFor(api: CowritingApi, doc: vscode.TextDocument, key: string): string { const baseline = api.diffViewController.getBaseline(key); const current = doc.getText(); return renderReview( baseline?.text ?? current, current, api.attributionController.spansFor(doc), api.proposalController.listProposals(doc), { pinned: baseline?.reason === "pinned" }, ); } /** A short fixed settle, for state that updates synchronously-ish after a command. */ export function settle(): Promise { return new Promise((r) => setTimeout(r, 150)); } /** Poll `predicate` every 100ms until it is true, or fail after `timeoutMs`. */ export async function settleUntil(predicate: () => boolean, timeoutMs = 5000): Promise { const start = Date.now(); while (!predicate()) { if (Date.now() - start > timeoutMs) { assert.fail(`settleUntil: predicate did not become true within ${timeoutMs}ms`); } await new Promise((r) => setTimeout(r, 100)); } }