Files
vscode-cowriting-plugin/scripts/smoke-native-loop.mjs
T
BenStullsBets 22c9da0cec test: full native-loop E2E (PUC-1/2/7/8) + real-SDK smoke (spec §6.8, §7.1 rung 3)
Task 9 of the native-surfaces migration plan. fullLoop.test.ts walks the
whole inner loop in one doc, stub-turned: enter (snapshot baseline) -> two
comment asks -> reply -> offer -> pending proposals (F12 optimistic-apply,
decorated + isApplied) -> human tweak inside a pending proposal's range
(INV-11: breaks the raw fingerprint anchor, but finalizeInPlace/"Keep" is
built to survive that) -> keep one (attribution split via spansFor: claude's
words + the human tweak, char-honest) -> reject the other (buffer text
returns EXACTLY to its pre-proposal text, INV-5) -> markReviewed -> change
count 0.

scripts/smoke-native-loop.mjs + test/e2e/smoke/nativeLoop.ts are the rung-3
manual gate: launches the real EDH against sandbox/, posts a real comment via
ThreadController.createThreadOnSelection with BOTH turns left unstubbed (the
real @cline/sdk, INV-8), waits for the reply/offer, makes + accepts the edit,
and prints the created proposal ids. Lives outside test/e2e/suite so it is
never swept into `npm run test:e2e`; `npm run smoke:native` builds +
compiles then runs it. Operator-run only (real credentials) -- not executed
here, verified by typecheck + a syntax/structural pass only.

300 unit + 86 workspace/5 no-workspace host E2E green (1 pending, pre-existing
#54 undo-suite skip).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 15:37:15 -07:00

68 lines
2.8 KiB
JavaScript

#!/usr/bin/env node
// Task 9 / spec §7.1 rung 3: the manual, real-@cline/sdk smoke for the native
// comment loop -- mirrors scripts/smoke-live-turn.mjs's role for F3 (a live
// login-backed check, deliberately NOT in CI), but this one drives the whole
// EDH (comment -> reply -> offer -> proposal needs vscode's own comment/doc
// APIs, unlike smoke-live-turn.mjs's bare module call) via
// test/e2e/smoke/nativeLoop.ts, launched exactly like test/e2e/runTest.ts
// launches the regular host-E2E suites -- just against a single smoke entry
// point that is NOT swept into `npm run test:e2e` (it lives outside
// test/e2e/suite, which is the only directory suite/index.ts's mocha glob
// searches).
//
// Prereqs: `npm run pretest:e2e` (builds the extension + compiles
// test/e2e/**). `npm run smoke:native` does this for you.
//
// Opens the real sandbox/ folder (the repo's EDH workspace root), writes a
// throwaway doc, posts a real comment via ThreadController.createThreadOnSelection,
// waits for the real @cline/sdk reply + offer, makes + accepts the edit, then
// prints the created proposal ids and deletes the throwaway doc.
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import { fileURLToPath } from "node:url";
import { runTests } from "@vscode/test-electron";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
async function main() {
const projectRoot = path.resolve(__dirname, "..");
const extensionDevelopmentPath = projectRoot;
const extensionTestsPath = path.resolve(projectRoot, "out/test/e2e/smoke/nativeLoop");
const sandbox = path.resolve(projectRoot, "sandbox");
if (!fs.existsSync(`${extensionTestsPath}.js`)) {
console.error(
`smoke-native-loop: ${extensionTestsPath}.js is missing -- run "npm run pretest:e2e" first (or "npm run smoke:native", which does this for you).`,
);
process.exit(1);
}
// Same macOS UNIX-socket-length workaround as test/e2e/runTest.ts (a long
// worktree path + the default .vscode-test/user-data dir can blow past the
// ~103-char limit).
const userDataRoot = process.platform === "win32" ? os.tmpdir() : "/tmp";
const userDataDir = fs.mkdtempSync(path.join(userDataRoot, "cwud-smoke-"));
try {
await runTests({
extensionDevelopmentPath,
extensionTestsPath,
launchArgs: [sandbox, "--disable-extensions", "--user-data-dir", userDataDir],
});
console.log("smoke-native-loop: PASS");
process.exit(0);
} catch (err) {
console.error(
`smoke-native-loop: FAILED (expected when Claude Code is absent/signed out, or the sandbox/ folder is missing): ${
err instanceof Error ? err.message : String(err)
}`,
);
process.exit(1);
} finally {
fs.rmSync(userDataDir, { recursive: true, force: true });
}
}
main();