mirror of
https://github.com/block/buzz.git
synced 2026-11-13 21:01:53 +00:00
## Summary - backing out of the backup step and clicking the CTA again reuses the existing key - the button still said "Create a new identity key", which is misleading for a security-sensitive action - when a key is already loaded, label it "Continue with existing identity key" Closes #2318 ## Test plan - [ ] first-run: button still says "Create a new identity key" - [ ] create key → backup → back: button says "Continue with existing identity key" and shows the same key Made with [Cursor](https://cursor.com) --------- Signed-off-by: Taksh <takshkothari09@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
144 lines
5.0 KiB
TypeScript
144 lines
5.0 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
import { installMockBridge } from "../helpers/bridge";
|
|
import { waitForAnimations } from "../helpers/animations";
|
|
|
|
async function enterMachineBackup(page: import("@playwright/test").Page) {
|
|
await installMockBridge(page, undefined, {
|
|
skipCommunitySeed: true,
|
|
skipOnboardingSeed: true,
|
|
});
|
|
await page.goto("/");
|
|
await page.getByRole("button", { name: "Create a new identity key" }).click();
|
|
}
|
|
|
|
const SHOTS = "test-results/screenshots-onboarding";
|
|
|
|
test("backup step appears on fresh-key path after profile submit", async ({
|
|
page,
|
|
}) => {
|
|
await enterMachineBackup(page);
|
|
|
|
await expect(page.getByTestId("onboarding-page-backup")).toBeVisible();
|
|
await expect(
|
|
page.getByRole("heading", {
|
|
name: "Your unique identity key has been created",
|
|
}),
|
|
).toBeVisible();
|
|
});
|
|
|
|
test("backup step shows masked nsec from mock bridge", async ({ page }) => {
|
|
await enterMachineBackup(page);
|
|
|
|
await expect(page.getByTestId("onboarding-page-backup")).toBeVisible();
|
|
const nsecDisplay = page.getByTestId("nsec-value");
|
|
await expect(nsecDisplay).toBeVisible();
|
|
|
|
// Should start masked (blurred) — reveal button exists and eye icon visible.
|
|
const revealBtn = page.getByTestId("nsec-reveal-toggle");
|
|
await expect(revealBtn).toBeVisible();
|
|
await expect(nsecDisplay).toHaveCSS("filter", /blur/);
|
|
|
|
// Take a screenshot of the masked state. Capture the whole viewport: the CTAs
|
|
// are portaled into the docked footer outside the step subtree.
|
|
await waitForAnimations(page);
|
|
await page.screenshot({
|
|
path: `${SHOTS}/02-backup-step-masked.png`,
|
|
});
|
|
|
|
// Reveal and verify the mock nsec appears.
|
|
await revealBtn.click();
|
|
await expect(nsecDisplay).not.toHaveCSS("filter", /blur/);
|
|
await expect(nsecDisplay).toContainText("nsec1mock");
|
|
|
|
// Take a screenshot of the revealed state.
|
|
await waitForAnimations(page);
|
|
await page.screenshot({
|
|
path: `${SHOTS}/03-backup-step-revealed.png`,
|
|
});
|
|
});
|
|
|
|
test("backup step Next is enabled once the key is shown", async ({ page }) => {
|
|
await enterMachineBackup(page);
|
|
|
|
await expect(page.getByTestId("onboarding-page-backup")).toBeVisible();
|
|
await expect(page.getByTestId("nsec-value")).toBeVisible();
|
|
await expect(page.getByTestId("onboarding-next")).toBeEnabled();
|
|
});
|
|
|
|
test("backup step advances to machine setup on Next click", async ({
|
|
page,
|
|
}) => {
|
|
await enterMachineBackup(page);
|
|
|
|
await expect(page.getByTestId("onboarding-page-backup")).toBeVisible();
|
|
await expect(page.getByTestId("nsec-value")).toBeVisible();
|
|
await page.getByTestId("onboarding-next").click();
|
|
|
|
await expect(page.getByTestId("onboarding-page-2")).toBeVisible();
|
|
});
|
|
|
|
test("backup step back button returns to machine identity choice", async ({
|
|
page,
|
|
}) => {
|
|
await enterMachineBackup(page);
|
|
|
|
await expect(page.getByTestId("onboarding-page-backup")).toBeVisible();
|
|
await page.getByTestId("onboarding-back").click();
|
|
|
|
// Backing out preserves the loaded key — primary CTA continues setup rather
|
|
// than minting another identity (#2318).
|
|
await expect(
|
|
page.getByRole("button", { name: "Continue setup" }),
|
|
).toBeVisible();
|
|
await expect(
|
|
page.getByRole("button", { name: "Use a different key instead" }),
|
|
).toBeVisible();
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// B4: Error path coverage
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("backup step shows error banner and retry button when get_nsec fails", async ({
|
|
page,
|
|
}) => {
|
|
await installMockBridge(
|
|
page,
|
|
{ nsecError: "Keychain locked" },
|
|
{ skipCommunitySeed: true, skipOnboardingSeed: true },
|
|
);
|
|
await page.goto("/");
|
|
await page.getByRole("button", { name: "Create a new identity key" }).click();
|
|
|
|
await expect(page.getByTestId("onboarding-page-backup")).toBeVisible();
|
|
await expect(page.getByTestId("backup-load-error")).toBeVisible();
|
|
await expect(page.getByTestId("backup-retry")).toBeVisible();
|
|
// Next is blocked on error; Skip for now ghost is shown instead.
|
|
await expect(page.getByTestId("onboarding-next")).toBeDisabled();
|
|
await expect(page.getByTestId("backup-skip")).toBeVisible();
|
|
|
|
// Skip for now still advances to machine setup.
|
|
await page.getByTestId("backup-skip").click();
|
|
await expect(page.getByTestId("onboarding-page-2")).toBeVisible();
|
|
});
|
|
|
|
test("backup step retry succeeds and shows key after initial failure", async ({
|
|
page,
|
|
}) => {
|
|
// First call fails, second succeeds (sequenced via nsecErrors).
|
|
await installMockBridge(
|
|
page,
|
|
{ nsecErrors: ["Keychain locked", null] },
|
|
{ skipCommunitySeed: true, skipOnboardingSeed: true },
|
|
);
|
|
await page.goto("/");
|
|
await page.getByRole("button", { name: "Create a new identity key" }).click();
|
|
|
|
await expect(page.getByTestId("backup-load-error")).toBeVisible();
|
|
|
|
// Retry — second call succeeds.
|
|
await page.getByTestId("backup-retry").click();
|
|
await expect(page.getByTestId("nsec-value")).toBeVisible();
|
|
await expect(page.getByTestId("backup-load-error")).not.toBeVisible();
|
|
});
|