AdoptionConsentModal.test.tsx

2.9 KB · raw

1// @vitest-environment jsdom2// DRAFT DESTINATION: src/popup/components/AdoptionConsentModal.test.tsx3// T-A16..T-A20: source consent UI cannot grant without re-auth.45import { describe, expect, it, vi } from "vitest";6import { AdoptionConsentModal } from "./AdoptionConsentModal";7import { inputText, renderView } from "../views/view-test-utils";89function button(container: HTMLElement, text: string): HTMLButtonElement {10  const found = Array.from(container.querySelectorAll("button")).find((b) =>11    (b.textContent ?? "").includes(text),12  );13  if (!found) throw new Error(`button not found: ${text}`);14  return found as HTMLButtonElement;15}1617function mount(overrides: Partial<Parameters<typeof AdoptionConsentModal>[0]> = {}) {18  const props = {19    receiverDeviceName: "June's iPhone",20    sas: "895245",21    verifyMasterPassword: vi.fn(async () => true),22    onCancel: vi.fn(),23    onApprove: vi.fn(async () => {}),24    ...overrides,25  };26  const rendered = renderView(<AdoptionConsentModal {...props} />);27  return { ...rendered, props };28}2930describe("AdoptionConsentModal", () => {31  it("T-A16: renders receiver device name and consequence copy", () => {32    const { container } = mount();33    expect(container.textContent).toContain('"June\'s iPhone" wants to join this vault.');34    expect(container.textContent).toContain("copies your entire vault including all passwords and Pro");35    expect(container.textContent).toContain("8 9 5 2 4 5");36  });3738  it("T-A17: Share vault button is disabled until a password is entered", () => {39    const { container } = mount();40    const share = button(container, "Share vault")!;41    expect(share.disabled).toBe(true);42    inputText(container.querySelector("#adoption-consent-password") as HTMLInputElement, "pw");43    expect(share.disabled).toBe(false);44  });4546  it("T-A18: wrong password shows inline error and does not approve", async () => {47    const { container, props } = mount({ verifyMasterPassword: vi.fn(async () => false) });48    inputText(container.querySelector("#adoption-consent-password") as HTMLInputElement, "wrong");49    button(container, "Share vault").click();50    await Promise.resolve();5152    expect(container.textContent).toContain("Incorrect password");53    expect(props.onApprove).not.toHaveBeenCalled();54  });5556  it("T-A19: correct password calls onApprove", async () => {57    const { container, props } = mount({ verifyMasterPassword: vi.fn(async () => true) });58    inputText(container.querySelector("#adoption-consent-password") as HTMLInputElement, "correct");59    button(container, "Share vault").click();60    await Promise.resolve();6162    expect(props.verifyMasterPassword).toHaveBeenCalledWith("correct");63    expect(props.onApprove).toHaveBeenCalledTimes(1);64  });6566  it("T-A20: cancel closes without approval", () => {67    const { container, props } = mount();68    button(container, "Cancel").click();69    expect(props.onCancel).toHaveBeenCalledTimes(1);70    expect(props.onApprove).not.toHaveBeenCalled();71  });72});73