// Generated, do not edit. sha256:23dd50a7ad5448e3230fa33ba9e025d2fdfec896be66303dade6c4b550502fa8
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { installDom, parseSelector } from '../helpers/mini-dom.mjs';
const dom = installDom();
const html = s => { const el = dom.host(); el.innerHTML = s; return el; };
describe('mini-dom: parsing and serialising', () => {
it('builds elements, text and attributes, and decodes what esc() writes', () => {
const el = html('
x < y
');
const d = el.querySelector('div');
assert.equal(d.getAttribute('data-x'), '1 & 2');
assert.equal(d.title, `"q" 's'`);
assert.equal(d.textContent, 'x < y');
assert.equal(el.innerHTML, 'x < y
');
});
it('knows void elements, self-closing svg and a raw textarea', () => {
const el = html('na ');
assert.equal(el.children.length, 4);
assert.equal(el.querySelector('svg').children[0].localName, 'line');
assert.equal(el.querySelector('textarea').value, 'a & c');
assert.equal(el.querySelector('span').textContent, 'na');
});
it('a > inside a quoted attribute does not end the tag', () => {
const el = html('x ');
assert.equal(el.querySelector('button').title, 'a > b');
assert.equal(el.querySelector('button').textContent, 'x');
});
it('a stray closing tag is ignored, and replacing innerHTML detaches the old nodes', () => {
const el = html(' ab
');
assert.equal(el.querySelector('p').textContent, 'ab');
const p = el.querySelector('p');
el.innerHTML = 'new ';
assert.equal(p.isConnected, false);
assert.equal(el.querySelector('i').isConnected, true);
});
});
describe('mini-dom: selectors', () => {
const el = html(``);
it('tag, id, class, attribute with and without value, and :not', () => {
assert.equal(el.querySelectorAll('tr').length, 3);
assert.equal(el.querySelectorAll('tr[data-row-id]').length, 2);
assert.equal(el.querySelector('tr[data-row-id="2"]').dataset.rowId, '2');
assert.equal(el.querySelector('tr.row-expansion[data-exp-id="1"] td').textContent, 'drawer');
assert.equal(el.querySelectorAll('.table-wrap.has-exp').length, 1);
const free = el.querySelectorAll('input:not([disabled]):not([type="hidden"]), select:not([disabled])');
assert.deepEqual(free.map(i => i.dataset.field), ['c']);
});
it('descendant and child combinators are not the same', () => {
assert.equal(el.querySelectorAll('tbody td').length, 3);
assert.equal(el.querySelectorAll('table > td').length, 0);
assert.equal(el.querySelectorAll('tr > td').length, 3);
});
it('closest walks up and includes the element itself; matches tests one element', () => {
const td = el.querySelector('tr[data-row-id="1"] td');
assert.equal(td.closest('tr[data-row-id]').dataset.rowId, '1');
assert.equal(td.closest('td'), td);
assert.equal(td.closest('[data-save]'), null);
assert.equal(td.matches('.num'), true);
});
it('a selector it does not understand throws instead of matching nothing', () => {
assert.throws(() => parseSelector('tr:first-child'), /unsupported/);
assert.throws(() => parseSelector('a ~ b'), /unsupported/);
assert.throws(() => parseSelector('[x'), /unclosed/);
});
});
describe('mini-dom: form state', () => {
it('a select reads the selected option, then what was set', () => {
const el = html('A B X ');
const [s1, s2] = el.querySelectorAll('select');
assert.equal(s1.value, 'b');
assert.equal(s2.value, 'x');
s1.value = 'a';
assert.equal(s1.value, 'a');
});
it('an input reads its attribute until a value is set; a checkbox its checked', () => {
const el = html(' ');
const [t, c1, c2] = el.querySelectorAll('input');
assert.equal(t.value, '1');
t.value = '2';
assert.equal(t.value, '2');
assert.equal(t.getAttribute('value'), '1');
assert.equal(c1.checked, true);
assert.equal(c2.checked, false);
assert.equal(c1.type, 'checkbox');
assert.equal(t.type, 'text');
});
it('there is a head for scripts, and getComputedStyle reads the inline style', () => {
assert.equal(dom.document.head.parentNode, dom.document.documentElement);
dom.document.documentElement.style.setProperty('--accent', '#ff6b00');
assert.equal(getComputedStyle(dom.document.documentElement).getPropertyValue('--accent'), '#ff6b00');
});
it('focus moves activeElement, and contains sees it', () => {
const el = html(' ');
el.querySelector('input').focus();
assert.equal(dom.document.activeElement, el.querySelector('input'));
assert.equal(el.contains(dom.document.activeElement), true);
});
});
describe('mini-dom: events', () => {
it('bubbles through on-properties and listeners, and stopPropagation stops it', () => {
const el = html('');
const log = [];
el.querySelector('#outer').onclick = () => log.push('outer');
el.querySelector('#inner').addEventListener('click', e => { log.push('inner'); e.stopPropagation(); });
dom.click(el.querySelector('button'));
assert.deepEqual(log, ['inner']);
});
it('a capture listener on the document runs first, and target is the clicked element', () => {
const el = html('x ');
const log = [];
const cap = e => log.push(['doc', e.target.localName]);
dom.document.addEventListener('click', cap, true);
el.onclick = () => log.push(['host']);
dom.click(el.querySelector('span'));
dom.document.removeEventListener('click', cap, true);
assert.deepEqual(log, [['doc', 'span'], ['host']]);
});
it('dispatchEvent with a platform Event works, and keydown carries key and modifiers', () => {
const el = html(' ');
let got = null;
el.oninput = e => { got = e.type; };
el.querySelector('input').dispatchEvent(new Event('input', { bubbles: true }));
assert.equal(got, 'input');
let k = null;
el.onkeydown = e => { k = [e.key, e.ctrlKey]; e.preventDefault(); };
assert.equal(dom.key(el.querySelector('input'), 'Enter', { ctrlKey: true }), false);
assert.deepEqual(k, ['Enter', true]);
});
it('the document dispatches too, and a CustomEvent keeps its detail', () => {
let got = null;
const fn = e => { got = e.detail; };
dom.document.addEventListener('blur-changed', fn);
dom.document.dispatchEvent(new CustomEvent('blur-changed', { detail: { on: true } }));
dom.document.removeEventListener('blur-changed', fn);
assert.deepEqual(got, { on: true });
});
it('append adds several children in order', () => {
const el = html('');
el.append(dom.document.createElement('b'), dom.document.createElement('i'));
assert.deepEqual(el.children.map(c => c.localName), ['b', 'i']);
});
it('animation frames wait until they are flushed', () => {
let ran = false;
requestAnimationFrame(() => { ran = true; });
assert.equal(ran, false);
dom.flushFrames();
assert.equal(ran, true);
});
});