123456import { 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 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