mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-14 18:01:06 +00:00
test(context-menu): add unit tests
This commit is contained in:
parent
7c916828f2
commit
b3816606f6
3 changed files with 137 additions and 58 deletions
|
@ -1,58 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import {
|
|
||||||
ContextMenu,
|
|
||||||
ContextMenuDivider,
|
|
||||||
ContextMenuOption,
|
|
||||||
ContextMenuRadioGroup,
|
|
||||||
ContextMenuGroup,
|
|
||||||
} from "carbon-components-svelte";
|
|
||||||
import CopyFile from "carbon-icons-svelte/lib/CopyFile.svelte";
|
|
||||||
import Cut from "carbon-icons-svelte/lib/Cut.svelte";
|
|
||||||
import type { ComponentProps } from "svelte";
|
|
||||||
|
|
||||||
let ref: HTMLElement;
|
|
||||||
let selectedId = "0";
|
|
||||||
let selectedIds: ComponentProps<ContextMenuGroup>["selectedIds"] = [];
|
|
||||||
|
|
||||||
$: console.log("selectedId", selectedId);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div bind:this={ref}></div>
|
|
||||||
|
|
||||||
<ContextMenu target={null} open on:open={(e) => console.log(e.detail)}>
|
|
||||||
<ContextMenuOption
|
|
||||||
kind="danger"
|
|
||||||
indented
|
|
||||||
labelText="Copy"
|
|
||||||
shortcutText="⌘C"
|
|
||||||
icon={CopyFile}
|
|
||||||
/>
|
|
||||||
<ContextMenuOption indented labelText="Cut" shortcutText="⌘X" icon={Cut} />
|
|
||||||
<ContextMenuDivider />
|
|
||||||
<ContextMenuOption indented labelText="Export as">
|
|
||||||
<ContextMenuGroup labelText="Export options" bind:selectedIds>
|
|
||||||
<ContextMenuOption id="pdf" labelText="PDF" />
|
|
||||||
<ContextMenuOption id="txt" labelText="TXT" />
|
|
||||||
<ContextMenuOption id="mp3" labelText="MP3" />
|
|
||||||
</ContextMenuGroup>
|
|
||||||
</ContextMenuOption>
|
|
||||||
<ContextMenuDivider />
|
|
||||||
<ContextMenuOption selectable labelText="Remove metadata" />
|
|
||||||
<ContextMenuDivider />
|
|
||||||
<ContextMenuGroup labelText="Style options">
|
|
||||||
<ContextMenuOption id="0" labelText="Font smoothing" selected />
|
|
||||||
<ContextMenuOption id="1" labelText="Reduce noise" />
|
|
||||||
<ContextMenuOption id="2" labelText="Auto-sharpen" />
|
|
||||||
</ContextMenuGroup>
|
|
||||||
</ContextMenu>
|
|
||||||
|
|
||||||
<ContextMenu target={[null, ref]} on:open on:close>
|
|
||||||
<ContextMenuOption indented labelText="Open" />
|
|
||||||
<ContextMenuDivider />
|
|
||||||
<ContextMenuRadioGroup bind:selectedId labelText="Radio group">
|
|
||||||
<ContextMenuOption id="0" labelText="Set as foreground" />
|
|
||||||
<ContextMenuOption id="1" labelText="Set as background" />
|
|
||||||
</ContextMenuRadioGroup>
|
|
||||||
<ContextMenuDivider />
|
|
||||||
<ContextMenuOption indented labelText="Lock layer" />
|
|
||||||
</ContextMenu>
|
|
29
tests/ContextMenu/ContextMenu.test.svelte
Normal file
29
tests/ContextMenu/ContextMenu.test.svelte
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { ContextMenu, ContextMenuOption } from "carbon-components-svelte";
|
||||||
|
import type { ComponentProps } from "svelte";
|
||||||
|
|
||||||
|
export let target: ComponentProps<ContextMenu>["target"] = null;
|
||||||
|
export let open = false;
|
||||||
|
export let x = 0;
|
||||||
|
export let y = 0;
|
||||||
|
export let ref: ComponentProps<ContextMenu>["ref"] = null;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div data-testid="target">Right click me</div>
|
||||||
|
|
||||||
|
<ContextMenu
|
||||||
|
bind:target
|
||||||
|
bind:open
|
||||||
|
{x}
|
||||||
|
{y}
|
||||||
|
bind:ref
|
||||||
|
on:open={(e) => {
|
||||||
|
console.log("open", e.detail);
|
||||||
|
}}
|
||||||
|
on:close={() => {
|
||||||
|
console.log("close");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ContextMenuOption>Option 1</ContextMenuOption>
|
||||||
|
<ContextMenuOption>Option 2</ContextMenuOption>
|
||||||
|
</ContextMenu>
|
108
tests/ContextMenu/ContextMenu.test.ts
Normal file
108
tests/ContextMenu/ContextMenu.test.ts
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
import { render, screen } from "@testing-library/svelte";
|
||||||
|
import { user } from "../setup-tests";
|
||||||
|
import ContextMenu from "./ContextMenu.test.svelte";
|
||||||
|
|
||||||
|
describe("ContextMenu", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render with default props", () => {
|
||||||
|
render(ContextMenu);
|
||||||
|
|
||||||
|
const target = screen.getByTestId("target");
|
||||||
|
expect(target).toBeInTheDocument();
|
||||||
|
expect(target).toHaveTextContent("Right click me");
|
||||||
|
|
||||||
|
const menu = screen.getAllByRole("menu");
|
||||||
|
expect(menu[0]).toBeInTheDocument();
|
||||||
|
expect(menu[0]).toHaveClass("bx--menu");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render menu options", () => {
|
||||||
|
render(ContextMenu);
|
||||||
|
|
||||||
|
const options = screen.getAllByRole("menuitem");
|
||||||
|
expect(options).toHaveLength(2);
|
||||||
|
expect(options[0]).toHaveTextContent("Option 1");
|
||||||
|
expect(options[1]).toHaveTextContent("Option 2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should open on right click", async () => {
|
||||||
|
const consoleLog = vi.spyOn(console, "log");
|
||||||
|
render(ContextMenu);
|
||||||
|
|
||||||
|
const target = screen.getByTestId("target");
|
||||||
|
await user.pointer({ target, keys: "[MouseRight]" });
|
||||||
|
expect(consoleLog).toHaveBeenCalledWith("open", expect.any(HTMLElement));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should close on escape key", async () => {
|
||||||
|
const consoleLog = vi.spyOn(console, "log");
|
||||||
|
render(ContextMenu, { props: { open: true } });
|
||||||
|
|
||||||
|
await user.keyboard("{Escape}");
|
||||||
|
expect(consoleLog).toHaveBeenCalledWith("close");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should close on click outside", async () => {
|
||||||
|
const consoleLog = vi.spyOn(console, "log");
|
||||||
|
render(ContextMenu, { props: { open: true } });
|
||||||
|
|
||||||
|
await user.click(document.body);
|
||||||
|
expect(consoleLog).toHaveBeenCalledWith("close");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should handle keyboard navigation", async () => {
|
||||||
|
render(ContextMenu, { props: { open: true } });
|
||||||
|
|
||||||
|
const menu = screen.getAllByRole("menu")[0];
|
||||||
|
menu.focus();
|
||||||
|
|
||||||
|
// Arrow down
|
||||||
|
await user.keyboard("{ArrowDown}");
|
||||||
|
const options = screen.getAllByRole("menuitem");
|
||||||
|
expect(options[0].parentElement).toHaveFocus();
|
||||||
|
|
||||||
|
// Arrow up
|
||||||
|
await user.keyboard("{ArrowUp}");
|
||||||
|
expect(options[1].parentElement).toHaveFocus();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should handle custom target", async () => {
|
||||||
|
const consoleLog = vi.spyOn(console, "log");
|
||||||
|
render(ContextMenu);
|
||||||
|
|
||||||
|
const target = screen.getByTestId("target");
|
||||||
|
await user.pointer({ target, keys: "[MouseRight]" });
|
||||||
|
expect(consoleLog).toHaveBeenCalledWith("open", target);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should handle custom position", () => {
|
||||||
|
render(ContextMenu, {
|
||||||
|
props: {
|
||||||
|
open: true,
|
||||||
|
x: 100,
|
||||||
|
y: 200,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const menu = screen.getAllByRole("menu")[0];
|
||||||
|
expect(menu).toHaveStyle({
|
||||||
|
left: "100px",
|
||||||
|
top: "200px",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should handle nested menus", async () => {
|
||||||
|
render(ContextMenu, { props: { open: true } });
|
||||||
|
|
||||||
|
const menus = screen.getAllByRole("menu");
|
||||||
|
expect(menus[0]).toHaveAttribute("data-level", "1");
|
||||||
|
|
||||||
|
// Simulate nested menu
|
||||||
|
const nestedMenu = document.createElement("ul");
|
||||||
|
nestedMenu.setAttribute("data-level", "2");
|
||||||
|
menus[0].appendChild(nestedMenu);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue