import { test } from 'node:test'; import assert from 'node:assert/strict'; import { comboboxData } from './combobox.js'; test('free-typing combobox commits typed text as the value (SEV-392)', () => { const c = comboboxData({ options: ['BMW', 'Porsche', 'Tesla'] }); c.init(); c.query = 'Devin Sportscar'; // off-list classic c.onInput(); assert.equal(c.value, 'Devin Sportscar'); // accepted as-is, never blocked }); test('fuzzy filter matches prefix, substring + abbreviation subsequences (SEV-392)', () => { const c = comboboxData({ options: ['BMW', 'Mercedes-Benz', 'Porsche'] }); // prefix c.query = 'merc'; assert.ok(c.filtered.map((o) => o.label).includes('Mercedes-Benz')); // abbreviation subsequence (M…B) c.query = 'mb'; assert.ok(c.filtered.map((o) => o.label).includes('Mercedes-Benz')); // and it excludes non-matches c.query = 'xyz'; assert.equal(c.filtered.length, 0); }); test('choose() commits an option value + label; supports {value,label} (SEV-392)', () => { const c = comboboxData({ options: [{ value: 'CA', label: 'California' }, { value: 'OR', label: 'Oregon' }], allowFree: false, }); c.init(); c.choose({ value: 'OR', label: 'Oregon' }); assert.equal(c.value, 'OR'); assert.equal(c.query, 'Oregon'); assert.equal(c.isOpen, false); }); test('closed-list blur snaps back to the committed label (SEV-392)', () => { const c = comboboxData({ options: [{ value: 'CA', label: 'California' }], allowFree: false, value: 'CA', }); c.init(); assert.equal(c.query, 'California'); // init syncs query from value c.query = 'typing garbage'; c.onBlur(); assert.equal(c.value, 'CA'); // unchanged assert.equal(c.query, 'California'); // reverted }); test('empty query lists all options (capped) (SEV-392)', () => { const c = comboboxData({ options: ['a', 'b', 'c'] }); c.query = ''; assert.equal(c.filtered.length, 3); }); test('setOptions feeds reactive option lists (SEV-392)', () => { const c = comboboxData({ allowFree: true }); c.setOptions([]); // async source not loaded yet assert.equal(c.filtered.length, 0); c.setOptions(['BMW', 'Tesla']); // makes arrive assert.equal(c.filtered.length, 2); c.query = 'tes'; assert.deepEqual(c.filtered.map((o) => o.value), ['Tesla']); }); test('displayValue shows the code in the input, searches by label (SEV-408)', () => { const c = comboboxData({ options: [{ value: 'CA', label: 'California' }, { value: 'TX', label: 'Texas' }], allowFree: false, displayValue: true, }); c.init(); // search by name c.query = 'tex'; assert.deepEqual(c.filtered.map((o) => o.value), ['TX']); // choosing shows the CODE, not the name c.choose({ value: 'TX', label: 'Texas' }); assert.equal(c.value, 'TX'); assert.equal(c.query, 'TX'); }); test('displayValue syncs the code from an external value (SEV-408)', () => { const c = comboboxData({ options: [{ value: 'OR', label: 'Oregon' }], allowFree: false, displayValue: true, value: 'OR', }); c.init(); assert.equal(c.query, 'OR'); // shows code, not "Oregon" });