From f89e9df8f01ac8f0ca48df690e0b16da0093801b Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Thu, 20 Mar 2025 15:50:54 -0700 Subject: [PATCH] test(expandable-tile): add unit tests --- tests/ExpandableTile.test.svelte | 22 --- .../ExpandableTile/ExpandableTile.test.svelte | 46 ++++++ tests/ExpandableTile/ExpandableTile.test.ts | 149 ++++++++++++++++++ .../ExpandableTileCustom.test.svelte | 31 ++++ tests/setup-tests.ts | 37 +++++ 5 files changed, 263 insertions(+), 22 deletions(-) delete mode 100644 tests/ExpandableTile.test.svelte create mode 100644 tests/ExpandableTile/ExpandableTile.test.svelte create mode 100644 tests/ExpandableTile/ExpandableTile.test.ts create mode 100644 tests/ExpandableTile/ExpandableTileCustom.test.svelte diff --git a/tests/ExpandableTile.test.svelte b/tests/ExpandableTile.test.svelte deleted file mode 100644 index 53927f6d..00000000 --- a/tests/ExpandableTile.test.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - - -
Above the fold content here
-
Below the fold content here
-
- - -
Above the fold content here
-
Below the fold content here
-
- - -
Above the fold content here
-
Below the fold content here
-
diff --git a/tests/ExpandableTile/ExpandableTile.test.svelte b/tests/ExpandableTile/ExpandableTile.test.svelte new file mode 100644 index 00000000..9592038f --- /dev/null +++ b/tests/ExpandableTile/ExpandableTile.test.svelte @@ -0,0 +1,46 @@ + + + +
+ Above the fold content here +
+
+ Below the fold content here +
+
diff --git a/tests/ExpandableTile/ExpandableTile.test.ts b/tests/ExpandableTile/ExpandableTile.test.ts new file mode 100644 index 00000000..471722aa --- /dev/null +++ b/tests/ExpandableTile/ExpandableTile.test.ts @@ -0,0 +1,149 @@ +import { render, screen } from "@testing-library/svelte"; +import { user } from "../setup-tests"; +import ExpandableTile from "./ExpandableTile.test.svelte"; +import ExpandableTileCustom from "./ExpandableTileCustom.test.svelte"; + +describe("ExpandableTile", () => { + it("should render with default props", () => { + render(ExpandableTile); + + const tile = screen.getByRole("button"); + expect(tile).toBeInTheDocument(); + expect(tile).toHaveAttribute("aria-expanded", "false"); + expect(tile).toHaveAttribute("title", "Interact to expand Tile"); + expect(screen.getByTestId("above-content")).toBeInTheDocument(); + expect(screen.getByTestId("below-content")).toBeInTheDocument(); + }); + + it("should handle expanded state", () => { + render(ExpandableTile, { props: { expanded: true } }); + + const tile = screen.getByRole("button"); + expect(tile).toHaveAttribute("aria-expanded", "true"); + expect(tile).toHaveAttribute("title", "Interact to collapse Tile"); + expect(tile).toHaveClass("bx--tile--is-expanded"); + }); + + it("should handle light variant", () => { + render(ExpandableTile, { props: { light: true } }); + + expect(screen.getByRole("button")).toHaveClass("bx--tile--light"); + }); + + it("should handle custom icon text", async () => { + render(ExpandableTile, { + props: { + tileCollapsedIconText: "Custom collapsed text", + tileExpandedIconText: "Custom expanded text", + }, + }); + + const tile = screen.getByRole("button"); + expect(tile).toHaveAttribute("title", "Custom collapsed text"); + + await user.click(tile); + expect(tile).toHaveAttribute("title", "Custom expanded text"); + }); + + it("should handle custom labels", async () => { + render(ExpandableTile, { + props: { + tileCollapsedLabel: "Show more", + tileExpandedLabel: "Show less", + }, + }); + + expect(screen.getByText("Show more")).toBeInTheDocument(); + + await user.click(screen.getByRole("button")); + expect(screen.getByText("Show less")).toBeInTheDocument(); + }); + + it("should handle custom tabindex", () => { + render(ExpandableTile, { props: { tabindex: "1" } }); + + expect(screen.getByRole("button")).toHaveAttribute("tabindex", "1"); + }); + + it("should handle custom id", () => { + render(ExpandableTile, { props: { id: "custom-id" } }); + + expect(screen.getByRole("button")).toHaveAttribute("id", "custom-id"); + }); + + it("should toggle expanded state on click", async () => { + render(ExpandableTile); + + const tile = screen.getByRole("button"); + expect(tile).toHaveAttribute("aria-expanded", "false"); + + await user.click(tile); + expect(tile).toHaveAttribute("aria-expanded", "true"); + + await user.click(tile); + expect(tile).toHaveAttribute("aria-expanded", "false"); + }); + + it("should handle keyboard events", async () => { + render(ExpandableTile); + + const tile = screen.getByRole("button"); + await user.tab(); + expect(tile).toHaveFocus(); + + await user.keyboard("{Enter}"); + expect(tile).toHaveAttribute("aria-expanded", "true"); + + await user.keyboard(" "); + expect(tile).toHaveAttribute("aria-expanded", "false"); + }); + + it("should handle interactive content without toggling", async () => { + render(ExpandableTileCustom); + + const tileButton = screen.getAllByRole("button")[0]; + const link = screen.getByTestId("test-link"); + const button = screen.getByTestId("test-button"); + + expect(tileButton).toHaveAttribute("aria-expanded", "false"); + + await user.click(link); + expect(tileButton).toHaveAttribute("aria-expanded", "false"); + + await user.click(button); + expect(tileButton).toHaveAttribute("aria-expanded", "false"); + }); + + it("should handle mouse events", async () => { + render(ExpandableTile); + + const tile = screen.getByRole("button"); + await user.hover(tile); + await user.unhover(tile); + }); + + it("should handle custom content slots", () => { + render(ExpandableTile); + + const aboveContent = screen.getByTestId("above-content"); + const belowContent = screen.getByTestId("below-content"); + + expect(aboveContent).toHaveTextContent("Above the fold content here"); + expect(belowContent).toHaveTextContent("Below the fold content here"); + }); + + it("should handle max height and padding", async () => { + render(ExpandableTile, { + props: { + tileMaxHeight: 200, + tilePadding: 20, + }, + }); + + const tile = screen.getByRole("button"); + expect(tile.getAttribute("style")).toBe("max-height: 105px;"); + + await user.click(tile); + expect(tile.getAttribute("style")).toBe("max-height: none;"); + }); +}); diff --git a/tests/ExpandableTile/ExpandableTileCustom.test.svelte b/tests/ExpandableTile/ExpandableTileCustom.test.svelte new file mode 100644 index 00000000..035b59bf --- /dev/null +++ b/tests/ExpandableTile/ExpandableTileCustom.test.svelte @@ -0,0 +1,31 @@ + + + +
+ { + linkClicked = true; + }} + > + Test link + +

+ +
+
Below the fold content here
+
diff --git a/tests/setup-tests.ts b/tests/setup-tests.ts index c69af710..8f22aad9 100644 --- a/tests/setup-tests.ts +++ b/tests/setup-tests.ts @@ -6,4 +6,41 @@ import "../css/all.css"; // Mock scrollIntoView since it's not implemented in JSDOM Element.prototype.scrollIntoView = vi.fn(); +// Mock ResizeObserver since it's not implemented in JSDOM +class ResizeObserverMock { + callback: ResizeObserverCallback; + elements: Element[]; + + constructor(callback: ResizeObserverCallback) { + this.callback = callback; + this.elements = []; + } + + observe(element: Element) { + this.elements.push(element); + this.callback( + [ + { + target: element, + contentRect: { height: 100 } as DOMRectReadOnly, + borderBoxSize: [], + contentBoxSize: [], + devicePixelContentBoxSize: [], + }, + ], + this, + ); + } + + unobserve(element: Element) { + this.elements = this.elements.filter((el) => el !== element); + } + + disconnect() { + this.elements = []; + } +} + +global.ResizeObserver = ResizeObserverMock; + export const user = userEvent.setup();