web based infinite canvas
1import Sheet from "$lib/components/Sheet.svelte";
2import { describe, expect, it, vi } from "vitest";
3import { render } from "vitest-browser-svelte";
4import { page } from "vitest/browser";
5
6describe("Sheet", () => {
7 describe("visibility", () => {
8 it("should render when open is true", async () => {
9 render(Sheet, { open: true, title: "Test Sheet" });
10 const sheet = page.getByRole("dialog");
11 await expect.element(sheet).toBeInTheDocument();
12 });
13
14 it("should not render when open is false", async () => {
15 render(Sheet, { open: false, title: "Test Sheet" });
16 const sheet = page.getByRole("dialog");
17 await expect.element(sheet).not.toBeInTheDocument();
18 });
19 });
20
21 describe("positioning", () => {
22 it("should apply right side class", async () => {
23 render(Sheet, { open: true, side: "right", title: "Test" });
24
25 const sheet = page.getByRole("dialog");
26 await expect.element(sheet).toHaveClass("sheet-right");
27 });
28
29 it("should apply left side class", async () => {
30 render(Sheet, { open: true, side: "left", title: "Test" });
31
32 const sheet = page.getByRole("dialog");
33 await expect.element(sheet).toHaveClass("sheet-left");
34 });
35
36 it("should apply top side class", async () => {
37 render(Sheet, { open: true, side: "top", title: "Test" });
38
39 const sheet = page.getByRole("dialog");
40 await expect.element(sheet).toHaveClass("sheet-top");
41 });
42
43 it("should apply bottom side class", async () => {
44 render(Sheet, { open: true, side: "bottom", title: "Test" });
45
46 const sheet = page.getByRole("dialog");
47 await expect.element(sheet).toHaveClass("sheet-bottom");
48 });
49
50 it("should default to right side when no side is specified", async () => {
51 render(Sheet, { open: true, title: "Test" });
52
53 const sheet = page.getByRole("dialog");
54 await expect.element(sheet).toHaveClass("sheet-right");
55 });
56 });
57
58 describe("accessibility", () => {
59 it("should have correct ARIA attributes", async () => {
60 render(Sheet, { open: true, title: "Test Sheet" });
61
62 const sheet = page.getByRole("dialog");
63 await expect.element(sheet).toHaveAttribute("aria-modal", "true");
64 await expect.element(sheet).toHaveAttribute("aria-label", "Test Sheet");
65 });
66
67 it("should be focusable", async () => {
68 render(Sheet, { open: true, title: "Test Sheet" });
69
70 const sheet = page.getByRole("dialog");
71 await expect.element(sheet).toHaveAttribute("tabindex", "-1");
72 });
73 });
74
75 describe("close behavior", () => {
76 it("should call onClose when backdrop is clicked and closeOnBackdrop is true", async () => {
77 const onClose = vi.fn();
78
79 render(Sheet, { open: true, onClose, closeOnBackdrop: true, title: "Test" });
80
81 const backdrop = page.getByRole("presentation");
82 await backdrop.click({ position: { x: 5, y: 5 } });
83
84 expect(onClose).toHaveBeenCalledOnce();
85 });
86
87 it("should call onClose when Escape key is pressed and closeOnEscape is true", async () => {
88 const onClose = vi.fn();
89
90 render(Sheet, { open: true, onClose, closeOnEscape: true, title: "Test" });
91
92 const sheet = document.querySelector<HTMLElement>("[role=\"dialog\"]")!;
93
94 sheet.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", bubbles: true }));
95
96 expect(onClose).toHaveBeenCalledOnce();
97 });
98
99 it("should not call onClose when backdrop is clicked and closeOnBackdrop is false", async () => {
100 const onClose = vi.fn();
101
102 render(Sheet, { open: true, onClose, closeOnBackdrop: false, title: "Test" });
103
104 const backdrop = page.getByRole("presentation");
105 await backdrop.click({ position: { x: 5, y: 5 } });
106
107 expect(onClose).not.toHaveBeenCalled();
108 });
109
110 it("should not call onClose when Escape key is pressed and closeOnEscape is false", async () => {
111 const onClose = vi.fn();
112
113 render(Sheet, { open: true, onClose, closeOnEscape: false, title: "Test" });
114
115 const sheet = document.querySelector<HTMLElement>("[role=\"dialog\"]")!;
116
117 sheet.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", bubbles: true }));
118
119 expect(onClose).not.toHaveBeenCalled();
120 });
121 });
122
123 describe("styling", () => {
124 it("should apply custom class to sheet content", async () => {
125 render(Sheet, { open: true, title: "Test", class: "custom-class" });
126
127 const sheet = page.getByRole("dialog");
128 await expect.element(sheet).toHaveClass("custom-class");
129 });
130 });
131});