testSharedDependencyChangedOnBothSides

tcmts.cli.test.e2e.merge.testSharedDependencyChangedOnBothSides · #ltoghfxy · term

Both sides change a class their code shares (each adding a method), and one side's code uses its own method. The class is merged as text (the edits are apart), and the code taken from either side is re-derived against it, through what's between (each side had re-derived it for its own class): nothing is left using a version nothing names.

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 testSharedDependencyChangedOnBothSides = () => {
  const dir = tempDir("merge shared");
  const tcm = (...args: string[]) => okIn(dir, ...args);
  const update = (code: string) => {
    fs.writeFileSync(path.join(dir, "scratch.ts"), `// tcm: namespace lib\n${code}\n`);
    tcm("update");
  };
  const store = (first: string, second: string) =>
    `export class Store {\n  a(): number {\n    return 1;\n  }\n${first}\n  b(): number {\n    return 2;\n  }\n${second}}`;
  tcm("init");
  update(store("", ""));
  update(`import { Store } from "#codebase/lib";
export class Codebase {
  store = new Store();
}
export const render = (cb: Codebase) => cb.store.a();
export const main = () => render(new Codebase());`);
  tcm("branch", "b");

  // main adds a method after a(); b adds one after b(), and code using it
  update(store("\n  x(): number {\n    return 10;\n  }\n", ""));
  tcm("switch", "b");
  update(store("", "\n  y(): number {\n    return 3;\n  }\n"));
  update(
    `import { Codebase } from "#codebase/lib";\nexport const render = (cb: Codebase) => cb.store.a() + cb.store.y();`,
  );
  tcm("switch", "main");

  const merged = tcmIn(dir, "merge", "b");
  assert.equal(merged.status, 0, merged.out);
  assert.match(merged.out, /merged as text lib\.Store/);
  assert.doesNotMatch(merged.out, /conflict|no longer typecheck/);
  assert.match(merged.out, /merged cleanly/);
  assert.equal(tcm("run", "lib.main").trim(), "4");
  assert.match(tcm("view", "lib.Store"), /x\(\): number[\s\S]*y\(\): number/);
  const todo = tcm("todo");
  assert.doesNotMatch(todo, /unnamed version/);
  assert.match(todo, /nothing to do/);
}

uses