diff --git a/bun.lock b/bun.lock index 56b0b71c..044671dd 100644 --- a/bun.lock +++ b/bun.lock @@ -688,7 +688,7 @@ }, "packages/ui": { "name": "@wrnexus/ui", - "version": "0.8.59", + "version": "0.8.60", "dependencies": { "@wrnexus/core": "workspace:*", }, diff --git a/packages/dev-server/test/large-select-runtime.test.ts b/packages/dev-server/test/large-select-runtime.test.ts new file mode 100644 index 00000000..5b357b85 --- /dev/null +++ b/packages/dev-server/test/large-select-runtime.test.ts @@ -0,0 +1,60 @@ +import { expect, test } from "bun:test"; +import { mkdirSync, mkdtempSync, writeFileSync, readFileSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join, basename } from "node:path"; +import { buildRouter } from "@wrnexus/router"; +import { renderComponent } from "../../test/src/index.ts"; +import { createHandlers } from "../src/runtime.ts"; + +test("large timezone select responds through the complete page renderer", async () => { + const root = mkdtempSync(join(tmpdir(), "wrn-large-select-")); + try { + mkdirSync(join(root, "pages")); + mkdirSync(join(root, "components")); + writeFileSync(join(root, "pages/index.ts"), ""); + for (const name of ["AdvancedSelect", "SelectStyles", "Shell"]) + writeFileSync( + join(root, `components/${name}.wrn`), + `component ${name} { view {
} }`, + ); + const select = await renderComponent( + readFileSync(new URL("../../ui/components/AdvancedSelect.wrn", import.meta.url), "utf8"), + { + name: "timezone", + value: "UTC", + searchResultLimit: 40, + options: Intl.supportedValuesOf("timeZone").map((value) => ({ value, label: value })), + }, + ); + const handlers = createHandlers({ + mode: "development", + hmr: false, + router: buildRouter(root), + loadModule: async (file) => + basename(file) === "AdvancedSelect.wrn" + ? { render: () => select } + : basename(file) === "SelectStyles.wrn" + ? { render: () => "" } + : basename(file) === "Shell.wrn" + ? { render: () => "
" } + : { + default: () => + '
' + + '
'.repeat(4) + + "
", + }, + getMiddleware: async () => [], + assets: { serve: async () => null }, + }); + const response = await handlers.fetch(new Request("http://example.test/"), { + upgrade: () => false, + }); + expect(response?.status).toBe(200); + const html = await response!.text(); + expect(html).toContain("Asia/Kolkata"); + // Four full lists previously exceeded 11 MB, including hydration metadata. + expect(html.length).toBeLessThan(6_000_000); + } finally { + rmSync(root, { recursive: true, force: true }); + } +}, 15000); diff --git a/packages/ui/components/AdvancedSelect.wrn b/packages/ui/components/AdvancedSelect.wrn index 9f5b90ee..1042c55a 100644 --- a/packages/ui/components/AdvancedSelect.wrn +++ b/packages/ui/components/AdvancedSelect.wrn @@ -375,7 +375,7 @@ component AdvancedSelect { {#if visibleOptions(group.options || []).length}
{group.label}
- {#each group.options || [] as option} + {#each visibleOptions(group.options || []) as option}