Files
WRNexusJS/packages/ui/test/select-values.test.ts

87 lines
3.3 KiB
TypeScript

import { expect, test } from "bun:test";
import { readFileSync } from "node:fs";
import { mountHtml, renderComponent } from "../../test/src/index.ts";
import { uiComponentPath } from "../src/registry.ts";
test("Select follows a changed scalar prop after the native control was edited", async () => {
const dom = mountHtml(
await renderComponent(readFileSync(uiComponentPath("Select"), "utf8"), {
name: "controlled",
value: "a",
options: [
{ value: "a", label: "First" },
{ value: "b", label: "Second" },
],
}),
);
const root = dom.querySelector("[data-wrn-hydration], [data-scope]") as any;
const control = dom.querySelector("select") as HTMLSelectElement;
control.value = "";
root.__wrnexusScopeApi.set("value", "b");
expect(control.value).toBe("b");
root.__wrnexusScopeApi.set("value", "a");
expect(control.value).toBe("a");
});
test("Select emits a snapshot of multiple values before reactive validation updates", async () => {
const dom = mountHtml(
await renderComponent(readFileSync(uiComponentPath("Select"), "utf8"), {
name: "reviewers",
label: "Reviewers",
multiple: true,
values: ["a"],
options: [
{ value: "a", label: "First" },
{ value: "b", label: "Second" },
{ value: "c", label: "Third" },
],
}),
);
const root = dom.querySelector(".wrn-next--select")!;
const control = dom.querySelector("select") as HTMLSelectElement;
expect(Array.from(control.selectedOptions).map((option) => option.value)).toEqual(["a"]);
(dom.querySelector("[data-wrn-hydration], [data-scope]") as any).__wrnexusScopeApi.set("values", [
"a",
"c",
]);
expect(Array.from(control.selectedOptions).map((option) => option.value)).toEqual(["a", "c"]);
(dom.querySelector("[data-wrn-hydration], [data-scope]") as any).__wrnexusScopeApi.set("values", [
"a",
]);
const outputs: any[] = [];
root.addEventListener("input", (event) => outputs.push((event as CustomEvent).detail));
control.options[0].selected = false;
control.options[1].selected = true;
control.options[2].selected = true;
control.dispatchEvent(new (dom.window as any).Event("input", { bubbles: true }));
expect(outputs).toHaveLength(1);
expect(outputs[0].value).toBe("b");
expect(outputs[0].values).toEqual(["b", "c"]);
for (const option of Array.from(control.options)) option.selected = false;
expect(outputs[0].values).toEqual(["b", "c"]);
control.dispatchEvent(new (dom.window as any).Event("input", { bubbles: true }));
expect(outputs[1].values).toEqual([]);
});
test("Select preserves the scalar output for single selection", async () => {
const dom = mountHtml(
await renderComponent(readFileSync(uiComponentPath("Select"), "utf8"), {
name: "single",
value: "a",
options: [
{ value: "a", label: "First" },
{ value: "b", label: "Second" },
],
}),
);
let payload: any;
dom.querySelector(".wrn-next--select")!.addEventListener("input", (event) => {
payload = (event as CustomEvent).detail;
});
const control = dom.querySelector("select") as HTMLSelectElement;
control.value = "b";
control.dispatchEvent(new (dom.window as any).Event("input", { bubbles: true }));
expect(payload.value).toBe("b");
expect(payload.values).toEqual([]);
});