87 lines
3.3 KiB
TypeScript
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([]);
|
|
});
|