testSuitesRunAgainOnlyWhenCodeTheyRanChanged
A package's suites run its command, and run again only when code they ran changed; a result holds again when that code is back as it was.
import { okIn, tcmIn, tempDir } from "#codebase/tcmts/cli/test/e2e/harness"; import assert from "node:assert/strict"; import fs from "node:fs"; import path from "node:path"; export const testSuitesRunAgainOnlyWhenCodeTheyRanChanged = () => { const dir = tempDir("suites"); const ok = (...args: string[]) => okIn(dir, ...args); const scratch = (ns: string, text: string) => fs.writeFileSync(path.join(dir, "scratch.ts"), `// tcm: namespace ${ns}\n${text}`); ok("init"); scratch( "greeter", `export const greet = (name: string) => \`hello, \${name}\`; export const shout = (s: string) => s.toUpperCase(); export const main = (...args: string[]) => console.log(greet(args[0] ?? "world")); export const manifest = { name: "greeter", bin: { greet: "main" }, suites: { greet: ["e2e"] } }; `, ); ok("add"); // the test finds the command in GREET_BIN scratch( "greeter.e2e", `import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; export const testGreets = () => { const r = spawnSync(process.execPath, [process.env.GREET_BIN!, "tcm"], { encoding: "utf8" }); assert.equal(r.stdout, "hello, tcm\\n"); }; `, ); ok("add"); assert.match( ok("test"), /suites \(running greet\)\n {2}✓ greeter\.e2e\.testGreets[\s\S]*suites: 1 passed, 0 failed\n/, ); assert.match(ok("test"), /suites: 1 passed, 0 failed \(1 cached\)/); // (it's run as a program, not with the test definitions) assert.match(ok("test", "--definitions"), /no tests/); // shout isn't run by the test: changing it keeps the result scratch("greeter", `export const shout = (s: string) => s.toUpperCase() + "!";\n`); ok("update"); assert.match(ok("test"), /\(1 cached\)/); // greet is, so changing it runs the test again scratch("greeter", `export const greet = (name: string) => \`hi, \${name}\`;\n`); ok("update"); const failed = tcmIn(dir, "test"); assert.equal(failed.status, 1); assert.match( failed.out, /✗ greeter\.e2e\.testGreets[\s\S]*AssertionError[\s\S]*suites: 0 passed, 1 failed\n/, ); // a failure isn't kept: with nothing changed it runs again (it may have failed for what's around it) const again = tcmIn(dir, "test"); assert.match(again.out, /suites: 0 passed, 1 failed\n/); assert.doesNotMatch(again.out, /cached/); // changed back, the result from when it was this way holds again (as when branches are tested by turns) scratch("greeter", `export const greet = (name: string) => \`hello, \${name}\`;\n`); ok("update"); assert.match(ok("test"), /suites: 1 passed, 0 failed \(1 cached\)/); }