@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.
Files changed (215) hide show
  1. package/README.md +209 -202
  2. package/dist/components/data/calendar/Calendar.d.ts.map +1 -1
  3. package/dist/components/data/calendar/Calendar.js +3 -11
  4. package/dist/components/data/calendar/Calendar.js.map +2 -2
  5. package/dist/components/data/sheet/DataSheet.d.ts.map +1 -1
  6. package/dist/components/data/sheet/DataSheet.js +13 -16
  7. package/dist/components/data/sheet/DataSheet.js.map +2 -2
  8. package/dist/components/data/sheet/DataSheet.styles.d.ts.map +1 -1
  9. package/dist/components/data/sheet/DataSheet.styles.js +1 -1
  10. package/dist/components/data/sheet/DataSheet.styles.js.map +1 -1
  11. package/dist/components/data/sheet/DataSheetConfigDialog.d.ts.map +1 -1
  12. package/dist/components/data/sheet/DataSheetConfigDialog.js +27 -9
  13. package/dist/components/data/sheet/DataSheetConfigDialog.js.map +2 -2
  14. package/dist/components/disclosure/Dialog.d.ts +1 -1
  15. package/dist/components/disclosure/Dialog.d.ts.map +1 -1
  16. package/dist/components/disclosure/Dialog.js +5 -5
  17. package/dist/components/disclosure/Dialog.js.map +2 -2
  18. package/dist/components/disclosure/dialogZIndex.d.ts +1 -1
  19. package/dist/components/features/crud-detail/CrudDetail.js +23 -23
  20. package/dist/components/features/crud-detail/CrudDetail.js.map +2 -2
  21. package/dist/components/features/crud-sheet/CrudSheet.js +49 -49
  22. package/dist/components/features/crud-sheet/CrudSheet.js.map +2 -2
  23. package/dist/components/features/crud-sheet/types.d.ts +4 -4
  24. package/dist/components/features/crud-sheet/types.d.ts.map +1 -1
  25. package/dist/components/features/data-select-button/DataSelectButton.d.ts +25 -7
  26. package/dist/components/features/data-select-button/DataSelectButton.d.ts.map +1 -1
  27. package/dist/components/features/data-select-button/DataSelectButton.js +27 -12
  28. package/dist/components/features/data-select-button/DataSelectButton.js.map +2 -2
  29. package/dist/components/features/permission-table/PermissionTable.js +4 -4
  30. package/dist/components/features/permission-table/PermissionTable.js.map +2 -2
  31. package/dist/components/features/shared-data/SharedDataSelect.d.ts +22 -10
  32. package/dist/components/features/shared-data/SharedDataSelect.d.ts.map +1 -1
  33. package/dist/components/features/shared-data/SharedDataSelect.js +113 -29
  34. package/dist/components/features/shared-data/SharedDataSelect.js.map +2 -2
  35. package/dist/components/features/shared-data/SharedDataSelectButton.d.ts +3 -3
  36. package/dist/components/features/shared-data/SharedDataSelectButton.d.ts.map +1 -1
  37. package/dist/components/features/shared-data/SharedDataSelectButton.js.map +1 -1
  38. package/dist/components/features/shared-data/SharedDataSelectList.js +5 -4
  39. package/dist/components/features/shared-data/SharedDataSelectList.js.map +2 -2
  40. package/dist/components/feedback/notification/NotificationBanner.js +3 -3
  41. package/dist/components/feedback/notification/NotificationBanner.js.map +2 -2
  42. package/dist/components/feedback/notification/NotificationBell.d.ts.map +1 -1
  43. package/dist/components/feedback/notification/NotificationBell.js +12 -5
  44. package/dist/components/feedback/notification/NotificationBell.js.map +2 -2
  45. package/dist/components/feedback/notification/NotificationProvider.d.ts.map +1 -1
  46. package/dist/components/feedback/notification/NotificationProvider.js +3 -1
  47. package/dist/components/feedback/notification/NotificationProvider.js.map +2 -2
  48. package/dist/components/form-control/ThemeToggle.d.ts.map +1 -1
  49. package/dist/components/form-control/ThemeToggle.js +9 -6
  50. package/dist/components/form-control/ThemeToggle.js.map +2 -2
  51. package/dist/components/form-control/checkbox/Checkbox.d.ts.map +1 -1
  52. package/dist/components/form-control/checkbox/Checkbox.js +3 -1
  53. package/dist/components/form-control/checkbox/Checkbox.js.map +2 -2
  54. package/dist/components/form-control/checkbox/CheckboxGroup.js +1 -1
  55. package/dist/components/form-control/checkbox/CheckboxGroup.js.map +2 -2
  56. package/dist/components/form-control/checkbox/Radio.d.ts.map +1 -1
  57. package/dist/components/form-control/checkbox/Radio.js +3 -1
  58. package/dist/components/form-control/checkbox/Radio.js.map +2 -2
  59. package/dist/components/form-control/checkbox/RadioGroup.js +1 -1
  60. package/dist/components/form-control/checkbox/RadioGroup.js.map +2 -2
  61. package/dist/components/form-control/color-picker/ColorPicker.d.ts.map +1 -1
  62. package/dist/components/form-control/color-picker/ColorPicker.js +3 -1
  63. package/dist/components/form-control/color-picker/ColorPicker.js.map +2 -2
  64. package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
  65. package/dist/components/form-control/combobox/Combobox.js +9 -5
  66. package/dist/components/form-control/combobox/Combobox.js.map +2 -2
  67. package/dist/components/form-control/date-range-picker/DateRangePicker.js +9 -9
  68. package/dist/components/form-control/date-range-picker/DateRangePicker.js.map +2 -2
  69. package/dist/components/form-control/editor/EditorToolbar.js +3 -3
  70. package/dist/components/form-control/editor/EditorToolbar.js.map +2 -2
  71. package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
  72. package/dist/components/form-control/field/DatePicker.js +9 -3
  73. package/dist/components/form-control/field/DatePicker.js.map +2 -2
  74. package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
  75. package/dist/components/form-control/field/DateTimePicker.js +9 -3
  76. package/dist/components/form-control/field/DateTimePicker.js.map +2 -2
  77. package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
  78. package/dist/components/form-control/field/NumberInput.js +9 -3
  79. package/dist/components/form-control/field/NumberInput.js.map +2 -2
  80. package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
  81. package/dist/components/form-control/field/TextInput.js +10 -4
  82. package/dist/components/form-control/field/TextInput.js.map +2 -2
  83. package/dist/components/form-control/field/Textarea.d.ts.map +1 -1
  84. package/dist/components/form-control/field/Textarea.js +9 -3
  85. package/dist/components/form-control/field/Textarea.js.map +2 -2
  86. package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
  87. package/dist/components/form-control/field/TimePicker.js +9 -3
  88. package/dist/components/form-control/field/TimePicker.js.map +2 -2
  89. package/dist/components/form-control/numpad/Numpad.d.ts.map +1 -1
  90. package/dist/components/form-control/numpad/Numpad.js +5 -1
  91. package/dist/components/form-control/numpad/Numpad.js.map +2 -2
  92. package/dist/components/form-control/select/Select.js +7 -7
  93. package/dist/components/form-control/select/Select.js.map +2 -2
  94. package/dist/components/form-control/state-preset/StatePreset.d.ts.map +1 -1
  95. package/dist/components/form-control/state-preset/StatePreset.js +42 -20
  96. package/dist/components/form-control/state-preset/StatePreset.js.map +2 -2
  97. package/dist/components/layout/sidebar/SidebarContainer.js +3 -3
  98. package/dist/components/layout/sidebar/SidebarContainer.js.map +2 -2
  99. package/dist/components/layout/sidebar/SidebarMenu.d.ts.map +1 -1
  100. package/dist/components/layout/sidebar/SidebarMenu.js +5 -2
  101. package/dist/components/layout/sidebar/SidebarMenu.js.map +2 -2
  102. package/dist/components/layout/topbar/Topbar.js +3 -4
  103. package/dist/components/layout/topbar/Topbar.js.map +2 -2
  104. package/dist/components/layout/topbar/TopbarMenu.js +3 -3
  105. package/dist/components/layout/topbar/TopbarMenu.js.map +2 -2
  106. package/dist/hooks/createSelectionGroup.d.ts +2 -2
  107. package/dist/hooks/createSelectionGroup.d.ts.map +1 -1
  108. package/dist/hooks/createSelectionGroup.js +5 -2
  109. package/dist/hooks/createSelectionGroup.js.map +2 -2
  110. package/dist/providers/i18n/I18nContext.d.ts +0 -4
  111. package/dist/providers/i18n/I18nContext.d.ts.map +1 -1
  112. package/dist/providers/i18n/I18nContext.js +1 -5
  113. package/dist/providers/i18n/I18nContext.js.map +2 -2
  114. package/dist/providers/i18n/locales/en.d.ts +38 -0
  115. package/dist/providers/i18n/locales/en.d.ts.map +1 -1
  116. package/dist/providers/i18n/locales/en.js +39 -1
  117. package/dist/providers/i18n/locales/en.js.map +1 -1
  118. package/dist/providers/i18n/locales/ko.d.ts +38 -0
  119. package/dist/providers/i18n/locales/ko.d.ts.map +1 -1
  120. package/dist/providers/i18n/locales/ko.js +39 -1
  121. package/dist/providers/i18n/locales/ko.js.map +1 -1
  122. package/package.json +6 -6
  123. package/src/components/data/calendar/Calendar.tsx +3 -4
  124. package/src/components/data/sheet/DataSheet.styles.ts +1 -1
  125. package/src/components/data/sheet/DataSheet.tsx +14 -15
  126. package/src/components/data/sheet/DataSheetConfigDialog.tsx +12 -10
  127. package/src/components/data/sheet/types.ts +1 -1
  128. package/src/components/disclosure/Dialog.tsx +10 -10
  129. package/src/components/disclosure/dialogZIndex.ts +1 -1
  130. package/src/components/features/crud-detail/CrudDetail.tsx +25 -25
  131. package/src/components/features/crud-sheet/CrudSheet.tsx +53 -53
  132. package/src/components/features/crud-sheet/types.ts +4 -4
  133. package/src/components/features/data-select-button/DataSelectButton.tsx +51 -21
  134. package/src/components/features/permission-table/PermissionTable.tsx +3 -3
  135. package/src/components/features/shared-data/SharedDataSelect.tsx +172 -33
  136. package/src/components/features/shared-data/SharedDataSelectButton.tsx +3 -2
  137. package/src/components/features/shared-data/SharedDataSelectList.tsx +4 -4
  138. package/src/components/feedback/notification/NotificationBanner.tsx +3 -3
  139. package/src/components/feedback/notification/NotificationBell.tsx +6 -4
  140. package/src/components/feedback/notification/NotificationProvider.tsx +3 -1
  141. package/src/components/form-control/ThemeToggle.tsx +10 -6
  142. package/src/components/form-control/checkbox/Checkbox.tsx +4 -1
  143. package/src/components/form-control/checkbox/CheckboxGroup.tsx +1 -1
  144. package/src/components/form-control/checkbox/Radio.tsx +4 -1
  145. package/src/components/form-control/checkbox/RadioGroup.tsx +1 -1
  146. package/src/components/form-control/color-picker/ColorPicker.tsx +4 -1
  147. package/src/components/form-control/combobox/Combobox.tsx +6 -3
  148. package/src/components/form-control/date-range-picker/DateRangePicker.tsx +8 -8
  149. package/src/components/form-control/editor/EditorToolbar.tsx +23 -23
  150. package/src/components/form-control/field/DatePicker.tsx +6 -3
  151. package/src/components/form-control/field/DateTimePicker.tsx +6 -3
  152. package/src/components/form-control/field/NumberInput.tsx +6 -3
  153. package/src/components/form-control/field/TextInput.tsx +7 -4
  154. package/src/components/form-control/field/Textarea.tsx +6 -3
  155. package/src/components/form-control/field/TimePicker.tsx +6 -3
  156. package/src/components/form-control/numpad/Numpad.tsx +3 -1
  157. package/src/components/form-control/select/Select.tsx +7 -7
  158. package/src/components/form-control/state-preset/StatePreset.tsx +14 -12
  159. package/src/components/layout/sidebar/SidebarContainer.tsx +3 -3
  160. package/src/components/layout/sidebar/SidebarMenu.tsx +3 -1
  161. package/src/components/layout/topbar/Topbar.tsx +3 -3
  162. package/src/components/layout/topbar/TopbarMenu.tsx +3 -3
  163. package/src/hooks/createSelectionGroup.tsx +8 -4
  164. package/src/providers/i18n/I18nContext.tsx +0 -7
  165. package/src/providers/i18n/locales/en.ts +38 -0
  166. package/src/providers/i18n/locales/ko.ts +38 -0
  167. package/tailwind.config.ts +2 -2
  168. package/tests/components/data/kanban/Kanban.selection.spec.tsx +34 -24
  169. package/tests/components/disclosure/Dialog.spec.tsx +28 -28
  170. package/tests/components/disclosure/DialogProvider.spec.tsx +51 -25
  171. package/tests/components/features/address/AddressSearch.spec.tsx +12 -4
  172. package/tests/components/features/crud-detail/CrudDetail.spec.tsx +1 -0
  173. package/tests/components/features/crud-sheet/CrudSheet.spec.tsx +30 -6
  174. package/tests/components/features/data-select-button/DataSelectButton.spec.tsx +77 -56
  175. package/tests/components/features/permission-table/PermissionTable.spec.tsx +12 -8
  176. package/tests/components/features/shared-data/SharedDataSelect.spec.tsx +172 -0
  177. package/tests/components/features/shared-data/SharedDataSelectList.spec.tsx +14 -2
  178. package/tests/components/feedback/notification/LiveRegion.spec.tsx +20 -9
  179. package/tests/components/feedback/notification/NotificationBanner.spec.tsx +64 -46
  180. package/tests/components/feedback/notification/NotificationBell.spec.tsx +70 -51
  181. package/tests/components/feedback/notification/NotificationContext.spec.tsx +105 -78
  182. package/tests/components/form-control/checkbox/Checkbox.spec.tsx +25 -20
  183. package/tests/components/form-control/checkbox/CheckboxGroup.spec.tsx +53 -30
  184. package/tests/components/form-control/checkbox/Radio.spec.tsx +25 -20
  185. package/tests/components/form-control/checkbox/RadioGroup.spec.tsx +53 -30
  186. package/tests/components/form-control/color-picker/ColorPicker.spec.tsx +24 -15
  187. package/tests/components/form-control/combobox/Combobox.spec.tsx +92 -59
  188. package/tests/components/form-control/date-range-picker/DateRangePicker.spec.tsx +2 -2
  189. package/tests/components/form-control/field/DatePicker.spec.tsx +50 -44
  190. package/tests/components/form-control/field/DateTimePicker.spec.tsx +51 -45
  191. package/tests/components/form-control/field/NumberInput.spec.tsx +53 -47
  192. package/tests/components/form-control/field/TextInput.spec.tsx +50 -44
  193. package/tests/components/form-control/field/Textarea.spec.tsx +35 -29
  194. package/tests/components/form-control/field/TimePicker.spec.tsx +43 -37
  195. package/tests/components/form-control/numpad/Numpad.spec.tsx +175 -25
  196. package/tests/components/form-control/select/Select.spec.tsx +5 -0
  197. package/tests/components/form-control/select/SelectItem.spec.tsx +1 -0
  198. package/tests/components/layout/sidebar/Sidebar.spec.tsx +79 -35
  199. package/tests/components/layout/sidebar/SidebarContainer.spec.tsx +1 -0
  200. package/tests/components/layout/sidebar/SidebarMenu.spec.tsx +28 -17
  201. package/tests/components/layout/topbar/TopbarActions.spec.tsx +41 -23
  202. package/tests/components/layout/topbar/createTopbarActions.spec.tsx +1 -0
  203. package/tests/hooks/usePrint.spec.tsx +1 -1
  204. package/tests/hooks/useRouterLink.spec.tsx +2 -0
  205. package/tests/hooks/useSyncConfig.spec.tsx +1 -0
  206. package/tests/providers/ErrorLoggerProvider.spec.tsx +1 -0
  207. package/tests/providers/PwaUpdateProvider.spec.tsx +16 -6
  208. package/tests/providers/ServiceClientContext.spec.tsx +40 -25
  209. package/tests/providers/i18n/I18nContext.spec.tsx +3 -4
  210. package/tests/providers/shared-data/SharedDataProvider.spec.tsx +2 -0
  211. package/dist/hooks/usePrint.d.ts +0 -3
  212. package/dist/hooks/usePrint.d.ts.map +0 -1
  213. package/dist/hooks/usePrint.js +0 -5
  214. package/dist/hooks/usePrint.js.map +0 -6
  215. 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");