145 lines
4.9 KiB
TypeScript
145 lines
4.9 KiB
TypeScript
function assert(condition: unknown, message = "assertion failed"): void {
|
|
if (!condition) throw new Error(message);
|
|
}
|
|
|
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
import SearchableSelect, {
|
|
filterSearchableSelectOptions
|
|
} from "../src/components/SearchableSelect";
|
|
import {
|
|
ReferenceMultiSelect,
|
|
staticReferenceOptionProvider,
|
|
wildcardReferenceOption
|
|
} from "../src/components/ReferenceSelect";
|
|
import SelectionList, { SelectionListItem } from "../src/components/SelectionList";
|
|
import { PlatformLanguageProvider } from "../src/i18n/LanguageContext";
|
|
|
|
function noop() {}
|
|
|
|
const markup = renderToStaticMarkup(
|
|
<PlatformLanguageProvider>
|
|
<SelectionList label="i18n:govoplan-core.notifications.753a22b2" className="domain-list" data-source="inbox">
|
|
<SelectionListItem
|
|
selected
|
|
className="domain-row"
|
|
draggable
|
|
data-record-id="record-1"
|
|
onDragStart={noop}
|
|
onClick={noop}
|
|
>
|
|
<strong>Primary content</strong>
|
|
<small>Supporting content</small>
|
|
</SelectionListItem>
|
|
<SelectionListItem selected={false} disabled>
|
|
Disabled content
|
|
</SelectionListItem>
|
|
</SelectionList>
|
|
</PlatformLanguageProvider>
|
|
);
|
|
|
|
assert(markup.includes('role="listbox"'), "the root exposes listbox semantics");
|
|
assert(markup.includes('class="selection-list domain-list"'), "root caller classes are preserved");
|
|
assert(markup.includes('data-source="inbox"'), "root native properties pass through");
|
|
assert(markup.includes('aria-label="Notifications"'), "the accessible label is translated");
|
|
assert(markup.includes('role="option"'), "items expose option semantics");
|
|
assert(markup.includes('aria-selected="true"'), "selected state is exposed accessibly");
|
|
assert(markup.includes('class="selection-list-item is-selected domain-row"'), "selected and domain classes are composed");
|
|
assert(markup.includes('draggable="true"'), "native draggable properties pass through");
|
|
assert(markup.includes('data-record-id="record-1"'), "native data properties pass through");
|
|
assert(markup.includes("<strong>Primary content</strong><small>Supporting content</small>"), "React node content is preserved");
|
|
assert(markup.includes('type="button"'), "items default to non-submitting buttons");
|
|
assert(markup.includes('aria-selected="false"'), "unselected state is exposed accessibly");
|
|
assert(markup.includes('aria-disabled="true"'), "disabled state is exposed accessibly");
|
|
assert(markup.includes('disabled=""'), "disabled state uses the native button contract");
|
|
|
|
const nativeLabelMarkup = renderToStaticMarkup(
|
|
<SelectionList aria-label="Already translated">
|
|
<SelectionListItem selected={false}>Content</SelectionListItem>
|
|
</SelectionList>
|
|
);
|
|
assert(nativeLabelMarkup.includes('aria-label="Already translated"'), "native accessible labels pass through unchanged");
|
|
|
|
const directoryOptions = [
|
|
{
|
|
value: "account-1",
|
|
label: "Ada Lovelace",
|
|
description: "ada@example.test"
|
|
},
|
|
{
|
|
value: "group-1",
|
|
label: "Finance",
|
|
searchText: "cost centre"
|
|
}
|
|
];
|
|
assert(
|
|
filterSearchableSelectOptions(directoryOptions, "example").length === 1,
|
|
"searchable selects match option descriptions"
|
|
);
|
|
assert(
|
|
filterSearchableSelectOptions(directoryOptions, "cost centre")[0]?.value ===
|
|
"group-1",
|
|
"searchable selects include explicit search aliases"
|
|
);
|
|
|
|
const searchableMarkup = renderToStaticMarkup(
|
|
<PlatformLanguageProvider>
|
|
<SearchableSelect
|
|
id="assignment-target"
|
|
aria-label="Assignment target"
|
|
value="account-1"
|
|
options={directoryOptions}
|
|
onChange={() => undefined}
|
|
/>
|
|
</PlatformLanguageProvider>
|
|
);
|
|
assert(
|
|
searchableMarkup.includes('role="combobox"'),
|
|
"searchable selects expose combobox semantics"
|
|
);
|
|
assert(
|
|
searchableMarkup.includes('aria-controls="assignment-target-results"'),
|
|
"searchable selects associate their input and result list"
|
|
);
|
|
assert(
|
|
searchableMarkup.includes('value="Ada Lovelace"'),
|
|
"searchable selects render labels instead of technical ids"
|
|
);
|
|
|
|
const referenceMarkup = renderToStaticMarkup(
|
|
<PlatformLanguageProvider>
|
|
<ReferenceMultiSelect
|
|
id="policy-references"
|
|
aria-label="Policy references"
|
|
values={["group-1", "legacy-*", "removed"]}
|
|
onChange={() => undefined}
|
|
selectedOptions={[
|
|
{
|
|
value: "group-1",
|
|
label: "Finance",
|
|
description: "Access group"
|
|
}
|
|
]}
|
|
provider={staticReferenceOptionProvider([
|
|
{
|
|
value: "group-1",
|
|
label: "Finance",
|
|
description: "Access group"
|
|
}
|
|
])}
|
|
createCustomOption={(value) => wildcardReferenceOption(value)}
|
|
/>
|
|
</PlatformLanguageProvider>
|
|
);
|
|
assert(
|
|
referenceMarkup.includes("Finance"),
|
|
"reference multi-selects render known labels"
|
|
);
|
|
assert(
|
|
referenceMarkup.includes("Pattern"),
|
|
"reference multi-selects distinguish wildcard patterns"
|
|
);
|
|
assert(
|
|
referenceMarkup.includes("Unavailable reference"),
|
|
"reference multi-selects retain unavailable values"
|
|
);
|