diff options
| author | Adam Soltys <[email protected]> | 2026-10-07 13:25:49 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-07 13:25:49 -0700 |
| commit | 39ce1ef4c04bf010c75b3431be69174d6ef2c80a (patch) | |
| tree | 36c97d8912e3c47633edc77e5f45cb39dfb2a264 /tools | |
| parent | e3bc27dc7540fea6f8eaf5094627e28a089cf6b7 (diff) | |
| download | coinosv3-39ce1ef4c04bf010c75b3431be69174d6ef2c80a.tar.gz coinosv3-39ce1ef4c04bf010c75b3431be69174d6ef2c80a.zip | |
Setup wizard: a cover behind the avatar — twelve nature covers (self-hosted, Unsplash) cycled with arrows or a swipe, or upload your own; untouched, each pubkey gets its own default, published as the kind-0 banner beside the punk
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/onboard-cover-test.js | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/tools/onboard-cover-test.js b/tools/onboard-cover-test.js new file mode 100644 index 0000000..4262bc1 --- /dev/null +++ b/tools/onboard-cover-test.js @@ -0,0 +1,64 @@ +// The wizard's "Choose your look" step: a cover sits behind the avatar, +// defaulting to this pubkey's own, and its arrows (or a swipe) cycle the +// twelve nature covers with a counter; the preview copies are what load. +// Run: bun run build && bun tools/onboard-cover-test.js [screenshot.png] +import assert from 'node:assert/strict'; +import puppeteer from './puppeteer.js'; +const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); +const server = Bun.serve({ port: 0, async fetch(req) { + const p = new URL(req.url).pathname; + const f = Bun.file('dist' + (p === '/' ? '/index.html' : p)); + return (await f.exists()) ? new Response(f) : new Response(Bun.file('dist/index.html'), { headers: { 'content-type': 'text/html' } }); +} }); +const browser = await puppeteer.launch({ executablePath: '/usr/bin/google-chrome', headless: true, args: ['--no-sandbox'] }); +try { + const page = await browser.newPage(); + const errors = []; + page.on('pageerror', (e) => errors.push(String(e))); + await page.setViewport({ width: 390, height: 844, deviceScaleFactor: 2 }); + await page.goto(server.url.href); + await page.evaluate(() => localStorage.setItem('btc-wallet-network', 'regtest')); + await page.reload(); await sleep(1200); + const click = (x) => page.evaluate((x) => { const e = [...document.querySelectorAll('button')].find((n) => n.textContent.trim().toLowerCase().includes(x)); e?.click(); return !!e; }, x); + await click('create a new wallet'); await sleep(1500); + await click('skip verification'); await sleep(1500); + await page.evaluate(() => localStorage.setItem('btc-wallet-onb-step', 'avatar')); + await page.reload(); + await page.waitForSelector('.onb-cover', { timeout: 10000 }); + const state = () => page.evaluate(() => { + const c = document.querySelector('.onb-cover'); + return { count: document.querySelector('.onb-cover-count').textContent, bg: c.style.backgroundImage }; + }); + const first = await state(); + assert.match(first.count, /^\d+ \/ 12$/, 'a default cover is chosen: ' + first.count); + assert.match(first.bg, /covers-sm\/\d+\.webp/); + const n = Number(first.count.split(' ')[0]); + await page.click('.onb-cover-nav.next'); await sleep(100); + assert.equal((await state()).count, `${n % 12 + 1} / 12`, 'next moves on, wrapping at twelve'); + await page.click('.onb-cover-nav.prev'); await page.click('.onb-cover-nav.prev'); await sleep(100); + assert.equal((await state()).count, `${((n - 2 + 12) % 12) + 1} / 12`, 'previous goes back, wrapping'); + // a swipe left is "next" + const box = await (await page.$('.onb-cover')).boundingBox(); + const before = Number((await state()).count.split(' ')[0]); + // across the cover's open upper part (the avatar covers the lower middle) + const y = box.y + box.height * 0.3; + await page.mouse.move(box.x + box.width * 0.6, y); + await page.mouse.down(); await page.mouse.move(box.x + box.width * 0.3, y, { steps: 5 }); await page.mouse.up(); + await sleep(100); + assert.equal((await state()).count, `${before % 12 + 1} / 12`, 'a swipe left shows the next cover'); + // the cover image itself really loads, and the avatar sits over its bottom edge + const loaded = await page.evaluate(async () => { + const url = document.querySelector('.onb-cover').style.backgroundImage.match(/url\("?(.*?)"?\)/)[1]; + const im = new Image(); im.src = url; await im.decode(); return im.naturalWidth; + }); + assert.equal(loaded, 750); + const overlap = await page.evaluate(() => { + const c = document.querySelector('.onb-cover').getBoundingClientRect(), a = document.querySelector('.onb-avatar').getBoundingClientRect(); + return a.top < c.bottom && a.bottom > c.bottom; + }); + assert(overlap, 'the avatar overlaps the cover\'s bottom edge'); + if (process.argv[2]) await page.screenshot({ path: process.argv[2] }); + assert.deepEqual(errors, []); + console.log('✓ the look step: default cover, arrows and swipe cycle twelve covers, avatar over the cover'); +} finally { await browser.close(); server.stop(true); } +process.exit(0); |
