@simplysm/solid 13.0.70 → 13.0.72
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/README.md +1 -1
- package/dist/components/data/sheet/DataSheet.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheet.js +3 -6
- package/dist/components/data/sheet/DataSheet.js.map +1 -1
- package/dist/components/data/sheet/DataSheet.styles.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheet.styles.js +1 -1
- package/dist/components/data/sheet/DataSheet.styles.js.map +1 -1
- package/dist/components/disclosure/Dropdown.d.ts +6 -4
- package/dist/components/disclosure/Dropdown.d.ts.map +1 -1
- package/dist/components/disclosure/Dropdown.js +24 -8
- package/dist/components/disclosure/Dropdown.js.map +2 -2
- package/dist/components/disclosure/dialogZIndex.d.ts +2 -0
- package/dist/components/disclosure/dialogZIndex.d.ts.map +1 -1
- package/dist/components/disclosure/dialogZIndex.js +4 -0
- package/dist/components/disclosure/dialogZIndex.js.map +1 -1
- package/dist/components/features/crud-detail/CrudDetail.d.ts.map +1 -1
- package/dist/components/features/crud-detail/CrudDetail.js +16 -7
- package/dist/components/features/crud-detail/CrudDetail.js.map +2 -2
- package/dist/components/features/crud-sheet/CrudSheet.d.ts.map +1 -1
- package/dist/components/features/crud-sheet/CrudSheet.js +14 -5
- package/dist/components/features/crud-sheet/CrudSheet.js.map +2 -2
- package/dist/components/features/crudRegistry.d.ts +16 -0
- package/dist/components/features/crudRegistry.d.ts.map +1 -0
- package/dist/components/features/crudRegistry.js +37 -0
- package/dist/components/features/crudRegistry.js.map +6 -0
- package/dist/components/features/permission-table/PermissionTable.d.ts.map +1 -1
- package/dist/components/features/permission-table/PermissionTable.js +71 -86
- package/dist/components/features/permission-table/PermissionTable.js.map +2 -2
- package/dist/components/features/shared-data/SharedDataSelect.js +2 -4
- package/dist/components/features/shared-data/SharedDataSelect.js.map +2 -2
- package/dist/components/features/shared-data/SharedDataSelectList.d.ts +2 -4
- package/dist/components/features/shared-data/SharedDataSelectList.d.ts.map +1 -1
- package/dist/components/features/shared-data/SharedDataSelectList.js +11 -46
- package/dist/components/features/shared-data/SharedDataSelectList.js.map +2 -2
- package/dist/components/form-control/select/Select.d.ts.map +1 -1
- package/dist/components/form-control/select/Select.js +1 -1
- package/dist/components/form-control/select/Select.js.map +1 -1
- package/dist/helpers/createAppStructure.d.ts.map +1 -1
- package/dist/helpers/createAppStructure.js +3 -2
- package/dist/helpers/createAppStructure.js.map +1 -1
- package/dist/helpers/createHmrSafeContext.d.ts +3 -0
- package/dist/helpers/createHmrSafeContext.d.ts.map +1 -0
- package/dist/helpers/createHmrSafeContext.js +10 -0
- package/dist/helpers/createHmrSafeContext.js.map +6 -0
- package/dist/hooks/createSelectionGroup.d.ts.map +1 -1
- package/dist/hooks/createSelectionGroup.js +3 -2
- package/dist/hooks/createSelectionGroup.js.map +2 -2
- package/package.json +6 -5
- package/src/components/data/sheet/DataSheet.styles.ts +1 -1
- package/src/components/data/sheet/DataSheet.tsx +3 -4
- package/src/components/disclosure/Dropdown.tsx +31 -17
- package/src/components/disclosure/dialogZIndex.ts +5 -0
- package/src/components/features/crud-detail/CrudDetail.tsx +16 -5
- package/src/components/features/crud-sheet/CrudSheet.tsx +13 -3
- package/src/components/features/crudRegistry.ts +60 -0
- package/src/components/features/permission-table/PermissionTable.tsx +49 -46
- package/src/components/features/shared-data/SharedDataSelect.tsx +2 -2
- package/src/components/features/shared-data/SharedDataSelectList.tsx +11 -36
- package/src/components/form-control/select/Select.tsx +1 -5
- package/src/helpers/createAppStructure.ts +3 -2
- package/src/helpers/createHmrSafeContext.ts +8 -0
- package/src/hooks/createSelectionGroup.tsx +4 -2
- package/tests/components/data/List.spec.tsx +52 -52
- package/tests/components/data/Pagination.spec.tsx +43 -43
- package/tests/components/data/Table.spec.tsx +4 -4
- package/tests/components/data/kanban/Kanban.selection.spec.tsx +21 -21
- package/tests/components/data/sheet/DataSheet.spec.tsx +50 -50
- package/tests/components/disclosure/Collapse.spec.tsx +24 -24
- package/tests/components/disclosure/Dialog.spec.tsx +33 -33
- package/tests/components/disclosure/DialogProvider.spec.tsx +9 -9
- package/tests/components/disclosure/Dropdown.spec.tsx +134 -14
- package/tests/components/disclosure/Tabs.spec.tsx +21 -21
- package/tests/components/disclosure/dialogZIndex.spec.ts +45 -0
- package/tests/components/display/Alert.spec.tsx +4 -4
- package/tests/components/display/Barcode.spec.tsx +7 -7
- package/tests/components/display/Card.spec.tsx +3 -3
- package/tests/components/display/Link.spec.tsx +5 -5
- package/tests/components/display/Tag.spec.tsx +4 -4
- package/tests/components/features/address/AddressSearch.spec.tsx +3 -3
- package/tests/components/features/crudRegistry.spec.ts +119 -0
- package/tests/components/features/data-select-button/DataSelectButton.spec.tsx +8 -8
- package/tests/components/features/permission-table/PermissionTable.spec.tsx +43 -43
- package/tests/components/features/shared-data/SharedDataSelectList.spec.tsx +2 -17
- package/tests/components/feedback/busy/BusyContainer.spec.tsx +7 -7
- package/tests/components/feedback/notification/NotificationBell.spec.tsx +9 -9
- package/tests/components/feedback/print/Print.spec.tsx +4 -4
- package/tests/components/form-control/Button.spec.tsx +18 -18
- package/tests/components/form-control/checkbox/Checkbox.spec.tsx +20 -20
- package/tests/components/form-control/checkbox/CheckboxGroup.spec.tsx +12 -12
- package/tests/components/form-control/checkbox/Radio.spec.tsx +21 -21
- package/tests/components/form-control/checkbox/RadioGroup.spec.tsx +12 -12
- package/tests/components/form-control/color-picker/ColorPicker.spec.tsx +10 -10
- package/tests/components/form-control/combobox/Combobox.spec.tsx +16 -16
- package/tests/components/form-control/combobox/ComboboxItem.spec.tsx +7 -7
- package/tests/components/form-control/date-range-picker/DateRangePicker.spec.tsx +24 -24
- package/tests/components/form-control/field/DatePicker.spec.tsx +50 -50
- package/tests/components/form-control/field/DateTimePicker.spec.tsx +47 -47
- package/tests/components/form-control/field/NumberInput.spec.tsx +54 -54
- package/tests/components/form-control/field/TextInput.spec.tsx +49 -49
- package/tests/components/form-control/field/Textarea.spec.tsx +33 -33
- package/tests/components/form-control/field/TimePicker.spec.tsx +42 -42
- package/tests/components/form-control/numpad/Numpad.spec.tsx +40 -40
- package/tests/components/form-control/select/Select.spec.tsx +9 -9
- package/tests/components/form-control/select/SelectItem.spec.tsx +10 -10
- package/tests/helpers/createAppStructure.spec.tsx +57 -57
- package/tests/helpers/mergeStyles.spec.ts +31 -31
|
@@ -2,7 +2,7 @@ import { render } from "@solidjs/testing-library";
|
|
|
2
2
|
import { describe, it, expect } from "vitest";
|
|
3
3
|
import { Print } from "../../../../src/components/feedback/print/Print";
|
|
4
4
|
|
|
5
|
-
describe("Print
|
|
5
|
+
describe("Print", () => {
|
|
6
6
|
describe("basic rendering", () => {
|
|
7
7
|
it("renders children", () => {
|
|
8
8
|
const { getByText } = render(() => <Print>테스트 내용</Print>);
|
|
@@ -11,7 +11,7 @@ describe("Print 컴포넌트", () => {
|
|
|
11
11
|
});
|
|
12
12
|
|
|
13
13
|
describe("Print.Page", () => {
|
|
14
|
-
it("data-print-page
|
|
14
|
+
it("renders with data-print-page attribute", () => {
|
|
15
15
|
const { container } = render(() => (
|
|
16
16
|
<Print>
|
|
17
17
|
<Print.Page>페이지 1</Print.Page>
|
|
@@ -21,7 +21,7 @@ describe("Print 컴포넌트", () => {
|
|
|
21
21
|
expect(page).toBeTruthy();
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
-
it("
|
|
24
|
+
it("each Print.Page has data-print-page attribute", () => {
|
|
25
25
|
const { container } = render(() => (
|
|
26
26
|
<Print>
|
|
27
27
|
<Print.Page>페이지 1</Print.Page>
|
|
@@ -33,7 +33,7 @@ describe("Print 컴포넌트", () => {
|
|
|
33
33
|
expect(pages.length).toBe(3);
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
it("Print.Page children
|
|
36
|
+
it("renders Print.Page children", () => {
|
|
37
37
|
const { getByText } = render(() => (
|
|
38
38
|
<Print>
|
|
39
39
|
<Print.Page>페이지 내용</Print.Page>
|
|
@@ -2,23 +2,23 @@ import { render, fireEvent } from "@solidjs/testing-library";
|
|
|
2
2
|
import { describe, it, expect, vi } from "vitest";
|
|
3
3
|
import { Button } from "../../../src/components/form-control/Button";
|
|
4
4
|
|
|
5
|
-
describe("Button
|
|
5
|
+
describe("Button component", () => {
|
|
6
6
|
describe("basic rendering", () => {
|
|
7
|
-
it("children
|
|
7
|
+
it("renders children inside the button", () => {
|
|
8
8
|
const { getByRole } = render(() => <Button>Click Me</Button>);
|
|
9
9
|
const button = getByRole("button");
|
|
10
10
|
|
|
11
11
|
expect(button.textContent).toBe("Click Me");
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
it("type
|
|
14
|
+
it("defaults type to button", () => {
|
|
15
15
|
const { getByRole } = render(() => <Button>Click</Button>);
|
|
16
16
|
const button = getByRole("button");
|
|
17
17
|
|
|
18
18
|
expect(button.getAttribute("type")).toBe("button");
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
it("type
|
|
21
|
+
it("overrides type with submit", () => {
|
|
22
22
|
const { getByRole } = render(() => <Button type="submit">Submit</Button>);
|
|
23
23
|
const button = getByRole("button");
|
|
24
24
|
|
|
@@ -26,8 +26,8 @@ describe("Button 컴포넌트", () => {
|
|
|
26
26
|
});
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
describe("theme
|
|
30
|
-
it("
|
|
29
|
+
describe("theme prop", () => {
|
|
30
|
+
it("applies different styles per theme", () => {
|
|
31
31
|
const { getByRole: getDefault } = render(() => <Button>Click</Button>);
|
|
32
32
|
const { getByRole: getThemed } = render(() => <Button theme="danger">Click</Button>);
|
|
33
33
|
|
|
@@ -35,8 +35,8 @@ describe("Button 컴포넌트", () => {
|
|
|
35
35
|
});
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
describe("variant
|
|
39
|
-
it("
|
|
38
|
+
describe("variant prop", () => {
|
|
39
|
+
it("applies different styles per variant", () => {
|
|
40
40
|
const { getByRole: getOutline } = render(() => <Button>Click</Button>);
|
|
41
41
|
const { getByRole: getSolid } = render(() => <Button variant="solid">Click</Button>);
|
|
42
42
|
const { getByRole: getGhost } = render(() => <Button variant="ghost">Click</Button>);
|
|
@@ -51,8 +51,8 @@ describe("Button 컴포넌트", () => {
|
|
|
51
51
|
});
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
describe("size
|
|
55
|
-
it("
|
|
54
|
+
describe("size prop", () => {
|
|
55
|
+
it("applies different styles per size", () => {
|
|
56
56
|
const { getByRole: getDefault } = render(() => <Button>Click</Button>);
|
|
57
57
|
const { getByRole: getSm } = render(() => <Button size="sm">Click</Button>);
|
|
58
58
|
const { getByRole: getLg } = render(() => <Button size="lg">Click</Button>);
|
|
@@ -67,8 +67,8 @@ describe("Button 컴포넌트", () => {
|
|
|
67
67
|
});
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
-
describe("inset
|
|
71
|
-
it("
|
|
70
|
+
describe("inset prop", () => {
|
|
71
|
+
it("applies different styles when inset", () => {
|
|
72
72
|
const { getByRole: getDefault } = render(() => <Button>Click</Button>);
|
|
73
73
|
const { getByRole: getInset } = render(() => <Button inset>Click</Button>);
|
|
74
74
|
|
|
@@ -76,23 +76,23 @@ describe("Button 컴포넌트", () => {
|
|
|
76
76
|
});
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
-
describe("disabled
|
|
80
|
-
it("
|
|
79
|
+
describe("disabled prop", () => {
|
|
80
|
+
it("applies different styles when disabled", () => {
|
|
81
81
|
const { getByRole: getDefault } = render(() => <Button>Click</Button>);
|
|
82
82
|
const { getByRole: getDisabled } = render(() => <Button disabled>Click</Button>);
|
|
83
83
|
|
|
84
84
|
expect(getDefault("button").className).not.toBe(getDisabled("button").className);
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
-
it("
|
|
87
|
+
it("sets HTML disabled attribute when disabled=true", () => {
|
|
88
88
|
const { getByRole } = render(() => <Button disabled>Click</Button>);
|
|
89
89
|
|
|
90
90
|
expect(getByRole("button").hasAttribute("disabled")).toBe(true);
|
|
91
91
|
});
|
|
92
92
|
});
|
|
93
93
|
|
|
94
|
-
describe("
|
|
95
|
-
it("onClick handler
|
|
94
|
+
describe("event handling", () => {
|
|
95
|
+
it("calls onClick handler on click", () => {
|
|
96
96
|
const handleClick = vi.fn();
|
|
97
97
|
const { getByRole } = render(() => <Button onClick={handleClick}>Click</Button>);
|
|
98
98
|
|
|
@@ -101,7 +101,7 @@ describe("Button 컴포넌트", () => {
|
|
|
101
101
|
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
102
102
|
});
|
|
103
103
|
|
|
104
|
-
it("
|
|
104
|
+
it("blocks click when disabled", () => {
|
|
105
105
|
const { getByRole } = render(() => <Button disabled>Click</Button>);
|
|
106
106
|
|
|
107
107
|
expect(getByRole("button").hasAttribute("disabled")).toBe(true);
|
|
@@ -3,26 +3,26 @@ import { describe, it, expect, vi } from "vitest";
|
|
|
3
3
|
import { createSignal } from "solid-js";
|
|
4
4
|
import { Checkbox } from "../../../../src/components/form-control/checkbox/Checkbox";
|
|
5
5
|
|
|
6
|
-
describe("Checkbox
|
|
6
|
+
describe("Checkbox component", () => {
|
|
7
7
|
describe("basic rendering", () => {
|
|
8
|
-
it("checkbox role
|
|
8
|
+
it("renders with checkbox role", () => {
|
|
9
9
|
const { getByRole } = render(() => <Checkbox />);
|
|
10
10
|
expect(getByRole("checkbox")).toBeTruthy();
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
it("children
|
|
13
|
+
it("renders children as label", () => {
|
|
14
14
|
const { getByText } = render(() => <Checkbox>동의합니다</Checkbox>);
|
|
15
15
|
expect(getByText("동의합니다")).toBeTruthy();
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
it("
|
|
18
|
+
it("defaults to unchecked", () => {
|
|
19
19
|
const { getByRole } = render(() => <Checkbox />);
|
|
20
20
|
expect(getByRole("checkbox").getAttribute("aria-checked")).toBe("false");
|
|
21
21
|
});
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
describe("click behavior", () => {
|
|
25
|
-
it("
|
|
25
|
+
it("toggles checked state on click", () => {
|
|
26
26
|
const { getByRole } = render(() => <Checkbox />);
|
|
27
27
|
const checkbox = getByRole("checkbox");
|
|
28
28
|
|
|
@@ -33,7 +33,7 @@ describe("Checkbox 컴포넌트", () => {
|
|
|
33
33
|
expect(checkbox.getAttribute("aria-checked")).toBe("false");
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
-
it("
|
|
36
|
+
it("does not change when disabled", () => {
|
|
37
37
|
const { getByRole } = render(() => <Checkbox disabled />);
|
|
38
38
|
const checkbox = getByRole("checkbox");
|
|
39
39
|
|
|
@@ -42,8 +42,8 @@ describe("Checkbox 컴포넌트", () => {
|
|
|
42
42
|
});
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
describe("
|
|
46
|
-
it("Space
|
|
45
|
+
describe("keyboard behavior", () => {
|
|
46
|
+
it("toggles with Space key", () => {
|
|
47
47
|
const { getByRole } = render(() => <Checkbox />);
|
|
48
48
|
const checkbox = getByRole("checkbox");
|
|
49
49
|
|
|
@@ -55,13 +55,13 @@ describe("Checkbox 컴포넌트", () => {
|
|
|
55
55
|
});
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
-
describe("controlled
|
|
59
|
-
it("value prop
|
|
58
|
+
describe("controlled pattern", () => {
|
|
59
|
+
it("reflects value prop as checked state", () => {
|
|
60
60
|
const { getByRole } = render(() => <Checkbox value={true} />);
|
|
61
61
|
expect(getByRole("checkbox").getAttribute("aria-checked")).toBe("true");
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
it("onValueChange
|
|
64
|
+
it("calls onValueChange on click", () => {
|
|
65
65
|
const handleChange = vi.fn();
|
|
66
66
|
const { getByRole } = render(() => <Checkbox value={false} onValueChange={handleChange} />);
|
|
67
67
|
|
|
@@ -69,7 +69,7 @@ describe("Checkbox 컴포넌트", () => {
|
|
|
69
69
|
expect(handleChange).toHaveBeenCalledWith(true);
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
-
it("
|
|
72
|
+
it("updates when external state changes", () => {
|
|
73
73
|
const [value, setValue] = createSignal(false);
|
|
74
74
|
const { getByRole } = render(() => <Checkbox value={value()} onValueChange={setValue} />);
|
|
75
75
|
|
|
@@ -80,22 +80,22 @@ describe("Checkbox 컴포넌트", () => {
|
|
|
80
80
|
});
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
describe("
|
|
84
|
-
it("
|
|
83
|
+
describe("style variants", () => {
|
|
84
|
+
it("applies different styles per size", () => {
|
|
85
85
|
const { getByRole: getDefault } = render(() => <Checkbox />);
|
|
86
86
|
const { getByRole: getSm } = render(() => <Checkbox size="sm" />);
|
|
87
87
|
|
|
88
88
|
expect(getDefault("checkbox").className).not.toBe(getSm("checkbox").className);
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
-
it("
|
|
91
|
+
it("applies different styles when inset", () => {
|
|
92
92
|
const { getByRole: getDefault } = render(() => <Checkbox />);
|
|
93
93
|
const { getByRole: getInset } = render(() => <Checkbox inset />);
|
|
94
94
|
|
|
95
95
|
expect(getDefault("checkbox").className).not.toBe(getInset("checkbox").className);
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
it("disabled
|
|
98
|
+
it("applies disabled style", () => {
|
|
99
99
|
const { getByRole } = render(() => <Checkbox disabled />);
|
|
100
100
|
expect(getByRole("checkbox").classList.contains("opacity-30")).toBe(true);
|
|
101
101
|
});
|
|
@@ -110,25 +110,25 @@ describe("Checkbox 컴포넌트", () => {
|
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
describe("validation", () => {
|
|
113
|
-
it("
|
|
113
|
+
it("sets error message when required and unchecked", () => {
|
|
114
114
|
const { container } = render(() => <Checkbox required value={false} />);
|
|
115
115
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
116
116
|
expect(hiddenInput.validationMessage).toBe("This is a required selection");
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
-
it("required
|
|
119
|
+
it("is valid when required and checked", () => {
|
|
120
120
|
const { container } = render(() => <Checkbox required value={true} />);
|
|
121
121
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
122
122
|
expect(hiddenInput.validity.valid).toBe(true);
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
-
it("
|
|
125
|
+
it("sets error message returned by validate function", () => {
|
|
126
126
|
const { container } = render(() => <Checkbox value={true} validate={() => "커스텀 에러"} />);
|
|
127
127
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
128
128
|
expect(hiddenInput.validationMessage).toBe("커스텀 에러");
|
|
129
129
|
});
|
|
130
130
|
|
|
131
|
-
it("validate
|
|
131
|
+
it("is valid when validate function returns undefined", () => {
|
|
132
132
|
const { container } = render(() => <Checkbox value={true} validate={() => undefined} />);
|
|
133
133
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
134
134
|
expect(hiddenInput.validity.valid).toBe(true);
|
|
@@ -3,9 +3,9 @@ import { describe, it, expect, vi } from "vitest";
|
|
|
3
3
|
import { createSignal } from "solid-js";
|
|
4
4
|
import { CheckboxGroup } from "../../../../src/components/form-control/checkbox/CheckboxGroup";
|
|
5
5
|
|
|
6
|
-
describe("CheckboxGroup
|
|
6
|
+
describe("CheckboxGroup component", () => {
|
|
7
7
|
describe("basic rendering", () => {
|
|
8
|
-
it("
|
|
8
|
+
it("renders the container", () => {
|
|
9
9
|
const { container } = render(() => (
|
|
10
10
|
<CheckboxGroup>
|
|
11
11
|
<CheckboxGroup.Item value="a">A</CheckboxGroup.Item>
|
|
@@ -14,7 +14,7 @@ describe("CheckboxGroup 컴포넌트", () => {
|
|
|
14
14
|
expect(container.querySelector("div")).toBeTruthy();
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
it("
|
|
17
|
+
it("renders items as checkboxes", () => {
|
|
18
18
|
const { getAllByRole } = render(() => (
|
|
19
19
|
<CheckboxGroup>
|
|
20
20
|
<CheckboxGroup.Item value="a">A</CheckboxGroup.Item>
|
|
@@ -25,8 +25,8 @@ describe("CheckboxGroup 컴포넌트", () => {
|
|
|
25
25
|
});
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
describe("controlled
|
|
29
|
-
it("value prop
|
|
28
|
+
describe("controlled pattern", () => {
|
|
29
|
+
it("reflects value prop as selected state", () => {
|
|
30
30
|
const { getAllByRole } = render(() => (
|
|
31
31
|
<CheckboxGroup value={["a"]}>
|
|
32
32
|
<CheckboxGroup.Item value="a">A</CheckboxGroup.Item>
|
|
@@ -38,7 +38,7 @@ describe("CheckboxGroup 컴포넌트", () => {
|
|
|
38
38
|
expect(checkboxes[1].getAttribute("aria-checked")).toBe("false");
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
it("onValueChange
|
|
41
|
+
it("calls onValueChange on toggle", () => {
|
|
42
42
|
const handleChange = vi.fn();
|
|
43
43
|
const { getAllByRole } = render(() => (
|
|
44
44
|
<CheckboxGroup value={[]} onValueChange={handleChange}>
|
|
@@ -49,7 +49,7 @@ describe("CheckboxGroup 컴포넌트", () => {
|
|
|
49
49
|
expect(handleChange).toHaveBeenCalledWith(["a"]);
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
it("
|
|
52
|
+
it("updates when external state changes", () => {
|
|
53
53
|
const [value, setValue] = createSignal<string[]>([]);
|
|
54
54
|
const { getAllByRole } = render(() => (
|
|
55
55
|
<CheckboxGroup value={value()} onValueChange={setValue}>
|
|
@@ -63,13 +63,13 @@ describe("CheckboxGroup 컴포넌트", () => {
|
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
describe("validation", () => {
|
|
66
|
-
//
|
|
66
|
+
// The group's hidden input is positioned after the children's hidden inputs
|
|
67
67
|
const getGroupHiddenInput = (container: HTMLElement) => {
|
|
68
68
|
const inputs = container.querySelectorAll("input[aria-hidden='true']");
|
|
69
69
|
return inputs[inputs.length - 1] as HTMLInputElement;
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
it("
|
|
72
|
+
it("sets error message when required and no item selected", () => {
|
|
73
73
|
const { container } = render(() => (
|
|
74
74
|
<CheckboxGroup required value={[]}>
|
|
75
75
|
<CheckboxGroup.Item value="a">A</CheckboxGroup.Item>
|
|
@@ -78,7 +78,7 @@ describe("CheckboxGroup 컴포넌트", () => {
|
|
|
78
78
|
expect(getGroupHiddenInput(container).validationMessage).toBe("Please select an item");
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
-
it("required
|
|
81
|
+
it("is valid when required and item is selected", () => {
|
|
82
82
|
const { container } = render(() => (
|
|
83
83
|
<CheckboxGroup required value={["a"]}>
|
|
84
84
|
<CheckboxGroup.Item value="a">A</CheckboxGroup.Item>
|
|
@@ -87,7 +87,7 @@ describe("CheckboxGroup 컴포넌트", () => {
|
|
|
87
87
|
expect(getGroupHiddenInput(container).validity.valid).toBe(true);
|
|
88
88
|
});
|
|
89
89
|
|
|
90
|
-
it("
|
|
90
|
+
it("sets error message returned by validate function", () => {
|
|
91
91
|
const { container } = render(() => (
|
|
92
92
|
<CheckboxGroup value={["a"]} validate={() => "커스텀 에러"}>
|
|
93
93
|
<CheckboxGroup.Item value="a">A</CheckboxGroup.Item>
|
|
@@ -96,7 +96,7 @@ describe("CheckboxGroup 컴포넌트", () => {
|
|
|
96
96
|
expect(getGroupHiddenInput(container).validationMessage).toBe("커스텀 에러");
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
it("validate
|
|
99
|
+
it("is valid when validate function returns undefined", () => {
|
|
100
100
|
const { container } = render(() => (
|
|
101
101
|
<CheckboxGroup value={["a"]} validate={() => undefined}>
|
|
102
102
|
<CheckboxGroup.Item value="a">A</CheckboxGroup.Item>
|
|
@@ -3,26 +3,26 @@ import { describe, it, expect, vi } from "vitest";
|
|
|
3
3
|
import { createSignal } from "solid-js";
|
|
4
4
|
import { Radio } from "../../../../src/components/form-control/checkbox/Radio";
|
|
5
5
|
|
|
6
|
-
describe("Radio
|
|
6
|
+
describe("Radio component", () => {
|
|
7
7
|
describe("basic rendering", () => {
|
|
8
|
-
it("radio role
|
|
8
|
+
it("renders with radio role", () => {
|
|
9
9
|
const { getByRole } = render(() => <Radio />);
|
|
10
10
|
expect(getByRole("radio")).toBeTruthy();
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
it("children
|
|
13
|
+
it("renders children as label", () => {
|
|
14
14
|
const { getByText } = render(() => <Radio>옵션 A</Radio>);
|
|
15
15
|
expect(getByText("옵션 A")).toBeTruthy();
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
it("
|
|
18
|
+
it("defaults to unchecked", () => {
|
|
19
19
|
const { getByRole } = render(() => <Radio />);
|
|
20
20
|
expect(getByRole("radio").getAttribute("aria-checked")).toBe("false");
|
|
21
21
|
});
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
describe("click behavior", () => {
|
|
25
|
-
it("
|
|
25
|
+
it("selects on click", () => {
|
|
26
26
|
const { getByRole } = render(() => <Radio />);
|
|
27
27
|
const radio = getByRole("radio");
|
|
28
28
|
|
|
@@ -30,7 +30,7 @@ describe("Radio 컴포넌트", () => {
|
|
|
30
30
|
expect(radio.getAttribute("aria-checked")).toBe("true");
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
it("
|
|
33
|
+
it("does not deselect when already selected", () => {
|
|
34
34
|
const { getByRole } = render(() => <Radio value={true} />);
|
|
35
35
|
const radio = getByRole("radio");
|
|
36
36
|
|
|
@@ -38,7 +38,7 @@ describe("Radio 컴포넌트", () => {
|
|
|
38
38
|
expect(radio.getAttribute("aria-checked")).toBe("true");
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
it("
|
|
41
|
+
it("does not change when disabled", () => {
|
|
42
42
|
const { getByRole } = render(() => <Radio disabled />);
|
|
43
43
|
const radio = getByRole("radio");
|
|
44
44
|
|
|
@@ -47,8 +47,8 @@ describe("Radio 컴포넌트", () => {
|
|
|
47
47
|
});
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
describe("
|
|
51
|
-
it("Space
|
|
50
|
+
describe("keyboard behavior", () => {
|
|
51
|
+
it("selects with Space key", () => {
|
|
52
52
|
const { getByRole } = render(() => <Radio />);
|
|
53
53
|
const radio = getByRole("radio");
|
|
54
54
|
|
|
@@ -57,13 +57,13 @@ describe("Radio 컴포넌트", () => {
|
|
|
57
57
|
});
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
describe("controlled
|
|
61
|
-
it("value prop
|
|
60
|
+
describe("controlled pattern", () => {
|
|
61
|
+
it("reflects value prop as checked state", () => {
|
|
62
62
|
const { getByRole } = render(() => <Radio value={true} />);
|
|
63
63
|
expect(getByRole("radio").getAttribute("aria-checked")).toBe("true");
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
-
it("onValueChange
|
|
66
|
+
it("calls onValueChange on click", () => {
|
|
67
67
|
const handleChange = vi.fn();
|
|
68
68
|
const { getByRole } = render(() => <Radio value={false} onValueChange={handleChange} />);
|
|
69
69
|
|
|
@@ -71,7 +71,7 @@ describe("Radio 컴포넌트", () => {
|
|
|
71
71
|
expect(handleChange).toHaveBeenCalledWith(true);
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
it("
|
|
74
|
+
it("updates when external state changes", () => {
|
|
75
75
|
const [value, setValue] = createSignal(false);
|
|
76
76
|
const { getByRole } = render(() => <Radio value={value()} onValueChange={setValue} />);
|
|
77
77
|
|
|
@@ -82,21 +82,21 @@ describe("Radio 컴포넌트", () => {
|
|
|
82
82
|
});
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
-
describe("
|
|
86
|
-
it("
|
|
85
|
+
describe("style variants", () => {
|
|
86
|
+
it("indicator is circular", () => {
|
|
87
87
|
const { getByRole } = render(() => <Radio />);
|
|
88
88
|
const indicator = getByRole("radio").querySelector("div") as HTMLElement;
|
|
89
89
|
expect(indicator.classList.contains("rounded-full")).toBe(true);
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
it("
|
|
92
|
+
it("applies different styles per size", () => {
|
|
93
93
|
const { getByRole: getDefault } = render(() => <Radio />);
|
|
94
94
|
const { getByRole: getSm } = render(() => <Radio size="sm" />);
|
|
95
95
|
|
|
96
96
|
expect(getDefault("radio").className).not.toBe(getSm("radio").className);
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
it("disabled
|
|
99
|
+
it("applies disabled style", () => {
|
|
100
100
|
const { getByRole } = render(() => <Radio disabled />);
|
|
101
101
|
expect(getByRole("radio").classList.contains("opacity-30")).toBe(true);
|
|
102
102
|
});
|
|
@@ -111,25 +111,25 @@ describe("Radio 컴포넌트", () => {
|
|
|
111
111
|
});
|
|
112
112
|
|
|
113
113
|
describe("validation", () => {
|
|
114
|
-
it("
|
|
114
|
+
it("sets error message when required and not selected", () => {
|
|
115
115
|
const { container } = render(() => <Radio required value={false} />);
|
|
116
116
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
117
117
|
expect(hiddenInput.validationMessage).toBe("This is a required selection");
|
|
118
118
|
});
|
|
119
119
|
|
|
120
|
-
it("required
|
|
120
|
+
it("is valid when required and selected", () => {
|
|
121
121
|
const { container } = render(() => <Radio required value={true} />);
|
|
122
122
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
123
123
|
expect(hiddenInput.validity.valid).toBe(true);
|
|
124
124
|
});
|
|
125
125
|
|
|
126
|
-
it("
|
|
126
|
+
it("sets error message returned by validate function", () => {
|
|
127
127
|
const { container } = render(() => <Radio value={true} validate={() => "커스텀 에러"} />);
|
|
128
128
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
129
129
|
expect(hiddenInput.validationMessage).toBe("커스텀 에러");
|
|
130
130
|
});
|
|
131
131
|
|
|
132
|
-
it("validate
|
|
132
|
+
it("is valid when validate function returns undefined", () => {
|
|
133
133
|
const { container } = render(() => <Radio value={true} validate={() => undefined} />);
|
|
134
134
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
135
135
|
expect(hiddenInput.validity.valid).toBe(true);
|
|
@@ -3,9 +3,9 @@ import { describe, it, expect, vi } from "vitest";
|
|
|
3
3
|
import { createSignal } from "solid-js";
|
|
4
4
|
import { RadioGroup } from "../../../../src/components/form-control/checkbox/RadioGroup";
|
|
5
5
|
|
|
6
|
-
describe("RadioGroup
|
|
6
|
+
describe("RadioGroup component", () => {
|
|
7
7
|
describe("basic rendering", () => {
|
|
8
|
-
it("
|
|
8
|
+
it("renders the container", () => {
|
|
9
9
|
const { container } = render(() => (
|
|
10
10
|
<RadioGroup>
|
|
11
11
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|
|
@@ -14,7 +14,7 @@ describe("RadioGroup 컴포넌트", () => {
|
|
|
14
14
|
expect(container.querySelector("div")).toBeTruthy();
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
it("
|
|
17
|
+
it("renders items as radios", () => {
|
|
18
18
|
const { getAllByRole } = render(() => (
|
|
19
19
|
<RadioGroup>
|
|
20
20
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|
|
@@ -25,8 +25,8 @@ describe("RadioGroup 컴포넌트", () => {
|
|
|
25
25
|
});
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
describe("controlled
|
|
29
|
-
it("value prop
|
|
28
|
+
describe("controlled pattern", () => {
|
|
29
|
+
it("reflects value prop as selected state", () => {
|
|
30
30
|
const { getAllByRole } = render(() => (
|
|
31
31
|
<RadioGroup value="a">
|
|
32
32
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|
|
@@ -38,7 +38,7 @@ describe("RadioGroup 컴포넌트", () => {
|
|
|
38
38
|
expect(radios[1].getAttribute("aria-checked")).toBe("false");
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
it("onValueChange
|
|
41
|
+
it("calls onValueChange on selection", () => {
|
|
42
42
|
const handleChange = vi.fn();
|
|
43
43
|
const { getAllByRole } = render(() => (
|
|
44
44
|
<RadioGroup value={undefined} onValueChange={handleChange}>
|
|
@@ -49,7 +49,7 @@ describe("RadioGroup 컴포넌트", () => {
|
|
|
49
49
|
expect(handleChange).toHaveBeenCalledWith("a");
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
it("
|
|
52
|
+
it("updates when external state changes", () => {
|
|
53
53
|
const [value, setValue] = createSignal<string | undefined>(undefined);
|
|
54
54
|
const { getAllByRole } = render(() => (
|
|
55
55
|
<RadioGroup value={value()} onValueChange={setValue}>
|
|
@@ -63,13 +63,13 @@ describe("RadioGroup 컴포넌트", () => {
|
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
describe("validation", () => {
|
|
66
|
-
//
|
|
66
|
+
// The group's hidden input is positioned after the children's hidden inputs
|
|
67
67
|
const getGroupHiddenInput = (container: HTMLElement) => {
|
|
68
68
|
const inputs = container.querySelectorAll("input[aria-hidden='true']");
|
|
69
69
|
return inputs[inputs.length - 1] as HTMLInputElement;
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
it("
|
|
72
|
+
it("sets error message when required and no item selected", () => {
|
|
73
73
|
const { container } = render(() => (
|
|
74
74
|
<RadioGroup required value={undefined}>
|
|
75
75
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|
|
@@ -78,7 +78,7 @@ describe("RadioGroup 컴포넌트", () => {
|
|
|
78
78
|
expect(getGroupHiddenInput(container).validationMessage).toBe("Please select an item");
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
-
it("required
|
|
81
|
+
it("is valid when required and item is selected", () => {
|
|
82
82
|
const { container } = render(() => (
|
|
83
83
|
<RadioGroup required value="a">
|
|
84
84
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|
|
@@ -87,7 +87,7 @@ describe("RadioGroup 컴포넌트", () => {
|
|
|
87
87
|
expect(getGroupHiddenInput(container).validity.valid).toBe(true);
|
|
88
88
|
});
|
|
89
89
|
|
|
90
|
-
it("
|
|
90
|
+
it("sets error message returned by validate function", () => {
|
|
91
91
|
const { container } = render(() => (
|
|
92
92
|
<RadioGroup value="a" validate={() => "커스텀 에러"}>
|
|
93
93
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|
|
@@ -96,7 +96,7 @@ describe("RadioGroup 컴포넌트", () => {
|
|
|
96
96
|
expect(getGroupHiddenInput(container).validationMessage).toBe("커스텀 에러");
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
it("validate
|
|
99
|
+
it("is valid when validate function returns undefined", () => {
|
|
100
100
|
const { container } = render(() => (
|
|
101
101
|
<RadioGroup value="a" validate={() => undefined}>
|
|
102
102
|
<RadioGroup.Item value="a">A</RadioGroup.Item>
|