// link-dialog.mjs over a stub : one answer per opening, and a // second open() while it is up joins the first rather than leaving a // promise nobody will ever settle. import test from 'node:test' import assert from 'node:assert/strict' import { mountLinkDialog } from './link-dialog.mjs' function stubDialog () { const input = { value: '', select () {} } const listeners = {} return { input, returnValue: '', shown: 0, querySelector: () => input, addEventListener (name, fn) { listeners[name] = fn }, showModal () { this.shown++ }, close (value) { this.returnValue = value; listeners.close() } } } test('open resolves to the button that closed it and the trimmed field', async () => { const d = stubDialog() const dialog = mountLinkDialog(d) const p = dialog.open('https://old') assert.equal(d.input.value, 'https://old') assert.equal(dialog.isOpen, true) d.input.value = ' https://new ' d.close('insert') assert.deepEqual(await p, { action: 'insert', href: 'https://new' }) assert.equal(dialog.isOpen, false) // Escape closes with no returnValue: that is cancel. const q = dialog.open('') d.close('') assert.deepEqual(await q, { action: 'cancel', href: '' }) }) test('a second open while the dialog is up joins the first', async () => { const d = stubDialog() const dialog = mountLinkDialog(d) const first = dialog.open('https://a') d.input.value = 'https://typed' const second = dialog.open('https://b') assert.equal(d.shown, 1) assert.equal(d.input.value, 'https://typed', 'the field is not reseeded under the person') d.close('remove') assert.deepEqual(await first, { action: 'remove', href: 'https://typed' }) assert.deepEqual(await second, { action: 'remove', href: 'https://typed' }) }) test('a missing dialog mounts as nothing', () => { assert.equal(mountLinkDialog(null), null) })