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([]); });