"use strict";
var import_possibleAssertions = require("./possibleAssertions");
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}`);
}
test("Empty delta \u2192 empty array", () => {
  const delta = {
    hasStructuralChange: false,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [],
    elementsRemoved: [],
    repeatingCountChanges: [],
    repeatingItemsChanged: [],
    textChanges: [],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 0);
});
test("elementsAdded with a button \u2192 1 assertion, role-based locator, toBeVisible(), MEDIUM tier", () => {
  const delta = {
    hasStructuralChange: true,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [
      {
        logicalName: "save_btn",
        sectionLogicalName: "main",
        role: "button",
        accessibleName: "Save Changes",
        kind: "persistent"
      }
    ],
    elementsRemoved: [],
    repeatingCountChanges: [],
    repeatingItemsChanged: [],
    textChanges: [],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 1);
  assertEqual(assertions[0].code, "await expect(page.getByRole('button', { name: 'Save Changes' })).toBeVisible();");
  assertEqual(assertions[0].tier, "MEDIUM");
  if (!assertions[0].rationale.includes("button"))
    throw new Error("rationale should mention button role");
});
test("elementsRemoved with a textbox \u2192 .not.toBeVisible(), MEDIUM", () => {
  const delta = {
    hasStructuralChange: true,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [],
    elementsRemoved: [
      {
        logicalName: "email_input",
        sectionLogicalName: "form",
        role: "textbox",
        accessibleName: "Email"
      }
    ],
    repeatingCountChanges: [],
    repeatingItemsChanged: [],
    textChanges: [],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 1);
  assertEqual(assertions[0].code, "await expect(page.getByRole('textbox', { name: 'Email' })).not.toBeVisible();");
  assertEqual(assertions[0].tier, "MEDIUM");
  if (!assertions[0].rationale.includes("removed"))
    throw new Error("rationale should mention removed");
});
test("repeatingCountChanges 12 \u2192 13 \u2192 toHaveCount(13), HIGH", () => {
  const delta = {
    hasStructuralChange: true,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [],
    elementsRemoved: [],
    repeatingCountChanges: [
      {
        logicalName: "order_row_btn",
        sectionLogicalName: "main",
        role: "button",
        accessibleNameTemplate: "View details for order {orderId}",
        before: 12,
        after: 13,
        delta: 1
      }
    ],
    repeatingItemsChanged: [],
    textChanges: [],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 1);
  if (!assertions[0].code.includes("toHaveCount(13)"))
    throw new Error("code should include toHaveCount(13)");
  if (!assertions[0].code.includes(`new RegExp('^View details for order .+$', 'i')`))
    throw new Error("code should include RegExp constructor with template-derived pattern");
  assertEqual(assertions[0].tier, "HIGH");
  if (!assertions[0].rationale.includes("12") || !assertions[0].rationale.includes("13"))
    throw new Error("rationale should mention before and after counts");
});
test('textChanges "Inbox (5)" \u2192 "Inbox (6)" \u2192 toHaveText(...), HIGH', () => {
  const delta = {
    hasStructuralChange: false,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [],
    elementsRemoved: [],
    repeatingCountChanges: [],
    repeatingItemsChanged: [],
    textChanges: [
      {
        logicalName: "inbox_link",
        sectionLogicalName: "sidebar",
        role: "link",
        accessibleName: "Inbox (6)",
        before: "Inbox (5)",
        after: "Inbox (6)"
      }
    ],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 1);
  if (!assertions[0].code.includes("toHaveText('Inbox (6)')"))
    throw new Error("code should include toHaveText with after value");
  if (!assertions[0].code.includes("getByRole('link'"))
    throw new Error("code should use role-based locator");
  assertEqual(assertions[0].tier, "HIGH");
  if (!assertions[0].rationale.includes("Inbox (5)") || !assertions[0].rationale.includes("Inbox (6)"))
    throw new Error("rationale should mention before and after text");
});
test("elementsAdded with empty accessibleName + no testId + no stableId \u2192 skipped (zero output)", () => {
  const delta = {
    hasStructuralChange: true,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [
      {
        logicalName: "button_1",
        sectionLogicalName: "main",
        role: "button",
        accessibleName: "",
        kind: "persistent"
      }
    ],
    elementsRemoved: [],
    repeatingCountChanges: [],
    repeatingItemsChanged: [],
    textChanges: [],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 0, "should skip element with empty accessibleName");
});
test("Quote-escaping: accessibleName with quotes", () => {
  const delta = {
    hasStructuralChange: true,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [
      {
        logicalName: "greeting_btn",
        sectionLogicalName: "main",
        role: "button",
        accessibleName: "He said 'hi'",
        kind: "persistent"
      }
    ],
    elementsRemoved: [],
    repeatingCountChanges: [],
    repeatingItemsChanged: [],
    textChanges: [],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 1);
  if (!assertions[0].code.includes("\\'"))
    throw new Error("code should escape single quotes");
});
test("textChanges with empty accessibleName \u2192 skipped", () => {
  const delta = {
    hasStructuralChange: false,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [],
    elementsRemoved: [],
    repeatingCountChanges: [],
    repeatingItemsChanged: [],
    textChanges: [
      {
        logicalName: "icon_btn",
        sectionLogicalName: "main",
        role: "button",
        accessibleName: "",
        before: "",
        after: "New Text"
      }
    ],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 0, "should skip textChange with empty accessibleName");
});
test("repeatingCountChanges with empty accessibleNameTemplate \u2192 skipped", () => {
  const delta = {
    hasStructuralChange: true,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [],
    elementsRemoved: [],
    repeatingCountChanges: [
      {
        logicalName: "item",
        sectionLogicalName: "main",
        role: "listitem",
        accessibleNameTemplate: "",
        before: 5,
        after: 6,
        delta: 1
      }
    ],
    repeatingItemsChanged: [],
    textChanges: [],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 0, "should skip repeatingCountChange with empty accessibleNameTemplate");
});
test("Mixed delta with all four kinds \u2192 all four translations appear, ordered HIGH first then MEDIUM then LOW", () => {
  const delta = {
    hasStructuralChange: true,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [
      {
        logicalName: "save_btn",
        sectionLogicalName: "main",
        role: "button",
        accessibleName: "Save",
        kind: "persistent"
      },
      {
        logicalName: "notification_status",
        sectionLogicalName: "main",
        role: "status",
        accessibleName: "Operation complete",
        kind: "transient"
      }
    ],
    elementsRemoved: [
      {
        logicalName: "cancel_btn",
        sectionLogicalName: "main",
        role: "button",
        accessibleName: "Cancel"
      }
    ],
    repeatingCountChanges: [
      {
        logicalName: "order_row_btn",
        sectionLogicalName: "main",
        role: "button",
        accessibleNameTemplate: "View details for order {orderId}",
        before: 12,
        after: 13,
        delta: 1
      }
    ],
    repeatingItemsChanged: [],
    textChanges: [
      {
        logicalName: "inbox_link",
        sectionLogicalName: "sidebar",
        role: "link",
        accessibleName: "Inbox (6)",
        before: "Inbox (5)",
        after: "Inbox (6)"
      }
    ],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 5);
  assertEqual(assertions[0].tier, "HIGH");
  assertEqual(assertions[1].tier, "HIGH");
  assertEqual(assertions[2].tier, "MEDIUM");
  assertEqual(assertions[3].tier, "MEDIUM");
  assertEqual(assertions[4].tier, "LOW");
});
function makeBlueprint(url, sections = []) {
  return {
    schemaVersion: 1,
    url,
    capturedAt: "2026-01-01T00:00:00Z",
    pageHash: "0:0",
    sections
  };
}
test("Full capture with URL + heading \u2192 2 assertions, HIGH then LOW", () => {
  const blueprint = makeBlueprint("http://localhost:8055/settings/schema", [
    {
      name: "page",
      landmark: "main",
      elements: [
        {
          logicalName: "page_title",
          role: "heading",
          accessibleName: "Data Model",
          xpath: "//h1",
          mutability: "immutable",
          widgetType: "native",
          framePath: [],
          shadowRoot: false
        }
      ],
      repeatingElements: []
    }
  ]);
  const assertions = (0, import_possibleAssertions.buildFullCaptureAssertions)(blueprint);
  assertEqual(assertions.length, 2);
  assertEqual(assertions[0].tier, "HIGH");
  assertEqual(
    assertions[0].code,
    `await expect(page).toHaveURL('http://localhost:8055/settings/schema');`
  );
  assertEqual(assertions[1].tier, "LOW");
  assertEqual(
    assertions[1].code,
    `await expect(page.getByRole('heading', { name: 'Data Model' })).toBeVisible();`
  );
});
test("Full capture with URL only (no headings) \u2192 1 assertion", () => {
  const blueprint = makeBlueprint("http://localhost:8055/applications", [
    {
      name: "page",
      landmark: "main",
      elements: [
        {
          logicalName: "create_btn",
          role: "button",
          accessibleName: "Create new",
          xpath: "//button",
          mutability: "mutable",
          widgetType: "native",
          framePath: [],
          shadowRoot: false
        }
      ],
      repeatingElements: []
    }
  ]);
  const assertions = (0, import_possibleAssertions.buildFullCaptureAssertions)(blueprint);
  assertEqual(assertions.length, 1);
  assertEqual(assertions[0].tier, "HIGH");
});
test("Full capture with empty URL \u2192 no assertions", () => {
  const blueprint = makeBlueprint("", []);
  const assertions = (0, import_possibleAssertions.buildFullCaptureAssertions)(blueprint);
  assertEqual(assertions.length, 0);
});
test("Full capture skips heading with empty accessibleName", () => {
  const blueprint = makeBlueprint("http://example.com/", [
    {
      name: "page",
      landmark: "main",
      elements: [
        {
          logicalName: "unnamed_heading",
          role: "heading",
          accessibleName: "   ",
          xpath: "//h1",
          mutability: "immutable",
          widgetType: "native",
          framePath: [],
          shadowRoot: false
        }
      ],
      repeatingElements: []
    }
  ]);
  const assertions = (0, import_possibleAssertions.buildFullCaptureAssertions)(blueprint);
  assertEqual(assertions.length, 1);
  assertEqual(assertions[0].tier, "HIGH");
});
test("Full capture finds first heading across multiple sections", () => {
  const blueprint = makeBlueprint("http://example.com/page", [
    {
      name: "header",
      landmark: "banner",
      elements: [],
      // no heading here
      repeatingElements: []
    },
    {
      name: "page",
      landmark: "main",
      elements: [
        {
          logicalName: "main_heading",
          role: "heading",
          accessibleName: "Welcome",
          xpath: "//h1",
          mutability: "immutable",
          widgetType: "native",
          framePath: [],
          shadowRoot: false
        }
      ],
      repeatingElements: []
    }
  ]);
  const assertions = (0, import_possibleAssertions.buildFullCaptureAssertions)(blueprint);
  assertEqual(assertions.length, 2);
  assertEqual(assertions[1].rationale, 'Heading visible on destination page: "Welcome"');
});
test("Full capture escapes single-quotes in URL and heading", () => {
  const blueprint = makeBlueprint(`http://example.com/q?name='foo'`, [
    {
      name: "page",
      landmark: "main",
      elements: [
        {
          logicalName: "h1",
          role: "heading",
          accessibleName: `Bob's profile`,
          xpath: "//h1",
          mutability: "immutable",
          widgetType: "native",
          framePath: [],
          shadowRoot: false
        }
      ],
      repeatingElements: []
    }
  ]);
  const assertions = (0, import_possibleAssertions.buildFullCaptureAssertions)(blueprint);
  assertEqual(assertions.length, 2);
  assertEqual(assertions[0].code.includes(`\\'`), true);
  assertEqual(assertions[1].code.includes(`\\'`), true);
});
test("long accessibleName is preserved in generated code, not truncated", () => {
  const longName = "a".repeat(150);
  const delta = {
    hasStructuralChange: true,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [{
      logicalName: "long_btn",
      sectionLogicalName: "main",
      role: "button",
      accessibleName: longName
    }],
    elementsRemoved: [],
    repeatingCountChanges: [],
    repeatingItemsChanged: [],
    textChanges: [],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 1);
  if (!assertions[0].code.includes(longName))
    throw new Error("full accessibleName must appear in generated code");
  if (assertions[0].rationale.length > 200)
    throw new Error("rationale should be truncated for display");
});
test("long text-change values preserved in toHaveText, truncated in rationale", () => {
  const longAfter = "b".repeat(120);
  const delta = {
    hasStructuralChange: false,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [],
    elementsRemoved: [],
    repeatingCountChanges: [],
    repeatingItemsChanged: [],
    textChanges: [{
      logicalName: "msg",
      sectionLogicalName: "main",
      role: "status",
      accessibleName: "Status",
      before: "short",
      after: longAfter
    }],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 1);
  if (!assertions[0].code.includes(longAfter))
    throw new Error("full after-text must appear in toHaveText() argument");
});
test("templateToRegex emits new RegExp(...) so slashes in the template do not break the literal", () => {
  const delta = {
    hasStructuralChange: true,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [],
    elementsRemoved: [],
    repeatingCountChanges: [{
      logicalName: "page_link",
      sectionLogicalName: "main",
      role: "link",
      accessibleNameTemplate: "A/B page {n}",
      before: 0,
      after: 3,
      delta: 3
    }],
    repeatingItemsChanged: [],
    textChanges: [],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 1);
  if (!assertions[0].code.includes(`new RegExp('^A\\\\/B page .+$', 'i')`))
    throw new Error(
      "code should use new RegExp(...) constructor with escaped slash; got:\n" + assertions[0].code
    );
});
test('non-interactive non-heading roles get role-agnostic rationale (not "live region")', () => {
  const delta = {
    hasStructuralChange: true,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [{
      logicalName: "embed",
      sectionLogicalName: "main",
      role: "figure",
      accessibleName: "Embedded preview"
    }],
    elementsRemoved: [],
    repeatingCountChanges: [],
    repeatingItemsChanged: [],
    textChanges: [],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 1);
  if (assertions[0].rationale.includes("live region"))
    throw new Error('rationale should not call non-live-region roles "live region"');
  if (!assertions[0].rationale.startsWith("figure appeared"))
    throw new Error('rationale should be role-agnostic ("figure appeared..."); got: ' + assertions[0].rationale);
});
test('genuine live-region roles (status/alert) keep the "live region" rationale', () => {
  const delta = {
    hasStructuralChange: true,
    sectionsAdded: [],
    sectionsRemoved: [],
    elementsAdded: [{
      logicalName: "toast",
      sectionLogicalName: "main",
      role: "status",
      accessibleName: "Saved"
    }],
    elementsRemoved: [],
    repeatingCountChanges: [],
    repeatingItemsChanged: [],
    textChanges: [],
    enrichmentChanges: []
  };
  const assertions = (0, import_possibleAssertions.buildPossibleAssertions)(delta);
  assertEqual(assertions.length, 1);
  if (!assertions[0].rationale.includes("live region"))
    throw new Error('status role should keep the "live region" rationale; got: ' + assertions[0].rationale);
});
let passed = 0;
let failed = 0;
const failures = [];
for (const c of cases) {
  try {
    c.run();
    passed++;
  } catch (e) {
    failed++;
    failures.push({ name: c.name, error: e.message });
  }
}
console.log(`${passed}/${cases.length} passed${failed ? `, ${failed} failed` : ""}`);
for (const f of failures)
  console.error(`  \u2717 ${f.name}: ${f.error}`);
if (failed > 0) {
  process.exit(1);
}
