// selection.mjs's hash: #[/], read without ever throwing // — and its teardown, which is what keeps a resync from leaving a // second copy of every handler on the page's own elements. import test from 'node:test' import assert from 'node:assert/strict' import { parseHash, formatHash, mountSelection } from './selection.mjs' import { el, withDocument } from './dom-stub.mjs' test('parseHash splits the slide and the block, and survives a stray %', () => { assert.deepEqual(parseHash('#slideaaaaaaa'), { slide: 'slideaaaaaaa', block: '' }) assert.deepEqual(parseHash('#slideaaaaaaa/blockbbbbbbb'), { slide: 'slideaaaaaaa', block: 'blockbbbbbbb' }) assert.deepEqual(parseHash(''), { slide: '', block: '' }) assert.deepEqual(parseHash('#'), { slide: '', block: '' }) assert.deepEqual(parseHash('#%'), { slide: '%', block: '' }) assert.deepEqual(parseHash('#a%2Fb'), { slide: 'a', block: 'b' }) }) // A resync mounts a second selection over the SAME stage element and // the same document, so the first one has to let go of both. The // Escape handler is the one that bites: it is on `document`, so a // leaked one clears a selection nobody is holding any more. test('destroy takes the listeners off, and a second mount leaves one of each', () => { const ctx = withDocument() try { const stage = el('div', { 'slides-stage': '' }) const first = mountSelection({ stageEl: stage, getSlideId: () => 'slideaaaaaaa' }) assert.equal(stage.countListeners('click'), 1) assert.equal(ctx.document.countListeners('keydown'), 1) first.destroy() assert.equal(stage.countListeners('click'), 0) assert.equal(ctx.document.countListeners('keydown'), 0) const second = mountSelection({ stageEl: stage, getSlideId: () => 'slideaaaaaaa' }) assert.equal(stage.countListeners('click'), 1, 'one click handler, not one per resync') assert.equal(ctx.document.countListeners('keydown'), 1) second.destroy() } finally { ctx.restore() } }) test('formatHash is the inverse', () => { assert.equal(formatHash('s', 'b'), '#s/b') assert.equal(formatHash('s', ''), '#s') assert.equal(formatHash('', 'b'), '') })