jacquardSnapshot

← snapshot

3132 bytes
/**
 * Grouping is only safe when it hides nothing. These check the rule that
 * matters: a file whose changes are not fully explained by the group's
 * substitutions must never be folded into it.
 *
 * Run with `npm test`. TypeScript is stripped by node's type stripping.
 */
import test from "node:test";
import assert from "node:assert/strict";

import { diffLines, withElisions } from "../diff.ts";
import { editsOf, groupFiles, describe, signatureOf } from "../diff-group.ts";

const body = (op, call, extra = "") =>
  `pub async fn ${op}(req: Request) -> Result<Response, NetError> {\n` +
  `    let policy = Policy::default()${extra};\n` +
  `    ${call}(policy, || transport::${op}(&req)).await\n}\n`;

function editsFor(before, after) {
  return editsOf(withElisions(diffLines(before, after), 4));
}

test("a one-token rename reads as a single substitution", () => {
  const e = editsFor(body("fetch", "retry"), body("fetch", "retry_with_jitter"));
  assert.equal(e.substitutions.length, 1);
  assert.equal(describe(e.substitutions[0]), "retry → retry_with_jitter");
  assert.ok(e.fullyExplained);
});

test("the same rename in different files shares a signature", () => {
  const a = editsFor(body("fetch", "retry"), body("fetch", "retry_with_jitter"));
  const b = editsFor(body("push", "retry"), body("push", "retry_with_jitter"));
  assert.equal(signatureOf(a), signatureOf(b));
});

test("a file with an extra change is NOT foldable", () => {
  const e = editsFor(
    body("upload", "retry"),
    body("upload", "retry_with_jitter", ".timeout(Duration::from_secs(90))"),
  );
  // Two substitutions here, not one — so its signature differs from the bulk.
  const bulk = editsFor(body("fetch", "retry"), body("fetch", "retry_with_jitter"));
  assert.notEqual(signatureOf(e), signatureOf(bulk));
});

test("eight identical renames fold into one group; the odd file stays out", () => {
  const files = {};
  for (const op of ["fetch", "push", "poll", "stream", "probe", "resolve", "handshake"]) {
    files[`src/net/${op}.rs`] = editsFor(body(op, "retry"), body(op, "retry_with_jitter"));
  }
  files["src/net/upload.rs"] = editsFor(
    body("upload", "retry"),
    body("upload", "retry_with_jitter", ".timeout(Duration::from_secs(90))"),
  );

  const paths = Object.keys(files);
  const { groups, singles } = groupFiles(paths, (p) => files[p]);

  assert.equal(groups.length, 1, "one bulk rename");
  assert.equal(groups[0].paths.length, 7, "seven clean files folded");
  assert.ok(
    singles.includes("src/net/upload.rs"),
    "the file with an extra edit must be read on its own",
  );
  assert.equal(groups[0].substitutions[0].count, 7, "counts sum across the group");
});

test("a pure insertion is never folded", () => {
  const e = editsFor("a\nb\n", "a\nNEW\nb\n");
  assert.equal(signatureOf(e), null);
});

test("a lone matching file is not a group", () => {
  const only = { "x.rs": editsFor(body("fetch", "retry"), body("fetch", "retry_with_jitter")) };
  const { groups, singles } = groupFiles(["x.rs"], (p) => only[p]);
  assert.equal(groups.length, 0);
  assert.deepEqual(singles, ["x.rs"]);
});