69 lines
3.3 KiB
TypeScript
69 lines
3.3 KiB
TypeScript
function assert(condition: unknown, message = "assertion failed"): void {
|
|
if (!condition) throw new Error(message);
|
|
}
|
|
|
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
import PeoplePicker from "../src/components/people/PeoplePicker";
|
|
import {
|
|
dedupePeoplePickerItems,
|
|
externalPeoplePickerItem,
|
|
selectionFromPeoplePickerCandidate,
|
|
type PeoplePickerSearch
|
|
} from "../src/components/people/peoplePickerTypes";
|
|
import { PlatformLanguageProvider } from "../src/i18n/LanguageContext";
|
|
|
|
const account = {
|
|
selection_key: "account:account-1",
|
|
kind: "account" as const,
|
|
reference_id: "account-1",
|
|
display_name: "Ada Lovelace",
|
|
email: "Ada@Example.Test",
|
|
source_module: "access",
|
|
source_label: "Accounts"
|
|
};
|
|
const contact = {
|
|
selection_key: "contact:contact-1:ada@example.test",
|
|
kind: "contact" as const,
|
|
reference_id: "contact-1",
|
|
display_name: "Ada Contact",
|
|
email: "ada@example.test",
|
|
source_module: "addresses",
|
|
source_label: "Contacts"
|
|
};
|
|
|
|
const deduped = dedupePeoplePickerItems([account, contact]);
|
|
assert(deduped.length === 1, "the same email is selected only once across directory sources");
|
|
assert(deduped[0].reference_id === "account-1", "selection order decides which discoverable reference is retained");
|
|
|
|
const external = externalPeoplePickerItem(" Grace Hopper ", " GRACE@EXAMPLE.TEST ");
|
|
assert(external.display_name === "Grace Hopper", "manual names are normalized");
|
|
assert(external.email === "grace@example.test", "manual email addresses are normalized");
|
|
assert(external.selection_key === "external:grace@example.test", "manual entries receive stable opaque selection keys");
|
|
|
|
const selected = selectionFromPeoplePickerCandidate({ ...contact, disabled: true, disabled_reason: "Policy" });
|
|
assert(!("disabled" in selected), "result-only disabled state is not persisted in selections");
|
|
assert(!("disabled_reason" in selected), "result-only policy wording is not persisted in selections");
|
|
|
|
let searchCalled = false;
|
|
const search: PeoplePickerSearch = async () => {
|
|
searchCalled = true;
|
|
return [];
|
|
};
|
|
const markup = renderToStaticMarkup(
|
|
<PlatformLanguageProvider>
|
|
<PeoplePicker id="reviewers" value={[account]} onChange={() => undefined} search={search} help="Choose a reviewer." />
|
|
</PlatformLanguageProvider>
|
|
);
|
|
|
|
assert(!searchCalled, "directory search is server-driven after user input, not during static rendering");
|
|
assert(markup.includes('role="combobox"'), "search exposes combobox semantics");
|
|
assert(markup.includes('aria-autocomplete="list"'), "search declares list autocomplete behavior");
|
|
assert(markup.includes('aria-controls="reviewers-results"'), "search and grouped result list are associated");
|
|
assert(markup.includes("inline-help"), "non-obvious picker fields use central inline help");
|
|
assert(markup.includes('role="table"'), "selected people are rendered through the central DataGrid");
|
|
assert(markup.includes("Ada Lovelace"), "selected structured rows retain the display name");
|
|
assert(markup.includes("Ada@Example.Test"), "selected structured rows retain the email address");
|
|
assert(markup.includes('aria-label="Add person"'), "row add uses an accessible central table action");
|
|
assert(markup.includes('aria-label="Remove person"'), "row removal uses an accessible central table action");
|
|
assert(markup.includes("Add external person"), "manual external entry remains a separate structured action");
|