import assert from 'node:assert/strict'; import { readFile } from 'node:fs/promises'; import test from 'node:test'; import { createElement } from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; import { Select } from '../packages/ui-react/dist/index.js'; test('select action menus use dialog semantics in all variants; ordinary select stays a listbox', () => { for (const variant of ['integrated', 'split', 'inline']) { for (const withAction of [false, true]) { const markup = renderToStaticMarkup(createElement(Select, { label: 'Records', variant, value: 'one', onChange: () => {}, options: [{value: 'one', label: 'One', ...(withAction ? {action: {label: 'Delete One', icon: 'x', onAction: () => {}}} : {})}], })); assert.match(markup, new RegExp(`aria-haspopup="${withAction ? 'dialog' : 'listbox'}"`)); } } }); test('row action is independent of selection, closes first and uses canonical IconButton', async () => { const source = await readFile(new URL('../packages/ui-react/src/Select.tsx', import.meta.url), 'utf8'); assert.match(source, /<\/button>\s*\{option\.action \? { const css = await readFile(new URL('../packages/ui-core/styles.css', import.meta.url), 'utf8'); const rule = css.match(/\.nodedc-select-option-row > \.nodedc-icon-button \{([^}]+)\}/)?.[1]; assert.match(rule, /width: 2\.35rem/); assert.match(rule, /height: auto/); assert.match(rule, /border-radius: 0/); assert.match(rule, /background: transparent/); assert.match(rule, /box-shadow: none/); assert.match(rule, /color: var\(--nodedc-text-muted\)/); assert.match(css, /\.nodedc-select-option-row > \.nodedc-icon-button > svg \{ width: 15px; height: 15px; transform: none/); assert.match(css, /data-tone="danger"\]\:focus-visible \{ color: rgb\(var\(--nodedc-danger-rgb\)\)/); });