// Browser tests cover pw role snapshot plugin behavior.
import { describe, expect, it } from "vitest";
import {
  buildRoleSnapshotFromAiSnapshot,
  buildRoleSnapshotFromAriaSnapshot,
  getRoleSnapshotStats,
  parseRoleRef,
} from "./pw-role-snapshot.js";

describe("pw-role-snapshot", () => {
  it("adds refs for interactive elements", () => {
    const aria = [
      '- heading "Example" [level=1]',
      "- paragraph: hello",
      '- button "Submit"',
      "  - generic",
      '- link "Learn more"',
    ].join("\n");

    const res = buildRoleSnapshotFromAriaSnapshot(aria, { interactive: true });
    expect(res.snapshot).toContain("[ref=e1]");
    expect(res.snapshot).toContain("[ref=e2]");
    expect(res.snapshot).toContain('- button "Submit" [ref=e1]');
    expect(res.snapshot).toContain('- link "Learn more" [ref=e2]');
    expect(Object.keys(res.refs)).toEqual(["e1", "e2"]);
    expect(res.refs.e1?.role).toBe("button");
    expect(res.refs.e1?.name).toBe("Submit");
    expect(res.refs.e2?.role).toBe("link");
    expect(res.refs.e2?.name).toBe("Learn more");
  });

  it("uses nth only when duplicates exist", () => {
    const aria = ['- button "OK"', '- button "OK"', '- button "Cancel"'].join("\n");
    const res = buildRoleSnapshotFromAriaSnapshot(aria);
    expect(res.snapshot).toContain("[ref=e1]");
    expect(res.snapshot).toContain("[ref=e2] [nth=1]");
    expect(res.refs.e1?.nth).toBe(0);
    expect(res.refs.e2?.nth).toBe(1);
    expect(res.refs.e3?.nth).toBeUndefined();
  });
  it("respects maxDepth", () => {
    const aria = ['- region "Main"', "  - group", '    - button "Deep"'].join("\n");
    const res = buildRoleSnapshotFromAriaSnapshot(aria, { maxDepth: 1 });
    expect(res.snapshot).toContain('- region "Main"');
    expect(res.snapshot).toContain("  - group");
    expect(res.snapshot).not.toContain("button");
  });

  it("keeps named branches with refs and drops empty branches when compact", () => {
    const aria = ['- list "Menu":', '  - button "Save"', '- list "Empty":', "  - generic"].join(
      "\n",
    );

    const res = buildRoleSnapshotFromAriaSnapshot(aria, { compact: true });

    expect(res.snapshot).toBe('- list "Menu":\n  - button "Save" [ref=e1]');
  });

  it("computes stats", () => {
    const aria = ['- button "OK"', '- button "Cancel"'].join("\n");
    const res = buildRoleSnapshotFromAriaSnapshot(aria);
    const stats = getRoleSnapshotStats(res.snapshot, res.refs);
    expect(stats.refs).toBe(2);
    expect(stats.interactive).toBe(2);
    expect(stats.lines).toBeGreaterThan(0);
    expect(stats.chars).toBeGreaterThan(0);
  });

  it("returns a helpful message when no interactive elements exist", () => {
    const aria = ['- heading "Hello"', "- paragraph: world"].join("\n");
    const res = buildRoleSnapshotFromAriaSnapshot(aria, { interactive: true });
    expect(res.snapshot).toBe("(no interactive elements)");
    expect(Object.keys(res.refs)).toStrictEqual([]);
  });

  it("parses role refs", () => {
    expect(parseRoleRef("e12")).toBe("e12");
    expect(parseRoleRef("@e12")).toBe("e12");
    expect(parseRoleRef("ref=e12")).toBe("e12");
    expect(parseRoleRef("12")).toBe("12");
    expect(parseRoleRef("")).toBeNull();
  });

  it("preserves Playwright aria-ref ids in ai snapshots", () => {
    const ai = [
      "- navigation [ref=e1]:",
      '  - link "Home" [ref=e5]',
      '  - heading "Title" [ref=e6]',
      '  - button "Save" [ref=e7] [cursor=pointer]:',
      "  - paragraph: hello",
    ].join("\n");

    const res = buildRoleSnapshotFromAiSnapshot(ai, { interactive: true });
    expect(res.snapshot).toContain("[ref=e5]");
    expect(res.snapshot).toContain('- link "Home"');
    expect(res.snapshot).toContain('- button "Save"');
    expect(res.snapshot).not.toContain("navigation");
    expect(res.snapshot).not.toContain("heading");
    expect(Object.keys(res.refs).toSorted()).toEqual(["e5", "e7"]);
    expect(res.refs.e5?.role).toBe("link");
    expect(res.refs.e5?.name).toBe("Home");
    expect(res.refs.e7?.role).toBe("button");
    expect(res.refs.e7?.name).toBe("Save");
  });

  it("preserves numeric Playwright AI snapshot refs", () => {
    const ai = [
      "- navigation [ref=1]:",
      '  - link "Home" [ref=5]',
      '  - button "Save" [ref=7] [cursor=pointer]:',
    ].join("\n");

    const res = buildRoleSnapshotFromAiSnapshot(ai, { interactive: true });
    expect(res.snapshot).toContain("[ref=5]");
    expect(Object.keys(res.refs).toSorted()).toEqual(["5", "7"]);
    expect(res.refs["5"]?.role).toBe("link");
    expect(res.refs["5"]?.name).toBe("Home");
    expect(res.refs["7"]?.role).toBe("button");
    expect(res.refs["7"]?.name).toBe("Save");
  });
});
