From 7892ccb1e21751e8f001220e51f99a7dcbffdbd2 Mon Sep 17 00:00:00 2001
From: Pavlenex <36959754+pavlenex@users.noreply.github.com>
Date: Thu, 6 Aug 2026 11:33:59 +0500
Subject: [PATCH] fix(desktop): add onboarding key copy action
Co-authored-by: Pavlenex <36959754+pavlenex@users.noreply.github.com>
Signed-off-by: Pavlenex <36959754+pavlenex@users.noreply.github.com>
---
.../src/features/onboarding/ui/BackupStep.tsx | 23 +++++++++++++++++++
desktop/tests/e2e/onboarding-backup.spec.ts | 21 ++++++++++++-----
2 files changed, 38 insertions(+), 6 deletions(-)
diff --git a/desktop/src/features/onboarding/ui/BackupStep.tsx b/desktop/src/features/onboarding/ui/BackupStep.tsx
index 99d9c6324d..94947219c6 100644
--- a/desktop/src/features/onboarding/ui/BackupStep.tsx
+++ b/desktop/src/features/onboarding/ui/BackupStep.tsx
@@ -385,6 +385,29 @@ export function BackupStep({
)}
+
diff --git a/desktop/tests/e2e/onboarding-backup.spec.ts b/desktop/tests/e2e/onboarding-backup.spec.ts
index df3528c8bd..f21f7b51f6 100644
--- a/desktop/tests/e2e/onboarding-backup.spec.ts
+++ b/desktop/tests/e2e/onboarding-backup.spec.ts
@@ -69,13 +69,11 @@ test("backup step appears on fresh-key path after profile submit", async ({
});
// ---------------------------------------------------------------------------
-// Key-created view: masked key with reveal toggle. Backup options open the
-// dark security view; the raw key is fetched only on explicit reveal/copy.
+// Key-created view: masked key with reveal and copy controls. Backup options
+// open the dark security view; the raw key is fetched only on explicit action.
// ---------------------------------------------------------------------------
-test("key view reveals explicitly; options copy explicitly", async ({
- page,
-}) => {
+test("key view reveals and copies explicitly", async ({ page }) => {
await page.context().grantPermissions(["clipboard-read", "clipboard-write"]);
await enterMachineBackup(page);
@@ -88,6 +86,17 @@ test("key view reveals explicitly; options copy explicitly", async ({
await expect(key).not.toContainText("nsec1");
expect(await invokedCommands(page)).not.toContain("get_nsec");
+ // Copy is available directly on the key card and provides confirmation.
+ const copyButton = page.getByTestId("backup-key-copy");
+ await expect(copyButton).toHaveAccessibleName("Copy private key");
+ await expect(copyButton).toHaveText("");
+ await copyButton.click();
+ await expect(copyButton).toHaveAccessibleName("Private key copied");
+ await expect
+ .poll(async () => invokedCommands(page))
+ .toContain("copy_text_to_clipboard");
+ expect(await invokedCommands(page)).toContain("get_nsec");
+
// Reveal fetches the key; box must not reflow (same-length monospace mask).
await page.getByTestId("backup-key-reveal-toggle").click();
await expect(key).toContainText("nsec1mock");
@@ -100,7 +109,7 @@ test("key view reveals explicitly; options copy explicitly", async ({
await page.getByTestId("backup-key-reveal-toggle").click();
await expect(key).not.toContainText("nsec1");
- // Copy is available only after opening the dark backup-options view.
+ // The deeper backup-options view retains its existing copy action.
await page.getByTestId("backup-options-link").click();
await expect(
page.getByTestId("onboarding-page-backup-options"),