// @vitest-environment jsdom
// DRAFT DESTINATION: src/popup/views/AdoptVaultView.test.tsx plus onboarding
// contract additions in src/popup/views/contracts.test.tsx.
// T-A21..T-A25.
import { describe, expect, it, vi } from "vitest";
import { AdoptVaultView } from "./AdoptVaultView";
import { inputText, renderView } from "./view-test-utils";
function button(container: HTMLElement, text: string): HTMLButtonElement {
const found = Array.from(container.querySelectorAll("button")).find((b) =>
(b.textContent ?? "").includes(text),
);
if (!found) throw new Error(`button not found: ${text}`);
return found as HTMLButtonElement;
}
describe("vault adoption onboarding", () => {
it("T-A21: Onboarding offers Create vault, Restore from backup, and I already have Peach", () => {
// Integrate into contracts.test.tsx where Onboarding + LockView are mounted together.
document.body.innerHTML = `
`;
expect(document.body.textContent).toContain("Create vault");
expect(document.body.textContent).toContain("Restore from backup");
expect(document.body.textContent).toContain("I already have Peach");
});
it("T-A22: password screen uses the same minimum-length gate as create-vault", () => {
const view = renderView( {}} onDone={() => {}} startAdoption={vi.fn()} />);
const continueButton = button(view.container, "Continue");
expect(continueButton.disabled).toBe(true);
inputText(view.container.querySelector("#adopt-password") as HTMLInputElement, "short");
inputText(view.container.querySelector("#adopt-confirm-password") as HTMLInputElement, "short");
expect(view.container.textContent).toContain("need 7 more characters");
expect(continueButton.disabled).toBe(true);
});
it("T-A23: adoption flow reaches the SAS screen", async () => {
const startAdoption = vi.fn(async ({ confirmSAS }: { confirmSAS(sas: string): Promise }) => {
await confirmSAS("895245");
});
const view = renderView( {}} onDone={() => {}} startAdoption={startAdoption} />);
inputText(view.container.querySelector("#adopt-password") as HTMLInputElement, "receiver-passphrase-123");
inputText(view.container.querySelector("#adopt-confirm-password") as HTMLInputElement, "receiver-passphrase-123");
button(view.container, "Continue").click();
button(view.container, "Pair a device").click();
await Promise.resolve();
expect(view.container.textContent).toContain("Confirm this code matches");
expect(view.container.textContent).toContain("8 9 5 2 4 5");
});
it("T-A24: success leaves a vault and opens Peach", async () => {
const onDone = vi.fn();
const view = renderView(
{}}
onDone={onDone}
startAdoption={vi.fn(async () => {})}
/>,
);
inputText(view.container.querySelector("#adopt-password") as HTMLInputElement, "receiver-passphrase-123");
inputText(view.container.querySelector("#adopt-confirm-password") as HTMLInputElement, "receiver-passphrase-123");
button(view.container, "Continue").click();
button(view.container, "Pair a device").click();
await Promise.resolve();
expect(view.container.textContent).toContain("Joined your vault.");
button(view.container, "Open Peach").click();
expect(onDone).toHaveBeenCalledTimes(1);
});
it("T-A25: SAS cancel keeps receiver vault-less and returns to the password step", async () => {
let resolveSas: ((ok: boolean) => void) | null = null;
const createVault = vi.fn();
const view = renderView(
{}}
onDone={() => {}}
startAdoption={vi.fn(async ({ confirmSAS }) => {
await new Promise((resolve) => {
void confirmSAS("895245").then((ok) => {
if (ok) createVault();
resolve();
});
resolveSas = (ok) => { void ok; resolve(); };
});
})}
/>,
);
inputText(view.container.querySelector("#adopt-password") as HTMLInputElement, "receiver-passphrase-123");
inputText(view.container.querySelector("#adopt-confirm-password") as HTMLInputElement, "receiver-passphrase-123");
button(view.container, "Continue").click();
button(view.container, "Pair a device").click();
await Promise.resolve();
button(view.container, "Cancel").click();
resolveSas?.(false);
await Promise.resolve();
expect(createVault).not.toHaveBeenCalled();
expect(view.container.textContent).toContain("Set a password for this device.");
});
});