From ed8e2dc75b144e0bd00fa2c9c81da94e3ee31e15 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Thu, 20 Mar 2025 13:28:01 -0700 Subject: [PATCH] test(radio-tile): add unit tests --- tests/RadioTile.test.svelte | 17 -- tests/RadioTile/RadioTile.group.test.svelte | 25 +++ tests/RadioTile/RadioTile.single.test.svelte | 7 + tests/RadioTile/RadioTile.test.svelte | 43 ++++ tests/RadioTile/RadioTile.test.ts | 197 +++++++++++++++++++ tests/RadioTile/RadioTileCustom.test.svelte | 9 + 6 files changed, 281 insertions(+), 17 deletions(-) delete mode 100644 tests/RadioTile.test.svelte create mode 100644 tests/RadioTile/RadioTile.group.test.svelte create mode 100644 tests/RadioTile/RadioTile.single.test.svelte create mode 100644 tests/RadioTile/RadioTile.test.svelte create mode 100644 tests/RadioTile/RadioTile.test.ts create mode 100644 tests/RadioTile/RadioTileCustom.test.svelte diff --git a/tests/RadioTile.test.svelte b/tests/RadioTile.test.svelte deleted file mode 100644 index 45356d3b..00000000 --- a/tests/RadioTile.test.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - - { - console.log(e.detail); // string - }} -> - Lite plan - Standard plan - Plus plan - diff --git a/tests/RadioTile/RadioTile.group.test.svelte b/tests/RadioTile/RadioTile.group.test.svelte new file mode 100644 index 00000000..defafb8a --- /dev/null +++ b/tests/RadioTile/RadioTile.group.test.svelte @@ -0,0 +1,25 @@ + + + + {#each values as value} + {value} + {/each} + + +
+ Selected: {selected} +
+ + diff --git a/tests/RadioTile/RadioTile.single.test.svelte b/tests/RadioTile/RadioTile.single.test.svelte new file mode 100644 index 00000000..6a986a02 --- /dev/null +++ b/tests/RadioTile/RadioTile.single.test.svelte @@ -0,0 +1,7 @@ + + + +
Custom content
+
diff --git a/tests/RadioTile/RadioTile.test.svelte b/tests/RadioTile/RadioTile.test.svelte new file mode 100644 index 00000000..84d734e4 --- /dev/null +++ b/tests/RadioTile/RadioTile.test.svelte @@ -0,0 +1,43 @@ + + + + { + console.log("change"); + }} + on:keydown + on:click + on:mouseover + on:mouseenter + on:mouseleave + > + Test content + + diff --git a/tests/RadioTile/RadioTile.test.ts b/tests/RadioTile/RadioTile.test.ts new file mode 100644 index 00000000..351c01dc --- /dev/null +++ b/tests/RadioTile/RadioTile.test.ts @@ -0,0 +1,197 @@ +import { render, screen } from "@testing-library/svelte"; +import { user } from "../setup-tests"; +import RadioTile from "./RadioTile.test.svelte"; +import RadioTileCustom from "./RadioTileCustom.test.svelte"; +import RadioTileSingle from "./RadioTile.single.test.svelte"; +import RadioTileGroup from "./RadioTile.group.test.svelte"; + +describe("RadioTile", () => { + it("should render with default props", () => { + render(RadioTile); + + const input = screen.getByRole("radio"); + expect(input).toBeInTheDocument(); + expect(input).toHaveAttribute("name", "test-group"); + expect(input).toHaveAttribute("value", "test"); + expect(input).not.toBeChecked(); + expect(screen.getByText("Test content")).toBeInTheDocument(); + expect(screen.getByTitle("Tile checkmark")).toBeInTheDocument(); + }); + + it("should handle checked state", () => { + render(RadioTile, { + props: { checked: true }, + }); + + const input = screen.getByRole("radio"); + expect(input).toBeChecked(); + expect(screen.getByText("Test content").closest(".bx--tile")).toHaveClass( + "bx--tile--is-selected", + ); + }); + + it("should handle light variant", () => { + render(RadioTile, { + props: { light: true }, + }); + + expect(screen.getByText("Test content").closest(".bx--tile")).toHaveClass( + "bx--tile--light", + ); + }); + + it("should handle disabled state", () => { + render(RadioTile, { + props: { disabled: true }, + }); + + const input = screen.getByRole("radio"); + expect(input).toBeDisabled(); + expect(screen.getByText("Test content").closest(".bx--tile")).toHaveClass( + "bx--tile--disabled", + ); + }); + + it("should handle required state", () => { + render(RadioTile, { + props: { required: true }, + }); + + expect(screen.getByRole("radio")).toHaveAttribute("required"); + }); + + it("should handle custom value", () => { + render(RadioTile, { + props: { value: "custom-value" }, + }); + + expect(screen.getByRole("radio")).toHaveAttribute("value", "custom-value"); + }); + + it("should handle custom tabindex", () => { + render(RadioTile, { + props: { tabindex: "1" }, + }); + + expect(screen.getByRole("radio")).toHaveAttribute("tabindex", "1"); + }); + + it("should handle custom icon description", () => { + render(RadioTile, { + props: { iconDescription: "Custom checkmark" }, + }); + + expect(screen.getByTitle("Custom checkmark")).toBeInTheDocument(); + }); + + it("should handle custom id", () => { + render(RadioTile, { props: { id: "custom-id" } }); + + expect(screen.getByRole("radio")).toHaveAttribute("id", "custom-id"); + + const radioTileLabel = screen.getByText("Test content").closest("label"); + assert(radioTileLabel); + expect(radioTileLabel).toHaveAttribute("for", "custom-id"); + }); + + // TODO(bug): support standalone radio tile. + it.skip("should handle custom name", () => { + render(RadioTileSingle); + + expect(screen.getByRole("radio")).toHaveAttribute("name", "custom-name"); + }); + + it("should handle custom slots", () => { + render(RadioTileCustom); + + expect(screen.getByText("Custom content")).toBeInTheDocument(); + }); + + it("should handle change event", async () => { + const consoleLog = vi.spyOn(console, "log"); + render(RadioTile); + + const input = screen.getByRole("radio"); + await user.click(input); + + expect(input).toBeChecked(); + expect(consoleLog).toHaveBeenCalledWith("change"); + }); + + it("should handle keyboard events", async () => { + render(RadioTileGroup); + + const inputs = screen.getAllByRole("radio"); + + expect(inputs[1]).not.toHaveFocus(); + expect(inputs[1]).toBeChecked(); + + await user.tab(); + expect(inputs[1]).toHaveFocus(); + + await user.keyboard("{ArrowDown}"); + expect(inputs[2]).toHaveFocus(); + expect(inputs[2]).toBeChecked(); + + await user.keyboard("{ArrowDown}"); + expect(inputs[0]).toHaveFocus(); + expect(inputs[0]).toBeChecked(); + }); + + it("supports programmatic selection", async () => { + render(RadioTileGroup); + + const inputs = screen.getAllByRole("radio"); + expect(inputs[1]).not.toHaveFocus(); + expect(inputs[1]).toBeChecked(); + expect(screen.getByText(/Selected: Standard plan/)).toBeInTheDocument(); + + await user.click(inputs[2]); + expect(inputs[2]).toHaveFocus(); + expect(inputs[2]).toBeChecked(); + expect(screen.getByText(/Selected: Plus plan/)).toBeInTheDocument(); + + await user.click(screen.getByRole("button")); + expect(inputs[1]).not.toHaveFocus(); + expect(inputs[1]).toBeChecked(); + expect(screen.getByText(/Selected: Standard plan/)).toBeInTheDocument(); + }); + + it("should handle disabled state with events", async () => { + render(RadioTile, { + props: { disabled: true }, + }); + + const input = screen.getByRole("radio"); + await user.click(input); + expect(input).not.toBeChecked(); + }); + + it("should handle mouse events", async () => { + render(RadioTile); + + const tile = screen.getByText("Test content").closest(".bx--tile"); + assert(tile); + await user.hover(tile); + await user.unhover(tile); + }); + + it("should handle custom content slot", () => { + render(RadioTileCustom); + + const content = screen.getByText("Custom content"); + expect(content).toBeInTheDocument(); + expect(content.tagName).toBe("DIV"); + }); + + it("should handle TileGroup context", () => { + render(RadioTile, { props: { checked: true } }); + + const input = screen.getByRole("radio"); + expect(input).toBeChecked(); + expect(screen.getByText("Test content").closest(".bx--tile")).toHaveClass( + "bx--tile--is-selected", + ); + expect(input).toHaveAttribute("name", "test-group"); + }); +}); diff --git a/tests/RadioTile/RadioTileCustom.test.svelte b/tests/RadioTile/RadioTileCustom.test.svelte new file mode 100644 index 00000000..9d97ddf9 --- /dev/null +++ b/tests/RadioTile/RadioTileCustom.test.svelte @@ -0,0 +1,9 @@ + + + + +
Custom content
+
+