testChangeWhatImportsUseInOneSave

tcmts.cli.test.e2e.editing.testChangeWhatImportsUseInOneSave · #ygdz65sn · term

Removing a method from a class (Store) and its use in another (Codebase) in one scratch file, when what the file imports is typed with the first (an interface of what's needed, a function taking it): those are re-derived against the new class and saved with the file, rather than the file checked against them as they were (its Codebase no longer their old Core).

import { okIn, 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 testChangeWhatImportsUseInOneSave = () => {
  const dir = tempDir("change what imports use");
  const ok = (...args: string[]) => okIn(dir, ...args);
  ok("init");
  const write = (f: string, text: string) => fs.writeFileSync(path.join(dir, f), text);
  write(
    "lib.ts",
    `// tcm: namespace lib\n` +
      `export class Store {\n  a(): number { return 1; }\n  b(): number { return 2; }\n}\n` +
      `export interface Core { store: Store; }\n` +
      `export const keep = (cb: Core): number => cb.store.a();\n` +
      `export class Codebase implements Core {\n  store = new Store();\n  total(): number { return this.store.a() + this.store.b() + keep(this); }\n}\n` +
      `export const user = (cb: Codebase): number => cb.total();\n` +
      `export const other = (cb: Core): number => keep(cb) + 1;\n`,
  );
  ok("add", "lib.ts");
  fs.rmSync(path.join(dir, "scratch.ts"), { force: true });
  ok("edit", "lib.Store", "lib.Codebase");
  const scratch = path.join(dir, "scratch.ts");
  const text = fs.readFileSync(scratch, "utf8");
  fs.writeFileSync(
    scratch,
    text
      .replace(/\n {2}b\(\): number \{\n {4}return 2;\n {2}\}/, "")
      .replace(" + this.store.b()", ""),
  );
  const out = ok("update");
  assert.match(out, /~ update +lib\.Store/, out);
  assert.match(out, /~ update +lib\.Codebase/, out);
  assert.match(out, /lib\.keep/, out);
  assert.match(ok("todo"), /nothing to do/);
  assert.doesNotMatch(ok("view", "lib.Store"), /b\(\)/);
  // what uses the old interface follows (re-derived against the new one)
  assert.match(ok("view", "lib.other"), /keep\(cb\) \+ 1/);
}

uses