onboarding-adopt-path.test.tsx

4.7 KB · raw

1// @vitest-environment jsdom2// DRAFT DESTINATION: src/popup/views/AdoptVaultView.test.tsx plus onboarding3// contract additions in src/popup/views/contracts.test.tsx.4// T-A21..T-A25.56import { describe, expect, it, vi } from "vitest";7import { AdoptVaultView } from "./AdoptVaultView";8import { inputText, renderView } from "./view-test-utils";910function button(container: HTMLElement, text: string): HTMLButtonElement {11  const found = Array.from(container.querySelectorAll("button")).find((b) =>12    (b.textContent ?? "").includes(text),13  );14  if (!found) throw new Error(`button not found: ${text}`);15  return found as HTMLButtonElement;16}1718describe("vault adoption onboarding", () => {19  it("T-A21: Onboarding offers Create vault, Restore from backup, and I already have Peach", () => {20    // Integrate into contracts.test.tsx where Onboarding + LockView are mounted together.21    document.body.innerHTML = `22      <button>Create vault</button>23      <button>Restore from backup</button>24      <button>I already have Peach -></button>25    `;26    expect(document.body.textContent).toContain("Create vault");27    expect(document.body.textContent).toContain("Restore from backup");28    expect(document.body.textContent).toContain("I already have Peach");29  });3031  it("T-A22: password screen uses the same minimum-length gate as create-vault", () => {32    const view = renderView(<AdoptVaultView onCancel={() => {}} onDone={() => {}} startAdoption={vi.fn()} />);33    const continueButton = button(view.container, "Continue");34    expect(continueButton.disabled).toBe(true);35    inputText(view.container.querySelector("#adopt-password") as HTMLInputElement, "short");36    inputText(view.container.querySelector("#adopt-confirm-password") as HTMLInputElement, "short");37    expect(view.container.textContent).toContain("need 7 more characters");38    expect(continueButton.disabled).toBe(true);39  });4041  it("T-A23: adoption flow reaches the SAS screen", async () => {42    const startAdoption = vi.fn(async ({ confirmSAS }: { confirmSAS(sas: string): Promise<boolean> }) => {43      await confirmSAS("895245");44    });45    const view = renderView(<AdoptVaultView onCancel={() => {}} onDone={() => {}} startAdoption={startAdoption} />);46    inputText(view.container.querySelector("#adopt-password") as HTMLInputElement, "receiver-passphrase-123");47    inputText(view.container.querySelector("#adopt-confirm-password") as HTMLInputElement, "receiver-passphrase-123");48    button(view.container, "Continue").click();49    button(view.container, "Pair a device").click();50    await Promise.resolve();5152    expect(view.container.textContent).toContain("Confirm this code matches");53    expect(view.container.textContent).toContain("8 9 5 2 4 5");54  });5556  it("T-A24: success leaves a vault and opens Peach", async () => {57    const onDone = vi.fn();58    const view = renderView(59      <AdoptVaultView60        onCancel={() => {}}61        onDone={onDone}62        startAdoption={vi.fn(async () => {})}63      />,64    );65    inputText(view.container.querySelector("#adopt-password") as HTMLInputElement, "receiver-passphrase-123");66    inputText(view.container.querySelector("#adopt-confirm-password") as HTMLInputElement, "receiver-passphrase-123");67    button(view.container, "Continue").click();68    button(view.container, "Pair a device").click();69    await Promise.resolve();7071    expect(view.container.textContent).toContain("Joined your vault.");72    button(view.container, "Open Peach").click();73    expect(onDone).toHaveBeenCalledTimes(1);74  });7576  it("T-A25: SAS cancel keeps receiver vault-less and returns to the password step", async () => {77    let resolveSas: ((ok: boolean) => void) | null = null;78    const createVault = vi.fn();79    const view = renderView(80      <AdoptVaultView81        onCancel={() => {}}82        onDone={() => {}}83        startAdoption={vi.fn(async ({ confirmSAS }) => {84          await new Promise<void>((resolve) => {85            void confirmSAS("895245").then((ok) => {86              if (ok) createVault();87              resolve();88            });89            resolveSas = (ok) => { void ok; resolve(); };90          });91        })}92      />,93    );94    inputText(view.container.querySelector("#adopt-password") as HTMLInputElement, "receiver-passphrase-123");95    inputText(view.container.querySelector("#adopt-confirm-password") as HTMLInputElement, "receiver-passphrase-123");96    button(view.container, "Continue").click();97    button(view.container, "Pair a device").click();98    await Promise.resolve();99    button(view.container, "Cancel").click();100    resolveSas?.(false);101    await Promise.resolve();102103    expect(createVault).not.toHaveBeenCalled();104    expect(view.container.textContent).toContain("Set a password for this device.");105  });106});107