// The desktop app's update offer, without a browser: a newer version is told // of in words naming both versions, nothing else is; nothing installs until // asked, and only the update told of; a refusal (a signature that does not // verify, a download that fails) is reported, and a check that cannot reach // the manifest stays quiet. // // node test/update.test.mjs import { Updates, updateNotice } from '../src/update.js'; let fails = 0; const check = (ok, what) => { console.log(`${ok ? 'PASS' : 'FAIL'} ${what}`); if (!ok) fails += 1; }; // The app's commands, faked: `check` is what update_check answers, `install` what update_install does. function fake(answer, install = () => JSON.stringify({ error: 'the update was not installed: the signature does not verify' })) { const calls = []; const invoke = async (cmd, args) => { calls.push([cmd, args]); if (cmd === 'update_check') { if (answer instanceof Error) throw answer; return JSON.stringify(answer); } if (cmd === 'update_install') return install(); return JSON.stringify({ error: `no command ${cmd}` }); }; return { calls, invoke }; } const available = { state: 'available', version: '0.2.0', current: '0.1.0', notes: 'n' }; { const words = updateNotice(available); check(typeof words === 'string' && words.includes('0.2.0') && words.includes('0.1.0') && /signature/.test(words), `a newer version is told of, with both versions and the signature check (${words})`); for (const a of [{ state: 'current', version: '0.1.0' }, { state: 'off', reason: 'this build carries no update key' }, { error: 'offline' }, null, undefined]) { check(updateNotice(a) === null, `nothing is said for ${JSON.stringify(a)}`); } } { const f = fake(available); const u = new Updates(f.invoke); const v = await u.check(); check(v.state === 'available' && f.calls.length === 1 && f.calls[0][0] === 'update_check', 'a check asks the app once and installs nothing'); let err = ''; try { await u.install(); } catch (e) { err = e.message; } check(f.calls[1]?.[0] === 'update_install' && /signature does not verify/.test(err), `an install asked for runs the app's install, and its refusal is reported (${err})`); } { const f = fake({ state: 'off', reason: 'this copy was built from source' }); const u = new Updates(f.invoke); await u.check(); let err = ''; try { await u.install(); } catch (e) { err = e.message; } check(err === 'No update is waiting.' && !f.calls.some((c) => c[0] === 'update_install'), 'with no update told of, an install asks the app nothing'); } { const f = fake(available, () => JSON.stringify({ restarting: true })); const u = new Updates(f.invoke); await u.check(); let threw = false; try { await u.install(); } catch (e) { threw = true; } check(!threw && f.calls.filter((c) => c[0] === 'update_install').length === 1, 'an update that installs is installed once'); } { const f = fake(new Error('the app has no such command')); const u = new Updates(f.invoke); const v = await u.check(); check(v.error === 'the app has no such command' && updateNotice(v) === null && u.waiting === null, 'a check that fails is an answer that says nothing to the reader'); } console.log(fails ? `${fails} check(s) failed` : 'every check passed'); process.exit(fails ? 1 : 0);