Files
AtreidesAssetsFree/tests/ui/label-combobox.test.mjs
T

180 lines
6.0 KiB
JavaScript
Raw Permalink Normal View History

2026-10-29 11:57:29 +01:00
// Generated, do not edit. sha256:18ea78362b2006de67f8de24f1ba22509bacedd2360fbc539ff44c9c147a971f
import { describe, it, mock } from 'node:test';
import assert from 'node:assert/strict';
let gemeld = [];
mock.module('../../client/ui/dialog.js', { namedExports: { alert: (o) => { gemeld.push(o); } } });
const { labelComboMarkup, labelComboMount, labelComboRead } =
await import('../../client/ui/label-combobox.js');
function maakHost() {
const hidden = { value: '' };
const input = { value: '', gefocust: 0, focus() { this.gefocust++; } };
const datalist = { innerHTML: '' };
const addBtn = {};
const delBtn = { disabled: false };
const map = {
'[data-label-id]': hidden,
'[data-label-input]': input,
datalist,
'[data-label-add]': addBtn,
'[data-label-del]': delBtn,
};
return { querySelector: (sel) => map[sel] ?? null, hidden, input, datalist, addBtn, delBtn };
}
function maakApi(labels = [{ id: 1, name: 'Salaris' }, { id: 2, name: 'Spaargeld' }]) {
const rijen = [...labels];
let volgend = Math.max(0, ...rijen.map(l => l.id)) + 1;
return {
lijst: rijen,
aanroepen: { list: 0, create: 0 },
async listLabels() { this.aanroepen.list++; return [...rijen]; },
async createLabel({ name }) {
this.aanroepen.create++;
const id = volgend++;
rijen.push({ id, name });
return id;
},
};
}
describe('labelComboMarkup', () => {
it('levert de twee knoppen en het verborgen id-veld', () => {
const html = labelComboMarkup('labelId', 7);
assert.match(html, /data-label-add/);
assert.match(html, /data-label-del/);
assert.match(html, /data-label-id value="7"/);
});
it('escapet de veldnaam en laat een leeg id leeg', () => {
assert.match(labelComboMarkup('a"b', null), /data-field="a"b"/);
assert.match(labelComboMarkup('labelId', null), /data-label-id value=""/);
});
});
describe('labelComboRead', () => {
it('geeft null bij leeg en een getal bij een gekozen label', () => {
const host = maakHost();
host.hidden.value = '';
assert.equal(labelComboRead(host), null);
host.hidden.value = '3';
assert.equal(labelComboRead(host), 3);
assert.equal(labelComboRead(null), null);
});
});
describe('labelComboMount met een ASYNCHRONE labelApi', () => {
it('vult de datalist en zet het huidige label in het veld', async () => {
const host = maakHost();
const api = maakApi();
host.hidden.value = '2';
await labelComboMount(host, api, () => {});
assert.match(host.datalist.innerHTML, /Salaris/);
assert.match(host.datalist.innerHTML, /Spaargeld/);
assert.equal(host.input.value, 'Spaargeld', 'het gekoppelde label hoort in het veld te staan');
assert.equal(host.delBtn.disabled, false, 'ontkoppelen kan, want er hángt een label aan');
});
it('zet de ontkoppel-knop uit als er geen label hangt', async () => {
const host = maakHost();
await labelComboMount(host, maakApi(), () => {});
assert.equal(host.input.value, '');
assert.equal(host.delBtn.disabled, true);
});
it('koppelt met + een BESTAAND label zonder er een nieuw bij te maken', async () => {
const host = maakHost();
const api = maakApi();
const gekozen = [];
await labelComboMount(host, api, id => gekozen.push(id));
host.input.value = ' salaris ';
await host.addBtn.onclick();
assert.deepEqual(gekozen, [1], 'de naam hoort op te lossen naar het bestaande label');
assert.equal(api.aanroepen.create, 0, 'geen tweede label met dezelfde naam');
assert.equal(host.hidden.value, 1);
});
it('maakt met + een NIEUW label en verwerkt het meteen in de lijst', async () => {
const host = maakHost();
const api = maakApi();
const gekozen = [];
await labelComboMount(host, api, id => gekozen.push(id));
host.input.value = 'Vakantiegeld';
await host.addBtn.onclick();
assert.equal(api.aanroepen.create, 1);
assert.deepEqual(gekozen, [3]);
assert.equal(host.input.value, 'Vakantiegeld');
assert.match(host.datalist.innerHTML, /Vakantiegeld/);
});
it('doet met + bij een leeg veld niets dan focussen', async () => {
const host = maakHost();
const api = maakApi();
const gekozen = [];
await labelComboMount(host, api, id => gekozen.push(id));
host.input.value = ' ';
await host.addBtn.onclick();
assert.equal(api.aanroepen.create, 0);
assert.deepEqual(gekozen, []);
assert.equal(host.input.gefocust, 1);
});
it('meldt een fout van createLabel en koppelt dan niets', async () => {
gemeld = [];
const host = maakHost();
const api = maakApi();
api.createLabel = async () => { throw new Error('naam bestaat al'); };
const gekozen = [];
await labelComboMount(host, api, id => gekozen.push(id));
host.input.value = 'Nieuw';
await host.addBtn.onclick();
assert.equal(gemeld.length, 1);
assert.match(gemeld[0].message, /naam bestaat al/);
assert.deepEqual(gekozen, [], 'een mislukte aanmaak mag geen koppeling doorgeven');
});
it('ontkoppelt met − zonder het label zelf te raken', async () => {
const host = maakHost();
const api = maakApi();
host.hidden.value = '1';
const gekozen = [];
await labelComboMount(host, api, id => gekozen.push(id));
host.delBtn.onclick();
assert.deepEqual(gekozen, [null]);
assert.equal(host.hidden.value, '');
assert.equal(api.lijst.length, 2, 'het label blijft bestaan');
});
it('koppelt bij het typen van een bestaande naam, en wacht bij een nieuwe op +', async () => {
const host = maakHost();
const gekozen = [];
await labelComboMount(host, maakApi(), id => gekozen.push(id));
host.input.value = 'Spaargeld';
host.input.onchange();
assert.deepEqual(gekozen, [2]);
host.input.value = 'Bestaat nog niet';
host.input.onchange();
assert.deepEqual(gekozen, [2], 'een onbekende naam koppelt niets tot je op + drukt');
assert.equal(host.hidden.value, '');
assert.equal(host.delBtn.disabled, true);
host.input.value = '';
host.input.onchange();
assert.deepEqual(gekozen, [2, null], 'het veld leegmaken ontkoppelt');
});
});