test(structured-list): add unit tests

This commit is contained in:
Eric Liu 2025-03-20 16:02:16 -07:00
commit 059c7af88a
4 changed files with 236 additions and 100 deletions

View file

@ -1,100 +0,0 @@
<script lang="ts">
import {
StructuredList,
StructuredListSkeleton,
StructuredListBody,
StructuredListHead,
StructuredListCell,
StructuredListRow,
StructuredListInput,
} from "carbon-components-svelte";
import CheckmarkFilled from "carbon-icons-svelte/lib/CheckmarkFilled.svelte";
</script>
<StructuredList
selection
selected="row-1-value"
on:change={(e) => {
console.log(e.detail); // string
}}
>
<StructuredListHead>
<StructuredListRow head>
<StructuredListCell head>Column A</StructuredListCell>
<StructuredListCell head>Column B</StructuredListCell>
<StructuredListCell head>Column C</StructuredListCell>
</StructuredListRow>
</StructuredListHead>
<StructuredListBody>
<StructuredListRow>
<StructuredListCell noWrap>Row 1</StructuredListCell>
<StructuredListCell>Row 1</StructuredListCell>
<StructuredListCell>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc dui magna,
finibus id tortor sed, aliquet bibendum augue. Aenean posuere sem vel
euismod dignissim. Nulla ut cursus dolor. Pellentesque vulputate nisl a
porttitor interdum.
</StructuredListCell>
</StructuredListRow>
<StructuredListRow>
<StructuredListCell noWrap>Row 2</StructuredListCell>
<StructuredListCell>Row 2</StructuredListCell>
<StructuredListCell>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc dui magna,
finibus id tortor sed, aliquet bibendum augue. Aenean posuere sem vel
euismod dignissim. Nulla ut cursus dolor. Pellentesque vulputate nisl a
porttitor interdum.
</StructuredListCell>
</StructuredListRow>
<StructuredListRow>
<StructuredListCell noWrap>Row 3</StructuredListCell>
<StructuredListCell>Row 3</StructuredListCell>
<StructuredListCell>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc dui magna,
finibus id tortor sed, aliquet bibendum augue. Aenean posuere sem vel
euismod dignissim. Nulla ut cursus dolor. Pellentesque vulputate nisl a
porttitor interdum.
</StructuredListCell>
</StructuredListRow>
</StructuredListBody>
</StructuredList>
<StructuredList selection selected="row-1-value">
<StructuredListHead>
<StructuredListRow head>
<StructuredListCell head>ColumnA</StructuredListCell>
<StructuredListCell head>ColumnB</StructuredListCell>
<StructuredListCell head>ColumnC</StructuredListCell>
<StructuredListCell head>{""}</StructuredListCell>
</StructuredListRow>
</StructuredListHead>
<StructuredListBody>
{#each [1, 2, 3] as item}
<StructuredListRow label for="row-{item}">
<StructuredListCell>Row {item}</StructuredListCell>
<StructuredListCell>Row {item}</StructuredListCell>
<StructuredListCell>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc dui
magna, finibus id tortor sed, aliquet bibendum augue. Aenean posuere
sem vel euismod dignissim. Nulla ut cursus dolor. Pellentesque
vulputate nisl a porttitor interdum.
</StructuredListCell>
<StructuredListInput
id="row-{item}"
value="row-{item}-value"
title="row-{item}-title"
name="row-{item}-name"
/>
<StructuredListCell>
<CheckmarkFilled
class="bx--structured-list-svg"
aria-label="select an option"
title="select an option"
/>
</StructuredListCell>
</StructuredListRow>
{/each}
</StructuredListBody>
</StructuredList>
<StructuredListSkeleton rows={3} />

View file

@ -0,0 +1,79 @@
<script lang="ts">
import {
StructuredList,
StructuredListBody,
StructuredListHead,
StructuredListCell,
StructuredListRow,
StructuredListInput,
} from "carbon-components-svelte";
import CheckmarkFilled from "carbon-icons-svelte/lib/CheckmarkFilled.svelte";
import type { ComponentProps } from "svelte";
export let selected: ComponentProps<StructuredList>["selected"] = undefined;
export let condensed: ComponentProps<StructuredList>["condensed"] = false;
export let flush: ComponentProps<StructuredList>["flush"] = false;
export let selection: ComponentProps<StructuredList>["selection"] = false;
</script>
<StructuredList
bind:selected
{condensed}
{flush}
{selection}
on:click={() => {
console.log("click");
}}
on:mouseover={() => {
console.log("mouseover");
}}
on:mouseenter={() => {
console.log("mouseenter");
}}
on:mouseleave={() => {
console.log("mouseleave");
}}
on:change={(e) => {
console.log("change", e.detail);
}}
>
<StructuredListHead>
<StructuredListRow head>
<StructuredListCell head>Column A</StructuredListCell>
<StructuredListCell head>Column B</StructuredListCell>
<StructuredListCell head>Column C</StructuredListCell>
{#if selection}
<StructuredListCell head>{""}</StructuredListCell>
{/if}
</StructuredListRow>
</StructuredListHead>
<StructuredListBody>
{#each ["1", "2", "3"] as item}
<StructuredListRow
label={selection}
for={selection ? `row-${item}` : undefined}
>
<StructuredListCell noWrap>Row {item}</StructuredListCell>
<StructuredListCell>Row {item}</StructuredListCell>
<StructuredListCell>Content {item}</StructuredListCell>
{#if selection}
<StructuredListInput
id="row-{item}"
value="row-{item}-value"
title="row-{item}-title"
name="row-{item}-name"
/>
<StructuredListCell>
<CheckmarkFilled
class="bx--structured-list-svg"
aria-label="select an option"
title="select an option"
/>
</StructuredListCell>
{/if}
</StructuredListRow>
{/each}
</StructuredListBody>
</StructuredList>
<div data-testid="value">{selected}</div>

View file

@ -0,0 +1,131 @@
import { render, screen } from "@testing-library/svelte";
import { user } from "../setup-tests";
import StructuredList from "./StructuredList.test.svelte";
import StructuredListCustom from "./StructuredListCustom.test.svelte";
describe("StructuredList", () => {
it("should render with default props", () => {
render(StructuredList);
const list = screen.getByRole("table");
expect(list).toBeInTheDocument();
expect(list).toHaveClass("bx--structured-list");
// Check header cells
const headerCells = screen.getAllByRole("columnheader");
expect(headerCells).toHaveLength(3);
expect(headerCells[0]).toHaveTextContent("Column A");
expect(headerCells[1]).toHaveTextContent("Column B");
expect(headerCells[2]).toHaveTextContent("Column C");
// Check body cells
const cells = screen.getAllByRole("cell");
expect(cells).toHaveLength(9); // 3 rows x 3 columns
expect(cells[0]).toHaveTextContent("Row 1");
expect(cells[1]).toHaveTextContent("Row 1");
expect(cells[2]).toHaveTextContent("Content 1");
});
it("should handle condensed variant", () => {
render(StructuredList, { props: { condensed: true } });
expect(screen.getByRole("table")).toHaveClass(
"bx--structured-list--condensed",
);
});
it("should handle flush variant", () => {
render(StructuredList, { props: { flush: true } });
expect(screen.getByRole("table")).toHaveClass("bx--structured-list--flush");
});
it("should handle selection variant", () => {
render(StructuredList, { props: { selection: true } });
const list = screen.getByRole("table");
expect(list).toHaveClass("bx--structured-list--selection");
const inputs = screen.getAllByRole("radio");
expect(inputs).toHaveLength(3);
const checkmarks = screen.getAllByTitle("select an option");
expect(checkmarks).toHaveLength(3);
});
it("should handle selected state", async () => {
render(StructuredList, {
props: { selection: true, selected: "row-1-value" },
});
const selectedInput = screen.getByRole("radio", { checked: true });
expect(selectedInput.closest("label")).toHaveTextContent("Row 1");
await user.click(screen.getAllByRole("radio")[1]);
expect(
screen.getByRole("radio", { checked: true }).closest("label"),
).toHaveTextContent("Row 2");
});
it("should handle selection change", async () => {
render(StructuredList, { props: { selection: true } });
const secondInput = screen.getAllByRole("radio")[1];
await user.click(secondInput);
expect(screen.getByTestId("value").textContent).toBe("row-2-value");
});
it("should handle custom content", () => {
render(StructuredListCustom);
expect(screen.getByTestId("custom-header")).toHaveTextContent(
"Custom Header",
);
expect(screen.getByTestId("custom-content")).toHaveTextContent(
"Custom Content",
);
});
it("should handle mouse events", async () => {
const consoleLog = vi.spyOn(console, "log");
render(StructuredList);
const list = screen.getByRole("table");
await user.click(list);
expect(consoleLog).toHaveBeenCalledWith("click");
await user.hover(list);
expect(consoleLog).toHaveBeenCalledWith("mouseover");
await user.unhover(list);
expect(consoleLog).toHaveBeenCalledWith("mouseleave");
});
it("should handle noWrap cells", () => {
render(StructuredList);
const noWrapCells = screen
.getAllByRole("cell")
.filter(
(cell) =>
cell.textContent?.startsWith("Row") && cell.textContent?.length === 5,
);
noWrapCells.forEach((cell) => {
expect(cell).toHaveClass("bx--structured-list-td");
});
});
it("should emit change event on selection", async () => {
const consoleLog = vi.spyOn(console, "log");
render(StructuredList, { props: { selection: true } });
expect(consoleLog).not.toHaveBeenCalled();
await user.click(screen.getAllByRole("radio")[1]);
expect(consoleLog).toHaveBeenCalledWith("change", "row-2-value");
await user.click(screen.getAllByRole("radio")[0]);
expect(consoleLog).toHaveBeenCalledWith("change", "row-1-value");
});
});

View file

@ -0,0 +1,26 @@
<script lang="ts">
import {
StructuredList,
StructuredListBody,
StructuredListHead,
StructuredListCell,
StructuredListRow,
} from "carbon-components-svelte";
</script>
<StructuredList>
<StructuredListHead>
<StructuredListRow head>
<StructuredListCell head>
<div data-testid="custom-header">Custom Header</div>
</StructuredListCell>
</StructuredListRow>
</StructuredListHead>
<StructuredListBody>
<StructuredListRow>
<StructuredListCell>
<div data-testid="custom-content">Custom Content</div>
</StructuredListCell>
</StructuredListRow>
</StructuredListBody>
</StructuredList>