@simplysm/solid 13.0.71 → 13.0.74
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 +209 -202
- package/dist/components/data/calendar/Calendar.d.ts.map +1 -1
- package/dist/components/data/calendar/Calendar.js +3 -11
- package/dist/components/data/calendar/Calendar.js.map +2 -2
- package/dist/components/data/sheet/DataSheet.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheet.js +13 -16
- package/dist/components/data/sheet/DataSheet.js.map +2 -2
- 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/data/sheet/DataSheetConfigDialog.d.ts.map +1 -1
- package/dist/components/data/sheet/DataSheetConfigDialog.js +27 -9
- package/dist/components/data/sheet/DataSheetConfigDialog.js.map +2 -2
- package/dist/components/disclosure/Dialog.d.ts +1 -1
- package/dist/components/disclosure/Dialog.d.ts.map +1 -1
- package/dist/components/disclosure/Dialog.js +5 -5
- package/dist/components/disclosure/Dialog.js.map +2 -2
- package/dist/components/disclosure/dialogZIndex.d.ts +1 -1
- package/dist/components/features/crud-detail/CrudDetail.js +23 -23
- package/dist/components/features/crud-detail/CrudDetail.js.map +2 -2
- package/dist/components/features/crud-sheet/CrudSheet.js +49 -49
- package/dist/components/features/crud-sheet/CrudSheet.js.map +2 -2
- package/dist/components/features/crud-sheet/types.d.ts +4 -4
- package/dist/components/features/crud-sheet/types.d.ts.map +1 -1
- package/dist/components/features/data-select-button/DataSelectButton.d.ts +25 -7
- package/dist/components/features/data-select-button/DataSelectButton.d.ts.map +1 -1
- package/dist/components/features/data-select-button/DataSelectButton.js +27 -12
- package/dist/components/features/data-select-button/DataSelectButton.js.map +2 -2
- package/dist/components/features/permission-table/PermissionTable.js +4 -4
- package/dist/components/features/permission-table/PermissionTable.js.map +2 -2
- package/dist/components/features/shared-data/SharedDataSelect.d.ts +22 -10
- package/dist/components/features/shared-data/SharedDataSelect.d.ts.map +1 -1
- package/dist/components/features/shared-data/SharedDataSelect.js +113 -29
- package/dist/components/features/shared-data/SharedDataSelect.js.map +2 -2
- package/dist/components/features/shared-data/SharedDataSelectButton.d.ts +3 -3
- package/dist/components/features/shared-data/SharedDataSelectButton.d.ts.map +1 -1
- package/dist/components/features/shared-data/SharedDataSelectButton.js.map +1 -1
- package/dist/components/features/shared-data/SharedDataSelectList.js +5 -4
- package/dist/components/features/shared-data/SharedDataSelectList.js.map +2 -2
- package/dist/components/feedback/notification/NotificationBanner.js +3 -3
- package/dist/components/feedback/notification/NotificationBanner.js.map +2 -2
- package/dist/components/feedback/notification/NotificationBell.d.ts.map +1 -1
- package/dist/components/feedback/notification/NotificationBell.js +12 -5
- package/dist/components/feedback/notification/NotificationBell.js.map +2 -2
- package/dist/components/feedback/notification/NotificationProvider.d.ts.map +1 -1
- package/dist/components/feedback/notification/NotificationProvider.js +3 -1
- package/dist/components/feedback/notification/NotificationProvider.js.map +2 -2
- package/dist/components/form-control/ThemeToggle.d.ts.map +1 -1
- package/dist/components/form-control/ThemeToggle.js +9 -6
- package/dist/components/form-control/ThemeToggle.js.map +2 -2
- package/dist/components/form-control/checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/form-control/checkbox/Checkbox.js +3 -1
- package/dist/components/form-control/checkbox/Checkbox.js.map +2 -2
- package/dist/components/form-control/checkbox/CheckboxGroup.js +1 -1
- package/dist/components/form-control/checkbox/CheckboxGroup.js.map +2 -2
- package/dist/components/form-control/checkbox/Radio.d.ts.map +1 -1
- package/dist/components/form-control/checkbox/Radio.js +3 -1
- package/dist/components/form-control/checkbox/Radio.js.map +2 -2
- package/dist/components/form-control/checkbox/RadioGroup.js +1 -1
- package/dist/components/form-control/checkbox/RadioGroup.js.map +2 -2
- package/dist/components/form-control/color-picker/ColorPicker.d.ts.map +1 -1
- package/dist/components/form-control/color-picker/ColorPicker.js +3 -1
- package/dist/components/form-control/color-picker/ColorPicker.js.map +2 -2
- package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
- package/dist/components/form-control/combobox/Combobox.js +9 -5
- package/dist/components/form-control/combobox/Combobox.js.map +2 -2
- package/dist/components/form-control/date-range-picker/DateRangePicker.js +9 -9
- package/dist/components/form-control/date-range-picker/DateRangePicker.js.map +2 -2
- package/dist/components/form-control/editor/EditorToolbar.js +3 -3
- package/dist/components/form-control/editor/EditorToolbar.js.map +2 -2
- package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/DatePicker.js +9 -3
- package/dist/components/form-control/field/DatePicker.js.map +2 -2
- package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/DateTimePicker.js +9 -3
- package/dist/components/form-control/field/DateTimePicker.js.map +2 -2
- package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
- package/dist/components/form-control/field/NumberInput.js +9 -3
- package/dist/components/form-control/field/NumberInput.js.map +2 -2
- package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
- package/dist/components/form-control/field/TextInput.js +10 -4
- package/dist/components/form-control/field/TextInput.js.map +2 -2
- package/dist/components/form-control/field/Textarea.d.ts.map +1 -1
- package/dist/components/form-control/field/Textarea.js +9 -3
- package/dist/components/form-control/field/Textarea.js.map +2 -2
- package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
- package/dist/components/form-control/field/TimePicker.js +9 -3
- package/dist/components/form-control/field/TimePicker.js.map +2 -2
- package/dist/components/form-control/numpad/Numpad.d.ts.map +1 -1
- package/dist/components/form-control/numpad/Numpad.js +5 -1
- package/dist/components/form-control/numpad/Numpad.js.map +2 -2
- package/dist/components/form-control/select/Select.js +7 -7
- package/dist/components/form-control/select/Select.js.map +2 -2
- package/dist/components/form-control/state-preset/StatePreset.d.ts.map +1 -1
- package/dist/components/form-control/state-preset/StatePreset.js +42 -20
- package/dist/components/form-control/state-preset/StatePreset.js.map +2 -2
- package/dist/components/layout/sidebar/SidebarContainer.js +3 -3
- package/dist/components/layout/sidebar/SidebarContainer.js.map +2 -2
- package/dist/components/layout/sidebar/SidebarMenu.d.ts.map +1 -1
- package/dist/components/layout/sidebar/SidebarMenu.js +5 -2
- package/dist/components/layout/sidebar/SidebarMenu.js.map +2 -2
- package/dist/components/layout/topbar/Topbar.js +3 -4
- package/dist/components/layout/topbar/Topbar.js.map +2 -2
- package/dist/components/layout/topbar/TopbarMenu.js +3 -3
- package/dist/components/layout/topbar/TopbarMenu.js.map +2 -2
- package/dist/hooks/createSelectionGroup.d.ts +2 -2
- package/dist/hooks/createSelectionGroup.d.ts.map +1 -1
- package/dist/hooks/createSelectionGroup.js +5 -2
- package/dist/hooks/createSelectionGroup.js.map +2 -2
- package/dist/providers/i18n/I18nContext.d.ts +0 -4
- package/dist/providers/i18n/I18nContext.d.ts.map +1 -1
- package/dist/providers/i18n/I18nContext.js +1 -5
- package/dist/providers/i18n/I18nContext.js.map +2 -2
- package/dist/providers/i18n/locales/en.d.ts +38 -0
- package/dist/providers/i18n/locales/en.d.ts.map +1 -1
- package/dist/providers/i18n/locales/en.js +39 -1
- package/dist/providers/i18n/locales/en.js.map +1 -1
- package/dist/providers/i18n/locales/ko.d.ts +38 -0
- package/dist/providers/i18n/locales/ko.d.ts.map +1 -1
- package/dist/providers/i18n/locales/ko.js +39 -1
- package/dist/providers/i18n/locales/ko.js.map +1 -1
- package/package.json +6 -6
- package/src/components/data/calendar/Calendar.tsx +3 -4
- package/src/components/data/sheet/DataSheet.styles.ts +1 -1
- package/src/components/data/sheet/DataSheet.tsx +14 -15
- package/src/components/data/sheet/DataSheetConfigDialog.tsx +12 -10
- package/src/components/data/sheet/types.ts +1 -1
- package/src/components/disclosure/Dialog.tsx +10 -10
- package/src/components/disclosure/dialogZIndex.ts +1 -1
- package/src/components/features/crud-detail/CrudDetail.tsx +25 -25
- package/src/components/features/crud-sheet/CrudSheet.tsx +53 -53
- package/src/components/features/crud-sheet/types.ts +4 -4
- package/src/components/features/data-select-button/DataSelectButton.tsx +51 -21
- package/src/components/features/permission-table/PermissionTable.tsx +3 -3
- package/src/components/features/shared-data/SharedDataSelect.tsx +172 -33
- package/src/components/features/shared-data/SharedDataSelectButton.tsx +3 -2
- package/src/components/features/shared-data/SharedDataSelectList.tsx +4 -4
- package/src/components/feedback/notification/NotificationBanner.tsx +3 -3
- package/src/components/feedback/notification/NotificationBell.tsx +6 -4
- package/src/components/feedback/notification/NotificationProvider.tsx +3 -1
- package/src/components/form-control/ThemeToggle.tsx +10 -6
- package/src/components/form-control/checkbox/Checkbox.tsx +4 -1
- package/src/components/form-control/checkbox/CheckboxGroup.tsx +1 -1
- package/src/components/form-control/checkbox/Radio.tsx +4 -1
- package/src/components/form-control/checkbox/RadioGroup.tsx +1 -1
- package/src/components/form-control/color-picker/ColorPicker.tsx +4 -1
- package/src/components/form-control/combobox/Combobox.tsx +6 -3
- package/src/components/form-control/date-range-picker/DateRangePicker.tsx +8 -8
- package/src/components/form-control/editor/EditorToolbar.tsx +23 -23
- package/src/components/form-control/field/DatePicker.tsx +6 -3
- package/src/components/form-control/field/DateTimePicker.tsx +6 -3
- package/src/components/form-control/field/NumberInput.tsx +6 -3
- package/src/components/form-control/field/TextInput.tsx +7 -4
- package/src/components/form-control/field/Textarea.tsx +6 -3
- package/src/components/form-control/field/TimePicker.tsx +6 -3
- package/src/components/form-control/numpad/Numpad.tsx +3 -1
- package/src/components/form-control/select/Select.tsx +7 -7
- package/src/components/form-control/state-preset/StatePreset.tsx +14 -12
- package/src/components/layout/sidebar/SidebarContainer.tsx +3 -3
- package/src/components/layout/sidebar/SidebarMenu.tsx +3 -1
- package/src/components/layout/topbar/Topbar.tsx +3 -3
- package/src/components/layout/topbar/TopbarMenu.tsx +3 -3
- package/src/hooks/createSelectionGroup.tsx +8 -4
- package/src/providers/i18n/I18nContext.tsx +0 -7
- package/src/providers/i18n/locales/en.ts +38 -0
- package/src/providers/i18n/locales/ko.ts +38 -0
- package/tailwind.config.ts +2 -2
- package/tests/components/data/kanban/Kanban.selection.spec.tsx +34 -24
- package/tests/components/disclosure/Dialog.spec.tsx +28 -28
- package/tests/components/disclosure/DialogProvider.spec.tsx +51 -25
- package/tests/components/features/address/AddressSearch.spec.tsx +12 -4
- package/tests/components/features/crud-detail/CrudDetail.spec.tsx +1 -0
- package/tests/components/features/crud-sheet/CrudSheet.spec.tsx +30 -6
- package/tests/components/features/data-select-button/DataSelectButton.spec.tsx +77 -56
- package/tests/components/features/permission-table/PermissionTable.spec.tsx +12 -8
- package/tests/components/features/shared-data/SharedDataSelect.spec.tsx +172 -0
- package/tests/components/features/shared-data/SharedDataSelectList.spec.tsx +14 -2
- package/tests/components/feedback/notification/LiveRegion.spec.tsx +20 -9
- package/tests/components/feedback/notification/NotificationBanner.spec.tsx +64 -46
- package/tests/components/feedback/notification/NotificationBell.spec.tsx +70 -51
- package/tests/components/feedback/notification/NotificationContext.spec.tsx +105 -78
- package/tests/components/form-control/checkbox/Checkbox.spec.tsx +25 -20
- package/tests/components/form-control/checkbox/CheckboxGroup.spec.tsx +53 -30
- package/tests/components/form-control/checkbox/Radio.spec.tsx +25 -20
- package/tests/components/form-control/checkbox/RadioGroup.spec.tsx +53 -30
- package/tests/components/form-control/color-picker/ColorPicker.spec.tsx +24 -15
- package/tests/components/form-control/combobox/Combobox.spec.tsx +92 -59
- package/tests/components/form-control/date-range-picker/DateRangePicker.spec.tsx +2 -2
- package/tests/components/form-control/field/DatePicker.spec.tsx +50 -44
- package/tests/components/form-control/field/DateTimePicker.spec.tsx +51 -45
- package/tests/components/form-control/field/NumberInput.spec.tsx +53 -47
- package/tests/components/form-control/field/TextInput.spec.tsx +50 -44
- package/tests/components/form-control/field/Textarea.spec.tsx +35 -29
- package/tests/components/form-control/field/TimePicker.spec.tsx +43 -37
- package/tests/components/form-control/numpad/Numpad.spec.tsx +175 -25
- package/tests/components/form-control/select/Select.spec.tsx +5 -0
- package/tests/components/form-control/select/SelectItem.spec.tsx +1 -0
- package/tests/components/layout/sidebar/Sidebar.spec.tsx +79 -35
- package/tests/components/layout/sidebar/SidebarContainer.spec.tsx +1 -0
- package/tests/components/layout/sidebar/SidebarMenu.spec.tsx +28 -17
- package/tests/components/layout/topbar/TopbarActions.spec.tsx +41 -23
- package/tests/components/layout/topbar/createTopbarActions.spec.tsx +1 -0
- package/tests/hooks/usePrint.spec.tsx +1 -1
- package/tests/hooks/useRouterLink.spec.tsx +2 -0
- package/tests/hooks/useSyncConfig.spec.tsx +1 -0
- package/tests/providers/ErrorLoggerProvider.spec.tsx +1 -0
- package/tests/providers/PwaUpdateProvider.spec.tsx +16 -6
- package/tests/providers/ServiceClientContext.spec.tsx +40 -25
- package/tests/providers/i18n/I18nContext.spec.tsx +3 -4
- package/tests/providers/shared-data/SharedDataProvider.spec.tsx +2 -0
- package/dist/hooks/usePrint.d.ts +0 -3
- package/dist/hooks/usePrint.d.ts.map +0 -1
- package/dist/hooks/usePrint.js +0 -5
- package/dist/hooks/usePrint.js.map +0 -6
- package/src/hooks/usePrint.ts +0 -2
|
@@ -1,54 +1,60 @@
|
|
|
1
1
|
import { render, fireEvent } from "@solidjs/testing-library";
|
|
2
|
-
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
3
3
|
import { createSignal } from "solid-js";
|
|
4
4
|
import { TextInput } from "../../../../src/components/form-control/field/TextInput";
|
|
5
|
+
import { I18nProvider } from "../../../../src/providers/i18n/I18nContext";
|
|
6
|
+
import { ConfigProvider } from "../../../../src/providers/ConfigContext";
|
|
5
7
|
|
|
6
8
|
describe("TextInput component", () => {
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
localStorage.setItem("test.i18n-locale", JSON.stringify("en"));
|
|
11
|
+
});
|
|
12
|
+
|
|
7
13
|
describe("basic rendering", () => {
|
|
8
14
|
it("renders input element", () => {
|
|
9
|
-
const { container } = render(() => <TextInput
|
|
15
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput /></I18nProvider></ConfigProvider>);
|
|
10
16
|
const input = container.querySelector("input");
|
|
11
17
|
expect(input).toBeTruthy();
|
|
12
18
|
});
|
|
13
19
|
|
|
14
20
|
it("defaults type to text", () => {
|
|
15
|
-
const { container } = render(() => <TextInput
|
|
21
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput /></I18nProvider></ConfigProvider>);
|
|
16
22
|
const input = container.querySelector("input") as HTMLInputElement;
|
|
17
23
|
expect(input.type).toBe("text");
|
|
18
24
|
});
|
|
19
25
|
|
|
20
26
|
it("renders password input when type=password", () => {
|
|
21
|
-
const { container } = render(() => <TextInput type="password"
|
|
27
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput type="password" /></I18nProvider></ConfigProvider>);
|
|
22
28
|
const input = container.querySelector("input") as HTMLInputElement;
|
|
23
29
|
expect(input.type).toBe("password");
|
|
24
30
|
});
|
|
25
31
|
|
|
26
32
|
it("renders email input when type=email", () => {
|
|
27
|
-
const { container } = render(() => <TextInput type="email"
|
|
33
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput type="email" /></I18nProvider></ConfigProvider>);
|
|
28
34
|
const input = container.querySelector("input") as HTMLInputElement;
|
|
29
35
|
expect(input.type).toBe("email");
|
|
30
36
|
});
|
|
31
37
|
|
|
32
38
|
it("applies placeholder to input", () => {
|
|
33
|
-
const { container } = render(() => <TextInput placeholder="Enter text"
|
|
39
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput placeholder="Enter text" /></I18nProvider></ConfigProvider>);
|
|
34
40
|
const input = container.querySelector("input") as HTMLInputElement;
|
|
35
41
|
expect(input.placeholder).toBe("Enter text");
|
|
36
42
|
});
|
|
37
43
|
|
|
38
44
|
it("applies title to input", () => {
|
|
39
|
-
const { container } = render(() => <TextInput title="Input title"
|
|
45
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput title="Input title" /></I18nProvider></ConfigProvider>);
|
|
40
46
|
const input = container.querySelector("input") as HTMLInputElement;
|
|
41
47
|
expect(input.title).toBe("Input title");
|
|
42
48
|
});
|
|
43
49
|
|
|
44
50
|
it("defaults autocomplete to one-time-code", () => {
|
|
45
|
-
const { container } = render(() => <TextInput
|
|
51
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput /></I18nProvider></ConfigProvider>);
|
|
46
52
|
const input = container.querySelector("input") as HTMLInputElement;
|
|
47
53
|
expect(input.autocomplete).toBe("one-time-code");
|
|
48
54
|
});
|
|
49
55
|
|
|
50
56
|
it("applies explicitly specified autocomplete value", () => {
|
|
51
|
-
const { container } = render(() => <TextInput autocomplete="email"
|
|
57
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput autocomplete="email" /></I18nProvider></ConfigProvider>);
|
|
52
58
|
const input = container.querySelector("input") as HTMLInputElement;
|
|
53
59
|
expect(input.autocomplete).toBe("email");
|
|
54
60
|
});
|
|
@@ -56,14 +62,14 @@ describe("TextInput component", () => {
|
|
|
56
62
|
|
|
57
63
|
describe("controlled pattern", () => {
|
|
58
64
|
it("displays value prop in input", () => {
|
|
59
|
-
const { container } = render(() => <TextInput value="Hello"
|
|
65
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput value="Hello" /></I18nProvider></ConfigProvider>);
|
|
60
66
|
const input = container.querySelector("input") as HTMLInputElement;
|
|
61
67
|
expect(input.value).toBe("Hello");
|
|
62
68
|
});
|
|
63
69
|
|
|
64
70
|
it("calls onValueChange on input", () => {
|
|
65
71
|
const handleChange = vi.fn();
|
|
66
|
-
const { container } = render(() => <TextInput value="" onValueChange={handleChange}
|
|
72
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput value="" onValueChange={handleChange} /></I18nProvider></ConfigProvider>);
|
|
67
73
|
const input = container.querySelector("input") as HTMLInputElement;
|
|
68
74
|
|
|
69
75
|
fireEvent.input(input, { target: { value: "Test" } });
|
|
@@ -73,7 +79,7 @@ describe("TextInput component", () => {
|
|
|
73
79
|
|
|
74
80
|
it("updates input value when external state changes", () => {
|
|
75
81
|
const [value, setValue] = createSignal("Initial");
|
|
76
|
-
const { container } = render(() => <TextInput value={value()} onValueChange={setValue}
|
|
82
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput value={value()} onValueChange={setValue} /></I18nProvider></ConfigProvider>);
|
|
77
83
|
const input = container.querySelector("input") as HTMLInputElement;
|
|
78
84
|
|
|
79
85
|
expect(input.value).toBe("Initial");
|
|
@@ -85,7 +91,7 @@ describe("TextInput component", () => {
|
|
|
85
91
|
|
|
86
92
|
describe("uncontrolled pattern", () => {
|
|
87
93
|
it("manages value internally without onValueChange", () => {
|
|
88
|
-
const { container } = render(() => <TextInput value="Initial"
|
|
94
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput value="Initial" /></I18nProvider></ConfigProvider>);
|
|
89
95
|
const input = container.querySelector("input") as HTMLInputElement;
|
|
90
96
|
|
|
91
97
|
expect(input.value).toBe("Initial");
|
|
@@ -97,7 +103,7 @@ describe("TextInput component", () => {
|
|
|
97
103
|
|
|
98
104
|
describe("disabled state", () => {
|
|
99
105
|
it("renders as div when disabled=true", () => {
|
|
100
|
-
const { container } = render(() => <TextInput disabled value="Disabled text"
|
|
106
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput disabled value="Disabled text" /></I18nProvider></ConfigProvider>);
|
|
101
107
|
const input = container.querySelector("input:not([aria-hidden])");
|
|
102
108
|
const div = container.querySelector("div.sd-text-field");
|
|
103
109
|
|
|
@@ -106,12 +112,12 @@ describe("TextInput component", () => {
|
|
|
106
112
|
});
|
|
107
113
|
|
|
108
114
|
it("displays value when disabled", () => {
|
|
109
|
-
const { getByText } = render(() => <TextInput disabled value="Disabled text"
|
|
115
|
+
const { getByText } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput disabled value="Disabled text" /></I18nProvider></ConfigProvider>);
|
|
110
116
|
expect(getByText("Disabled text")).toBeTruthy();
|
|
111
117
|
});
|
|
112
118
|
|
|
113
119
|
it("applies disabled style", () => {
|
|
114
|
-
const { container } = render(() => <TextInput disabled value="Text"
|
|
120
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput disabled value="Text" /></I18nProvider></ConfigProvider>);
|
|
115
121
|
const div = container.querySelector("div.sd-text-field") as HTMLElement;
|
|
116
122
|
expect(div.classList.contains("bg-base-100")).toBe(true);
|
|
117
123
|
});
|
|
@@ -119,7 +125,7 @@ describe("TextInput component", () => {
|
|
|
119
125
|
|
|
120
126
|
describe("readonly state", () => {
|
|
121
127
|
it("renders as div when readonly=true", () => {
|
|
122
|
-
const { container } = render(() => <TextInput readonly value="Readonly text"
|
|
128
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput readonly value="Readonly text" /></I18nProvider></ConfigProvider>);
|
|
123
129
|
const input = container.querySelector("input:not([aria-hidden])");
|
|
124
130
|
const div = container.querySelector("div.sd-text-field");
|
|
125
131
|
|
|
@@ -128,14 +134,14 @@ describe("TextInput component", () => {
|
|
|
128
134
|
});
|
|
129
135
|
|
|
130
136
|
it("displays value when readonly", () => {
|
|
131
|
-
const { getByText } = render(() => <TextInput readonly value="Readonly text"
|
|
137
|
+
const { getByText } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput readonly value="Readonly text" /></I18nProvider></ConfigProvider>);
|
|
132
138
|
expect(getByText("Readonly text")).toBeTruthy();
|
|
133
139
|
});
|
|
134
140
|
});
|
|
135
141
|
|
|
136
142
|
describe("format option", () => {
|
|
137
143
|
it("displays value with format applied", () => {
|
|
138
|
-
const { container } = render(() => <TextInput format="XXX-XXXX-XXXX" value="01012345678"
|
|
144
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput format="XXX-XXXX-XXXX" value="01012345678" /></I18nProvider></ConfigProvider>);
|
|
139
145
|
const input = container.querySelector("input") as HTMLInputElement;
|
|
140
146
|
expect(input.value).toBe("010-1234-5678");
|
|
141
147
|
});
|
|
@@ -143,7 +149,7 @@ describe("TextInput component", () => {
|
|
|
143
149
|
it("passes raw value to onValueChange when format is applied", () => {
|
|
144
150
|
const handleChange = vi.fn();
|
|
145
151
|
const { container } = render(() => (
|
|
146
|
-
<TextInput format="XXX-XXXX-XXXX" value="" onValueChange={handleChange}
|
|
152
|
+
<ConfigProvider clientName="test"><I18nProvider><TextInput format="XXX-XXXX-XXXX" value="" onValueChange={handleChange} /></I18nProvider></ConfigProvider>
|
|
147
153
|
));
|
|
148
154
|
const input = container.querySelector("input") as HTMLInputElement;
|
|
149
155
|
|
|
@@ -156,13 +162,13 @@ describe("TextInput component", () => {
|
|
|
156
162
|
|
|
157
163
|
describe("size option", () => {
|
|
158
164
|
it("applies small padding when size=sm", () => {
|
|
159
|
-
const { container } = render(() => <TextInput size="sm"
|
|
165
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput size="sm" /></I18nProvider></ConfigProvider>);
|
|
160
166
|
const wrapper = container.firstChild as HTMLElement;
|
|
161
167
|
expect(wrapper.classList.contains("py-0.5")).toBe(true);
|
|
162
168
|
});
|
|
163
169
|
|
|
164
170
|
it("applies large padding when size=lg", () => {
|
|
165
|
-
const { container } = render(() => <TextInput size="lg"
|
|
171
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput size="lg" /></I18nProvider></ConfigProvider>);
|
|
166
172
|
const wrapper = container.firstChild as HTMLElement;
|
|
167
173
|
expect(wrapper.classList.contains("py-2")).toBe(true);
|
|
168
174
|
});
|
|
@@ -170,7 +176,7 @@ describe("TextInput component", () => {
|
|
|
170
176
|
|
|
171
177
|
describe("inset style", () => {
|
|
172
178
|
it("removes border and applies inset background when inset=true", () => {
|
|
173
|
-
const { container } = render(() => <TextInput inset
|
|
179
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput inset /></I18nProvider></ConfigProvider>);
|
|
174
180
|
const outer = container.firstChild as HTMLElement;
|
|
175
181
|
const contentDiv = outer.querySelector("[data-text-field-content]") as HTMLElement;
|
|
176
182
|
expect(contentDiv.classList.contains("border-none")).toBe(true);
|
|
@@ -178,7 +184,7 @@ describe("TextInput component", () => {
|
|
|
178
184
|
});
|
|
179
185
|
|
|
180
186
|
it("shows content div and no input when inset + readonly", () => {
|
|
181
|
-
const { container } = render(() => <TextInput inset readonly value="Hello"
|
|
187
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput inset readonly value="Hello" /></I18nProvider></ConfigProvider>);
|
|
182
188
|
const outer = container.firstChild as HTMLElement;
|
|
183
189
|
expect(outer.classList.contains("relative")).toBe(true);
|
|
184
190
|
|
|
@@ -191,7 +197,7 @@ describe("TextInput component", () => {
|
|
|
191
197
|
});
|
|
192
198
|
|
|
193
199
|
it("shows hidden content div and input when inset + editable", () => {
|
|
194
|
-
const { container } = render(() => <TextInput inset value="Hello"
|
|
200
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput inset value="Hello" /></I18nProvider></ConfigProvider>);
|
|
195
201
|
const outer = container.firstChild as HTMLElement;
|
|
196
202
|
|
|
197
203
|
const contentDiv = outer.querySelector("[data-text-field-content]") as HTMLElement;
|
|
@@ -204,7 +210,7 @@ describe("TextInput component", () => {
|
|
|
204
210
|
});
|
|
205
211
|
|
|
206
212
|
it("shows NBSP in content div when inset + empty value", () => {
|
|
207
|
-
const { container } = render(() => <TextInput inset readonly
|
|
213
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput inset readonly /></I18nProvider></ConfigProvider>);
|
|
208
214
|
const outer = container.firstChild as HTMLElement;
|
|
209
215
|
const contentDiv = outer.querySelector("[data-text-field-content]") as HTMLElement;
|
|
210
216
|
expect(contentDiv.textContent).toBe("\u00A0");
|
|
@@ -212,7 +218,7 @@ describe("TextInput component", () => {
|
|
|
212
218
|
|
|
213
219
|
it("content div is always in DOM when toggling inset + readonly/editable", () => {
|
|
214
220
|
const [readonly, setReadonly] = createSignal(true);
|
|
215
|
-
const { container } = render(() => <TextInput inset readonly={readonly()} value="Test"
|
|
221
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput inset readonly={readonly()} value="Test" /></I18nProvider></ConfigProvider>);
|
|
216
222
|
const outer = container.firstChild as HTMLElement;
|
|
217
223
|
|
|
218
224
|
let contentDiv = outer.querySelector("[data-text-field-content]");
|
|
@@ -229,7 +235,7 @@ describe("TextInput component", () => {
|
|
|
229
235
|
describe("class merging", () => {
|
|
230
236
|
it("merges custom class with existing styles", () => {
|
|
231
237
|
// eslint-disable-next-line tailwindcss/no-custom-classname
|
|
232
|
-
const { container } = render(() => <TextInput class="my-custom-class"
|
|
238
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput class="my-custom-class" /></I18nProvider></ConfigProvider>);
|
|
233
239
|
const wrapper = container.firstChild as HTMLElement;
|
|
234
240
|
expect(wrapper.classList.contains("my-custom-class")).toBe(true);
|
|
235
241
|
});
|
|
@@ -237,20 +243,20 @@ describe("TextInput component", () => {
|
|
|
237
243
|
|
|
238
244
|
describe("default style", () => {
|
|
239
245
|
it("applies default border style", () => {
|
|
240
|
-
const { container } = render(() => <TextInput
|
|
246
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput /></I18nProvider></ConfigProvider>);
|
|
241
247
|
const wrapper = container.firstChild as HTMLElement;
|
|
242
248
|
expect(wrapper.classList.contains("border")).toBe(true);
|
|
243
249
|
expect(wrapper.classList.contains("border-base-200")).toBe(true);
|
|
244
250
|
});
|
|
245
251
|
|
|
246
252
|
it("changes border color on focus", () => {
|
|
247
|
-
const { container } = render(() => <TextInput
|
|
253
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput /></I18nProvider></ConfigProvider>);
|
|
248
254
|
const wrapper = container.firstChild as HTMLElement;
|
|
249
255
|
expect(wrapper.classList.contains("focus-within:border-primary-500")).toBe(true);
|
|
250
256
|
});
|
|
251
257
|
|
|
252
258
|
it("applies dark mode style", () => {
|
|
253
|
-
const { container } = render(() => <TextInput
|
|
259
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput /></I18nProvider></ConfigProvider>);
|
|
254
260
|
const wrapper = container.firstChild as HTMLElement;
|
|
255
261
|
expect(wrapper.classList.contains("dark:border-base-700")).toBe(true);
|
|
256
262
|
expect(wrapper.classList.contains("dark:bg-primary-950/30")).toBe(true);
|
|
@@ -259,41 +265,41 @@ describe("TextInput component", () => {
|
|
|
259
265
|
|
|
260
266
|
describe("validation", () => {
|
|
261
267
|
it("sets error message in hidden input when required and empty", () => {
|
|
262
|
-
const { container } = render(() => <TextInput required value=""
|
|
268
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput required value="" /></I18nProvider></ConfigProvider>);
|
|
263
269
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
264
270
|
expect(hiddenInput.validationMessage).toBe("This is a required field");
|
|
265
271
|
});
|
|
266
272
|
|
|
267
273
|
it("is valid when required and value exists", () => {
|
|
268
|
-
const { container } = render(() => <TextInput required value="hello"
|
|
274
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput required value="hello" /></I18nProvider></ConfigProvider>);
|
|
269
275
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
270
276
|
expect(hiddenInput.validity.valid).toBe(true);
|
|
271
277
|
});
|
|
272
278
|
|
|
273
279
|
it("sets error message when minLength is violated", () => {
|
|
274
|
-
const { container } = render(() => <TextInput minLength={3} value="ab"
|
|
280
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput minLength={3} value="ab" /></I18nProvider></ConfigProvider>);
|
|
275
281
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
276
282
|
expect(hiddenInput.validationMessage).toBe("Enter at least 3 characters");
|
|
277
283
|
});
|
|
278
284
|
|
|
279
285
|
it("sets error message when maxLength is violated", () => {
|
|
280
|
-
const { container } = render(() => <TextInput maxLength={5} value="abcdef"
|
|
286
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput maxLength={5} value="abcdef" /></I18nProvider></ConfigProvider>);
|
|
281
287
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
282
288
|
expect(hiddenInput.validationMessage).toBe("Enter up to 5 characters");
|
|
283
289
|
});
|
|
284
290
|
|
|
285
291
|
it("sets error message when pattern is violated", () => {
|
|
286
|
-
const { container } = render(() => <TextInput pattern="^[0-9]+$" value="abc"
|
|
292
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><TextInput pattern="^[0-9]+$" value="abc" /></I18nProvider></ConfigProvider>);
|
|
287
293
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
288
294
|
expect(hiddenInput.validationMessage).toBe("The input format is invalid");
|
|
289
295
|
});
|
|
290
296
|
|
|
291
297
|
it("sets error message returned by validate function", () => {
|
|
292
298
|
const { container } = render(() => (
|
|
293
|
-
<TextInput
|
|
299
|
+
<ConfigProvider clientName="test"><I18nProvider><TextInput
|
|
294
300
|
validate={(v) => (v.includes("@") ? undefined : "이메일 형식이 아닙니다")}
|
|
295
301
|
value="hello"
|
|
296
|
-
|
|
302
|
+
/></I18nProvider></ConfigProvider>
|
|
297
303
|
));
|
|
298
304
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
299
305
|
expect(hiddenInput.validationMessage).toBe("이메일 형식이 아닙니다");
|
|
@@ -301,11 +307,11 @@ describe("TextInput component", () => {
|
|
|
301
307
|
|
|
302
308
|
it("runs validate function after base validators pass", () => {
|
|
303
309
|
const { container } = render(() => (
|
|
304
|
-
<TextInput
|
|
310
|
+
<ConfigProvider clientName="test"><I18nProvider><TextInput
|
|
305
311
|
required
|
|
306
312
|
validate={(v) => (v.includes("@") ? undefined : "이메일 형식이 아닙니다")}
|
|
307
313
|
value=""
|
|
308
|
-
|
|
314
|
+
/></I18nProvider></ConfigProvider>
|
|
309
315
|
));
|
|
310
316
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
311
317
|
expect(hiddenInput.validationMessage).toBe("This is a required field");
|
|
@@ -315,11 +321,11 @@ describe("TextInput component", () => {
|
|
|
315
321
|
describe("Prefix slot", () => {
|
|
316
322
|
it("renders TextInput.Prefix slot", () => {
|
|
317
323
|
render(() => (
|
|
318
|
-
<TextInput>
|
|
324
|
+
<ConfigProvider clientName="test"><I18nProvider><TextInput>
|
|
319
325
|
<TextInput.Prefix>
|
|
320
326
|
<span data-testid="prefix">P</span>
|
|
321
327
|
</TextInput.Prefix>
|
|
322
|
-
</TextInput>
|
|
328
|
+
</TextInput></I18nProvider></ConfigProvider>
|
|
323
329
|
));
|
|
324
330
|
|
|
325
331
|
expect(document.querySelector('[data-testid="prefix"]')).not.toBeNull();
|
|
@@ -327,11 +333,11 @@ describe("TextInput component", () => {
|
|
|
327
333
|
|
|
328
334
|
it("applies gap class when Prefix slot is used", () => {
|
|
329
335
|
const { container } = render(() => (
|
|
330
|
-
<TextInput>
|
|
336
|
+
<ConfigProvider clientName="test"><I18nProvider><TextInput>
|
|
331
337
|
<TextInput.Prefix>
|
|
332
338
|
<span>P</span>
|
|
333
339
|
</TextInput.Prefix>
|
|
334
|
-
</TextInput>
|
|
340
|
+
</TextInput></I18nProvider></ConfigProvider>
|
|
335
341
|
));
|
|
336
342
|
|
|
337
343
|
const wrapper = container.querySelector("[data-text-field]") as HTMLElement;
|
|
@@ -1,24 +1,30 @@
|
|
|
1
1
|
import { render, fireEvent } from "@solidjs/testing-library";
|
|
2
|
-
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
3
3
|
import { createSignal } from "solid-js";
|
|
4
4
|
import { Textarea } from "../../../../src/components/form-control/field/Textarea";
|
|
5
|
+
import { I18nProvider } from "../../../../src/providers/i18n/I18nContext";
|
|
6
|
+
import { ConfigProvider } from "../../../../src/providers/ConfigContext";
|
|
5
7
|
|
|
6
8
|
describe("Textarea component", () => {
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
localStorage.setItem("test.i18n-locale", JSON.stringify("en"));
|
|
11
|
+
});
|
|
12
|
+
|
|
7
13
|
describe("basic rendering", () => {
|
|
8
14
|
it("renders textarea element", () => {
|
|
9
|
-
const { container } = render(() => <Textarea
|
|
15
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea /></I18nProvider></ConfigProvider>);
|
|
10
16
|
const textarea = container.querySelector("textarea");
|
|
11
17
|
expect(textarea).toBeTruthy();
|
|
12
18
|
});
|
|
13
19
|
|
|
14
20
|
it("applies placeholder to textarea", () => {
|
|
15
|
-
const { container } = render(() => <Textarea placeholder="내용을 입력하세요"
|
|
21
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea placeholder="내용을 입력하세요" /></I18nProvider></ConfigProvider>);
|
|
16
22
|
const textarea = container.querySelector("textarea") as HTMLTextAreaElement;
|
|
17
23
|
expect(textarea.placeholder).toBe("내용을 입력하세요");
|
|
18
24
|
});
|
|
19
25
|
|
|
20
26
|
it("applies title to textarea", () => {
|
|
21
|
-
const { container } = render(() => <Textarea title="Textarea title"
|
|
27
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea title="Textarea title" /></I18nProvider></ConfigProvider>);
|
|
22
28
|
const textarea = container.querySelector("textarea") as HTMLTextAreaElement;
|
|
23
29
|
expect(textarea.title).toBe("Textarea title");
|
|
24
30
|
});
|
|
@@ -26,14 +32,14 @@ describe("Textarea component", () => {
|
|
|
26
32
|
|
|
27
33
|
describe("controlled pattern", () => {
|
|
28
34
|
it("displays value prop in textarea", () => {
|
|
29
|
-
const { container } = render(() => <Textarea value="Hello"
|
|
35
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea value="Hello" /></I18nProvider></ConfigProvider>);
|
|
30
36
|
const textarea = container.querySelector("textarea") as HTMLTextAreaElement;
|
|
31
37
|
expect(textarea.value).toBe("Hello");
|
|
32
38
|
});
|
|
33
39
|
|
|
34
40
|
it("calls onValueChange on input", () => {
|
|
35
41
|
const handleChange = vi.fn();
|
|
36
|
-
const { container } = render(() => <Textarea value="" onValueChange={handleChange}
|
|
42
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea value="" onValueChange={handleChange} /></I18nProvider></ConfigProvider>);
|
|
37
43
|
const textarea = container.querySelector("textarea") as HTMLTextAreaElement;
|
|
38
44
|
|
|
39
45
|
fireEvent.input(textarea, { target: { value: "Test" } });
|
|
@@ -43,7 +49,7 @@ describe("Textarea component", () => {
|
|
|
43
49
|
|
|
44
50
|
it("updates textarea value when external state changes", () => {
|
|
45
51
|
const [value, setValue] = createSignal("Initial");
|
|
46
|
-
const { container } = render(() => <Textarea value={value()} onValueChange={setValue}
|
|
52
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea value={value()} onValueChange={setValue} /></I18nProvider></ConfigProvider>);
|
|
47
53
|
const textarea = container.querySelector("textarea") as HTMLTextAreaElement;
|
|
48
54
|
|
|
49
55
|
expect(textarea.value).toBe("Initial");
|
|
@@ -55,7 +61,7 @@ describe("Textarea component", () => {
|
|
|
55
61
|
|
|
56
62
|
describe("uncontrolled pattern", () => {
|
|
57
63
|
it("manages value internally without onValueChange", () => {
|
|
58
|
-
const { container } = render(() => <Textarea value="Initial"
|
|
64
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea value="Initial" /></I18nProvider></ConfigProvider>);
|
|
59
65
|
const textarea = container.querySelector("textarea") as HTMLTextAreaElement;
|
|
60
66
|
|
|
61
67
|
expect(textarea.value).toBe("Initial");
|
|
@@ -67,18 +73,18 @@ describe("Textarea component", () => {
|
|
|
67
73
|
|
|
68
74
|
describe("disabled state", () => {
|
|
69
75
|
it("does not render textarea when disabled=true", () => {
|
|
70
|
-
const { container } = render(() => <Textarea disabled value="Disabled text"
|
|
76
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea disabled value="Disabled text" /></I18nProvider></ConfigProvider>);
|
|
71
77
|
const textarea = container.querySelector("textarea");
|
|
72
78
|
expect(textarea).toBeFalsy();
|
|
73
79
|
});
|
|
74
80
|
|
|
75
81
|
it("displays value when disabled", () => {
|
|
76
|
-
const { getByText } = render(() => <Textarea disabled value="Disabled text"
|
|
82
|
+
const { getByText } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea disabled value="Disabled text" /></I18nProvider></ConfigProvider>);
|
|
77
83
|
expect(getByText("Disabled text")).toBeTruthy();
|
|
78
84
|
});
|
|
79
85
|
|
|
80
86
|
it("applies disabled style", () => {
|
|
81
|
-
const { container } = render(() => <Textarea disabled value="Text"
|
|
87
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea disabled value="Text" /></I18nProvider></ConfigProvider>);
|
|
82
88
|
const wrapper = container.firstChild as HTMLElement;
|
|
83
89
|
expect(wrapper.classList.contains("bg-base-100")).toBe(true);
|
|
84
90
|
});
|
|
@@ -86,26 +92,26 @@ describe("Textarea component", () => {
|
|
|
86
92
|
|
|
87
93
|
describe("readonly state", () => {
|
|
88
94
|
it("does not render textarea when readonly=true", () => {
|
|
89
|
-
const { container } = render(() => <Textarea readonly value="Readonly text"
|
|
95
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea readonly value="Readonly text" /></I18nProvider></ConfigProvider>);
|
|
90
96
|
const textarea = container.querySelector("textarea");
|
|
91
97
|
expect(textarea).toBeFalsy();
|
|
92
98
|
});
|
|
93
99
|
|
|
94
100
|
it("displays value when readonly", () => {
|
|
95
|
-
const { getByText } = render(() => <Textarea readonly value="Readonly text"
|
|
101
|
+
const { getByText } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea readonly value="Readonly text" /></I18nProvider></ConfigProvider>);
|
|
96
102
|
expect(getByText("Readonly text")).toBeTruthy();
|
|
97
103
|
});
|
|
98
104
|
});
|
|
99
105
|
|
|
100
106
|
describe("size option", () => {
|
|
101
107
|
it("applies small padding when size=sm", () => {
|
|
102
|
-
const { container } = render(() => <Textarea size="sm"
|
|
108
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea size="sm" /></I18nProvider></ConfigProvider>);
|
|
103
109
|
const wrapper = container.firstChild as HTMLElement;
|
|
104
110
|
expect(wrapper.classList.contains("py-0.5")).toBe(true);
|
|
105
111
|
});
|
|
106
112
|
|
|
107
113
|
it("applies large padding when size=lg", () => {
|
|
108
|
-
const { container } = render(() => <Textarea size="lg"
|
|
114
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea size="lg" /></I18nProvider></ConfigProvider>);
|
|
109
115
|
const wrapper = container.firstChild as HTMLElement;
|
|
110
116
|
expect(wrapper.classList.contains("py-2")).toBe(true);
|
|
111
117
|
});
|
|
@@ -113,7 +119,7 @@ describe("Textarea component", () => {
|
|
|
113
119
|
|
|
114
120
|
describe("inset style", () => {
|
|
115
121
|
it("removes border and applies inset background when inset=true", () => {
|
|
116
|
-
const { container } = render(() => <Textarea inset
|
|
122
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea inset /></I18nProvider></ConfigProvider>);
|
|
117
123
|
const wrapper = container.firstChild as HTMLElement;
|
|
118
124
|
expect(wrapper.classList.contains("relative")).toBe(true);
|
|
119
125
|
const content = wrapper.querySelector("[data-textarea-field-content]") as HTMLElement;
|
|
@@ -122,7 +128,7 @@ describe("Textarea component", () => {
|
|
|
122
128
|
});
|
|
123
129
|
|
|
124
130
|
it("shows content div and no textarea when inset + readonly", () => {
|
|
125
|
-
const { container } = render(() => <Textarea inset readonly value="Hello"
|
|
131
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea inset readonly value="Hello" /></I18nProvider></ConfigProvider>);
|
|
126
132
|
const outer = container.firstChild as HTMLElement;
|
|
127
133
|
expect(outer.classList.contains("relative")).toBe(true);
|
|
128
134
|
|
|
@@ -134,7 +140,7 @@ describe("Textarea component", () => {
|
|
|
134
140
|
});
|
|
135
141
|
|
|
136
142
|
it("shows hidden content div and textarea when inset + editable", () => {
|
|
137
|
-
const { container } = render(() => <Textarea inset value="Hello"
|
|
143
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea inset value="Hello" /></I18nProvider></ConfigProvider>);
|
|
138
144
|
const outer = container.firstChild as HTMLElement;
|
|
139
145
|
|
|
140
146
|
const contentDiv = outer.querySelector("[data-textarea-field-content]") as HTMLElement;
|
|
@@ -147,7 +153,7 @@ describe("Textarea component", () => {
|
|
|
147
153
|
});
|
|
148
154
|
|
|
149
155
|
it("shows NBSP in content div when inset + empty value", () => {
|
|
150
|
-
const { container } = render(() => <Textarea inset readonly
|
|
156
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea inset readonly /></I18nProvider></ConfigProvider>);
|
|
151
157
|
const outer = container.firstChild as HTMLElement;
|
|
152
158
|
const contentDiv = outer.querySelector("[data-textarea-field-content]") as HTMLElement;
|
|
153
159
|
expect(contentDiv.textContent).toContain("\u00A0");
|
|
@@ -157,7 +163,7 @@ describe("Textarea component", () => {
|
|
|
157
163
|
describe("class merging", () => {
|
|
158
164
|
it("merges custom class with existing styles", () => {
|
|
159
165
|
// eslint-disable-next-line tailwindcss/no-custom-classname
|
|
160
|
-
const { container } = render(() => <Textarea class="my-custom-class"
|
|
166
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea class="my-custom-class" /></I18nProvider></ConfigProvider>);
|
|
161
167
|
const wrapper = container.firstChild as HTMLElement;
|
|
162
168
|
expect(wrapper.classList.contains("my-custom-class")).toBe(true);
|
|
163
169
|
});
|
|
@@ -165,7 +171,7 @@ describe("Textarea component", () => {
|
|
|
165
171
|
|
|
166
172
|
describe("auto height adjustment", () => {
|
|
167
173
|
it("renders hidden div for height measurement", () => {
|
|
168
|
-
const { container } = render(() => <Textarea value="Test"
|
|
174
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea value="Test" /></I18nProvider></ConfigProvider>);
|
|
169
175
|
const wrapper = container.firstChild as HTMLElement;
|
|
170
176
|
const hiddenDiv = wrapper.querySelector("[data-hidden-content]") as HTMLElement;
|
|
171
177
|
expect(hiddenDiv).toBeTruthy();
|
|
@@ -175,35 +181,35 @@ describe("Textarea component", () => {
|
|
|
175
181
|
|
|
176
182
|
describe("validation", () => {
|
|
177
183
|
it("sets error message in hidden input when required and empty", () => {
|
|
178
|
-
const { container } = render(() => <Textarea required value=""
|
|
184
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea required value="" /></I18nProvider></ConfigProvider>);
|
|
179
185
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
180
186
|
expect(hiddenInput.validationMessage).toBe("This is a required field");
|
|
181
187
|
});
|
|
182
188
|
|
|
183
189
|
it("is valid when required and value exists", () => {
|
|
184
|
-
const { container } = render(() => <Textarea required value="hello"
|
|
190
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea required value="hello" /></I18nProvider></ConfigProvider>);
|
|
185
191
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
186
192
|
expect(hiddenInput.validity.valid).toBe(true);
|
|
187
193
|
});
|
|
188
194
|
|
|
189
195
|
it("sets error message when minLength is violated", () => {
|
|
190
|
-
const { container } = render(() => <Textarea minLength={3} value="ab"
|
|
196
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea minLength={3} value="ab" /></I18nProvider></ConfigProvider>);
|
|
191
197
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
192
198
|
expect(hiddenInput.validationMessage).toBe("Enter at least 3 characters");
|
|
193
199
|
});
|
|
194
200
|
|
|
195
201
|
it("sets error message when maxLength is violated", () => {
|
|
196
|
-
const { container } = render(() => <Textarea maxLength={5} value="abcdef"
|
|
202
|
+
const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><Textarea maxLength={5} value="abcdef" /></I18nProvider></ConfigProvider>);
|
|
197
203
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
198
204
|
expect(hiddenInput.validationMessage).toBe("Enter up to 5 characters");
|
|
199
205
|
});
|
|
200
206
|
|
|
201
207
|
it("sets error message returned by validate function", () => {
|
|
202
208
|
const { container } = render(() => (
|
|
203
|
-
<Textarea
|
|
209
|
+
<ConfigProvider clientName="test"><I18nProvider><Textarea
|
|
204
210
|
validate={(v) => (v.includes("@") ? undefined : "이메일 형식이 아닙니다")}
|
|
205
211
|
value="hello"
|
|
206
|
-
|
|
212
|
+
/></I18nProvider></ConfigProvider>
|
|
207
213
|
));
|
|
208
214
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
209
215
|
expect(hiddenInput.validationMessage).toBe("이메일 형식이 아닙니다");
|
|
@@ -211,11 +217,11 @@ describe("Textarea component", () => {
|
|
|
211
217
|
|
|
212
218
|
it("runs validate function after base validators pass", () => {
|
|
213
219
|
const { container } = render(() => (
|
|
214
|
-
<Textarea
|
|
220
|
+
<ConfigProvider clientName="test"><I18nProvider><Textarea
|
|
215
221
|
required
|
|
216
222
|
validate={(v) => (v.includes("@") ? undefined : "이메일 형식이 아닙니다")}
|
|
217
223
|
value=""
|
|
218
|
-
|
|
224
|
+
/></I18nProvider></ConfigProvider>
|
|
219
225
|
));
|
|
220
226
|
const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
|
|
221
227
|
expect(hiddenInput.validationMessage).toBe("This is a required field");
|