testSquashedLandingKeepsItsStepsOwn

tcmts.cli.test.e2e.merge.testSquashedLandingKeepsItsStepsOwn · #p6m45hwk · term

A branch squashed in is one entry whose only parent is main's: its steps stay its own, so a push of main sends what it ended with, not each version along the way; it counts as landed until it changes again.

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 testSquashedLandingKeepsItsStepsOwn = () => {
  const root = tempDir("squash");
  const dir = path.join(root, "a");
  fs.mkdirSync(dir);
  const tcm = (...args: string[]) => okIn(dir, ...args);
  const scratch = (text: string) => fs.writeFileSync(path.join(dir, "scratch.ts"), text);
  tcm("init");
  scratch(`// tcm: namespace lib\nexport const square = (x: number): number => x * x;\n`);
  tcm("add");
  tcm("branch", "feature");
  tcm("switch", "feature");
  // three steps on the branch: two versions of square on the way to the last
  for (const body of ["x ** 2", "Math.pow(x, 2)", "x * x * 1"]) {
    scratch(`// tcm: namespace lib\nexport const square = (x: number): number => ${body};\n`);
    tcm("update");
  }
  scratch(`// tcm: namespace lib\nexport const cube = (x: number): number => x ** 3;\n`);
  tcm("add");
  tcm("switch", "main");
  scratch(`// tcm: namespace lib\nexport const label = "powers";\n`);
  tcm("add");

  const entries = () => (tcm("history", "100").match(/^#[a-z2-7]+/gm) ?? []).length;
  const before = entries();
  assert.match(tcm("merge", "feature", "--squash"), /merged feature into main as one entry/);
  assert.equal(entries(), before + 1, "one entry, and none of the branch's");
  assert.match(tcm("view", "lib.square"), /x \* x \* 1/);
  assert.match(tcm("ls", "lib"), /lib\.cube[\s\S]*lib\.label/);
  assert.doesNotMatch(tcm("status"), /branches with work main doesn't have/, "it landed");
  assert.match(tcm("merge", "feature", "--squash"), /already has everything/);

  // pushed, main sends the versions its own entries name: square's first and last, cube and label
  const b = path.join(root, "b");
  fs.mkdirSync(b);
  okIn(b, "init");
  fs.rmSync(path.join(b, "scratch.ts"));
  tcm("remote", "add", "origin", b);
  assert.match(tcm("push"), /sent 4 definition\(s\)/);

  // more work on the branch is work main doesn't have again
  tcm("switch", "feature");
  scratch(`// tcm: namespace lib\nexport const cube = (x: number): number => x * x * x;\n`);
  tcm("update");
  tcm("switch", "main");
  assert.match(tcm("status"), /branches with work main doesn't have\n\s+feature/);
}

uses