testMergeSummary

tcmts.cli.mcp.testMergeSummary · #yjfjpvhk · term

import { mergeSummary } from "#codebase/tcmts/cli/mcp";
import assert from "node:assert/strict";

export const testMergeSummary = () => {
  assert.equal(
    mergeSummary("merged main into session/x\n  no changes\n\n  merged cleanly"),
    "merged main into session/x\n  no changes\n  merged cleanly",
  );
  const out = [
    "fast-forwarded main to session/x",
    "",
    "  edited",
    "    ~ lib.square  #aaaaaaaa → #bbbbbbbb",
    "        export const square = (x: number) =>",
    "      - x * x",
    "      + x ** 2",
    "",
    "  updated because a dependency changed (code unchanged)",
    "    ~ lib.area  #cccccccc → #dddddddd  via lib.square",
    "    ~ lib.volume  #eeeeeeee → #ffffffff  via lib.square",
  ].join("\n");
  assert.equal(
    mergeSummary(out),
    "fast-forwarded main to session/x\n  edited: lib.square\n  updated because a dependency changed (code unchanged): 2",
  );
  // a merge stopping on a conflict: what's conflicted by name, and the conflict lines (not every edit's code)
  const conflicted = [
    "merged main into session/x",
    "",
    "  edited",
    "    ~ lib.render  #aaaaaaaa → #bbbbbbbb",
    "      - export const render = () => 1",
    "      + export const render = () => 2",
    "",
    "  conflicted",
    "    ! lib.Store  #cccccccc, #dddddddd",
    "",
    "  merged as text lib.Codebase (both sides edited it, apart: their edits are combined, and it typechecks)",
    "  conflict lib.Store: cccccccc (ours: session/x) vs dddddddd (theirs: main)  tcm resolve lib.Store cccccccc keeps ours: session/x",
  ].join("\n");
  const brief = mergeSummary(conflicted);
  assert.match(brief, /^ {2}edited: lib\.render$/m);
  assert.match(brief, /^ {2}conflicted: lib\.Store$/m);
  assert.match(brief, /^ {2}merged as text lib\.Codebase/m);
  assert.match(
    brief,
    /^ {2}conflict lib\.Store: cccccccc \(ours: session\/x\) vs dddddddd \(theirs: main\)/m,
  );
  assert.doesNotMatch(brief, /export const/);
}

uses