Files
NODEDC_DESIGN_GUIDELINE/scripts/select-actions-contract.test.mjs

40 lines
2.2 KiB
JavaScript

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 \? <IconButton/);
assert.match(source, /disabled=\{option\.action\.disabled\}/);
assert.match(source, /close\(\);[\s\S]*triggerButton.current\?\.focus\(\);\s*option\.action\?\.onAction\(\)/);
assert.match(source, /role=\{withActions \? undefined : "option"\}/);
});
test('row action matches the compact session catalog without a circular backing', async () => {
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\)\)/);
});