testPatchAddsImportsItsGiven

tcmts.cli.test.e2e.editing.testPatchAddsImportsItsGiven · #4k7mcidd · term

tcm patch adds imports it's given (--imports, or imports in --patches), for names importing what the code uses can't find: an alias, say. They're shown with the change, and go if the code doesn't use them; a file kept as written has none to add to.

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 testPatchAddsImportsItsGiven = () => {
  const dir = tempDir("patch imports");
  const ok = (...args: string[]) => okIn(dir, ...args);
  ok("init");
  fs.writeFileSync(
    path.join(dir, "m.ts"),
    `// tcm: namespace m\nexport const g = (x: number): number => x + 1;\nexport const h = (x: number): number => x + 2;\n`,
  );
  fs.mkdirSync(path.join(dir, "docs"));
  fs.writeFileSync(path.join(dir, "docs", "page.md"), "# Page\n");
  ok("add", "m.ts");
  ok("add", "docs/page.md", "--into", "docs");
  fs.rmSync(path.join(dir, "m.ts"));
  const one = ok(
    "patch",
    "m.g",
    "--old",
    "x + 1",
    "--new",
    'x + pjoin("a").length',
    "--imports",
    JSON.stringify([
      { name: "join", from: "node:path", as: "pjoin" },
      { name: "tmpdir", from: "node:os" },
    ]),
  );
  assert.match(one, /\+ import \{ join as pjoin \} from "node:path";/);
  const g = ok("view", "m.g");
  assert.match(g, /import \{ join as pjoin \} from "node:path";[\s\S]*x \+ pjoin\("a"\)\.length/);
  // (one it doesn't use goes)
  assert.doesNotMatch(g, /tmpdir/);
  const many = ok(
    "patch",
    "--patches",
    JSON.stringify([
      {
        name: "m.h",
        edits: [{ old: "x + 2", new: 'x + pb("a").length' }],
        imports: [{ name: "basename", from: "node:path/posix", as: "pb" }],
      },
      { name: "docs.page", edits: [{ old: "# Page", new: "# The page" }] },
    ]),
  );
  assert.match(many, /imports:\s+\+ import \{ basename as pb \} from "node:path\/posix";/);
  assert.match(ok("view", "m.h"), /import \{ basename as pb \} from "node:path\/posix";/);
  const page = tcmIn(
    dir,
    "patch",
    "docs.page",
    "--old",
    "The page",
    "--new",
    "Page",
    "--imports",
    JSON.stringify([{ name: "x", from: "y" }]),
  );
  assert.notEqual(page.status, 0);
  assert.match(page.out, /docs\.page is a file kept as written: it has no imports to add to/);
  const bad = tcmIn(
    dir,
    "patch",
    "m.g",
    "--old",
    "x +",
    "--new",
    "x -",
    "--imports",
    JSON.stringify([{ name: "*", from: "node:os" }]),
  );
  assert.match(bad.out, /`default` or `\*` with `as`/);
}

uses