From 1e558b52a74b1facc04ab3c80b72e2f93050d63b Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Tue, 4 Aug 2026 07:29:55 -0700 Subject: [PATCH] Document test click helper function, and fix and rename its args. --- test/GLOBALS.mjs | 79 +++++++++++++++++++----------------- test/test.blocks.mjs | 34 ++++++++-------- test/test.ledger.mjs | 6 ++- test/test.manage-rolodex.mjs | 10 ++--- test/test.tools.mjs | 5 +-- test/test.wallet-sign.mjs | 15 +++---- 6 files changed, 74 insertions(+), 75 deletions(-) diff --git a/test/GLOBALS.mjs b/test/GLOBALS.mjs index 5a17bab..b6159e2 100644 --- a/test/GLOBALS.mjs +++ b/test/GLOBALS.mjs @@ -74,50 +74,53 @@ function pass (name) { } /** + * Adds a button to the DOM at the bottom of the body and scrolls it into view. + * Clicking it fires the passed onclick listener. An optional post-click delay + * can be configured in order to reset relevant timers e.g. user activation. * - * @param {string} text - * @param {AsyncFunction} fn - * @param {object} [opt] - * @param {number} [opt.timeout] + * @param {string} label - button label + * @param {AsyncFunction} onclick - onclick handler + * @param {object} [opt] - configure click + * @param {number} [opt.delay] - seconds to wait after clicking before returning * @returns {Promise} */ -export async function click (text, fn, opt) { - async function wait (timeout) { - if (typeof timeout === 'number' && timeout > 0) { - if (timeout > 300) { - throw new RangeError('Click test should not wait more than 5 minutes', { cause: timeout }) +export async function click (label, onclick, opt) { + async function wait (delay) { + if (typeof delay === 'number' && delay > 0) { + if (delay > 300) { + throw new RangeError('Post-click delay 5 minutes or less', { cause: delay }) } - console.log(`Click done, waiting ${timeout} seconds to reset transient user activation timer...`) - return await new Promise(r => setTimeout(r, timeout * 1000)) + console.log(`Click done, waiting ${delay} seconds to reset transient user activation timer...`) + return new Promise(r => setTimeout(r, delay * 1000)) } - if (isNode) { - await wait(opt?.timeout) - return await fn() - } - const { timeout } = opt - return new Promise((resolve, reject) => { - const button = document.createElement('button') - const hourglass = document.createTextNode('⏳') - button.innerText = text - button.onclick = async () => { - button.disabled = true - button.innerText = 'Waiting for device...' - button.after(hourglass) - try { - const result = await fn() - resolve(result) - } catch (err) { - reject(err) - } finally { - hourglass.remove() - button.remove() - await wait(opt?.timeout) - } - } - document.body.appendChild(button) - window?.scrollTo(0, document.body.scrollHeight) - }) } + const { delay } = opt + if (isNode) { + await wait(delay) + return await onclick() + } + return new Promise((resolve, reject) => { + const button = document.createElement('button') + const hourglass = document.createTextNode('⏳') + button.innerText = label + button.onclick = async () => { + button.disabled = true + button.innerText = 'Waiting for device...' + button.after(hourglass) + try { + const result = await onclick() + resolve(result) + } catch (err) { + reject(err) + } finally { + hourglass.remove() + button.remove() + await wait(delay) + } + } + document.body.appendChild(button) + window?.scrollTo(0, document.body.scrollHeight) + }) } export function stats (times) { diff --git a/test/test.blocks.mjs b/test/test.blocks.mjs index 7313996..0278cea 100644 --- a/test/test.blocks.mjs +++ b/test/test.blocks.mjs @@ -17,7 +17,7 @@ await Promise.all([ await assert.resolves(click( 'Sign and autogen PoW when processing', async () => block.sign(OPEN_BLOCK.key), - { timeout: 6 } + { delay: 6 } )) assert.nullish(block.work) @@ -113,7 +113,7 @@ await Promise.all([ await assert.resolves(click( 'Sign with BLAKE2b', async () => wallet.sign(1, block), - { timeout: 6 } + { delay: 6 } )) assert.ok(await block.verify(BLAKE2B_PUBLIC_1)) @@ -129,7 +129,7 @@ await Promise.all([ await assert.resolves(click( 'Sign with BIP-44', async () => wallet.sign(0, block), - { timeout: 6 } + { delay: 6 } )) assert.ok(await block.verify(PUBLIC_0)) @@ -145,7 +145,7 @@ await Promise.all([ await assert.resolves(click( 'Sign with Exodus', async () => wallet.sign(0, block), - { timeout: 6 } + { delay: 6 } )) assert.ok(await block.verify(EXODUS.PUBLIC_0)) @@ -172,7 +172,7 @@ await Promise.all([ await assert.rejects(click( 'Fail to sign while locked', async () => wallet.sign(0, block), - { timeout: 6 } + { delay: 6 } )) assert.ok(block.signature === undefined) @@ -187,7 +187,7 @@ await Promise.all([ await assert.resolves(click( 'Sign open block with key', async () => block.sign(OPEN_BLOCK.key), - { timeout: 6 } + { delay: 6 } )) assert.equal(block.hash, OPEN_BLOCK.hash) assert.equal(block.signature, OPEN_BLOCK.signature) @@ -201,7 +201,7 @@ await Promise.all([ await assert.resolves(click( 'Sign receive block with key', async () => block.sign(RECEIVE_BLOCK.key), - { timeout: 6 } + { delay: 6 } )) assert.equal(block.hash, RECEIVE_BLOCK.hash) @@ -215,7 +215,7 @@ await Promise.all([ await assert.resolves(click( 'Sign receive block without work', async () => block.sign(RECEIVE_BLOCK.key), - { timeout: 6 } + { delay: 6 } )) assert.equal(block.hash, RECEIVE_BLOCK.hash) @@ -236,7 +236,7 @@ await Promise.all([ await assert.resolves(click( 'Sign Ledger-derived block using BIP-44 wallet', async () => wallet.sign(0, block), - { timeout: 6 } + { delay: 6 } )) assert.equal(block.signature, LEDGER_NANOS.OPEN_BLOCK.signature) @@ -253,7 +253,7 @@ await Promise.all([ await assert.resolves(click( 'Sign send block with key', async () => block.sign(SEND_BLOCK.key), - { timeout: 6 } + { delay: 6 } )) assert.equal(block.hash, SEND_BLOCK.hash) @@ -267,7 +267,7 @@ await Promise.all([ await assert.resolves(click( 'Sign send block without work', async () => block.sign(SEND_BLOCK.key), - { timeout: 6 } + { delay: 6 } )) assert.equal(block.hash, SEND_BLOCK.hash) @@ -285,7 +285,7 @@ await Promise.all([ await assert.resolves(click( 'Sign change block with key', async () => block.sign('781186FB9EF17DB6E3D1056550D9FAE5D5BBADA6A6BC370E4CBB938B1DC71DA3'), // Did not find a private key at nano docs for this address - { timeout: 6 } + { delay: 6 } )) assert.equal(block.signature?.toUpperCase(), 'A3C3C66D6519CBC0A198E56855942DEACC6EF741021A1B11279269ADC587DE1DA53CD478B8A47553231104CF24D742E1BB852B0546B87038C19BAE20F9082B0D') @@ -299,7 +299,7 @@ await Promise.all([ await assert.resolves(click( 'Sign change block without work', async () => block.sign(PRIVATE_0), - { timeout: 6 } + { delay: 6 } )) assert.equal(block.signature?.toUpperCase(), '2BD2F905E74B5BEE3E2277CED1D1E3F7535E5286B6E22F7B08A814AA9E5C4E1FEA69B61D60B435ADC2CE756E6EE5F5BE7EC691FE87E024A0B22A3D980CA5B305') @@ -315,7 +315,7 @@ await Promise.all([ 'fail to sign without args', //@ts-expect-error async () => block.sign(), - { timeout: 6 } + { delay: 6 } )) assert.nullish(block.signature) @@ -323,21 +323,21 @@ await Promise.all([ 'fail to sign with null arg', //@ts-expect-error async () => block.sign(null), - { timeout: 6 } + { delay: 6 } )) assert.nullish(block.signature) await assert.rejects(click( 'fail to sign with invalid string length', async () => block.sign('1'), - { timeout: 6 } + { delay: 6 } )) assert.nullish(block.signature) await assert.rejects(click( 'fail to sign with invalid string characters', async () => block.sign('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'), - { timeout: 6 } + { delay: 6 } )) assert.nullish(block.signature) }) diff --git a/test/test.ledger.mjs b/test/test.ledger.mjs index 1004cb4..f815b20 100644 --- a/test/test.ledger.mjs +++ b/test/test.ledger.mjs @@ -54,7 +54,8 @@ await Promise.all([ await click( 'Reset permissions, then click to continue', - async () => new Promise(r => setTimeout(r, 5000)) + async () => { }, + { delay: 6 } ) await assert.rejects(wallet.unlock()) assert.equal(wallet.isLocked, true) @@ -384,7 +385,8 @@ await Promise.all([ await click( 'Click to finish Ledger tests by destroying wallet', - async () => new Promise(r => setTimeout(r)) + async () => { }, + { delay: 0 } ) await assert.resolves(wallet.destroy()) await assert.rejects(wallet.unlock()) diff --git a/test/test.manage-rolodex.mjs b/test/test.manage-rolodex.mjs index 5e0de97..5a78f31 100644 --- a/test/test.manage-rolodex.mjs +++ b/test/test.manage-rolodex.mjs @@ -191,10 +191,9 @@ await Promise.all([ 'Sign and then verify Rolodex data/signature', async () => { signature = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0 + NANO_TEST_VECTORS.PUBLIC_0, data) - } + }, + { delay: 6 } )) - console.log('Click done, waiting 6 seconds to reset transient user activation timer...') - await new Promise(r => setTimeout(r, 6000)) await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)) const result = await Rolodex.verify('JohnDoe', signature, data) @@ -210,10 +209,9 @@ await Promise.all([ 'Sign and then reject invalid Rolodex data/signature', async () => { signature = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0 + NANO_TEST_VECTORS.PUBLIC_0, data) - } + }, + { delay: 6 } )) - console.log('Click done, waiting 6 seconds to reset transient user activation timer...') - await new Promise(r => setTimeout(r, 6000)) await assert.resolves(Rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1)) const result = await Rolodex.verify('JaneSmith', signature, data) diff --git a/test/test.tools.mjs b/test/test.tools.mjs index a9ffbc3..8ce86c5 100644 --- a/test/test.tools.mjs +++ b/test/test.tools.mjs @@ -108,10 +108,9 @@ await Promise.all([ 'Sign single string', async () => { result = Tools.sign(NANO_TEST_VECTORS.PRIVATE_0 + NANO_TEST_VECTORS.PUBLIC_0, m) - } + }, + { delay: 6 } )) - console.log('Click done, waiting 6 seconds to reset transient user activation timer...') - await new Promise(r => setTimeout(r, 6000)) assert.equal(result.toLowerCase(), '0ceebbc0b9b3a270a30bad1eef4eddc0931effd8d5c0b7cab007fcc61f30d3ee9760cd93d7eeb5b654ecc0d9d17bc7a6d53bee54aa163a8272f425fb1184e30e') }) diff --git a/test/test.wallet-sign.mjs b/test/test.wallet-sign.mjs index a579c7b..71c67e2 100644 --- a/test/test.wallet-sign.mjs +++ b/test/test.wallet-sign.mjs @@ -22,10 +22,9 @@ await Promise.all([ 'Sign arbitrary string', async () => { signature = await wallet.sign(0, data) - } + }, + { delay: 6 } )) - console.log('Click done, waiting 6 seconds to reset transient user activation timer...') - await new Promise(r => setTimeout(r, 6000)) assert.ok(await Tools.verify(account.publicKey, signature, data)) await assert.resolves(wallet.destroy()) }) @@ -39,10 +38,9 @@ await Promise.all([ await assert.resolves(click( 'Sign to test subsequent verification success', - async () => sendBlock.sign(wallet, 0) + async () => sendBlock.sign(wallet, 0), + { delay: 6 } )) - console.log('Click done, waiting 6 seconds to reset transient user activation timer...') - await new Promise(r => setTimeout(r, 6000)) assert.ok(await sendBlock.verify(account.publicKey)) await assert.resolves(wallet.destroy()) @@ -57,10 +55,9 @@ await Promise.all([ await assert.resolves(click( 'Sign to test subsequent verification failure', - async () => sendBlock.sign(wallet, 0) + async () => sendBlock.sign(wallet, 0), + { delay: 6 } )) - console.log('Click done, waiting 6 seconds to reset transient user activation timer...') - await new Promise(r => setTimeout(r, 6000)) assert.ok(await sendBlock.verify(account.publicKey)) -- 2.52.0