@tangle-network/ui 11.51.7 → 11.51.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +6 -0
- package/dist/chat/chat-message.js +2 -7
- package/dist/chat/user-message.js +3 -5
- package/dist/files/file-card.js +1 -1
- package/dist/files/file-tree.d.ts +0 -6
- package/dist/files/file-tree.js +2 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/primitives/hover-card.d.ts +22 -13
- package/dist/primitives/hover-card.js +149 -40
- package/dist/primitives/popover.d.ts +3 -1
- package/dist/primitives/popover.js +15 -12
- package/dist/primitives/upload-progress.d.ts +0 -6
- package/dist/primitives/upload-progress.js +2 -6
- package/dist/run/run-group.js +2 -2
- package/dist/run/run-item-primitives.js +2 -2
- package/dist/run/run-row-shell.js +2 -2
- package/dist/utils/format.d.ts +14 -12
- package/dist/utils/format.js +50 -30
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +2 -2
- package/package.json +11 -2
- package/src/chat/chat-message.tsx +2 -7
- package/src/chat/user-message.tsx +3 -5
- package/src/editor/source-markdown-editor.test.tsx +7 -7
- package/src/files/file-tree.tsx +2 -7
- package/src/primitives/hover-card.tsx +64 -74
- package/src/primitives/popover.tsx +3 -3
- package/src/primitives/upload-progress.tsx +2 -7
- package/src/utils/format.ts +50 -33
- package/src/utils/index.ts +1 -1
- package/src/editor/document-editor-pane.test.tsx +0 -60
- package/src/editor/editor-lazy.test.tsx +0 -102
- package/src/editor/editor-peers.test.ts +0 -250
- package/src/editor/editor-provider.test.tsx +0 -226
- package/src/editor/markdown-document-editor.test.tsx +0 -126
- package/src/editor/tiptap-editor.test.tsx +0 -228
- package/src/files/file-artifact-pane.test.tsx +0 -301
- package/src/files/file-card.test.tsx +0 -62
- package/src/files/file-list.test.tsx +0 -81
- package/src/files/pdf-loader.test.ts +0 -130
- package/src/files/pdf-viewer.test.tsx +0 -245
- package/src/files/rich-file-tree.test.tsx +0 -90
- package/src/markdown/api-presentation.test.tsx +0 -63
- package/src/markdown/code-block.test.tsx +0 -201
- package/src/markdown/markdown-table.test.tsx +0 -76
- package/src/markdown/markdown.test.tsx +0 -166
- package/src/openui/schema.test.tsx +0 -158
- package/src/primitives/button.test.tsx +0 -230
- package/src/primitives/card.test.tsx +0 -71
- package/src/primitives/chip.test.tsx +0 -200
- package/src/primitives/date-picker.test.tsx +0 -146
- package/src/primitives/dialog.test.tsx +0 -75
- package/src/primitives/input.test.tsx +0 -161
- package/src/primitives/interaction-states.test.tsx +0 -287
- package/src/primitives/pagination-alert.test.tsx +0 -180
- package/src/primitives/popover-collapsible-alert-dialog-context-menu-slider.test.tsx +0 -165
- package/src/primitives/radio-group.test.tsx +0 -26
- package/src/primitives/segmented-control.test.tsx +0 -451
- package/src/primitives/table.test.tsx +0 -72
- package/src/primitives/theme-toggle.test.tsx +0 -168
- package/src/primitives/toast.test.tsx +0 -130
- package/src/primitives/wizard.test.tsx +0 -106
- package/src/run/expandable-content.test.tsx +0 -52
- package/src/utils/format.test.ts +0 -58
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import { render, screen } from "@testing-library/react";
|
|
2
|
-
import userEvent from "@testing-library/user-event";
|
|
3
|
-
import type * as React from "react";
|
|
4
|
-
import { describe, expect, it, vi } from "vitest";
|
|
5
|
-
import { Alert, AlertDescription, AlertTitle } from "./alert";
|
|
6
|
-
import { Pagination, pageSlots } from "./pagination";
|
|
7
|
-
|
|
8
|
-
const PALETTE = /\b(?:bg|text|border)-(?:slate|zinc|gray|neutral|blue|green|red|amber|emerald|black|white)(?:-\d|\b)/;
|
|
9
|
-
|
|
10
|
-
describe("pageSlots", () => {
|
|
11
|
-
it("lists every page when they fit", () => {
|
|
12
|
-
expect(pageSlots(0, 1)).toEqual([0]);
|
|
13
|
-
expect(pageSlots(3, 7)).toEqual([0, 1, 2, 3, 4, 5, 6]);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it("keeps the same number of slots as the current page moves", () => {
|
|
17
|
-
expect(pageSlots(0, 10)).toEqual([0, 1, 2, 3, 4, "gap-end", 9]);
|
|
18
|
-
expect(pageSlots(5, 10)).toEqual([0, "gap-start", 4, 5, 6, "gap-end", 9]);
|
|
19
|
-
expect(pageSlots(9, 10)).toEqual([0, "gap-start", 5, 6, 7, 8, 9]);
|
|
20
|
-
for (let page = 0; page < 40; page++) expect(pageSlots(page, 40)).toHaveLength(7);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("clamps a page outside the range", () => {
|
|
24
|
-
expect(pageSlots(-3, 10)).toEqual(pageSlots(0, 10));
|
|
25
|
-
expect(pageSlots(99, 10)).toEqual(pageSlots(9, 10));
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
describe("Pagination", () => {
|
|
30
|
-
it("renders nothing for a single page", () => {
|
|
31
|
-
const { container } = render(<Pagination page={0} pageCount={1} onPageChange={vi.fn()} />);
|
|
32
|
-
expect(container).toBeEmptyDOMElement();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("marks the current page and moves with previous, next and a number", async () => {
|
|
36
|
-
const user = userEvent.setup();
|
|
37
|
-
const onPageChange = vi.fn();
|
|
38
|
-
render(<Pagination page={4} pageCount={12} onPageChange={onPageChange} />);
|
|
39
|
-
|
|
40
|
-
expect(screen.getByRole("navigation", { name: "Pagination" })).toBeInTheDocument();
|
|
41
|
-
const current = screen.getByRole("button", { name: "Page 5" });
|
|
42
|
-
expect(current).toHaveAttribute("aria-current", "page");
|
|
43
|
-
expect(current.className).not.toMatch(PALETTE);
|
|
44
|
-
|
|
45
|
-
await user.click(screen.getByRole("button", { name: "Previous page" }));
|
|
46
|
-
await user.click(screen.getByRole("button", { name: "Next page" }));
|
|
47
|
-
await user.click(screen.getByRole("button", { name: "Page 12" }));
|
|
48
|
-
expect(onPageChange.mock.calls).toEqual([[3], [5], [11]]);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it("disables previous on the first page and next on the last", () => {
|
|
52
|
-
const { rerender } = render(<Pagination page={0} pageCount={3} onPageChange={vi.fn()} />);
|
|
53
|
-
expect(screen.getByRole("button", { name: "Previous page" })).toBeDisabled();
|
|
54
|
-
rerender(<Pagination page={2} pageCount={3} onPageChange={vi.fn()} />);
|
|
55
|
-
expect(screen.getByRole("button", { name: "Next page" })).toBeDisabled();
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it("does not report the page that is already current", async () => {
|
|
59
|
-
const user = userEvent.setup();
|
|
60
|
-
const onPageChange = vi.fn();
|
|
61
|
-
render(<Pagination page={1} pageCount={3} onPageChange={onPageChange} />);
|
|
62
|
-
await user.click(screen.getByRole("button", { name: "Page 2" }));
|
|
63
|
-
expect(onPageChange).not.toHaveBeenCalled();
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
describe("Pagination link mode", () => {
|
|
68
|
-
const hrefFor = (page: number) => `?page=${page + 1}`;
|
|
69
|
-
|
|
70
|
-
it("renders links to one-based URLs from zero-based pages", () => {
|
|
71
|
-
render(<Pagination page={4} pageCount={12} hrefFor={hrefFor} />);
|
|
72
|
-
|
|
73
|
-
expect(screen.queryByRole("button")).not.toBeInTheDocument();
|
|
74
|
-
expect(screen.getByRole("link", { name: "Previous page" })).toHaveAttribute("href", "?page=4");
|
|
75
|
-
expect(screen.getByRole("link", { name: "Next page" })).toHaveAttribute("href", "?page=6");
|
|
76
|
-
expect(screen.getByRole("link", { name: "Page 1" })).toHaveAttribute("href", "?page=1");
|
|
77
|
-
expect(screen.getByRole("link", { name: "Page 12" })).toHaveAttribute("href", "?page=12");
|
|
78
|
-
|
|
79
|
-
const current = screen.getByRole("link", { name: "Page 5" });
|
|
80
|
-
expect(current.tagName).toBe("A");
|
|
81
|
-
expect(current).toHaveAttribute("href", "?page=5");
|
|
82
|
-
expect(current).toHaveAttribute("aria-current", "page");
|
|
83
|
-
expect(screen.getByRole("link", { name: "Page 4" })).not.toHaveAttribute("aria-current");
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("renders a disabled previous or next as a span without an href", () => {
|
|
87
|
-
const { rerender } = render(<Pagination page={0} pageCount={3} hrefFor={hrefFor} />);
|
|
88
|
-
const previous = screen.getByRole("link", { name: "Previous page" });
|
|
89
|
-
expect(previous.tagName).toBe("SPAN");
|
|
90
|
-
expect(previous).toHaveAttribute("aria-disabled", "true");
|
|
91
|
-
expect(previous).not.toHaveAttribute("href");
|
|
92
|
-
expect(previous.className).toContain("aria-disabled:opacity-50");
|
|
93
|
-
expect(screen.getByRole("link", { name: "Next page" })).toHaveAttribute("href", "?page=2");
|
|
94
|
-
|
|
95
|
-
rerender(<Pagination page={2} pageCount={3} hrefFor={hrefFor} />);
|
|
96
|
-
const next = screen.getByRole("link", { name: "Next page" });
|
|
97
|
-
expect(next.tagName).toBe("SPAN");
|
|
98
|
-
expect(next).toHaveAttribute("aria-disabled", "true");
|
|
99
|
-
expect(next).not.toHaveAttribute("href");
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it("renders each enabled control with a custom link component", () => {
|
|
103
|
-
const received: string[] = [];
|
|
104
|
-
const RouterLink = ({ href, ...props }: React.ComponentProps<"a">) => {
|
|
105
|
-
received.push(href ?? "");
|
|
106
|
-
return <a data-router-link="" href={href} {...props} />;
|
|
107
|
-
};
|
|
108
|
-
render(<Pagination page={1} pageCount={3} hrefFor={hrefFor} linkComponent={RouterLink} />);
|
|
109
|
-
|
|
110
|
-
expect(received).toEqual(["?page=1", "?page=1", "?page=2", "?page=3", "?page=3"]);
|
|
111
|
-
const current = screen.getByRole("link", { name: "Page 2" });
|
|
112
|
-
expect(current).toHaveAttribute("data-router-link");
|
|
113
|
-
expect(current).toHaveAttribute("aria-current", "page");
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it("reports a plain click on another page and ignores the current page and new-tab clicks", async () => {
|
|
117
|
-
const user = userEvent.setup();
|
|
118
|
-
const onPageChange = vi.fn();
|
|
119
|
-
render(
|
|
120
|
-
<Pagination
|
|
121
|
-
page={1}
|
|
122
|
-
pageCount={3}
|
|
123
|
-
hrefFor={hrefFor}
|
|
124
|
-
linkComponent={({ onClick, ...props }: React.ComponentProps<"a">) => (
|
|
125
|
-
<a
|
|
126
|
-
{...props}
|
|
127
|
-
onClick={(event) => {
|
|
128
|
-
onClick?.(event);
|
|
129
|
-
event.preventDefault();
|
|
130
|
-
}}
|
|
131
|
-
/>
|
|
132
|
-
)}
|
|
133
|
-
onPageChange={onPageChange}
|
|
134
|
-
/>,
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
await user.click(screen.getByRole("link", { name: "Next page" }));
|
|
138
|
-
await user.click(screen.getByRole("link", { name: "Page 2" }));
|
|
139
|
-
await user.keyboard("{Meta>}");
|
|
140
|
-
await user.click(screen.getByRole("link", { name: "Page 1" }));
|
|
141
|
-
await user.keyboard("{/Meta}");
|
|
142
|
-
expect(onPageChange.mock.calls).toEqual([[2]]);
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it("requires onPageChange or hrefFor, and a link component only with hrefFor", () => {
|
|
146
|
-
const rejected = [
|
|
147
|
-
// @ts-expect-error neither onPageChange nor hrefFor
|
|
148
|
-
() => <Pagination page={0} pageCount={2} />,
|
|
149
|
-
// @ts-expect-error linkComponent without hrefFor
|
|
150
|
-
() => <Pagination page={0} pageCount={2} onPageChange={vi.fn()} linkComponent="a" />,
|
|
151
|
-
];
|
|
152
|
-
expect(rejected).toHaveLength(2);
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
describe("Alert", () => {
|
|
157
|
-
it("paints a tone from the matched Brand status triple", () => {
|
|
158
|
-
render(
|
|
159
|
-
<Alert tone="warning">
|
|
160
|
-
<AlertTitle>Policy is changing</AlertTitle>
|
|
161
|
-
<AlertDescription>Seats above the limit are removed next cycle.</AlertDescription>
|
|
162
|
-
</Alert>,
|
|
163
|
-
);
|
|
164
|
-
const alert = screen.getByRole("alert");
|
|
165
|
-
expect(alert.className).toContain("bg-[var(--surface-warning-bg)]");
|
|
166
|
-
expect(alert.className).toContain("text-[var(--surface-warning-text)]");
|
|
167
|
-
expect(alert.className).not.toMatch(PALETTE);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it("uses role status for quiet tones and keeps an explicit role", () => {
|
|
171
|
-
const { rerender } = render(<Alert tone="info">Saved</Alert>);
|
|
172
|
-
expect(screen.getByRole("status")).toHaveTextContent("Saved");
|
|
173
|
-
rerender(
|
|
174
|
-
<Alert tone="neutral" role="note">
|
|
175
|
-
Note
|
|
176
|
-
</Alert>,
|
|
177
|
-
);
|
|
178
|
-
expect(screen.getByRole("note")).toHaveAttribute("data-tone", "neutral");
|
|
179
|
-
});
|
|
180
|
-
});
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
2
|
-
import userEvent from "@testing-library/user-event";
|
|
3
|
-
import { beforeAll, describe, expect, it, vi } from "vitest";
|
|
4
|
-
import {
|
|
5
|
-
AlertDialog,
|
|
6
|
-
AlertDialogAction,
|
|
7
|
-
AlertDialogCancel,
|
|
8
|
-
AlertDialogContent,
|
|
9
|
-
AlertDialogDescription,
|
|
10
|
-
AlertDialogTitle,
|
|
11
|
-
AlertDialogTrigger,
|
|
12
|
-
} from "./alert-dialog";
|
|
13
|
-
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./collapsible";
|
|
14
|
-
import {
|
|
15
|
-
ContextMenu,
|
|
16
|
-
ContextMenuContent,
|
|
17
|
-
ContextMenuItem,
|
|
18
|
-
ContextMenuSub,
|
|
19
|
-
ContextMenuSubContent,
|
|
20
|
-
ContextMenuSubTrigger,
|
|
21
|
-
ContextMenuTrigger,
|
|
22
|
-
} from "./context-menu";
|
|
23
|
-
import { Popover, PopoverContent, PopoverTrigger } from "./popover";
|
|
24
|
-
import { Slider } from "./slider";
|
|
25
|
-
|
|
26
|
-
const PALETTE = /\b(?:bg|text|border)-(?:slate|zinc|gray|neutral|blue|green|red|amber|emerald|black|white)(?:-\d|\b)/;
|
|
27
|
-
|
|
28
|
-
describe("Popover", () => {
|
|
29
|
-
it("opens from its trigger on a token surface and closes on Escape", async () => {
|
|
30
|
-
const user = userEvent.setup();
|
|
31
|
-
render(
|
|
32
|
-
<Popover>
|
|
33
|
-
<PopoverTrigger>Filters</PopoverTrigger>
|
|
34
|
-
<PopoverContent>Only failed runs</PopoverContent>
|
|
35
|
-
</Popover>,
|
|
36
|
-
);
|
|
37
|
-
await user.click(screen.getByRole("button", { name: "Filters" }));
|
|
38
|
-
const content = await screen.findByRole("dialog");
|
|
39
|
-
expect(content).toHaveTextContent("Only failed runs");
|
|
40
|
-
expect(content.className).toContain("bg-card");
|
|
41
|
-
expect(content.className).not.toMatch(PALETTE);
|
|
42
|
-
await user.keyboard("{Escape}");
|
|
43
|
-
await waitFor(() => expect(screen.queryByRole("dialog")).toBeNull());
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
describe("Collapsible", () => {
|
|
48
|
-
it("reports its expanded state on the trigger", async () => {
|
|
49
|
-
const user = userEvent.setup();
|
|
50
|
-
render(
|
|
51
|
-
<Collapsible>
|
|
52
|
-
<CollapsibleTrigger>Details</CollapsibleTrigger>
|
|
53
|
-
<CollapsibleContent>Hidden body</CollapsibleContent>
|
|
54
|
-
</Collapsible>,
|
|
55
|
-
);
|
|
56
|
-
const trigger = screen.getByRole("button", { name: "Details" });
|
|
57
|
-
expect(trigger).toHaveAttribute("aria-expanded", "false");
|
|
58
|
-
expect(screen.queryByText("Hidden body")).toBeNull();
|
|
59
|
-
await user.click(trigger);
|
|
60
|
-
expect(trigger).toHaveAttribute("aria-expanded", "true");
|
|
61
|
-
expect(screen.getByText("Hidden body")).toBeVisible();
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
describe("AlertDialog", () => {
|
|
66
|
-
it("focuses Cancel on open so a destructive action is never under Enter", async () => {
|
|
67
|
-
const user = userEvent.setup();
|
|
68
|
-
const onDelete = vi.fn();
|
|
69
|
-
render(
|
|
70
|
-
<AlertDialog>
|
|
71
|
-
<AlertDialogTrigger>Delete project</AlertDialogTrigger>
|
|
72
|
-
<AlertDialogContent>
|
|
73
|
-
<AlertDialogTitle>Delete this project?</AlertDialogTitle>
|
|
74
|
-
<AlertDialogDescription>Its sandboxes stop.</AlertDialogDescription>
|
|
75
|
-
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
76
|
-
<AlertDialogAction tone="destructive" onClick={onDelete}>
|
|
77
|
-
Delete
|
|
78
|
-
</AlertDialogAction>
|
|
79
|
-
</AlertDialogContent>
|
|
80
|
-
</AlertDialog>,
|
|
81
|
-
);
|
|
82
|
-
await user.click(screen.getByRole("button", { name: "Delete project" }));
|
|
83
|
-
const dialog = await screen.findByRole("alertdialog", { name: "Delete this project?" });
|
|
84
|
-
expect(dialog).toHaveAccessibleDescription("Its sandboxes stop.");
|
|
85
|
-
expect(screen.getByRole("button", { name: "Cancel" })).toHaveFocus();
|
|
86
|
-
const action = screen.getByRole("button", { name: "Delete" });
|
|
87
|
-
expect(action.className).toContain("bg-destructive");
|
|
88
|
-
await user.click(action);
|
|
89
|
-
expect(onDelete).toHaveBeenCalledOnce();
|
|
90
|
-
await waitFor(() => expect(screen.queryByRole("alertdialog")).toBeNull());
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
describe("ContextMenu", () => {
|
|
95
|
-
it("opens on contextmenu and runs the chosen item", async () => {
|
|
96
|
-
const onRename = vi.fn();
|
|
97
|
-
render(
|
|
98
|
-
<ContextMenu>
|
|
99
|
-
<ContextMenuTrigger>File row</ContextMenuTrigger>
|
|
100
|
-
<ContextMenuContent>
|
|
101
|
-
<ContextMenuItem onSelect={onRename}>Rename</ContextMenuItem>
|
|
102
|
-
<ContextMenuItem tone="destructive">Delete</ContextMenuItem>
|
|
103
|
-
</ContextMenuContent>
|
|
104
|
-
</ContextMenu>,
|
|
105
|
-
);
|
|
106
|
-
fireEvent.contextMenu(screen.getByText("File row"));
|
|
107
|
-
const menu = await screen.findByRole("menu");
|
|
108
|
-
expect(menu.className).toContain("bg-card");
|
|
109
|
-
expect(screen.getByRole("menuitem", { name: "Delete" }).className).toContain("text-destructive");
|
|
110
|
-
fireEvent.click(screen.getByRole("menuitem", { name: "Rename" }));
|
|
111
|
-
expect(onRename).toHaveBeenCalledOnce();
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it("portals submenu content out of the clipped parent menu", async () => {
|
|
115
|
-
const user = userEvent.setup();
|
|
116
|
-
render(
|
|
117
|
-
<ContextMenu>
|
|
118
|
-
<ContextMenuTrigger>File row</ContextMenuTrigger>
|
|
119
|
-
<ContextMenuContent>
|
|
120
|
-
<ContextMenuSub>
|
|
121
|
-
<ContextMenuSubTrigger>Move to</ContextMenuSubTrigger>
|
|
122
|
-
<ContextMenuSubContent>
|
|
123
|
-
<ContextMenuItem>Archive</ContextMenuItem>
|
|
124
|
-
</ContextMenuSubContent>
|
|
125
|
-
</ContextMenuSub>
|
|
126
|
-
</ContextMenuContent>
|
|
127
|
-
</ContextMenu>,
|
|
128
|
-
);
|
|
129
|
-
fireEvent.contextMenu(screen.getByText("File row"));
|
|
130
|
-
const parent = await screen.findByRole("menu");
|
|
131
|
-
await user.hover(screen.getByRole("menuitem", { name: "Move to" }));
|
|
132
|
-
await user.keyboard("{ArrowRight}");
|
|
133
|
-
const archive = await screen.findByRole("menuitem", { name: "Archive" });
|
|
134
|
-
expect(parent.contains(archive)).toBe(false);
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
describe("Slider", () => {
|
|
139
|
-
beforeAll(() => {
|
|
140
|
-
// Radix measures the thumb with ResizeObserver, which jsdom lacks.
|
|
141
|
-
globalThis.ResizeObserver ??= class {
|
|
142
|
-
observe() {}
|
|
143
|
-
unobserve() {}
|
|
144
|
-
disconnect() {}
|
|
145
|
-
};
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it("renders one labelled thumb per value", () => {
|
|
149
|
-
render(<Slider defaultValue={[20, 80]} thumbLabels={["Minimum", "Maximum"]} />);
|
|
150
|
-
const thumbs = screen.getAllByRole("slider");
|
|
151
|
-
expect(thumbs).toHaveLength(2);
|
|
152
|
-
expect(thumbs[0]).toHaveAccessibleName("Minimum");
|
|
153
|
-
expect(thumbs[1]).toHaveAttribute("aria-valuenow", "80");
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it("moves with the keyboard and reports the value", async () => {
|
|
157
|
-
const user = userEvent.setup();
|
|
158
|
-
const onValueChange = vi.fn();
|
|
159
|
-
render(<Slider aria-label="Budget" defaultValue={[50]} step={10} onValueChange={onValueChange} />);
|
|
160
|
-
expect(screen.getByRole("slider")).toHaveAccessibleName("Budget");
|
|
161
|
-
screen.getByRole("slider").focus();
|
|
162
|
-
await user.keyboard("{ArrowRight}");
|
|
163
|
-
expect(onValueChange).toHaveBeenLastCalledWith([60]);
|
|
164
|
-
});
|
|
165
|
-
});
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { cleanup, render, screen } from "@testing-library/react";
|
|
3
|
-
import userEvent from "@testing-library/user-event";
|
|
4
|
-
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
5
|
-
import { Label } from "./label";
|
|
6
|
-
import { RadioGroup, RadioGroupItem } from "./radio-group";
|
|
7
|
-
|
|
8
|
-
afterEach(cleanup);
|
|
9
|
-
|
|
10
|
-
describe("RadioGroup", () => {
|
|
11
|
-
it("chooses one item by click or arrow key and reports its value", async () => {
|
|
12
|
-
const onValueChange = vi.fn();
|
|
13
|
-
render(
|
|
14
|
-
<RadioGroup aria-label="Plan" defaultValue="basic" onValueChange={onValueChange}>
|
|
15
|
-
<div><RadioGroupItem id="basic" value="basic" /><Label htmlFor="basic">Basic</Label></div>
|
|
16
|
-
<div><RadioGroupItem id="pro" value="pro" /><Label htmlFor="pro">Pro</Label></div>
|
|
17
|
-
</RadioGroup>,
|
|
18
|
-
);
|
|
19
|
-
expect(screen.getByRole("radiogroup", { name: "Plan" })).toBeTruthy();
|
|
20
|
-
expect(screen.getByRole("radio", { name: "Basic" })).toHaveAttribute("aria-checked", "true");
|
|
21
|
-
await userEvent.click(screen.getByText("Pro"));
|
|
22
|
-
expect(onValueChange).toHaveBeenLastCalledWith("pro");
|
|
23
|
-
expect(screen.getByRole("radio", { name: "Pro" })).toHaveAttribute("aria-checked", "true");
|
|
24
|
-
expect(screen.getByRole("radio", { name: "Basic" })).toHaveAttribute("aria-checked", "false");
|
|
25
|
-
});
|
|
26
|
-
});
|