WIP test(ui-shell): add unit tests

This commit is contained in:
Eric Liu 2025-04-12 15:21:31 -07:00
commit 88fb7beda3
6 changed files with 99 additions and 323 deletions

View file

@ -1,60 +0,0 @@
<script lang="ts">
import {
Header,
HeaderNav,
HeaderNavItem,
HeaderNavMenu,
SideNav,
SideNavItems,
SideNavMenu,
SideNavMenuItem,
SideNavLink,
SkipToContent,
Content,
Grid,
Row,
Column,
} from "carbon-components-svelte";
let isSideNavOpen = false;
</script>
<Header company="IBM" platformName="Carbon Svelte" bind:isSideNavOpen>
<div slot="skip-to-content">
<SkipToContent />
</div>
<HeaderNav>
<HeaderNavItem href="/" text="Link 1" />
<HeaderNavItem href="/" text="Link 2" />
<HeaderNavItem href="/" text="Link 3" />
<HeaderNavMenu text="Menu">
<HeaderNavItem href="/" text="Link 1" />
<HeaderNavItem href="/" text="Link 2" />
<HeaderNavItem href="/" text="Link 3" />
</HeaderNavMenu>
</HeaderNav>
</Header>
<SideNav bind:isOpen={isSideNavOpen}>
<SideNavItems>
<SideNavLink text="Link 1" />
<SideNavLink text="Link 2" />
<SideNavLink text="Link 3" />
<SideNavMenu text="Menu">
<SideNavMenuItem href="/" text="Link 1" />
<SideNavMenuItem href="/" text="Link 2" />
<SideNavMenuItem href="/" text="Link 3" />
</SideNavMenu>
</SideNavItems>
</SideNav>
<Content>
<Grid>
<Row>
<Column>
<h1>Welcome</h1>
</Column>
</Row>
</Grid>
</Content>

View file

@ -1,119 +0,0 @@
<script lang="ts">
import {
Header,
HeaderUtilities,
HeaderAction,
HeaderSearch,
HeaderPanelLinks,
HeaderPanelDivider,
HeaderPanelLink,
SideNav,
SideNavItems,
SideNavMenu,
SideNavMenuItem,
SideNavLink,
SkipToContent,
Content,
Grid,
Row,
Column,
} from "carbon-components-svelte";
import type { ComponentProps } from "svelte";
let isSideNavOpen = false;
let isOpen = false;
let ref: ComponentProps<HeaderSearch>["ref"] = null;
let active = false;
let value = "";
let selectedResultIndex = 1;
$: results =
value.length > 2
? [
{
href: "/",
text: "Result 1",
description: "Result description",
},
{
href: "/",
text: "Result 2",
description: "Result description",
},
{
href: "/",
text: "Result 3",
description: "Result description",
},
]
: [];
$: console.log("ref", ref);
$: console.log("active", active);
$: console.log("value", value);
$: console.log("selectedResultIndex", selectedResultIndex);
</script>
<Header company="IBM" platformName="Carbon Svelte" bind:isSideNavOpen>
<div slot="skip-to-content">
<SkipToContent />
</div>
<HeaderUtilities>
<HeaderSearch
bind:ref
bind:active
bind:value
bind:selectedResultIndex
{results}
on:active
on:inactive
on:clear={() => {
console.log("on:clear");
}}
on:select={(e) => {
console.log("on:select", e.detail);
}}
on:paste
let:result
let:index
>
<div>{result.text}{index}</div>
</HeaderSearch>
<HeaderAction bind:isOpen>
<HeaderPanelLinks>
<HeaderPanelDivider>Switcher subject 1</HeaderPanelDivider>
<HeaderPanelLink>Switcher item 1</HeaderPanelLink>
<HeaderPanelDivider>Switcher subject 2</HeaderPanelDivider>
<HeaderPanelLink>Switcher item 1</HeaderPanelLink>
<HeaderPanelLink>Switcher item 2</HeaderPanelLink>
<HeaderPanelLink>Switcher item 3</HeaderPanelLink>
<HeaderPanelLink>Switcher item 4</HeaderPanelLink>
<HeaderPanelLink>Switcher item 5</HeaderPanelLink>
</HeaderPanelLinks>
</HeaderAction>
</HeaderUtilities>
</Header>
<SideNav bind:isOpen={isSideNavOpen}>
<SideNavItems>
<SideNavLink text="Link 1" />
<SideNavLink text="Link 2" />
<SideNavLink text="Link 3" />
<SideNavMenu text="Menu">
<SideNavMenuItem href="/" text="Link 1" />
<SideNavMenuItem href="/" text="Link 2" />
<SideNavMenuItem href="/" text="Link 3" />
</SideNavMenu>
</SideNavItems>
</SideNav>
<Content>
<Grid>
<Row>
<Column>
<h1>Welcome</h1>
</Column>
</Row>
</Grid>
</Content>

View file

@ -1,66 +0,0 @@
<script lang="ts">
import {
Header,
HeaderUtilities,
HeaderAction,
HeaderPanelLinks,
HeaderPanelDivider,
HeaderPanelLink,
SideNav,
SideNavItems,
SideNavMenu,
SideNavMenuItem,
SideNavLink,
SkipToContent,
Content,
Grid,
Row,
Column,
} from "carbon-components-svelte";
let isSideNavOpen = false;
let isOpen = false;
</script>
<Header company="IBM" platformName="Carbon Svelte" bind:isSideNavOpen>
<div slot="skip-to-content">
<SkipToContent />
</div>
<HeaderUtilities>
<HeaderAction bind:isOpen transition={false}>
<HeaderPanelLinks>
<HeaderPanelDivider>Switcher subject 1</HeaderPanelDivider>
<HeaderPanelLink>Switcher item 1</HeaderPanelLink>
<HeaderPanelDivider>Switcher subject 2</HeaderPanelDivider>
<HeaderPanelLink>Switcher item 1</HeaderPanelLink>
<HeaderPanelLink>Switcher item 2</HeaderPanelLink>
<HeaderPanelLink>Switcher item 3</HeaderPanelLink>
<HeaderPanelLink>Switcher item 4</HeaderPanelLink>
<HeaderPanelLink>Switcher item 5</HeaderPanelLink>
</HeaderPanelLinks>
</HeaderAction>
</HeaderUtilities>
</Header>
<SideNav bind:isOpen={isSideNavOpen}>
<SideNavItems>
<SideNavLink text="Link 1" />
<SideNavLink text="Link 2" />
<SideNavLink text="Link 3" />
<SideNavMenu text="Menu">
<SideNavMenuItem href="/" text="Link 1" />
<SideNavMenuItem href="/" text="Link 2" />
<SideNavMenuItem href="/" text="Link 3" />
</SideNavMenu>
</SideNavItems>
</SideNav>
<Content>
<Grid>
<Row>
<Column>
<h1>Welcome</h1>
</Column>
</Row>
</Grid>
</Content>

View file

@ -1,77 +0,0 @@
<script lang="ts">
import {
Header,
HeaderUtilities,
HeaderAction,
HeaderGlobalAction,
HeaderPanelLinks,
HeaderPanelDivider,
HeaderPanelLink,
SideNav,
SideNavItems,
SideNavMenu,
SideNavMenuItem,
SideNavLink,
SkipToContent,
Content,
Grid,
Row,
Column,
} from "carbon-components-svelte";
import SettingsAdjust from "carbon-icons-svelte/lib/SettingsAdjust.svelte";
import { quintOut } from "svelte/easing";
let isSideNavOpen = false;
let isOpen = false;
</script>
<Header company="IBM" platformName="Carbon Svelte" bind:isSideNavOpen>
<div slot="skip-to-content">
<SkipToContent />
</div>
<HeaderUtilities>
<HeaderGlobalAction iconDescription="Settings" icon={SettingsAdjust} />
<HeaderAction
bind:isOpen
on:open
on:close
iconDescription="Switcher"
tooltipAlignment="start"
transition={{ duration: 400, easing: quintOut }}
>
<HeaderPanelLinks>
<HeaderPanelDivider>Switcher subject 1</HeaderPanelDivider>
<HeaderPanelLink>Switcher item 1</HeaderPanelLink>
<HeaderPanelDivider>Switcher subject 2</HeaderPanelDivider>
<HeaderPanelLink>Switcher item 1</HeaderPanelLink>
<HeaderPanelLink>Switcher item 2</HeaderPanelLink>
<HeaderPanelLink>Switcher item 3</HeaderPanelLink>
<HeaderPanelLink>Switcher item 4</HeaderPanelLink>
<HeaderPanelLink>Switcher item 5</HeaderPanelLink>
</HeaderPanelLinks>
</HeaderAction>
</HeaderUtilities>
</Header>
<SideNav bind:isOpen={isSideNavOpen}>
<SideNavItems>
<SideNavLink text="Link 1" />
<SideNavLink text="Link 2" />
<SideNavLink text="Link 3" />
<SideNavMenu text="Menu">
<SideNavMenuItem href="/" text="Link 1" />
<SideNavMenuItem href="/" text="Link 2" />
<SideNavMenuItem href="/" text="Link 3" />
</SideNavMenu>
</SideNavItems>
</SideNav>
<Content>
<Grid>
<Row>
<Column>
<h1>Welcome</h1>
</Column>
</Row>
</Grid>
</Content>

View file

@ -1,3 +1,5 @@
<svelte:options accessors />
<script lang="ts">
import {
Header,
@ -16,7 +18,7 @@
Column,
} from "carbon-components-svelte";
let isSideNavOpen = false;
export let isSideNavOpen = false;
</script>
<Header

View file

@ -0,0 +1,96 @@
import { render, screen } from "@testing-library/svelte";
import { user } from "../setup-tests";
import PersistedHamburgerMenuTest from "./PersistedHamburgerMenu.test.svelte";
describe("PersistedHamburgerMenu Example", () => {
it("renders the complete header structure with persistent hamburger menu", () => {
render(PersistedHamburgerMenuTest);
// Verify header and company/platform name
const header = screen.getByRole("banner");
expect(header).toBeInTheDocument();
expect(screen.getByText("IBM")).toBeInTheDocument();
expect(screen.getByText("Carbon Svelte")).toBeInTheDocument();
// Verify navigation items
expect(screen.getAllByRole("link", { name: "Link 1" })).toHaveLength(2);
expect(screen.getAllByRole("link", { name: "Link 2" })).toHaveLength(2);
expect(screen.getAllByRole("link", { name: "Link 3" })).toHaveLength(2);
// Verify menu
const menu = screen.getByRole("menuitem", { name: "Menu" });
expect(menu).toBeInTheDocument();
expect(menu).toHaveAttribute("aria-haspopup", "menu");
expect(menu).toHaveAttribute("aria-expanded", "false");
// Verify skip to content
expect(
screen.getByRole("link", { name: "Skip to main content" }),
).toBeInTheDocument();
// Verify content
expect(screen.getByRole("main")).toBeInTheDocument();
expect(
screen.getByRole("heading", { name: "Welcome" }),
).toBeInTheDocument();
});
it("renders side navigation with persistent hamburger menu", () => {
render(PersistedHamburgerMenuTest);
// Verify side nav is present
const sideNav = screen.getByRole("complementary");
expect(sideNav).toBeInTheDocument();
// Verify side nav links
const sideNavItems = sideNav.querySelectorAll(".bx--side-nav__item");
expect(sideNavItems).toHaveLength(4); // 3 links + 1 menu
// Verify side nav menu
const sideNavMenu = sideNav.querySelector(".bx--side-nav__submenu");
expect(sideNavMenu).toBeInTheDocument();
expect(sideNavMenu).toHaveAttribute("aria-expanded", "false");
});
it("handles side navigation state with persistent hamburger menu", async () => {
const { component } = render(PersistedHamburgerMenuTest);
// Initial state
expect(component.isSideNavOpen).toBe(false);
// Simulate opening side nav
component.isSideNavOpen = true;
await new Promise((resolve) => setTimeout(resolve, 0));
// Verify header has expanded class
const header = screen.getByRole("banner");
expect(header).toHaveClass("bx--header--expanded");
// Verify side nav is expanded
const sideNav = screen.getByRole("complementary");
expect(sideNav).toHaveClass("bx--side-nav--expanded");
});
it("handles navigation menu interaction in side nav", async () => {
render(PersistedHamburgerMenuTest);
// Open side nav first
const { component } = render(PersistedHamburgerMenuTest);
component.isSideNavOpen = true;
await new Promise((resolve) => setTimeout(resolve, 0));
const menu = screen
.getByRole("complementary")
.querySelector(".bx--side-nav__submenu");
await user.click(menu!);
// Verify menu is expanded
expect(menu).toHaveAttribute("aria-expanded", "true");
// Verify menu items are visible
const menuItems = screen
.getByRole("complementary")
.querySelectorAll(".bx--side-nav__item");
expect(menuItems).toHaveLength(7); // 3 main items + menu + 3 submenu items
});
});