aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-11-07 08:08:25 -0700
committerAdam Soltys <[email protected]>2026-11-07 08:08:25 -0700
commit1d689216a87311298f362bb6b3d29c0ce5246821 (patch)
tree07d876a00145979872988b7a73101b521fce31a5 /tools
parent88585916cec0343b4c4fc3b75d931ad460ad00cc (diff)
downloadcoinosv3-1d689216a87311298f362bb6b3d29c0ce5246821.tar.gz
coinosv3-1d689216a87311298f362bb6b3d29c0ce5246821.zip
A new seed phrase comes in three steps: a heads-up, the words, then one word to pick. "Reintroduce the seed phrase preamble telling users to write it down but don't give it a warning icon … an intermediary step before we display the seed phrase … instead of verify and skip buttons just have a next and another intermediate step that asks for just the 5th seed word and gives a few options to click and also a skip button" (Adam, 2026-11-07). Creating a wallet (front door, Accounts, signInAnother) now opens on a plain note, "Next you'll see your seed phrase: 12 words … Write them down on paper, in order … make sure no one is looking", with Show seed phrase; the words page has one Next; the check asks "Which one is word #5?" with four of the phrase's own words as buttons (a wrong one turns red and says "Not that one"), Skip, and Show the words again. The gift claim's new-wallet backup gets the same three steps in place of its warning box and typed three-word check, and a sign-in's "Write down your recovery phrase" shows its explanation first and the words behind Show seed phrase (Later still on both). createStep starts at 'intro'; pickConfirm returns { index, options, wrong }
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01VMan6Ts5Tktega8VbLg31q
Diffstat (limited to 'tools')
-rw-r--r--tools/gift-profile-setup-test.js37
-rw-r--r--tools/onboard-backup-test.js10
2 files changed, 26 insertions, 21 deletions
diff --git a/tools/gift-profile-setup-test.js b/tools/gift-profile-setup-test.js
index 9304d1a..04e58c5 100644
--- a/tools/gift-profile-setup-test.js
+++ b/tools/gift-profile-setup-test.js
@@ -53,7 +53,11 @@ try {
page.on('pageerror', (e) => errors.push(String(e)));
await page.setViewport({ width: 390, height: 844, deviceScaleFactor: 2 });
await toSeed(page, 'Happy birthday! 🎂 <b>not bold</b>');
- await click(page, 'skip verification');
+ check('a heads-up comes before the words', /no one is looking/i.test(await text(page)) && await page.evaluate(() => !document.querySelector('.words')));
+ await click(page, 'show seed phrase');
+ check('...then the words, with Next', await page.evaluate(() => document.querySelectorAll('.words .w').length === 12) && await click(page, 'next'));
+ check('...then one word to pick, or Skip', await waitText(page, /which one is word #5/i, 5000) && await page.evaluate(() => document.querySelectorAll('.quiz-opt').length === 4));
+ await click(page, 'skip');
check('the seed done: the wizard asks for a username', await waitText(page, /now pick a username/i, 10000), (await text(page)).slice(0, 200));
check('...with the claim form (or its wait) and Not now', await page.evaluate(() => !!document.querySelector('.onb')) && /not now/i.test(await text(page)));
if (process.argv[2]) await page.screenshot({ path: process.argv[2] });
@@ -66,30 +70,25 @@ try {
p2.on('pageerror', (e) => errors.push(String(e)));
await p2.setViewport({ width: 390, height: 844, deviceScaleFactor: 2 });
await toSeed(p2);
- check('Verify backup opens the word check', await click(p2, 'verify') && await waitText(p2, /word #?\d/i, 5000));
- await sleep(500);
- // the verify page doesn't show the words: read them from the account
- const filled = await p2.evaluate(() => {
- const accs = JSON.parse(sessionStorage.getItem('btc-wallet-accounts') || '{}');
- const list = Array.isArray(accs) ? accs : accs.accounts || accs.list || [];
- const m = list.map((a) => a.mnemonic).filter(Boolean).pop(); if (!m) return false;
- const w = m.split(' ');
- for (const lab of document.querySelectorAll('label.field')) {
- const n = Number(lab.querySelector('.lab').textContent.match(/\d+/)[0]);
- const inp = lab.querySelector('input');
- const set = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value').set;
- set.call(inp, w[n - 1]); inp.dispatchEvent(new Event('input', { bubbles: true }));
- }
- return true;
- });
+ await click(p2, 'show seed phrase');
+ const fifth = await p2.evaluate(() => document.querySelectorAll('.words .w .t')[4]?.textContent.trim());
+ check('Next opens the word check', await click(p2, 'next') && await waitText(p2, /which one is word #5/i, 5000));
+ // a wrong pick says so and stays
+ const wrongOk = await p2.evaluate((right) => {
+ const b = [...document.querySelectorAll('.quiz-opt')].find((x) => x.textContent.trim() !== right); b?.click(); return !!b;
+ }, fifth);
+ await sleep(300);
+ check('...a wrong word is marked, and the check stays', wrongOk && await p2.evaluate(() => !!document.querySelector('.quiz-opt.wrong')) && /not that one/i.test(await text(p2)));
+ const filled = await p2.evaluate((right) => {
+ const b = [...document.querySelectorAll('.quiz-opt')].find((x) => x.textContent.trim() === right); b?.click(); return !!b;
+ }, fifth);
if (filled) {
- await click(p2, 'open wallet');
check('a verified seed leads to the username step too', await waitText(p2, /now pick a username/i, 10000));
await click(p2, 'not now');
let gone = false;
for (let i = 0; i < 20 && !gone; i++) { await sleep(250); gone = !(await p2.evaluate(() => !!document.querySelector('.onb'))); }
check('Not now: into the wallet, the wizard gone', gone, (await text(p2)).slice(0, 200));
- } else console.log(' (accounts not in localStorage — verify path not driven)');
+ } else check('the right word is among the choices', false);
check('no page errors', errors.length === 0, errors.join(' | '));
} finally { await browser.close(); server.stop(true); }
console.log(ok ? '\n✅ a gift\'s new wallet is offered a name, a picture and a cover' : '\n❌ failed');
diff --git a/tools/onboard-backup-test.js b/tools/onboard-backup-test.js
index 3eefb02..8fc1071 100644
--- a/tools/onboard-backup-test.js
+++ b/tools/onboard-backup-test.js
@@ -87,8 +87,11 @@ try {
// words on screen at once, with what they are.
await page.evaluate(() => document.getElementById('onb-create')?.click());
await sleep(600);
- // the warning box that said "write these 12 words down" is gone
- // (2026-11-06): the words themselves are the explanation
+ // a heads-up first, no warning icon (2026-11-07): sensitive words next
+ const intro = await page.evaluate(() => ({ words: document.querySelectorAll('.words .w').length, text: document.body.innerText, warn: !!document.querySelector('.warn-box') }));
+ check('the words wait behind a heads-up to write them down', intro.words === 0 && /write them down/i.test(intro.text) && !intro.warn && !/⚠/.test(intro.text));
+ await page.evaluate(() => document.getElementById('seed-intro-next')?.click());
+ await sleep(400);
const made = await page.evaluate(() => document.querySelectorAll('.words .w .t').length);
check('the way in shows what the wallet actually is: its twelve words', made === 12, made + ' words');
await page.close();
@@ -135,6 +138,9 @@ try {
{
const { page, ctx, seed } = await signIn();
check('a sign-in is asked to write the phrase down', await waitText(page, 'write down your recovery phrase'));
+ check('...with the words behind Show seed phrase', await page.evaluate(() => !document.querySelector('.words')));
+ await click(page, 'show seed phrase');
+ await sleep(300);
const shown = await page.evaluate(() => [...document.querySelectorAll('.words .w .t')].map((e) => e.textContent.trim()));
check('...and the real twelve words are on screen', shown.length === 12 && shown.join(' ') === seed,
shown.length + ' words' + (shown.join(' ') === seed ? ', matching the derived seed' : ', WRONG'));