testMirrorMoves

tcmts.cli.test.e2e.mirror.testMirrorMoves · #s5dctu6n · term

a definition moved to another namespace moves to its file, and what imports it follows

import { okIn, tempDir } from "#codebase/tcmts/cli/test/e2e/harness";
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import fs from "node:fs";
import path from "node:path";

export const testMirrorMoves = () => {
  const root = tempDir("mirror");
  const repo = path.join(root, "moves");
  const cbDir = path.join(root, "moves-cb");
  fs.mkdirSync(path.join(repo, "src"), { recursive: true });
  fs.mkdirSync(path.join(repo, "scripts"));
  fs.writeFileSync(path.join(repo, "package.json"), JSON.stringify({ type: "module" }));
  fs.writeFileSync(path.join(repo, "src", "math.ts"), `export function double(x: number): number {\n  return x * 2;\n}\n\nexport const half = (x: number): number => x / 2;\n\nexport const halfDouble = (x: number): number => half(double(x));\n`);
  fs.writeFileSync(path.join(repo, "src", "use.ts"), `import { double, half } from "./math.ts";\n\nexport const quarter = (x: number): number => half(half(x));\nexport const quad = (x: number): number => double(double(x));\n`);
  fs.writeFileSync(path.join(repo, "src", "extra.ts"), `export const one = 1;\n`);
  const report = `import { half } from "../src/math.ts";\n\nconsole.log(half(8));\n`;
  fs.writeFileSync(path.join(repo, "scripts", "report.ts"), report);
  assert.equal(spawnSync("git", ["-C", repo, "init", "-q"]).status, 0);
  fs.mkdirSync(cbDir);
  const run = (...args: string[]) => okIn(cbDir, ...args);
  const read = (f: string) => fs.readFileSync(path.join(repo, f), "utf8");
  run("init");
  run("import", path.join(repo, "src"), "--into", "app", "--mirror");

  assert.match(run("mv", "app.math.half", "app.extra.half"), /mirror: wrote/);
  // its declaration moves; the file it left imports it for the code there that still uses it
  assert.equal(read("src/math.ts"), `import { half } from "./extra.ts";\nexport function double(x: number): number {\n  return x * 2;\n}\n\nexport const halfDouble = (x: number): number => half(double(x));\n`);
  assert.equal(read("src/extra.ts"), `export const one = 1;\n\nexport const half = (x: number): number => x / 2;\n`);
  // imports of it follow it, splitting one that brought others too, outside the mirror as well
  assert.equal(read("src/use.ts"), `import { double } from "./math.ts";\nimport { half } from "./extra.ts";\n\nexport const quarter = (x: number): number => half(half(x));\nexport const quad = (x: number): number => double(double(x));\n`);
  assert.equal(read("scripts/report.ts"), `import { half } from "../src/extra.ts";\n\nconsole.log(half(8));\n`);
  assert.match(run("mirror", "--check"), /the files hash to what the codebase holds/);

  // moved back and renamed at once
  run("mv", "app.extra.half", "app.math.halve");
  assert.doesNotMatch(read("src/extra.ts"), /half/);
  assert.match(read("src/math.ts"), /export const halfDouble = \(x: number\): number => halve\(double\(x\)\);/);
  assert.match(read("src/use.ts"), /import \{ double, halve \} from "\.\/math\.ts";|import \{ double \} from "\.\/math\.ts";\nimport \{ halve \} from "\.\/math\.ts";/);
  assert.match(read("scripts/report.ts"), /import \{ halve \} from "\.\.\/src\/math\.ts";\n\nconsole\.log\(halve\(8\)\);/);
  assert.match(run("mirror", "--check"), /the files hash to what the codebase holds/);
}

uses