release: WRNexusJS 0.5.10

This commit is contained in:
2026-07-30 13:36:29 +05:30
parent 8fc6f15402
commit d1b0c55b53
159 changed files with 7509 additions and 604 deletions
+239 -1
View File
@@ -22,7 +22,7 @@ test("generated component reference documents every bundled component and its pr
readFileSync(join(uiComponentsDir(), "..", "component-catalog.json"), "utf8"),
) as { components: Array<{ name: string }> };
expect(reference.count).toBe(uiComponentNames().length);
expect(reference.count).toBe(85);
expect(reference.count).toBe(90);
expect(reference.components.map((component) => component.name)).toEqual(
expect.arrayContaining(uiComponentNames()),
);
@@ -160,6 +160,234 @@ test("screenshot-directed canonical components are bundled", () => {
expect(uiComponentNames()).toEqual(expect.arrayContaining(required));
});
test("navbar supports brands, nested menus, actions, utility slots, and public events", () => {
const source = readFileSync(uiComponentPath("Navbar"), "utf8");
expect(source).toContain('slot name="topbar"');
expect(source).toContain('slot name="actions"');
expect(source).toContain("brand = {}");
expect(source).toContain("actions = []");
expect(source).toContain("openOnHover = false");
expect(source).toContain('maxWidth = "full"');
expect(source).toContain("item.children");
expect(source).toContain("child.children");
expect(source).toContain("wire-navbar__dropdown--{item.type || 'dropdown'}");
for (const event of ["toggle", "open", "close", "select", "action"]) {
expect(source).toContain(`@event ${event} = function`);
}
});
test("auth form uses package schemas, disables native validation, and renders a full-width submit control", async () => {
const source = readFileSync(uiComponentPath("AuthForm"), "utf8");
expect(source).toContain('return "auth-login"');
expect(source).toContain('data-schema="{schemaName()}"');
expect(source).toContain('data-wrnexus-runtime="auth"');
expect(source).toContain('novalidate="true"');
expect(source).toContain('fullWidth="true"');
const html = await renderComponent(source, { mode: "sign-in" });
expect(html).toContain('data-schema="auth-login"');
expect(html).toContain('data-wrnexus-runtime="auth"');
expect(html).toContain("novalidate");
expect(html).toContain("wire-auth-form__submit");
expect(html).toContain('fullWidth="true"');
});
test("footer supports typed entries, responsive columns, pre/post slots, and events", () => {
const source = readFileSync(uiComponentPath("Footer"), "utf8");
expect(source).toContain('slot name="pre-footer"');
expect(source).toContain('slot name="post-footer"');
expect(source).toContain('slot name="copyright-left"');
expect(source).toContain('slot name="copyright-right"');
expect(source).toContain('item.type === "header"');
expect(source).toContain("wire-footer--columns-{columns}");
expect(source).toContain("@event select = function");
expect(source).toContain("@event action = function");
});
test("navbar renders a brand, nested dropdowns, mega groups, and actions", async () => {
const html = await renderComponent(readFileSync(uiComponentPath("Navbar"), "utf8"), {
brand: {
label: "Police Management System",
description: "Public portal",
href: "/",
},
items: [
{
label: "Services",
type: "dropdown",
children: [{ label: "Reports", href: "/reports" }],
},
{
label: "Safety",
type: "mega",
columns: 2,
children: [
{
label: "Resources",
children: [{ label: "Guidance", href: "/guidance" }],
},
],
},
],
actions: [{ label: "Sign in", href: "/login", variant: "primary" }],
});
expect(html).toContain("Police Management System");
expect(html).toContain("Public portal");
expect(html).toContain("Reports");
expect(html).toContain("Guidance");
expect(html).toContain("wire-navbar__dropdown--mega");
expect(html).toContain("data-wrn-navbar");
expect(html).toContain('name="wire-navbar-menu"');
expect(html).toContain("Sign in");
});
test("navbar closes sibling menus and menus close after an outside pointer press", async () => {
const html = await renderComponent(readFileSync(uiComponentPath("Navbar"), "utf8"), {
items: [
{ label: "Services", children: [{ label: "Reports", href: "/reports" }] },
{ label: "Safety", children: [{ label: "Guidance", href: "/guidance" }] },
],
});
const dom = mountHtml(html);
const menus = Array.from(dom.querySelectorAll(".wire-navbar__dropdown")) as HTMLDetailsElement[];
menus[0].open = true;
menus[0].dispatchEvent(
new (dom.window as { Event: typeof Event }).Event("toggle", { bubbles: false }),
);
menus[1].open = true;
menus[1].dispatchEvent(
new (dom.window as { Event: typeof Event }).Event("toggle", { bubbles: false }),
);
expect(menus[0].open).toBe(false);
expect(menus[1].open).toBe(true);
dom.document.body.dispatchEvent(
new (dom.window as { Event: typeof Event }).Event("pointerdown", { bubbles: true }),
);
expect(menus[1].open).toBe(false);
});
test("navbar optionally opens menus on hover and renders full-width mode", async () => {
const html = await renderComponent(readFileSync(uiComponentPath("Navbar"), "utf8"), {
openOnHover: true,
maxWidth: "full",
items: [{ label: "Services", children: [{ label: "Reports", href: "/reports" }] }],
});
const dom = mountHtml(html);
const navbar = dom.querySelector("[data-wrn-navbar]");
const menu = dom.querySelector(".wire-navbar__dropdown") as HTMLDetailsElement;
expect(navbar?.classList.contains("wire-navbar--width-full")).toBe(true);
expect(navbar?.getAttribute("data-open-on-hover")).toBe("true");
menu.dispatchEvent(new (dom.window as { Event: typeof Event }).Event("pointerenter"));
expect(menu.open).toBe(true);
menu.dispatchEvent(new (dom.window as { Event: typeof Event }).Event("pointerleave"));
expect(menu.open).toBe(true);
await new Promise((resolve) => setTimeout(resolve, 280));
expect(menu.open).toBe(false);
});
test("navbar hover menu stays open while the pointer crosses into its panel", async () => {
const html = await renderComponent(readFileSync(uiComponentPath("Navbar"), "utf8"), {
openOnHover: true,
items: [{ label: "Services", children: [{ label: "Reports", href: "/reports" }] }],
});
const dom = mountHtml(html);
const menu = dom.querySelector(".wire-navbar__dropdown") as HTMLDetailsElement;
const panel = dom.querySelector(".wire-navbar__panel") as HTMLElement;
const DomEvent = (dom.window as { Event: typeof Event }).Event;
menu.dispatchEvent(new DomEvent("pointerenter"));
menu.dispatchEvent(new DomEvent("pointerleave"));
panel.dispatchEvent(new DomEvent("pointerenter", { bubbles: true }));
await new Promise((resolve) => setTimeout(resolve, 280));
expect(menu.open).toBe(true);
});
test("preference switcher keeps only one popover open and closes outside", async () => {
const html = await renderComponent(
readFileSync(uiComponentPath("PreferenceSwitcher"), "utf8"),
{},
);
const dom = mountHtml(html);
const menus = Array.from(dom.querySelectorAll(".wire-preferences__menu")) as HTMLDetailsElement[];
const DomEvent = (dom.window as { Event: typeof Event }).Event;
menus[0].open = true;
menus[0].dispatchEvent(new DomEvent("toggle"));
menus[1].open = true;
menus[1].dispatchEvent(new DomEvent("toggle"));
expect(menus[0].open).toBe(false);
expect(menus[1].open).toBe(true);
dom.document.body.dispatchEvent(new DomEvent("pointerdown", { bubbles: true }));
expect(menus[1].open).toBe(false);
});
test("sidebar renders compact grouped submenu navigation and a mobile drawer trigger", async () => {
const html = await renderComponent(readFileSync(uiComponentPath("Sidebar"), "utf8"), {
label: "Operations",
orientation: "vertical",
items: [
{ label: "Dashboard", href: "/dashboard", value: "dashboard" },
{
label: "Case management",
children: [
{ label: "Assigned cases", href: "/cases", value: "cases" },
{ label: "Evidence", href: "/evidence", value: "evidence" },
],
},
],
});
expect(html).toContain("wire-sidebar-toggle");
expect(html).toContain("wire-sidebar-backdrop");
expect(html).toContain("wire-sidebar-group");
expect(html).toContain("Assigned cases");
expect(html).toContain("Evidence");
});
test("dropdown renders slotted account triggers, menu structure, and public events", async () => {
const source = readFileSync(uiComponentPath("Dropdown"), "utf8");
const html = await renderComponent(source, {
label: "Account menu",
items: [
{ type: "header", label: "Account" },
{ label: "Profile", href: "/profile", icon: "icon-[lucide--user]" },
{ type: "divider" },
{ label: "Sign out", href: "/logout", danger: true },
],
});
expect(source).toContain('slot name="trigger"');
expect(source).toContain("@event select = function");
expect(html).toContain("wire-dropdown__panel");
expect(html).toContain("Profile");
expect(html).toContain("wire-dropdown__item--danger");
});
test("footer renders header and link entries with the requested column count", async () => {
const html = await renderComponent(readFileSync(uiComponentPath("Footer"), "utf8"), {
columns: 4,
items: [
{ type: "header", label: "Support" },
{ type: "link", label: "Contact", href: "/contact" },
],
copyright: "Public service platform",
});
expect(html).toContain("wire-footer--columns-4");
expect(html).toContain("wire-footer__column");
expect(html).toContain("wire-footer__column-links");
expect(html).toContain("wire-footer__heading");
expect(html).toContain("Support");
expect(html).toContain('href="/contact"');
expect(html).toContain("Public service platform");
});
test("component-system CSS includes responsive, theme-token, focus, and reduced-motion rules", () => {
const css = uiCss();
expect(css).toContain("@media (max-width: 768px)");
@@ -184,6 +412,16 @@ test("component-system CSS includes responsive, theme-token, focus, and reduced-
expect(css).toContain(".wire-next--table");
expect(css).toContain('[data-show="false"]');
expect(css).toContain("display: none !important");
expect(css).toMatch(
/\.wire-navbar__brand-copy strong\s*\{[^}]*font-size: 0\.9rem;[^}]*font-weight: 600;/s,
);
expect(css).toMatch(
/\.wire-navbar__menu-link,[\s\S]*?font-size: 0\.8125rem;[\s\S]*?font-weight: 500;/,
);
expect(css).toMatch(
/\.wire-footer__heading\s*\{[^}]*font-size: 0\.8125rem;[^}]*font-weight: 600;/s,
);
expect(css).toMatch(/\.wire-footer__link\s*\{[^}]*font-size: 0\.8125rem;[^}]*font-weight: 400;/s);
});
test("component boundaries have no default margins and expose the canonical class prop", () => {