/** * The three facts a first-run walkthrough has to keep apart. * * Conflating them is what makes onboarding annoying: an offer that reappears * every morning, a walkthrough that drops out on refresh, or a "skip" that * quietly counts as done. */ import assert from 'node:assert/strict'; import { test, beforeEach } from 'node:test'; import { shouldOfferTour, type TourState } from './tourState'; const state = (over: Partial = {}): TourState => ({ prompted: false, active: false, skipped: [], ...over, }); beforeEach(() => { delete (globalThis as { localStorage?: unknown }).localStorage; }); test('a new account with work to do is offered the walkthrough', () => { assert.equal(shouldOfferTour(state(), true), true); }); // Asked once. An offer that returns on every sign-in stops being an offer and // becomes something to dismiss without reading. test('somebody who already said no is not asked again', () => { assert.equal(shouldOfferTour(state({ prompted: true }), true), false); }); test('somebody already in the walkthrough is not offered it again', () => { assert.equal(shouldOfferTour(state({ active: true, prompted: true }), true), false); }); /* The check that matters most. A shop already selling is not a first-run case however new the account is — three of the four live merchants on 31 Aug were trading and still missing a licence number, and offering them a setup tour would read as the console not knowing what it is looking at. */ test('a shop with nothing left to do is never offered a walkthrough', () => { assert.equal(shouldOfferTour(state(), false), false); assert.equal(shouldOfferTour(state({ prompted: false }), false), false); }); // Storage the browser refuses must not throw, and must fail towards offering // the guidance rather than silently swallowing it. test('unavailable storage reads as nothing recorded', async () => { const { readTour } = await import('./tourState'); const read = readTour(1475, 1141); assert.equal(read.prompted, false); assert.equal(read.active, false); assert.deepEqual(read.skipped, []); });