import { compileFunction } from 'node:vm'; import assert from 'node:assert/strict'; import test from 'node:test'; import fs from 'node:fs'; import { createRequire } from 'node:module'; import React from 'react'; import ts from 'typescript'; // Exercise the real component's event/state contract; this is not browser visual QA. const require = createRequire(import.meta.url); const source = fs.readFileSync( new URL( '../../resources/js/components/territory-search-select.tsx', import.meta.url, ), 'utf8', ); const compiled = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, jsx: ts.JsxEmit.ReactJSX, }, }).outputText; function harness(overrides = {}) { const memory = []; let cursor = 0; const chosen = []; const hooks = { ...React, useState(initial) { const i = cursor++; if (!(i in memory)) memory[i] = initial; return [ memory[i], (value) => { memory[i] = typeof value === 'function' ? value(memory[i]) : value; }, ]; }, useRef: () => ({ current: null }), useEffect: () => {}, }; const module = { exports: {} }; compileFunction(compiled, ['require', 'module', 'exports'])( (name) => (name === 'react' ? hooks : require(name)), module, module.exports, ); const options = [ { id: 'province-a', name: 'Nampula' }, { id: 'province-b', name: 'Maputo Província' }, ]; const props = { id: 'territory', label: 'Província', search: '', options, onSearch(query) { props.search = query; }, onChange(option) { chosen.push(option); props.selected = option; }, ...overrides, }; let tree; const flat = (node) => !node || typeof node !== 'object' ? [] : [ node, ...React.Children.toArray(node.props?.children).flatMap(flat), ]; const render = () => { cursor = 0; tree = module.exports.default(props); return tree; }; const find = (predicate) => flat(tree).find(predicate); const input = () => find((node) => node.type === 'input'); const key = (value) => input().props.onKeyDown({ key: value, preventDefault() {} }); render(); return { props, chosen, render, find, input, key, options }; } void test('one search input owns the dropdown; the separate select is absent', () => { const h = harness(); assert.equal( h.find((node) => node.type === 'select'), undefined, ); assert.equal(h.input().props.role, 'combobox'); assert.equal(h.input().props['aria-expanded'], false); h.input().props.onFocus(); h.render(); assert.equal(h.input().props['aria-expanded'], true); assert.ok(h.find((node) => node.props?.role === 'listbox')); h.find( (node) => node.props?.role === 'option' && node.props.id === 'territory-options-1', ).props.onClick(); h.render(); assert.deepEqual(h.chosen, [h.options[1]]); assert.equal(h.input().props.value, 'Maputo Província'); assert.equal(h.input().props['aria-expanded'], false); }); void test('typing and Escape preserve the existing selection until an option is explicitly chosen', () => { const selected = { id: 'saved', name: 'Selecção guardada fora desta página', }; const h = harness({ selected }); h.input().props.onFocus(); h.render(); h.input().props.onChange({ target: { value: 'Map' } }); h.render(); assert.equal(h.props.search, 'Map'); assert.deepEqual(h.chosen, []); h.key('Escape'); h.render(); assert.equal(h.input().props.value, selected.name); assert.deepEqual(h.chosen, []); }); void test('arrow keys and Enter choose from the list; loading cannot commit an old result', () => { const h = harness(); h.input().props.onFocus(); h.render(); h.key('ArrowDown'); h.render(); h.key('ArrowDown'); h.render(); assert.equal( h.input().props['aria-activedescendant'], 'territory-options-1', ); h.key('Enter'); h.render(); assert.deepEqual(h.chosen, [h.options[1]]); const busy = harness({ loading: true }); busy.input().props.onFocus(); busy.render(); busy.key('Enter'); assert.deepEqual(busy.chosen, []); }); void test('clear is explicit; disabled dependent levels cannot expose the dropdown', () => { const h = harness({ selected: { id: 'saved', name: 'Nampula' } }); h.find( (node) => node.props?.['aria-label'] === 'Limpar Província', ).props.onClick(); h.render(); assert.deepEqual(h.chosen, [undefined]); assert.equal(h.input().props.value, ''); const disabled = harness({ disabled: true }); assert.equal(disabled.input().props.disabled, true); assert.equal( disabled.find((node) => node.props?.role === 'listbox'), undefined, ); });