"use strict";
var import_blueprintDiff = require("./blueprintDiff");
const cases = [];
function test(name, run) {
  cases.push({ name, run });
}
function assertEqual(actual, expected, msg) {
  const a = JSON.stringify(actual);
  const e = JSON.stringify(expected);
  if (a !== e)
    throw new Error(`${msg ?? "assertEqual"} \u2014 expected ${e}, got ${a}`);
}
function makeElement(overrides = {}) {
  return {
    logicalName: "el",
    role: "button",
    accessibleName: "Click me",
    xpath: "//button",
    mutability: "immutable",
    widgetType: "native",
    framePath: [],
    shadowRoot: false,
    stableId: null,
    testId: null,
    fingerprint: null,
    ...overrides
  };
}
function makeRepeating(overrides = {}) {
  return {
    logicalName: "view_details_for_order_btn",
    role: "button",
    accessibleNameTemplate: "View details for order {orderId}",
    parameters: ["orderId"],
    xpathPattern: ".//button[{row}]",
    indexParameter: "orderId",
    items: [],
    mutability: "immutable",
    widgetType: "native",
    framePath: [],
    shadowRoot: false,
    stableId: null,
    testId: null,
    fingerprint: null,
    ...overrides
  };
}
function makeSection(name, elements = [], reps = []) {
  return { name, landmark: "main", elements, repeatingElements: reps };
}
function makeBlueprint(url, sections, pageHash = "h1") {
  return {
    schemaVersion: 1,
    url,
    capturedAt: "2026-04-30T00:00:00.000Z",
    pageHash,
    sections
  };
}
test("diffBlueprints: identical blueprints have no changes", () => {
  const bp = makeBlueprint("http://x/a", [makeSection("header", [makeElement()])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(bp, bp);
  assertEqual(d.hasStructuralChange, false);
  assertEqual(d.sectionsAdded, []);
  assertEqual(d.sectionsRemoved, []);
  assertEqual(d.elementsAdded, []);
  assertEqual(d.elementsRemoved, []);
  assertEqual(d.textChanges, []);
});
test("diffBlueprints: urlChange emitted when URL differs", () => {
  const a = makeBlueprint("http://x/a", [makeSection("main")]);
  const b = makeBlueprint("http://x/b", [makeSection("main")]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.urlChange, { before: "http://x/a", after: "http://x/b" });
});
test("diffBlueprints: pageHashChange emitted when hash differs", () => {
  const a = makeBlueprint("http://x/a", [makeSection("main")], "h1");
  const b = makeBlueprint("http://x/a", [makeSection("main")], "h2");
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.pageHashChange, { before: "h1", after: "h2" });
});
test("diffBlueprints: hasStructuralChange false when only URL and pageHash changed", () => {
  const a = makeBlueprint("http://x/a", [makeSection("main")], "h1");
  const b = makeBlueprint("http://x/b", [makeSection("main")], "h2");
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.urlChange, { before: "http://x/a", after: "http://x/b" });
  assertEqual(d.pageHashChange, { before: "h1", after: "h2" });
  assertEqual(d.hasStructuralChange, false);
});
test("diffBlueprints: sectionsAdded / sectionsRemoved", () => {
  const a = makeBlueprint("http://x", [makeSection("a")]);
  const b = makeBlueprint("http://x", [makeSection("a"), makeSection("b")]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.sectionsAdded, [{ sectionLogicalName: "b" }]);
  assertEqual(d.sectionsRemoved, []);
  assertEqual(d.hasStructuralChange, true);
});
test("diffBlueprints: elementsAdded in existing section", () => {
  const a = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "a" })])]);
  const b = makeBlueprint("http://x", [makeSection("main", [
    makeElement({ logicalName: "a" }),
    makeElement({ logicalName: "b", accessibleName: "Second" })
  ])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.elementsAdded.length, 1);
  assertEqual(d.elementsAdded[0].logicalName, "b");
  assertEqual(d.elementsAdded[0].kind, "persistent");
});
test("diffBlueprints: elementsAdded with role=status tagged transient", () => {
  const a = makeBlueprint("http://x", [makeSection("main")]);
  const b = makeBlueprint("http://x", [makeSection("main", [
    makeElement({ logicalName: "toast", role: "status", accessibleName: "Saved" })
  ])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.elementsAdded[0].kind, "transient");
});
test("diffBlueprints: role=alert is transient", () => {
  const a = makeBlueprint("http://x", [makeSection("main")]);
  const b = makeBlueprint("http://x", [makeSection("main", [
    makeElement({ logicalName: "err", role: "alert", accessibleName: "Error" })
  ])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.elementsAdded[0].kind, "transient");
});
test("diffBlueprints: elementsRemoved", () => {
  const a = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "a" })])]);
  const b = makeBlueprint("http://x", [makeSection("main")]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.elementsRemoved.length, 1);
  assertEqual(d.elementsRemoved[0].logicalName, "a");
});
test("diffBlueprints: same logicalName in different sections is not accidentally matched", () => {
  const a = makeBlueprint("http://x", [
    makeSection("header", [makeElement({ logicalName: "login_btn", accessibleName: "Log in" })]),
    makeSection("footer", [makeElement({ logicalName: "login_btn", accessibleName: "Sign in" })])
  ]);
  const b = makeBlueprint("http://x", [
    makeSection("header", [makeElement({ logicalName: "login_btn", accessibleName: "Log in" })])
    // footer's login_btn removed
  ]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.elementsRemoved.length, 1);
  assertEqual(d.elementsRemoved[0].logicalName, "login_btn");
  assertEqual(d.elementsRemoved[0].sectionLogicalName, "footer");
  assertEqual(d.textChanges, []);
  assertEqual(d.elementsAdded, []);
});
test("diffBlueprints: repeatingCountChanges 12 -> 13", () => {
  const items12 = Array.from({ length: 12 }, (_, i) => ({ parameters: { orderId: String(i + 1) } }));
  const items13 = [...items12, { parameters: { orderId: "13" } }];
  const a = makeBlueprint("http://x", [makeSection("list", [], [makeRepeating({ items: items12 })])]);
  const b = makeBlueprint("http://x", [makeSection("list", [], [makeRepeating({ items: items13 })])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.repeatingCountChanges.length, 1);
  assertEqual(d.repeatingCountChanges[0].before, 12);
  assertEqual(d.repeatingCountChanges[0].after, 13);
  assertEqual(d.repeatingCountChanges[0].delta, 1);
  assertEqual(d.repeatingCountChanges[0].role, "button");
  assertEqual(d.repeatingCountChanges[0].accessibleNameTemplate, "View details for order {orderId}");
});
test("diffBlueprints: repeatingItemsChanged detects same-count composition shift", () => {
  const items1 = [{ parameters: { orderId: "1" } }, { parameters: { orderId: "2" } }];
  const items2 = [{ parameters: { orderId: "1" } }, { parameters: { orderId: "3" } }];
  const a = makeBlueprint("http://x", [makeSection("list", [], [makeRepeating({ items: items1 })])]);
  const b = makeBlueprint("http://x", [makeSection("list", [], [makeRepeating({ items: items2 })])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.repeatingCountChanges, []);
  assertEqual(d.repeatingItemsChanged.length, 1);
  assertEqual(d.repeatingItemsChanged[0].changed, true);
});
test("diffBlueprints: textChanges on matched element", () => {
  const a = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "status", accessibleName: "Pending" })])]);
  const b = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "status", accessibleName: "Cancelled" })])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.textChanges.length, 1);
  assertEqual(d.textChanges[0].before, "Pending");
  assertEqual(d.textChanges[0].after, "Cancelled");
  assertEqual(d.textChanges[0].role, "button");
  assertEqual(d.textChanges[0].accessibleName, "Cancelled");
});
test("diffBlueprints: whitespace-only text changes ignored", () => {
  const a = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "s", accessibleName: "Saved" })])]);
  const b = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "s", accessibleName: "Saved " })])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.textChanges, []);
});
test("diffBlueprints: text truncated to 200 chars", () => {
  const long = "x".repeat(300);
  const a = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "s", accessibleName: "a" })])]);
  const b = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "s", accessibleName: long })])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  if (d.textChanges[0].after.length > 200)
    throw new Error(`text not truncated: ${d.textChanges[0].after.length}`);
});
test("diffBlueprints: enrichmentChanges for mutability flip", () => {
  const a = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "x", mutability: "immutable" })])]);
  const b = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "x", mutability: "mutable" })])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.enrichmentChanges.length, 1);
  assertEqual(d.enrichmentChanges[0].field, "mutability");
});
test("diffBlueprints: enrichmentChanges for widgetType flip", () => {
  const a = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "x", widgetType: "native" })])]);
  const b = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "x", widgetType: "custom", fingerprint: "abcdef0123456789" })])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.enrichmentChanges.length, 1);
  assertEqual(d.enrichmentChanges[0].field, "widgetType");
  assertEqual(d.enrichmentChanges[0].before, "native");
  assertEqual(d.enrichmentChanges[0].after, "custom");
});
test("diffBlueprints: hasStructuralChange false when only text changed", () => {
  const a = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "s", accessibleName: "A" })])]);
  const b = makeBlueprint("http://x", [makeSection("main", [makeElement({ logicalName: "s", accessibleName: "B" })])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.hasStructuralChange, false);
});
test("diffBlueprints: element matched via stableId when logicalName drifts", () => {
  const a = makeBlueprint("http://x", [makeSection("main", [
    makeElement({ logicalName: "status_region", stableId: "toast-region", accessibleName: "" })
  ])]);
  const b = makeBlueprint("http://x", [makeSection("main", [
    makeElement({ logicalName: "order_placed_status", stableId: "toast-region", accessibleName: "Order placed" })
  ])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.elementsAdded, []);
  assertEqual(d.elementsRemoved, []);
  assertEqual(d.textChanges.length, 1);
  assertEqual(d.textChanges[0].before, "");
  assertEqual(d.textChanges[0].after, "Order placed");
  assertEqual(d.textChanges[0].role, "button");
  assertEqual(d.textChanges[0].accessibleName, "Order placed");
  assertEqual(d.hasStructuralChange, false);
});
test("diffBlueprints: element matched via testId when logicalName drifts", () => {
  const a = makeBlueprint("http://x", [makeSection("main", [
    makeElement({ logicalName: "save_btn", testId: "save-action", accessibleName: "Save" })
  ])]);
  const b = makeBlueprint("http://x", [makeSection("main", [
    makeElement({ logicalName: "saving_btn", testId: "save-action", accessibleName: "Saving\u2026" })
  ])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.elementsAdded, []);
  assertEqual(d.elementsRemoved, []);
  assertEqual(d.textChanges.length, 1);
});
test("diffBlueprints: elements with no stable identity fall through to add+remove when logicalName drifts", () => {
  const a = makeBlueprint("http://x", [makeSection("main", [
    makeElement({ logicalName: "alpha", stableId: null, testId: null, accessibleName: "Alpha" })
  ])]);
  const b = makeBlueprint("http://x", [makeSection("main", [
    makeElement({ logicalName: "beta", stableId: null, testId: null, accessibleName: "Beta" })
  ])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.elementsAdded.length, 1);
  assertEqual(d.elementsRemoved.length, 1);
});
test("diffBlueprints: duplicate testId in same section disables testId fallback", () => {
  const a = makeBlueprint("http://x", [makeSection("main", [
    makeElement({ logicalName: "alpha_btn", testId: "shared-tid", accessibleName: "Alpha" }),
    makeElement({ logicalName: "beta_btn", testId: "shared-tid", accessibleName: "Beta" })
  ])]);
  const b = makeBlueprint("http://x", [makeSection("main", [
    makeElement({ logicalName: "alpha_renamed", testId: "shared-tid", accessibleName: "Alpha Renamed" }),
    makeElement({ logicalName: "beta_renamed", testId: "shared-tid", accessibleName: "Beta Renamed" })
  ])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.elementsAdded.length, 2);
  assertEqual(d.elementsRemoved.length, 2);
  assertEqual(d.textChanges.length, 0);
});
test("diffBlueprints: unique testId still falls back to match correctly", () => {
  const a = makeBlueprint("http://x", [makeSection("main", [
    makeElement({ logicalName: "unique_btn", testId: "unique-tid", accessibleName: "Unique" }),
    makeElement({ logicalName: "dup_a", testId: "dup-tid", accessibleName: "Dup A" }),
    makeElement({ logicalName: "dup_b", testId: "dup-tid", accessibleName: "Dup B" })
  ])]);
  const b = makeBlueprint("http://x", [makeSection("main", [
    makeElement({ logicalName: "unique_renamed", testId: "unique-tid", accessibleName: "Unique Renamed" }),
    makeElement({ logicalName: "dup_a", testId: "dup-tid", accessibleName: "Dup A" }),
    makeElement({ logicalName: "dup_b", testId: "dup-tid", accessibleName: "Dup B" })
  ])]);
  const d = (0, import_blueprintDiff.diffBlueprints)(a, b);
  assertEqual(d.elementsAdded.length, 0);
  assertEqual(d.elementsRemoved.length, 0);
  assertEqual(d.textChanges.length, 1);
});
let failed = 0;
for (const { name, run } of cases) {
  try {
    run();
    console.log("  \u2713", name);
  } catch (e) {
    failed++;
    console.log("  \u2717", name);
    console.log("     ", e.message);
  }
}
if (failed > 0) {
  console.log(`
${failed}/${cases.length} failed`);
  process.exit(1);
}
console.log(`
${cases.length} passed`);
