test(pagination): add unit tests

This commit is contained in:
Eric Liu 2025-03-17 18:05:00 -07:00
commit a73000ffbe
3 changed files with 240 additions and 24 deletions

View file

@ -0,0 +1,41 @@
<script lang="ts">
import { Pagination } from "carbon-components-svelte";
export let page = 1;
export let totalItems = 0;
export let disabled = false;
export let forwardText = "Next page";
export let backwardText = "Previous page";
export let itemsPerPageText = "Items per page:";
export let pageInputDisabled = false;
export let pageSizeInputDisabled = false;
export let pageSize = 10;
export let pageSizes: ReadonlyArray<number> = [10];
export let pagesUnknown = false;
</script>
<Pagination
bind:page
{totalItems}
{disabled}
{forwardText}
{backwardText}
{itemsPerPageText}
{pageInputDisabled}
{pageSizeInputDisabled}
bind:pageSize
{pageSizes}
{pagesUnknown}
on:change={(e) => {
console.log("change", e.detail);
}}
on:click:button--previous={(e) => {
console.log("previous", e.detail);
}}
on:click:button--next={(e) => {
console.log("next", e.detail);
}}
on:update={(e) => {
console.log("update", e.detail);
}}
/>

View file

@ -0,0 +1,199 @@
import { render, screen, within } from "@testing-library/svelte";
import { user } from "../setup-tests";
import Pagination from "./Pagination.test.svelte";
describe("Pagination", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("should render with default props", () => {
render(Pagination);
expect(screen.getByText("Items per page:")).toBeInTheDocument();
expect(
screen.getByRole("button", { name: "Next page" }),
).toBeInTheDocument();
expect(
screen.getByRole("button", { name: "Previous page" }),
).toBeInTheDocument();
});
it("should render with custom total items", () => {
render(Pagination, {
props: { totalItems: 102 },
});
expect(screen.getByText("110 of 102 items")).toBeInTheDocument();
});
it("should handle custom page sizes", () => {
render(Pagination, {
props: {
totalItems: 102,
pageSizes: [10, 15, 20],
pageSize: 15,
},
});
const select = screen.getByRole("combobox", { name: "Items per page:" });
expect(select).toHaveValue("15");
const options = within(select).getAllByRole("option");
expect(options).toHaveLength(3);
expect(options[0]).toHaveTextContent("10");
expect(options[1]).toHaveTextContent("15");
expect(options[2]).toHaveTextContent("20");
});
it("should handle page navigation", async () => {
const consoleLog = vi.spyOn(console, "log");
render(Pagination, {
props: { totalItems: 102, page: 1 },
});
const nextButton = screen.getByRole("button", { name: "Next page" });
await user.click(nextButton);
expect(consoleLog).toHaveBeenCalledWith("next", { page: 2 });
expect(consoleLog).toHaveBeenCalledWith("change", { page: 2 });
const prevButton = screen.getByRole("button", { name: "Previous page" });
await user.click(prevButton);
expect(consoleLog).toHaveBeenCalledWith("previous", { page: 1 });
expect(consoleLog).toHaveBeenCalledWith("change", { page: 1 });
});
it("should handle page size changes", async () => {
const consoleLog = vi.spyOn(console, "log");
render(Pagination, {
props: {
totalItems: 102,
pageSizes: [10, 15, 20],
},
});
const select = screen.getByRole("combobox", { name: "Items per page:" });
await user.selectOptions(select, "15");
expect(consoleLog).toHaveBeenCalledWith("change", { pageSize: 10 });
expect(consoleLog).toHaveBeenCalledWith("update", {
pageSize: 15,
page: 1,
});
});
it("should handle page selection", async () => {
const consoleLog = vi.spyOn(console, "log");
render(Pagination, {
props: { totalItems: 102, pageSizes: [5, 10, 15] },
});
const pageSelect = screen.getAllByRole("combobox");
await user.selectOptions(pageSelect[0], "5");
expect(consoleLog).toHaveBeenCalledWith("change", { pageSize: 10 });
expect(consoleLog).toHaveBeenCalledWith("update", { pageSize: 5, page: 1 });
});
it("should disable navigation buttons when disabled", () => {
render(Pagination, {
props: { disabled: true },
});
const prevButton = screen.getByRole("button", { name: "Previous page" });
const nextButton = screen.getByRole("button", { name: "Next page" });
expect(prevButton).toBeDisabled();
expect(nextButton).toBeDisabled();
});
it("should handle custom button text", () => {
render(Pagination, {
props: {
forwardText: "Next",
backwardText: "Previous",
},
});
expect(
screen.getByRole("button", { name: "Previous" }),
).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Next" })).toBeInTheDocument();
});
it("should handle custom items per page text", () => {
render(Pagination, {
props: {
itemsPerPageText: "Show:",
},
});
expect(screen.getByText("Show:")).toBeInTheDocument();
});
it("should handle disabled page input", () => {
render(Pagination, {
props: { pageInputDisabled: true },
});
expect(
screen.queryByRole("combobox", { name: "Page number" }),
).not.toBeInTheDocument();
});
it("should handle disabled page size input", () => {
render(Pagination, {
props: { pageSizeInputDisabled: true },
});
expect(
screen.queryByRole("combobox", { name: "Items per page:" }),
).not.toBeInTheDocument();
});
it("should handle unknown pages", () => {
render(Pagination, {
props: { pagesUnknown: true },
});
expect(screen.getByText("110 items")).toBeInTheDocument();
expect(screen.getByText("page 1")).toBeInTheDocument();
});
it("should update when page or pageSize changes", async () => {
const consoleLog = vi.spyOn(console, "log");
render(Pagination, {
props: { totalItems: 102, pageSizes: [5, 10, 15] },
});
// Change page size
const pageSizeSelect = screen.getAllByRole("combobox");
await user.selectOptions(pageSizeSelect[0], "15");
expect(consoleLog).toHaveBeenCalledWith("change", { pageSize: 10 });
expect(consoleLog).toHaveBeenCalledWith("update", {
pageSize: 15,
page: 1,
});
// Change page
const pageSelect = screen.getAllByRole("combobox");
await user.selectOptions(pageSelect[1], "2");
expect(consoleLog).toHaveBeenCalledWith("change", { pageSize: 10 });
expect(consoleLog).toHaveBeenCalledWith("update", {
pageSize: 15,
page: 2,
});
});
it("should handle edge cases", () => {
render(Pagination, {
props: {
totalItems: 0,
page: 1,
pageSize: 10,
},
});
expect(screen.getByText("00 of 0 items")).toBeInTheDocument();
});
});