69 lines · 2.6 KB
import { describe, expect, test } from "bun:test";
import { formatSignature, makeCommit, sanitizeIdent, signatureNow } from "./objects";

const decoder = new TextDecoder();

describe("sanitizeIdent", () => {
  test("strips angle brackets so a name cannot carry a second mailbox", () => {
    expect(sanitizeIdent("Mallory <ceo@corp.example>")).toBe("Mallory ceo@corp.example");
  });

  test("collapses newlines and control characters onto one line", () => {
    expect(sanitizeIdent("Mallory\ngpgsig evil\r\n\u0000x")).toBe("Mallory gpgsig evil x");
  });

  test("trims leading and trailing crud like git does", () => {
    expect(sanitizeIdent("  .,Mallory;: ")).toBe("Mallory");
  });

  test("keeps ordinary unicode names", () => {
    expect(sanitizeIdent("Zoë O'Brien-Łukasz")).toBe("Zoë O'Brien-Łukasz");
  });
});

describe("formatSignature", () => {
  test("never emits a forged mailbox or an extra header line", () => {
    const line = formatSignature({
      name: "Mallory <ceo@corp.example>\nparent 0000000000000000000000000000000000000000",
      email: "mallory@x",
      timestamp: 1_700_000_000,
      timezone: "+0000",
    });
    expect(line).toBe(
      "Mallory ceo@corp.example parent 0000000000000000000000000000000000000000 <mallory@x> 1700000000 +0000",
    );
    expect(line.includes("\n")).toBe(false);
    expect(line.indexOf("<")).toBe(line.lastIndexOf("<"));
  });

  test("falls back to a placeholder when the name sanitizes to nothing", () => {
    expect(formatSignature({ name: "<>", email: "a@b", timestamp: 1, timezone: "+0000" })).toBe(