@usefui/components 1.5.1
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 +233 -0
- package/LICENSE +21 -0
- package/README.md +0 -0
- package/babel.config.js +12 -0
- package/dist/index.d.mts +1299 -0
- package/dist/index.d.ts +1299 -0
- package/dist/index.js +3701 -0
- package/dist/index.mjs +3586 -0
- package/package.json +44 -0
- package/src/__tests__/Accordion.test.tsx +106 -0
- package/src/__tests__/Avatar.test.tsx +89 -0
- package/src/__tests__/Badge.test.tsx +58 -0
- package/src/__tests__/Button.test.tsx +88 -0
- package/src/__tests__/Checkbox.test.tsx +106 -0
- package/src/__tests__/Collapsible.test.tsx +79 -0
- package/src/__tests__/Dialog.test.tsx +109 -0
- package/src/__tests__/Dropdown.test.tsx +159 -0
- package/src/__tests__/Field.test.tsx +100 -0
- package/src/__tests__/OTPField.test.tsx +199 -0
- package/src/__tests__/Overlay.test.tsx +70 -0
- package/src/__tests__/Page.test.tsx +98 -0
- package/src/__tests__/Portal.test.tsx +28 -0
- package/src/__tests__/Sheet.test.tsx +125 -0
- package/src/__tests__/Switch.test.tsx +90 -0
- package/src/__tests__/Tabs.test.tsx +129 -0
- package/src/__tests__/Toggle.test.tsx +67 -0
- package/src/__tests__/Toolbar.test.tsx +147 -0
- package/src/__tests__/Tooltip.test.tsx +88 -0
- package/src/accordion/Accordion.stories.tsx +89 -0
- package/src/accordion/hooks/index.tsx +39 -0
- package/src/accordion/index.tsx +170 -0
- package/src/avatar/Avatar.stories.tsx +62 -0
- package/src/avatar/index.tsx +90 -0
- package/src/avatar/styles/index.ts +79 -0
- package/src/badge/Badge.stories.tsx +60 -0
- package/src/badge/index.tsx +58 -0
- package/src/badge/styles/index.ts +109 -0
- package/src/button/Button.stories.tsx +47 -0
- package/src/button/index.tsx +79 -0
- package/src/button/styles/index.ts +180 -0
- package/src/checkbox/Checkbox.stories.tsx +100 -0
- package/src/checkbox/hooks/index.tsx +40 -0
- package/src/checkbox/index.tsx +147 -0
- package/src/checkbox/styles/index.ts +139 -0
- package/src/collapsible/Collapsible.stories.tsx +95 -0
- package/src/collapsible/hooks/index.tsx +50 -0
- package/src/collapsible/index.tsx +137 -0
- package/src/dialog/Dialog.stories.tsx +73 -0
- package/src/dialog/hooks/index.tsx +35 -0
- package/src/dialog/index.tsx +221 -0
- package/src/dialog/styles/index.ts +72 -0
- package/src/divider/index.ts +10 -0
- package/src/dropdown/Dropdown.stories.tsx +100 -0
- package/src/dropdown/hooks/index.tsx +64 -0
- package/src/dropdown/index.tsx +316 -0
- package/src/dropdown/styles/index.ts +90 -0
- package/src/field/Field.stories.tsx +146 -0
- package/src/field/hooks/index.tsx +28 -0
- package/src/field/index.tsx +183 -0
- package/src/field/styles/index.ts +166 -0
- package/src/index.ts +33 -0
- package/src/otp-field/OTPField.stories.tsx +50 -0
- package/src/otp-field/hooks/index.tsx +13 -0
- package/src/otp-field/index.tsx +234 -0
- package/src/otp-field/styles/index.ts +33 -0
- package/src/otp-field/types/index.ts +23 -0
- package/src/overlay/Overlay.stories.tsx +59 -0
- package/src/overlay/index.tsx +58 -0
- package/src/overlay/styles/index.ts +26 -0
- package/src/page/Page.stories.tsx +85 -0
- package/src/page/index.tsx +265 -0
- package/src/page/styles/index.ts +59 -0
- package/src/portal/Portal.stories.tsx +27 -0
- package/src/portal/index.tsx +36 -0
- package/src/scrollarea/Scrollarea.stories.tsx +99 -0
- package/src/scrollarea/index.tsx +27 -0
- package/src/scrollarea/styles/index.ts +71 -0
- package/src/sheet/Sheet.stories.tsx +86 -0
- package/src/sheet/hooks/index.tsx +47 -0
- package/src/sheet/index.tsx +190 -0
- package/src/sheet/styles/index.ts +69 -0
- package/src/switch/Switch.stories.tsx +96 -0
- package/src/switch/hooks/index.tsx +33 -0
- package/src/switch/index.tsx +122 -0
- package/src/switch/styles/index.ts +118 -0
- package/src/table/index.tsx +138 -0
- package/src/table/styles/index.ts +48 -0
- package/src/tabs/Tabs.stories.tsx +87 -0
- package/src/tabs/hooks/index.tsx +35 -0
- package/src/tabs/index.tsx +161 -0
- package/src/tabs/styles/index.ts +9 -0
- package/src/toggle/Toggle.stories.tsx +118 -0
- package/src/toggle/index.tsx +55 -0
- package/src/toggle/styles/index.ts +0 -0
- package/src/toolbar/Toolbar.stories.tsx +89 -0
- package/src/toolbar/hooks/index.tsx +35 -0
- package/src/toolbar/index.tsx +243 -0
- package/src/toolbar/styles/index.ts +129 -0
- package/src/tooltip/Tooltip.stories.tsx +60 -0
- package/src/tooltip/index.tsx +177 -0
- package/src/tooltip/styles/index.ts +38 -0
- package/src/utils/index.ts +2 -0
- package/tsconfig.json +18 -0
- package/vitest.config.ts +16 -0
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@usefui/components",
|
|
3
|
+
"version": "1.5.1",
|
|
4
|
+
"description": "Open Source React components library",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"react",
|
|
10
|
+
"typescript",
|
|
11
|
+
"accessibility",
|
|
12
|
+
"ui",
|
|
13
|
+
"components",
|
|
14
|
+
"ui-components"
|
|
15
|
+
],
|
|
16
|
+
"author": "Nicolas Nunes",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"@types/react": "*",
|
|
20
|
+
"@types/react-dom": "*",
|
|
21
|
+
"@types/styled-components": "*",
|
|
22
|
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0",
|
|
23
|
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0",
|
|
24
|
+
"styled-components": "^5.1.34"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/react": "^18.3.23",
|
|
28
|
+
"@types/react-dom": "^18.3.7",
|
|
29
|
+
"@types/styled-components": "^5.1.34",
|
|
30
|
+
"react": "^18.3.1",
|
|
31
|
+
"react-dom": "^18.3.1",
|
|
32
|
+
"styled-components": "^5.3.11",
|
|
33
|
+
"typescript": "^5.9.2",
|
|
34
|
+
"@usefui/core": "^1.3.3",
|
|
35
|
+
"@usefui/hooks": "^1.3.3",
|
|
36
|
+
"@usefui/tokens": "^1.5.2"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"test": "vitest run --coverage --logHeapUsage",
|
|
40
|
+
"test:coverage": "open coverage/lcov-report/index.html",
|
|
41
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
42
|
+
"lint": "tsc"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { test, vi, afterEach, describe, expect } from "vitest";
|
|
4
|
+
import {
|
|
5
|
+
screen,
|
|
6
|
+
render,
|
|
7
|
+
cleanup,
|
|
8
|
+
waitFor,
|
|
9
|
+
fireEvent,
|
|
10
|
+
} from "@testing-library/react";
|
|
11
|
+
import { axe, toHaveNoViolations } from "jest-axe";
|
|
12
|
+
|
|
13
|
+
import { Accordion } from "../../src/accordion";
|
|
14
|
+
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
vi.clearAllMocks();
|
|
17
|
+
vi.resetModules();
|
|
18
|
+
cleanup();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
expect.extend(toHaveNoViolations);
|
|
22
|
+
describe("Accordion", () => {
|
|
23
|
+
test("Renders without accessibility violation", async () => {
|
|
24
|
+
const { container } = render(
|
|
25
|
+
<Accordion.Root>
|
|
26
|
+
<Accordion>
|
|
27
|
+
<Accordion.Trigger value="1">1</Accordion.Trigger>
|
|
28
|
+
<Accordion.Content value="1" defaultOpen>
|
|
29
|
+
2
|
|
30
|
+
</Accordion.Content>
|
|
31
|
+
</Accordion>
|
|
32
|
+
</Accordion.Root>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const ComponentContainer = await axe(container);
|
|
36
|
+
expect(ComponentContainer).toHaveNoViolations();
|
|
37
|
+
});
|
|
38
|
+
test("Renders with accessibility definition", async () => {
|
|
39
|
+
render(
|
|
40
|
+
<Accordion.Root>
|
|
41
|
+
<Accordion>
|
|
42
|
+
<Accordion.Trigger value="1">1</Accordion.Trigger>
|
|
43
|
+
<Accordion.Content value="1">1</Accordion.Content>
|
|
44
|
+
</Accordion>
|
|
45
|
+
</Accordion.Root>
|
|
46
|
+
);
|
|
47
|
+
const Trigger = screen.getByLabelText("button-action");
|
|
48
|
+
|
|
49
|
+
expect(Trigger).toBeDefined();
|
|
50
|
+
expect(() => screen.getByRole("article")).toThrow();
|
|
51
|
+
|
|
52
|
+
fireEvent.click(Trigger);
|
|
53
|
+
await waitFor(() => {
|
|
54
|
+
const Content = screen.getByRole("article");
|
|
55
|
+
expect(Content).toBeDefined();
|
|
56
|
+
expect(Content.getAttribute("aria-expanded")).toBe("true");
|
|
57
|
+
expect(Content.getAttribute("data-value")).toBe("1");
|
|
58
|
+
expect(Content.getAttribute("aria-labelledby")).toBeDefined();
|
|
59
|
+
expect(Content.getAttribute("id")).toBeDefined();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
test("Fires the defined callback function and toggle the content when the trigger is clicked", async () => {
|
|
63
|
+
const onClickCallback = vi.fn();
|
|
64
|
+
render(
|
|
65
|
+
<Accordion.Root>
|
|
66
|
+
<Accordion>
|
|
67
|
+
<Accordion.Trigger
|
|
68
|
+
onClick={onClickCallback}
|
|
69
|
+
value="1"
|
|
70
|
+
name="trigger-1"
|
|
71
|
+
>
|
|
72
|
+
Trigger 1
|
|
73
|
+
</Accordion.Trigger>
|
|
74
|
+
<Accordion.Trigger value="2" name="trigger-2">
|
|
75
|
+
Trigger 2
|
|
76
|
+
</Accordion.Trigger>
|
|
77
|
+
<Accordion.Content value="1" defaultOpen>
|
|
78
|
+
Content 1
|
|
79
|
+
</Accordion.Content>
|
|
80
|
+
<Accordion.Content value="2">Content 2</Accordion.Content>
|
|
81
|
+
</Accordion>
|
|
82
|
+
</Accordion.Root>
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
expect(screen.getByText("Content 1")).toBeDefined();
|
|
86
|
+
|
|
87
|
+
fireEvent.click(screen.getByLabelText("trigger-2-action"));
|
|
88
|
+
await waitFor(() => {
|
|
89
|
+
expect(() => screen.getByText("Content 1")).toThrow();
|
|
90
|
+
expect(screen.getByText("Content 2")).toBeDefined();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
fireEvent.click(screen.getByLabelText("trigger-1-action"));
|
|
94
|
+
await waitFor(() => {
|
|
95
|
+
expect(() => screen.getByText("Content 2")).toThrow();
|
|
96
|
+
expect(screen.getByText("Content 1")).toBeDefined();
|
|
97
|
+
expect(onClickCallback).toHaveBeenCalledTimes(1);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
fireEvent.click(screen.getByLabelText("trigger-1-action"));
|
|
101
|
+
await waitFor(() => {
|
|
102
|
+
expect(() => screen.getByText("Content 1")).toThrow();
|
|
103
|
+
expect(() => screen.getByText("Content 2")).toThrow();
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { test, vi, afterEach, describe, expect } from "vitest";
|
|
4
|
+
import { screen, render, cleanup } from "@testing-library/react";
|
|
5
|
+
import { axe, toHaveNoViolations } from "jest-axe";
|
|
6
|
+
|
|
7
|
+
import { Avatar, AvataStatusEnum } from "../../src/avatar";
|
|
8
|
+
import { ComponentSizeEnum, TComponentSize } from "../../../../types";
|
|
9
|
+
|
|
10
|
+
afterEach(async () => {
|
|
11
|
+
vi.clearAllMocks();
|
|
12
|
+
vi.resetModules();
|
|
13
|
+
cleanup();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
expect.extend(toHaveNoViolations);
|
|
17
|
+
describe("Avatar", () => {
|
|
18
|
+
test("Renders without accessibility violation", async () => {
|
|
19
|
+
const { container } = render(
|
|
20
|
+
<Avatar
|
|
21
|
+
sizing={ComponentSizeEnum.Small}
|
|
22
|
+
status={AvataStatusEnum.Online}
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
const ComponentContainer = await axe(container);
|
|
26
|
+
expect(ComponentContainer).toHaveNoViolations();
|
|
27
|
+
});
|
|
28
|
+
test("Renders with accessibility definition", async () => {
|
|
29
|
+
render(
|
|
30
|
+
<Avatar
|
|
31
|
+
sizing={ComponentSizeEnum.Small}
|
|
32
|
+
status={AvataStatusEnum.Online}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const avatarLabel = "small-user-avatar";
|
|
37
|
+
const AvatarWrapper = screen.getByLabelText(avatarLabel);
|
|
38
|
+
const AvatarStatus = screen.getByLabelText(`${avatarLabel}-status`);
|
|
39
|
+
|
|
40
|
+
expect(AvatarWrapper).toBeDefined();
|
|
41
|
+
expect(AvatarWrapper.getAttribute("data-size")).toBe("small");
|
|
42
|
+
expect(AvatarWrapper.getAttribute("data-status")).toBe("online");
|
|
43
|
+
|
|
44
|
+
expect(AvatarStatus).toBeDefined();
|
|
45
|
+
expect(AvatarStatus.getAttribute("role")).toBe("img");
|
|
46
|
+
expect(AvatarStatus.getAttribute("data-status")).toBe("online");
|
|
47
|
+
});
|
|
48
|
+
test("Renders with Image as background", async () => {
|
|
49
|
+
render(<Avatar src="http://www.bui/tests" />);
|
|
50
|
+
|
|
51
|
+
const avatarLabel = "medium-user-avatar";
|
|
52
|
+
const AvatarWrapper = screen.getByLabelText(avatarLabel);
|
|
53
|
+
const AvatarImage = screen.getByLabelText("medium-user-avatar-image");
|
|
54
|
+
|
|
55
|
+
expect(AvatarWrapper).toBeDefined();
|
|
56
|
+
expect(AvatarImage).toBeDefined();
|
|
57
|
+
expect(AvatarWrapper.getAttribute("data-size")).toBe("medium");
|
|
58
|
+
});
|
|
59
|
+
test("Renders variants without accessibility violation", async () => {
|
|
60
|
+
const SizeVariants = [
|
|
61
|
+
ComponentSizeEnum.Small,
|
|
62
|
+
ComponentSizeEnum.Medium,
|
|
63
|
+
ComponentSizeEnum.Large,
|
|
64
|
+
];
|
|
65
|
+
const StatusVariants = [
|
|
66
|
+
AvataStatusEnum.Online,
|
|
67
|
+
AvataStatusEnum.Away,
|
|
68
|
+
AvataStatusEnum.Busy,
|
|
69
|
+
AvataStatusEnum.Offline,
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const { container } = render(
|
|
73
|
+
<React.Fragment>
|
|
74
|
+
{StatusVariants.map((variant, key) => (
|
|
75
|
+
<Avatar
|
|
76
|
+
key={variant}
|
|
77
|
+
status={variant}
|
|
78
|
+
sizing={
|
|
79
|
+
(SizeVariants[key] as TComponentSize) ?? ComponentSizeEnum.Small
|
|
80
|
+
}
|
|
81
|
+
/>
|
|
82
|
+
))}
|
|
83
|
+
</React.Fragment>
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const ComponentContainer = await axe(container);
|
|
87
|
+
expect(ComponentContainer).toHaveNoViolations();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { test, vi, afterEach, describe, expect } from "vitest";
|
|
4
|
+
import { render, cleanup } from "@testing-library/react";
|
|
5
|
+
import { axe, toHaveNoViolations } from "jest-axe";
|
|
6
|
+
|
|
7
|
+
import { Badge } from "../../src/badge";
|
|
8
|
+
|
|
9
|
+
afterEach(async () => {
|
|
10
|
+
vi.clearAllMocks();
|
|
11
|
+
vi.resetModules();
|
|
12
|
+
cleanup();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
expect.extend(toHaveNoViolations);
|
|
16
|
+
const handleClick = vi.fn();
|
|
17
|
+
|
|
18
|
+
describe("Badge", () => {
|
|
19
|
+
test("Renders without accessibility violation", async () => {
|
|
20
|
+
const { container } = render(
|
|
21
|
+
<Badge aria-label="test-badge" onClick={handleClick}>
|
|
22
|
+
Test
|
|
23
|
+
</Badge>
|
|
24
|
+
);
|
|
25
|
+
const ComponentContainer = await axe(container);
|
|
26
|
+
expect(ComponentContainer).toHaveNoViolations();
|
|
27
|
+
});
|
|
28
|
+
test("Renders variants without accessibility violation", async () => {
|
|
29
|
+
const Variants = [
|
|
30
|
+
"primary",
|
|
31
|
+
"secondary",
|
|
32
|
+
"border",
|
|
33
|
+
"error",
|
|
34
|
+
"warning",
|
|
35
|
+
"success",
|
|
36
|
+
"meta",
|
|
37
|
+
];
|
|
38
|
+
const Shapes = ["square", "smooth", "round"];
|
|
39
|
+
|
|
40
|
+
const { container } = render(
|
|
41
|
+
<React.Fragment>
|
|
42
|
+
{Variants.map((variant) => (
|
|
43
|
+
<Badge key={variant} variant={variant as any}>
|
|
44
|
+
{variant}
|
|
45
|
+
</Badge>
|
|
46
|
+
))}
|
|
47
|
+
{Shapes.map((variant) => (
|
|
48
|
+
<Badge key={variant} variant={variant as any}>
|
|
49
|
+
{variant}
|
|
50
|
+
</Badge>
|
|
51
|
+
))}
|
|
52
|
+
</React.Fragment>
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const ComponentContainer = await axe(container);
|
|
56
|
+
expect(ComponentContainer).toHaveNoViolations();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { test, vi, afterEach, describe, expect } from "vitest";
|
|
4
|
+
import { screen, render, cleanup, fireEvent } from "@testing-library/react";
|
|
5
|
+
import { axe, toHaveNoViolations } from "jest-axe";
|
|
6
|
+
|
|
7
|
+
import { Button } from "../../src/button";
|
|
8
|
+
import { ComponentVariantEnum } from "../../../../types";
|
|
9
|
+
|
|
10
|
+
afterEach(async () => {
|
|
11
|
+
vi.clearAllMocks();
|
|
12
|
+
vi.resetModules();
|
|
13
|
+
cleanup();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
expect.extend(toHaveNoViolations);
|
|
17
|
+
const handleClick = vi.fn();
|
|
18
|
+
|
|
19
|
+
describe("Button", () => {
|
|
20
|
+
test("Renders with accessibility definition", async () => {
|
|
21
|
+
render(<Button onClick={handleClick}>Test</Button>);
|
|
22
|
+
|
|
23
|
+
expect(screen.getByRole("button").getAttribute("type")).toEqual("button");
|
|
24
|
+
expect(screen.getByRole("button").getAttribute("tabIndex")).toEqual("0");
|
|
25
|
+
expect(screen.getByRole("button").getAttribute("name")).toEqual("button");
|
|
26
|
+
expect(screen.getByRole("button").getAttribute("aria-disabled")).toEqual(
|
|
27
|
+
"false"
|
|
28
|
+
);
|
|
29
|
+
expect(screen.getByRole("button").getAttribute("aria-label")).toEqual(
|
|
30
|
+
"button-action"
|
|
31
|
+
);
|
|
32
|
+
expect(screen.getByRole("button").getAttribute("data-size")).toEqual(
|
|
33
|
+
"medium"
|
|
34
|
+
);
|
|
35
|
+
expect(screen.getByRole("button").getAttribute("data-raw")).toEqual(
|
|
36
|
+
"false"
|
|
37
|
+
);
|
|
38
|
+
expect(screen.getByRole("button").getAttribute("aria-description")).toEqual(
|
|
39
|
+
"button-action:button/disabled:false"
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
test("Renders variants without accessibility violation", async () => {
|
|
43
|
+
const ButtonsVariants = [
|
|
44
|
+
ComponentVariantEnum.Primary,
|
|
45
|
+
ComponentVariantEnum.Secondary,
|
|
46
|
+
ComponentVariantEnum.Tertiary,
|
|
47
|
+
ComponentVariantEnum.Ghost,
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const { container } = render(
|
|
51
|
+
<React.Fragment>
|
|
52
|
+
{ButtonsVariants.map((variant) => (
|
|
53
|
+
<Button
|
|
54
|
+
key={variant}
|
|
55
|
+
name={`test-styled-${variant}`}
|
|
56
|
+
variant={variant}
|
|
57
|
+
>
|
|
58
|
+
{variant}
|
|
59
|
+
</Button>
|
|
60
|
+
))}
|
|
61
|
+
</React.Fragment>
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const ComponentContainer = await axe(container);
|
|
65
|
+
expect(ComponentContainer).toHaveNoViolations();
|
|
66
|
+
|
|
67
|
+
ButtonsVariants.map((variant) => {
|
|
68
|
+
expect(
|
|
69
|
+
screen
|
|
70
|
+
.getByLabelText(`test-styled-${variant}-action`)
|
|
71
|
+
.getAttribute("data-variant")
|
|
72
|
+
).toBe(variant);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
test("Renders without accessibility violation", async () => {
|
|
76
|
+
const { container } = render(
|
|
77
|
+
<Button name="test" onClick={handleClick}>
|
|
78
|
+
Test
|
|
79
|
+
</Button>
|
|
80
|
+
);
|
|
81
|
+
const ComponentContainer = await axe(container);
|
|
82
|
+
const ButtonComponent = screen.getByRole("button");
|
|
83
|
+
|
|
84
|
+
expect(ComponentContainer).toHaveNoViolations();
|
|
85
|
+
fireEvent.click(ButtonComponent);
|
|
86
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { test, vi, afterEach, describe, expect } from "vitest";
|
|
4
|
+
import {
|
|
5
|
+
screen,
|
|
6
|
+
render,
|
|
7
|
+
cleanup,
|
|
8
|
+
waitFor,
|
|
9
|
+
fireEvent,
|
|
10
|
+
} from "@testing-library/react";
|
|
11
|
+
import { axe, toHaveNoViolations } from "jest-axe";
|
|
12
|
+
|
|
13
|
+
import { Checkbox } from "../../src/checkbox";
|
|
14
|
+
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
vi.clearAllMocks();
|
|
17
|
+
vi.resetModules();
|
|
18
|
+
cleanup();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const onClickCallback = vi.fn();
|
|
22
|
+
const onChangeCallback = vi.fn();
|
|
23
|
+
const CheckboxDefault = () => {
|
|
24
|
+
return (
|
|
25
|
+
<Checkbox.Root>
|
|
26
|
+
<Checkbox
|
|
27
|
+
checked={false}
|
|
28
|
+
onClick={onClickCallback}
|
|
29
|
+
onChange={onChangeCallback}
|
|
30
|
+
name="test"
|
|
31
|
+
>
|
|
32
|
+
<Checkbox.Indicator />
|
|
33
|
+
</Checkbox>
|
|
34
|
+
</Checkbox.Root>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
expect.extend(toHaveNoViolations);
|
|
39
|
+
describe("Checkbox", () => {
|
|
40
|
+
test("Renders without accessibility violation", async () => {
|
|
41
|
+
const { container } = render(<CheckboxDefault />);
|
|
42
|
+
const ComponentContainer = await axe(container);
|
|
43
|
+
|
|
44
|
+
expect(ComponentContainer).toHaveNoViolations();
|
|
45
|
+
});
|
|
46
|
+
test("Renders with accessibility definition", () => {
|
|
47
|
+
render(<CheckboxDefault />);
|
|
48
|
+
const CheckboxComponent = screen.getByLabelText("test-native-checkbox");
|
|
49
|
+
|
|
50
|
+
expect(CheckboxComponent.getAttribute("type")).toBe("checkbox");
|
|
51
|
+
expect(CheckboxComponent.getAttribute("tabindex")).toBe("0");
|
|
52
|
+
expect(CheckboxComponent.getAttribute("value")).toBe("unchecked");
|
|
53
|
+
expect(CheckboxComponent.getAttribute("aria-checked")).toBe("false");
|
|
54
|
+
expect(CheckboxComponent.getAttribute("aria-disabled")).toBe("false");
|
|
55
|
+
expect(CheckboxComponent.getAttribute("aria-required")).toBe("false");
|
|
56
|
+
expect(CheckboxComponent.getAttribute("data-state")).toBe("unchecked");
|
|
57
|
+
});
|
|
58
|
+
test("Toggle checked state on click and fire callback function", async () => {
|
|
59
|
+
render(<CheckboxDefault />);
|
|
60
|
+
const CheckboxComponent = screen.getByLabelText("test-checkbox");
|
|
61
|
+
const CheckboxNative = screen.getByLabelText("test-native-checkbox");
|
|
62
|
+
|
|
63
|
+
expect(CheckboxComponent.getAttribute("data-state")).toBe("unchecked");
|
|
64
|
+
|
|
65
|
+
expect(CheckboxNative.getAttribute("value")).toBe("unchecked");
|
|
66
|
+
expect(CheckboxNative.getAttribute("aria-checked")).toBe("false");
|
|
67
|
+
|
|
68
|
+
fireEvent.click(CheckboxNative);
|
|
69
|
+
await waitFor(() => {
|
|
70
|
+
expect(onClickCallback).toHaveBeenCalled();
|
|
71
|
+
expect(screen.getByTitle("Checked")).toBeDefined();
|
|
72
|
+
|
|
73
|
+
expect(CheckboxComponent.getAttribute("data-state")).toBe("checked");
|
|
74
|
+
expect(CheckboxNative.getAttribute("value")).toBe("checked");
|
|
75
|
+
expect(CheckboxNative.getAttribute("aria-checked")).toBe("true");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
fireEvent.click(CheckboxNative);
|
|
79
|
+
await waitFor(() => {
|
|
80
|
+
expect(onClickCallback).toHaveBeenCalled();
|
|
81
|
+
expect(CheckboxComponent.getAttribute("data-state")).toBe("unchecked");
|
|
82
|
+
expect(CheckboxNative.getAttribute("value")).toBe("unchecked");
|
|
83
|
+
expect(CheckboxNative.getAttribute("aria-checked")).toBe("false");
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
test("Renders as checked if defaultChecked is defined", async () => {
|
|
87
|
+
render(
|
|
88
|
+
<Checkbox.Root>
|
|
89
|
+
<Checkbox
|
|
90
|
+
name="test"
|
|
91
|
+
defaultChecked
|
|
92
|
+
onClick={onClickCallback}
|
|
93
|
+
onChange={onChangeCallback}
|
|
94
|
+
>
|
|
95
|
+
<Checkbox.Indicator />
|
|
96
|
+
</Checkbox>
|
|
97
|
+
</Checkbox.Root>
|
|
98
|
+
);
|
|
99
|
+
const CheckboxComponent = screen.getByLabelText("test-checkbox");
|
|
100
|
+
const CheckboxNative = screen.getByLabelText("test-native-checkbox");
|
|
101
|
+
|
|
102
|
+
expect(CheckboxComponent.getAttribute("data-state")).toBe("checked");
|
|
103
|
+
expect(CheckboxNative.getAttribute("value")).toBe("checked");
|
|
104
|
+
expect(CheckboxNative.getAttribute("aria-checked")).toBe("true");
|
|
105
|
+
});
|
|
106
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { test, vi, afterEach, describe, expect } from "vitest";
|
|
4
|
+
import {
|
|
5
|
+
screen,
|
|
6
|
+
render,
|
|
7
|
+
cleanup,
|
|
8
|
+
waitFor,
|
|
9
|
+
fireEvent,
|
|
10
|
+
} from "@testing-library/react";
|
|
11
|
+
import { axe, toHaveNoViolations } from "jest-axe";
|
|
12
|
+
|
|
13
|
+
import { Collapsible } from "../../src/collapsible";
|
|
14
|
+
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
vi.clearAllMocks();
|
|
17
|
+
vi.resetModules();
|
|
18
|
+
cleanup();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const onClickCallback = vi.fn();
|
|
22
|
+
const CollapsibleDefault = (args: {
|
|
23
|
+
defaultOpen?: boolean;
|
|
24
|
+
showFirstChild?: boolean;
|
|
25
|
+
}) => {
|
|
26
|
+
return (
|
|
27
|
+
<Collapsible.Root>
|
|
28
|
+
<Collapsible>
|
|
29
|
+
<Collapsible.Trigger onClick={onClickCallback}>
|
|
30
|
+
Trigger
|
|
31
|
+
</Collapsible.Trigger>
|
|
32
|
+
<Collapsible.Content
|
|
33
|
+
defaultOpen={args.defaultOpen}
|
|
34
|
+
showFirstChild={args.showFirstChild}
|
|
35
|
+
aria-label="test-content"
|
|
36
|
+
>
|
|
37
|
+
<p key={1}>Item 1</p>
|
|
38
|
+
<p key={2}>Item 2</p>
|
|
39
|
+
</Collapsible.Content>
|
|
40
|
+
</Collapsible>
|
|
41
|
+
</Collapsible.Root>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
expect.extend(toHaveNoViolations);
|
|
46
|
+
describe("Collapsible", () => {
|
|
47
|
+
test("Renders without accessibility violation", async () => {
|
|
48
|
+
const { container } = render(<CollapsibleDefault />);
|
|
49
|
+
const ComponentContainer = await axe(container);
|
|
50
|
+
expect(ComponentContainer).toHaveNoViolations();
|
|
51
|
+
});
|
|
52
|
+
test("Renders with accessibility definition", () => {
|
|
53
|
+
render(<CollapsibleDefault />);
|
|
54
|
+
const TriggerComponent = screen.getByRole("button");
|
|
55
|
+
|
|
56
|
+
expect(TriggerComponent.getAttribute("aria-disabled")).toBe("false");
|
|
57
|
+
expect(TriggerComponent.getAttribute("data-expanded")).toBe("false");
|
|
58
|
+
expect(TriggerComponent.getAttribute("data-state")).toBe("closed");
|
|
59
|
+
});
|
|
60
|
+
test("Fires the defined callback function and toggle the content when the trigger is clicked", async () => {
|
|
61
|
+
render(<CollapsibleDefault showFirstChild defaultOpen />);
|
|
62
|
+
const TriggerComponent = screen.getByRole("button");
|
|
63
|
+
const FirstChild = screen.queryByText("Item 1");
|
|
64
|
+
const ContentContainer = screen.getByLabelText("test-content");
|
|
65
|
+
|
|
66
|
+
expect(TriggerComponent).toBeDefined();
|
|
67
|
+
expect(FirstChild).toBeDefined();
|
|
68
|
+
expect(ContentContainer.getAttribute("data-state")).toBe("open");
|
|
69
|
+
|
|
70
|
+
fireEvent.click(TriggerComponent);
|
|
71
|
+
await waitFor(() => {
|
|
72
|
+
expect(onClickCallback).toHaveBeenCalled();
|
|
73
|
+
|
|
74
|
+
expect(FirstChild).toBeDefined();
|
|
75
|
+
expect(ContentContainer.getAttribute("data-state")).toBe("closed");
|
|
76
|
+
expect(screen.queryByText("Item 2")).toBe(null);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { test, vi, afterEach, describe, expect } from "vitest";
|
|
4
|
+
import {
|
|
5
|
+
screen,
|
|
6
|
+
render,
|
|
7
|
+
cleanup,
|
|
8
|
+
waitFor,
|
|
9
|
+
fireEvent,
|
|
10
|
+
} from "@testing-library/react";
|
|
11
|
+
import { axe, toHaveNoViolations } from "jest-axe";
|
|
12
|
+
|
|
13
|
+
import { Dialog } from "../../src/dialog";
|
|
14
|
+
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
vi.clearAllMocks();
|
|
17
|
+
vi.resetModules();
|
|
18
|
+
cleanup();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const onClickCallback = vi.fn();
|
|
22
|
+
const onClickCallbackInner = vi.fn();
|
|
23
|
+
const onClickCallbackOverlay = vi.fn();
|
|
24
|
+
const DialogDefault = (args: { open?: boolean; closeOnInteract?: boolean }) => {
|
|
25
|
+
return (
|
|
26
|
+
<Dialog.Root>
|
|
27
|
+
<Dialog.Trigger name="external" onClick={onClickCallback}>
|
|
28
|
+
Ext Trigger
|
|
29
|
+
</Dialog.Trigger>
|
|
30
|
+
|
|
31
|
+
<Dialog open={args.open} aria-label="test-dialog">
|
|
32
|
+
<h4>Dialog component</h4>
|
|
33
|
+
<Dialog.Menu>
|
|
34
|
+
<Dialog.Control name="inner" onClick={onClickCallbackInner}>
|
|
35
|
+
Close
|
|
36
|
+
</Dialog.Control>
|
|
37
|
+
</Dialog.Menu>
|
|
38
|
+
</Dialog>
|
|
39
|
+
<Dialog.Overlay
|
|
40
|
+
aria-label="overlay"
|
|
41
|
+
closeOnInteract={Boolean(args.closeOnInteract)}
|
|
42
|
+
onClick={onClickCallbackOverlay}
|
|
43
|
+
/>
|
|
44
|
+
</Dialog.Root>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
expect.extend(toHaveNoViolations);
|
|
49
|
+
describe("Dialog", () => {
|
|
50
|
+
test("Renders without accessibility violation", async () => {
|
|
51
|
+
const { container } = render(<DialogDefault open />);
|
|
52
|
+
const ComponentContainer = await axe(container);
|
|
53
|
+
|
|
54
|
+
expect(ComponentContainer).toHaveNoViolations();
|
|
55
|
+
});
|
|
56
|
+
test("Renders with accessibility definition", async () => {
|
|
57
|
+
render(<DialogDefault />);
|
|
58
|
+
const ExtTrigger = screen.getByLabelText("external-action");
|
|
59
|
+
|
|
60
|
+
expect(ExtTrigger.getAttribute("aria-expanded")).toBe("false");
|
|
61
|
+
expect(ExtTrigger.getAttribute("data-state")).toBe("closed");
|
|
62
|
+
|
|
63
|
+
fireEvent.click(ExtTrigger);
|
|
64
|
+
await waitFor(() => {
|
|
65
|
+
const Content = screen.getByLabelText("test-dialog");
|
|
66
|
+
const InnerTrigger = screen.getByLabelText("inner-action");
|
|
67
|
+
|
|
68
|
+
expect(ExtTrigger.getAttribute("aria-expanded")).toBe("true");
|
|
69
|
+
expect(ExtTrigger.getAttribute("data-state")).toBe("open");
|
|
70
|
+
|
|
71
|
+
expect(InnerTrigger.getAttribute("aria-expanded")).toBe("true");
|
|
72
|
+
expect(InnerTrigger.getAttribute("data-state")).toBe("open");
|
|
73
|
+
|
|
74
|
+
expect(Content.getAttribute("role")).toBe("dialog");
|
|
75
|
+
expect(Content.getAttribute("data-state")).toBe("open");
|
|
76
|
+
expect(Content.getAttribute("tabIndex")).toBe("-1");
|
|
77
|
+
expect(Content.getAttribute("aria-labelledby")).toBeDefined();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
test("Fires the defined callback functions and toggle the content when the triggers are clicked", async () => {
|
|
81
|
+
render(<DialogDefault />);
|
|
82
|
+
|
|
83
|
+
fireEvent.click(screen.getByLabelText("external-action"));
|
|
84
|
+
await waitFor(() => expect(onClickCallback).toHaveBeenCalled());
|
|
85
|
+
|
|
86
|
+
fireEvent.click(screen.getByLabelText("inner-action"));
|
|
87
|
+
await waitFor(() => expect(onClickCallbackInner).toHaveBeenCalled());
|
|
88
|
+
});
|
|
89
|
+
test("Renders the component by default if open is defined", async () => {
|
|
90
|
+
render(<DialogDefault open />);
|
|
91
|
+
await waitFor(() =>
|
|
92
|
+
expect(screen.getByLabelText("test-dialog")).toBeDefined()
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
test("Removes the component from the DOM if the Overlay is clicked and closeOnInteract is defined", async () => {
|
|
96
|
+
render(<DialogDefault open closeOnInteract />);
|
|
97
|
+
await waitFor(() => {
|
|
98
|
+
const Overlay = screen.getByLabelText("overlay");
|
|
99
|
+
|
|
100
|
+
expect(Overlay).toBeDefined();
|
|
101
|
+
expect(Overlay.getAttribute("aria-hidden")).toBe("true");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
fireEvent.click(screen.getByLabelText("overlay"));
|
|
105
|
+
expect(onClickCallbackOverlay).toHaveBeenCalled();
|
|
106
|
+
expect(() => screen.getByRole("region")).toThrow();
|
|
107
|
+
expect(() => screen.getByLabelText("overlay")).toThrow();
|
|
108
|
+
});
|
|
109
|
+
});
|