@pie-lib/config-ui 13.0.3 → 13.0.4-next.0

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 (188) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +11 -0
  2. package/dist/alert-dialog.d.ts +44 -0
  3. package/dist/alert-dialog.js +47 -0
  4. package/dist/checkbox.d.ts +34 -0
  5. package/dist/checkbox.js +57 -0
  6. package/dist/choice-configuration/feedback-menu.d.ts +32 -0
  7. package/dist/choice-configuration/feedback-menu.js +85 -0
  8. package/dist/choice-configuration/index.d.ts +62 -0
  9. package/dist/choice-configuration/index.js +240 -0
  10. package/dist/choice-utils.d.ts +21 -0
  11. package/dist/choice-utils.js +15 -0
  12. package/dist/feedback-config/feedback-selector.d.ts +33 -0
  13. package/dist/feedback-config/feedback-selector.js +92 -0
  14. package/dist/feedback-config/group.d.ts +21 -0
  15. package/dist/feedback-config/group.js +33 -0
  16. package/dist/feedback-config/index.d.ts +48 -0
  17. package/dist/feedback-config/index.js +96 -0
  18. package/dist/form-section.d.ts +25 -0
  19. package/dist/form-section.js +25 -0
  20. package/dist/help.d.ts +41 -0
  21. package/dist/help.js +61 -0
  22. package/dist/index.d.ts +31 -0
  23. package/dist/index.js +34 -0
  24. package/dist/input.d.ts +29 -0
  25. package/dist/input.js +65 -0
  26. package/dist/inputs.d.ts +63 -0
  27. package/dist/inputs.js +70 -0
  28. package/dist/langs.d.ts +41 -0
  29. package/dist/langs.js +76 -0
  30. package/dist/layout/config-layout.d.ts +10 -0
  31. package/dist/layout/config-layout.js +75 -0
  32. package/dist/layout/index.d.ts +11 -0
  33. package/dist/layout/index.js +10 -0
  34. package/dist/layout/layout-contents.d.ts +21 -0
  35. package/dist/layout/layout-contents.js +70 -0
  36. package/dist/layout/settings-box.d.ts +19 -0
  37. package/dist/layout/settings-box.js +31 -0
  38. package/dist/mui-box/index.d.ts +21 -0
  39. package/dist/mui-box/index.js +47 -0
  40. package/dist/node_modules/.bun/@babel_runtime@7.29.7/node_modules/@babel/runtime/helpers/esm/extends.js +12 -0
  41. package/dist/node_modules/.bun/@babel_runtime@7.29.7/node_modules/@babel/runtime/helpers/esm/inheritsLoose.js +7 -0
  42. package/dist/node_modules/.bun/@babel_runtime@7.29.7/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +12 -0
  43. package/dist/node_modules/.bun/@babel_runtime@7.29.7/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js +8 -0
  44. package/dist/node_modules/.bun/react-measure@2.5.2_6dbf9a050bc9aadb/node_modules/react-measure/dist/index.esm.js +122 -0
  45. package/dist/node_modules/.bun/resize-observer-polyfill@1.5.1/node_modules/resize-observer-polyfill/dist/ResizeObserver.es.js +276 -0
  46. package/dist/number-text-field-custom.d.ts +51 -0
  47. package/dist/number-text-field-custom.js +192 -0
  48. package/dist/number-text-field.d.ts +47 -0
  49. package/dist/number-text-field.js +122 -0
  50. package/dist/radio-with-label.d.ts +25 -0
  51. package/dist/radio-with-label.js +27 -0
  52. package/dist/settings/display-size.d.ts +26 -0
  53. package/dist/settings/display-size.js +45 -0
  54. package/dist/settings/index.d.ts +45 -0
  55. package/dist/settings/index.js +63 -0
  56. package/dist/settings/panel.d.ts +27 -0
  57. package/dist/settings/panel.js +201 -0
  58. package/dist/settings/settings-radio-label.d.ts +25 -0
  59. package/dist/settings/settings-radio-label.js +29 -0
  60. package/dist/settings/toggle.d.ts +25 -0
  61. package/dist/settings/toggle.js +33 -0
  62. package/dist/tabs/index.d.ts +22 -0
  63. package/dist/tabs/index.js +39 -0
  64. package/dist/tags-input/index.d.ts +21 -0
  65. package/dist/tags-input/index.js +83 -0
  66. package/dist/two-choice.d.ts +43 -0
  67. package/dist/two-choice.js +79 -0
  68. package/dist/with-stateful-model.d.ts +42 -0
  69. package/dist/with-stateful-model.js +32 -0
  70. package/package.json +30 -18
  71. package/CHANGELOG.json +0 -32
  72. package/CHANGELOG.md +0 -2419
  73. package/LICENSE.md +0 -5
  74. package/lib/alert-dialog.js +0 -68
  75. package/lib/alert-dialog.js.map +0 -1
  76. package/lib/checkbox.js +0 -84
  77. package/lib/checkbox.js.map +0 -1
  78. package/lib/choice-configuration/feedback-menu.js +0 -129
  79. package/lib/choice-configuration/feedback-menu.js.map +0 -1
  80. package/lib/choice-configuration/index.js +0 -381
  81. package/lib/choice-configuration/index.js.map +0 -1
  82. package/lib/choice-utils.js +0 -42
  83. package/lib/choice-utils.js.map +0 -1
  84. package/lib/feedback-config/feedback-selector.js +0 -155
  85. package/lib/feedback-config/feedback-selector.js.map +0 -1
  86. package/lib/feedback-config/group.js +0 -61
  87. package/lib/feedback-config/group.js.map +0 -1
  88. package/lib/feedback-config/index.js +0 -146
  89. package/lib/feedback-config/index.js.map +0 -1
  90. package/lib/form-section.js +0 -44
  91. package/lib/form-section.js.map +0 -1
  92. package/lib/help.js +0 -106
  93. package/lib/help.js.map +0 -1
  94. package/lib/index.js +0 -186
  95. package/lib/index.js.map +0 -1
  96. package/lib/input.js +0 -106
  97. package/lib/input.js.map +0 -1
  98. package/lib/inputs.js +0 -105
  99. package/lib/inputs.js.map +0 -1
  100. package/lib/langs.js +0 -136
  101. package/lib/langs.js.map +0 -1
  102. package/lib/layout/config-layout.js +0 -137
  103. package/lib/layout/config-layout.js.map +0 -1
  104. package/lib/layout/index.js +0 -21
  105. package/lib/layout/index.js.map +0 -1
  106. package/lib/layout/layout-contents.js +0 -160
  107. package/lib/layout/layout-contents.js.map +0 -1
  108. package/lib/layout/settings-box.js +0 -57
  109. package/lib/layout/settings-box.js.map +0 -1
  110. package/lib/mui-box/index.js +0 -63
  111. package/lib/mui-box/index.js.map +0 -1
  112. package/lib/number-text-field-custom.js +0 -376
  113. package/lib/number-text-field-custom.js.map +0 -1
  114. package/lib/number-text-field.js +0 -229
  115. package/lib/number-text-field.js.map +0 -1
  116. package/lib/radio-with-label.js +0 -48
  117. package/lib/radio-with-label.js.map +0 -1
  118. package/lib/settings/display-size.js +0 -61
  119. package/lib/settings/display-size.js.map +0 -1
  120. package/lib/settings/index.js +0 -110
  121. package/lib/settings/index.js.map +0 -1
  122. package/lib/settings/panel.js +0 -392
  123. package/lib/settings/panel.js.map +0 -1
  124. package/lib/settings/settings-radio-label.js +0 -51
  125. package/lib/settings/settings-radio-label.js.map +0 -1
  126. package/lib/settings/toggle.js +0 -63
  127. package/lib/settings/toggle.js.map +0 -1
  128. package/lib/tabs/index.js +0 -75
  129. package/lib/tabs/index.js.map +0 -1
  130. package/lib/tags-input/index.js +0 -149
  131. package/lib/tags-input/index.js.map +0 -1
  132. package/lib/two-choice.js +0 -136
  133. package/lib/two-choice.js.map +0 -1
  134. package/lib/with-stateful-model.js +0 -61
  135. package/lib/with-stateful-model.js.map +0 -1
  136. package/src/__tests__/alert-dialog.test.jsx +0 -183
  137. package/src/__tests__/checkbox.test.jsx +0 -152
  138. package/src/__tests__/choice-utils.test.js +0 -12
  139. package/src/__tests__/form-section.test.jsx +0 -328
  140. package/src/__tests__/help.test.jsx +0 -184
  141. package/src/__tests__/input.test.jsx +0 -156
  142. package/src/__tests__/langs.test.jsx +0 -376
  143. package/src/__tests__/number-text-field-custom.test.jsx +0 -255
  144. package/src/__tests__/number-text-field.test.jsx +0 -263
  145. package/src/__tests__/radio-with-label.test.jsx +0 -155
  146. package/src/__tests__/settings-panel.test.js +0 -187
  147. package/src/__tests__/settings.test.jsx +0 -452
  148. package/src/__tests__/tabs.test.jsx +0 -188
  149. package/src/__tests__/two-choice.test.js +0 -110
  150. package/src/__tests__/with-stateful-model.test.jsx +0 -139
  151. package/src/alert-dialog.jsx +0 -75
  152. package/src/checkbox.jsx +0 -61
  153. package/src/choice-configuration/__tests__/feedback-menu.test.jsx +0 -151
  154. package/src/choice-configuration/__tests__/index.test.jsx +0 -234
  155. package/src/choice-configuration/feedback-menu.jsx +0 -96
  156. package/src/choice-configuration/index.jsx +0 -357
  157. package/src/choice-utils.js +0 -30
  158. package/src/feedback-config/__tests__/feedback-config.test.jsx +0 -141
  159. package/src/feedback-config/__tests__/feedback-selector.test.jsx +0 -97
  160. package/src/feedback-config/feedback-selector.jsx +0 -112
  161. package/src/feedback-config/group.jsx +0 -51
  162. package/src/feedback-config/index.jsx +0 -111
  163. package/src/form-section.jsx +0 -31
  164. package/src/help.jsx +0 -79
  165. package/src/index.js +0 -55
  166. package/src/input.jsx +0 -72
  167. package/src/inputs.jsx +0 -69
  168. package/src/langs.jsx +0 -111
  169. package/src/layout/__tests__/config.layout.test.jsx +0 -59
  170. package/src/layout/__tests__/layout-content.test.jsx +0 -3
  171. package/src/layout/config-layout.jsx +0 -103
  172. package/src/layout/index.js +0 -4
  173. package/src/layout/layout-contents.jsx +0 -117
  174. package/src/layout/settings-box.jsx +0 -32
  175. package/src/mui-box/index.jsx +0 -56
  176. package/src/number-text-field-custom.jsx +0 -333
  177. package/src/number-text-field.jsx +0 -215
  178. package/src/radio-with-label.jsx +0 -30
  179. package/src/settings/display-size.jsx +0 -53
  180. package/src/settings/index.js +0 -83
  181. package/src/settings/panel.jsx +0 -333
  182. package/src/settings/settings-radio-label.jsx +0 -32
  183. package/src/settings/toggle.jsx +0 -46
  184. package/src/tabs/index.jsx +0 -47
  185. package/src/tags-input/__tests__/index.test.jsx +0 -113
  186. package/src/tags-input/index.jsx +0 -116
  187. package/src/two-choice.jsx +0 -90
  188. package/src/with-stateful-model.jsx +0 -36
@@ -1,376 +0,0 @@
1
- import { render, screen } from '@testing-library/react';
2
- import userEvent from '@testing-library/user-event';
3
- import React from 'react';
4
- import { Langs, LanguageControls } from '../langs';
5
-
6
- describe('Langs Component', () => {
7
- let onChange;
8
- const renderComponent = (extras = {}) => {
9
- const defaults = {
10
- uid: '1',
11
- onChange,
12
- langs: ['en-US', 'es-ES'],
13
- selected: 'en-US',
14
- };
15
- const props = { ...defaults, ...extras };
16
- return render(<Langs {...props} />);
17
- };
18
-
19
- beforeEach(() => {
20
- onChange = jest.fn();
21
- });
22
-
23
- describe('rendering', () => {
24
- it('renders language selector with options', () => {
25
- renderComponent();
26
-
27
- // Select should be present
28
- const select = screen.getByRole('combobox');
29
- expect(select).toBeInTheDocument();
30
-
31
- // Should show selected value - MUI Select displays value as text content
32
- expect(select).toHaveTextContent('en-US');
33
- });
34
-
35
- it('renders with custom label', () => {
36
- renderComponent({ label: 'Choose Language' });
37
- expect(screen.getByText('Choose Language')).toBeInTheDocument();
38
- });
39
-
40
- it('renders all language options', () => {
41
- const { container } = renderComponent({
42
- langs: ['en-US', 'es-ES', 'fr-FR', 'de-DE'],
43
- });
44
-
45
- const select = screen.getByRole('combobox');
46
- expect(select).toBeInTheDocument();
47
- });
48
-
49
- it('renders with multiple languages', () => {
50
- const langs = ['en-US', 'es-ES', 'fr-FR', 'pt-BR'];
51
- renderComponent({ langs });
52
-
53
- const select = screen.getByRole('combobox');
54
- expect(select).toHaveTextContent('en-US');
55
- });
56
-
57
- it('renders FormControl with proper structure', () => {
58
- const { container } = renderComponent();
59
-
60
- expect(container.querySelector('[class*="MuiFormControl"]')).toBeInTheDocument();
61
- });
62
- });
63
-
64
- describe('user interactions', () => {
65
- it('calls onChange when user selects a language', async () => {
66
- const user = userEvent.setup();
67
- renderComponent();
68
-
69
- const select = screen.getByRole('combobox');
70
-
71
- // Open the select and choose es-ES
72
- await user.click(select);
73
- await user.click(screen.getByRole('option', { name: 'es-ES' }));
74
-
75
- expect(onChange).toHaveBeenCalledWith('es-ES');
76
- });
77
-
78
- it('calls onChange with correct value', async () => {
79
- const user = userEvent.setup();
80
- renderComponent({ selected: 'es-ES' });
81
-
82
- const select = screen.getByRole('combobox');
83
-
84
- await user.click(select);
85
- await user.click(screen.getByRole('option', { name: 'en-US' }));
86
-
87
- expect(onChange).toHaveBeenCalledWith('en-US');
88
- });
89
-
90
- it('opens dropdown on click', async () => {
91
- const user = userEvent.setup();
92
- renderComponent({
93
- langs: ['en-US', 'es-ES', 'fr-FR'],
94
- });
95
-
96
- const select = screen.getByRole('combobox');
97
- await user.click(select);
98
-
99
- expect(screen.getByRole('option', { name: 'en-US' })).toBeInTheDocument();
100
- expect(screen.getByRole('option', { name: 'es-ES' })).toBeInTheDocument();
101
- expect(screen.getByRole('option', { name: 'fr-FR' })).toBeInTheDocument();
102
- });
103
-
104
- it('does not call onChange if no onChange prop provided', async () => {
105
- const user = userEvent.setup();
106
- const { container } = render(<Langs uid="1" langs={['en-US', 'es-ES']} selected="en-US" />);
107
-
108
- const select = screen.getByRole('combobox');
109
- await user.click(select);
110
- await user.click(screen.getByRole('option', { name: 'es-ES' }));
111
-
112
- // Should not throw any error
113
- expect(select).toBeInTheDocument();
114
- });
115
- });
116
-
117
- describe('props handling', () => {
118
- it('accepts custom uid', () => {
119
- const customUid = 'custom-uid-123';
120
- const { container } = renderComponent({ uid: customUid });
121
-
122
- const input = container.querySelector(`#${customUid}`);
123
- expect(input).toBeInTheDocument();
124
- });
125
-
126
- it('generates random uid if not provided', () => {
127
- const { container } = render(<Langs onChange={onChange} langs={['en-US', 'es-ES']} selected="en-US" />);
128
-
129
- const select = screen.getByRole('combobox');
130
- expect(select).toBeInTheDocument();
131
- });
132
-
133
- it('handles empty label', () => {
134
- renderComponent({ label: '' });
135
-
136
- const select = screen.getByRole('combobox');
137
- expect(select).toBeInTheDocument();
138
- });
139
-
140
- it('handles very long label', () => {
141
- const longLabel = 'Choose the language you would like to use for editing this content';
142
- renderComponent({ label: longLabel });
143
-
144
- expect(screen.getByText(longLabel)).toBeInTheDocument();
145
- });
146
- });
147
-
148
- describe('value updates', () => {
149
- it('updates selected value when prop changes', () => {
150
- const { rerender } = renderComponent({ selected: 'en-US' });
151
-
152
- let select = screen.getByRole('combobox');
153
- expect(select).toHaveTextContent('en-US');
154
-
155
- rerender(<Langs uid="1" onChange={onChange} langs={['en-US', 'es-ES']} selected="es-ES" />);
156
-
157
- select = screen.getByRole('combobox');
158
- expect(select).toHaveTextContent('es-ES');
159
- });
160
-
161
- it('maintains state when language options change', async () => {
162
- const user = userEvent.setup();
163
- const { rerender } = renderComponent({
164
- langs: ['en-US', 'es-ES'],
165
- selected: 'en-US',
166
- });
167
-
168
- rerender(<Langs uid="1" onChange={onChange} langs={['en-US', 'es-ES', 'fr-FR']} selected="en-US" />);
169
-
170
- const select = screen.getByRole('combobox');
171
- expect(select).toHaveTextContent('en-US');
172
- });
173
- });
174
-
175
- describe('keyboard navigation', () => {
176
- it('opens dropdown with keyboard', async () => {
177
- const user = userEvent.setup();
178
- renderComponent({
179
- langs: ['en-US', 'es-ES'],
180
- });
181
-
182
- const select = screen.getByRole('combobox');
183
- select.focus();
184
-
185
- await user.keyboard(' ');
186
-
187
- expect(screen.getByRole('option', { name: 'en-US' })).toBeInTheDocument();
188
- });
189
- });
190
-
191
- describe('accessibility', () => {
192
- it('has proper label association', () => {
193
- renderComponent({ label: 'Select Language' });
194
-
195
- const select = screen.getByRole('combobox');
196
- expect(select).toBeInTheDocument();
197
- });
198
-
199
- it('renders options with proper roles', async () => {
200
- const user = userEvent.setup();
201
- renderComponent({
202
- langs: ['en-US', 'es-ES', 'fr-FR'],
203
- });
204
-
205
- const select = screen.getByRole('combobox');
206
- await user.click(select);
207
-
208
- const options = screen.getAllByRole('option');
209
- expect(options.length).toBe(3);
210
- });
211
- });
212
- });
213
-
214
- describe('LanguageControls Component', () => {
215
- const defaultProps = {
216
- langs: ['en-US', 'es-ES', 'fr-FR'],
217
- activeLang: 'en-US',
218
- defaultLang: 'en-US',
219
- onActiveLangChange: jest.fn(),
220
- onDefaultLangChange: jest.fn(),
221
- };
222
-
223
- beforeEach(() => {
224
- jest.clearAllMocks();
225
- });
226
-
227
- describe('rendering', () => {
228
- it('renders both language selectors', () => {
229
- render(<LanguageControls {...defaultProps} />);
230
-
231
- expect(screen.getByText('Choose language to edit')).toBeInTheDocument();
232
- expect(screen.getByText('Default language')).toBeInTheDocument();
233
- });
234
-
235
- it('renders with correct initial values', () => {
236
- render(<LanguageControls {...defaultProps} />);
237
-
238
- const selects = screen.getAllByRole('combobox');
239
- expect(selects).toHaveLength(2);
240
- });
241
-
242
- it('applies custom className', () => {
243
- const { container } = render(<LanguageControls {...defaultProps} className="custom-class" />);
244
-
245
- expect(container.querySelector('.custom-class')).toBeInTheDocument();
246
- });
247
- });
248
-
249
- describe('user interactions', () => {
250
- it('calls onActiveLangChange when active language is changed', async () => {
251
- const user = userEvent.setup();
252
- const onActiveLangChange = jest.fn();
253
-
254
- render(<LanguageControls {...defaultProps} activeLang="en-US" onActiveLangChange={onActiveLangChange} />);
255
-
256
- const selects = screen.getAllByRole('combobox');
257
- const activeSelect = selects[0];
258
-
259
- await user.click(activeSelect);
260
- await user.click(screen.getByRole('option', { name: 'es-ES' }));
261
-
262
- expect(onActiveLangChange).toHaveBeenCalledWith('es-ES');
263
- });
264
-
265
- it('calls onDefaultLangChange when default language is changed', async () => {
266
- const user = userEvent.setup();
267
- const onDefaultLangChange = jest.fn();
268
-
269
- render(<LanguageControls {...defaultProps} defaultLang="en-US" onDefaultLangChange={onDefaultLangChange} />);
270
-
271
- const selects = screen.getAllByRole('combobox');
272
- const defaultSelect = selects[1];
273
-
274
- await user.click(defaultSelect);
275
- await user.click(screen.getByRole('option', { name: 'fr-FR' }));
276
-
277
- expect(onDefaultLangChange).toHaveBeenCalledWith('fr-FR');
278
- });
279
-
280
- it('handles independent language changes', async () => {
281
- const user = userEvent.setup();
282
- const onActiveLangChange = jest.fn();
283
- const onDefaultLangChange = jest.fn();
284
-
285
- render(
286
- <LanguageControls
287
- {...defaultProps}
288
- activeLang="en-US"
289
- defaultLang="en-US"
290
- onActiveLangChange={onActiveLangChange}
291
- onDefaultLangChange={onDefaultLangChange}
292
- />,
293
- );
294
-
295
- const selects = screen.getAllByRole('combobox');
296
-
297
- // Change active language
298
- await user.click(selects[0]);
299
- await user.click(screen.getByRole('option', { name: 'es-ES' }));
300
-
301
- expect(onActiveLangChange).toHaveBeenCalledWith('es-ES');
302
- expect(onDefaultLangChange).not.toHaveBeenCalled();
303
- });
304
- });
305
-
306
- describe('props handling', () => {
307
- it('displays correct language options', async () => {
308
- const user = userEvent.setup();
309
- render(<LanguageControls {...defaultProps} langs={['en-US', 'es-ES', 'fr-FR', 'de-DE']} />);
310
-
311
- const selects = screen.getAllByRole('combobox');
312
- await user.click(selects[0]);
313
-
314
- expect(screen.getByRole('option', { name: 'en-US' })).toBeInTheDocument();
315
- expect(screen.getByRole('option', { name: 'es-ES' })).toBeInTheDocument();
316
- expect(screen.getByRole('option', { name: 'fr-FR' })).toBeInTheDocument();
317
- expect(screen.getByRole('option', { name: 'de-DE' })).toBeInTheDocument();
318
- });
319
-
320
- it('maintains different active and default languages', async () => {
321
- const user = userEvent.setup();
322
- render(<LanguageControls {...defaultProps} activeLang="es-ES" defaultLang="en-US" />);
323
-
324
- const selects = screen.getAllByRole('combobox');
325
- expect(selects[0]).toHaveTextContent('es-ES');
326
- expect(selects[1]).toHaveTextContent('en-US');
327
- });
328
- });
329
-
330
- describe('updates', () => {
331
- it('updates when activeLang prop changes', () => {
332
- const { rerender } = render(<LanguageControls {...defaultProps} activeLang="en-US" />);
333
-
334
- let selects = screen.getAllByRole('combobox');
335
- expect(selects[0]).toHaveTextContent('en-US');
336
-
337
- rerender(<LanguageControls {...defaultProps} activeLang="es-ES" />);
338
-
339
- selects = screen.getAllByRole('combobox');
340
- expect(selects[0]).toHaveTextContent('es-ES');
341
- });
342
-
343
- it('updates when defaultLang prop changes', () => {
344
- const { rerender } = render(<LanguageControls {...defaultProps} defaultLang="en-US" />);
345
-
346
- let selects = screen.getAllByRole('combobox');
347
- expect(selects[1]).toHaveTextContent('en-US');
348
-
349
- rerender(<LanguageControls {...defaultProps} defaultLang="fr-FR" />);
350
-
351
- selects = screen.getAllByRole('combobox');
352
- expect(selects[1]).toHaveTextContent('fr-FR');
353
- });
354
-
355
- it('updates when langs prop changes', async () => {
356
- const user = userEvent.setup();
357
- const { rerender } = render(<LanguageControls {...defaultProps} langs={['en-US', 'es-ES']} />);
358
-
359
- rerender(<LanguageControls {...defaultProps} langs={['en-US', 'es-ES', 'fr-FR']} />);
360
-
361
- const selects = screen.getAllByRole('combobox');
362
- await user.click(selects[0]);
363
-
364
- expect(screen.getByRole('option', { name: 'fr-FR' })).toBeInTheDocument();
365
- });
366
- });
367
-
368
- describe('accessibility', () => {
369
- it('has proper semantic structure', () => {
370
- const { container } = render(<LanguageControls {...defaultProps} />);
371
-
372
- const selects = screen.getAllByRole('combobox');
373
- expect(selects.length).toBe(2);
374
- });
375
- });
376
- });
@@ -1,255 +0,0 @@
1
- import React from 'react';
2
- import { fireEvent, render, screen, waitFor } from '@testing-library/react';
3
- import userEvent from '@testing-library/user-event';
4
- import { NumberTextFieldCustom } from '../number-text-field-custom';
5
-
6
- describe('NumberTextFieldCustom', () => {
7
- const defaultProps = {
8
- value: 1,
9
- onChange: jest.fn(),
10
- };
11
-
12
- beforeEach(() => {
13
- jest.clearAllMocks();
14
- });
15
-
16
- describe('rendering', () => {
17
- it('renders input field', () => {
18
- render(<NumberTextFieldCustom {...defaultProps} />);
19
- const input = screen.getByRole('spinbutton');
20
- expect(input).toBeInTheDocument();
21
- });
22
-
23
- it('renders with custom label', () => {
24
- render(<NumberTextFieldCustom {...defaultProps} label="Custom Label" />);
25
- expect(screen.getByLabelText('Custom Label')).toBeInTheDocument();
26
- });
27
-
28
- it('renders add and remove buttons', () => {
29
- render(<NumberTextFieldCustom {...defaultProps} />);
30
- const buttons = screen.getAllByRole('button');
31
- expect(buttons.length).toBeGreaterThanOrEqual(2);
32
- });
33
-
34
- it('renders with custom className', () => {
35
- const { container } = render(<NumberTextFieldCustom {...defaultProps} className="custom-class" />);
36
- expect(container.querySelector('.custom-class')).toBeInTheDocument();
37
- });
38
-
39
- it('renders with custom inputClassName', () => {
40
- const { container } = render(<NumberTextFieldCustom {...defaultProps} inputClassName="input-class" />);
41
- expect(container.querySelector('.input-class')).toBeInTheDocument();
42
- });
43
-
44
- it('renders as disabled when disabled prop is true', () => {
45
- render(<NumberTextFieldCustom {...defaultProps} disabled={true} />);
46
- const input = screen.getByRole('spinbutton');
47
- expect(input).toBeDisabled();
48
- });
49
-
50
- it('renders with error styling when error is true', () => {
51
- render(<NumberTextFieldCustom {...defaultProps} error={true} />);
52
- const input = screen.getByRole('spinbutton');
53
- expect(input).toHaveAttribute('aria-invalid', 'true');
54
- });
55
-
56
- it('renders helper text when provided', () => {
57
- render(<NumberTextFieldCustom {...defaultProps} helperText="This is a helper text" />);
58
- expect(screen.getByText('This is a helper text')).toBeInTheDocument();
59
- });
60
-
61
- it('renders with different variant', () => {
62
- render(<NumberTextFieldCustom {...defaultProps} variant="outlined" />);
63
- const input = screen.getByRole('spinbutton');
64
- expect(input).toBeInTheDocument();
65
- });
66
-
67
- it('renders with text alignment', () => {
68
- const { container } = render(<NumberTextFieldCustom {...defaultProps} textAlign="left" />);
69
- expect(container.querySelector('input')).toBeInTheDocument();
70
- });
71
- });
72
-
73
- describe('custom values', () => {
74
- it('accepts custom values array', () => {
75
- render(<NumberTextFieldCustom {...defaultProps} customValues={['small', 'medium', 'large']} value="medium" />);
76
- const input = screen.getByRole('spinbutton');
77
- expect(input).toBeInTheDocument();
78
- });
79
-
80
- it('handles empty custom values array', () => {
81
- render(<NumberTextFieldCustom {...defaultProps} customValues={[]} value={5} />);
82
- const input = screen.getByRole('spinbutton');
83
- expect(input).toHaveValue(5);
84
- });
85
-
86
- it('displays custom value when selected', () => {
87
- render(<NumberTextFieldCustom {...defaultProps} customValues={['auto', 'fixed', 'dynamic']} value="fixed" />);
88
- const input = screen.getByRole('spinbutton');
89
- expect(input).toBeInTheDocument();
90
- });
91
- });
92
-
93
- describe('step functionality', () => {
94
- it('uses default step of 1', () => {
95
- const onChange = jest.fn();
96
- render(<NumberTextFieldCustom {...defaultProps} value={5} onChange={onChange} />);
97
- expect(screen.getByRole('spinbutton')).toBeInTheDocument();
98
- });
99
-
100
- it('uses custom step value', () => {
101
- const onChange = jest.fn();
102
- render(<NumberTextFieldCustom {...defaultProps} value={5} step={0.5} onChange={onChange} />);
103
- expect(screen.getByRole('spinbutton')).toBeInTheDocument();
104
- });
105
-
106
- it('increments value by step with add button', async () => {
107
- const user = userEvent.setup();
108
- const onChange = jest.fn();
109
- render(<NumberTextFieldCustom {...defaultProps} value={5} step={2} onChange={onChange} />);
110
-
111
- const buttons = screen.getAllByRole('button');
112
- const addButton = buttons.find((btn) => btn.querySelector('[data-testid], svg'));
113
-
114
- if (addButton) {
115
- await user.click(addButton);
116
- }
117
- });
118
-
119
- it('decrements value by step with remove button', async () => {
120
- const user = userEvent.setup();
121
- const onChange = jest.fn();
122
- render(<NumberTextFieldCustom {...defaultProps} value={5} step={1} onChange={onChange} />);
123
-
124
- const buttons = screen.getAllByRole('button');
125
- const removeButton = buttons[0];
126
-
127
- if (removeButton) {
128
- await user.click(removeButton);
129
- }
130
- });
131
- });
132
-
133
- describe('min/max constraints', () => {
134
- it('clamps value to min', async () => {
135
- const user = userEvent.setup();
136
- render(<NumberTextFieldCustom {...defaultProps} value={0} min={1} max={10} />);
137
-
138
- const input = screen.getByRole('spinbutton');
139
- fireEvent.blur(input);
140
-
141
- await waitFor(() => {
142
- expect(input).toHaveValue(1);
143
- });
144
- });
145
-
146
- it('clamps value to max', async () => {
147
- const user = userEvent.setup();
148
- render(<NumberTextFieldCustom {...defaultProps} value={15} min={1} max={10} />);
149
-
150
- const input = screen.getByRole('spinbutton');
151
- fireEvent.blur(input);
152
-
153
- await waitFor(() => {
154
- expect(input).toHaveValue(10);
155
- });
156
- });
157
-
158
- it('handles only min constraint', () => {
159
- render(<NumberTextFieldCustom {...defaultProps} value={5} min={3} />);
160
- expect(screen.getByRole('spinbutton')).toHaveValue(5);
161
- });
162
-
163
- it('handles only max constraint', () => {
164
- render(<NumberTextFieldCustom {...defaultProps} value={5} max={10} />);
165
- expect(screen.getByRole('spinbutton')).toHaveValue(5);
166
- });
167
- });
168
-
169
- describe('props updates', () => {
170
- it('updates value when prop changes', () => {
171
- const { rerender } = render(<NumberTextFieldCustom {...defaultProps} value={5} />);
172
-
173
- let input = screen.getByRole('spinbutton');
174
- expect(input).toHaveValue(5);
175
-
176
- rerender(<NumberTextFieldCustom {...defaultProps} value={8} />);
177
-
178
- input = screen.getByRole('spinbutton');
179
- expect(input).toHaveValue(8);
180
- });
181
-
182
- it('updates when label changes', () => {
183
- const { rerender } = render(<NumberTextFieldCustom {...defaultProps} label="Old Label" />);
184
-
185
- expect(screen.getByLabelText('Old Label')).toBeInTheDocument();
186
-
187
- rerender(<NumberTextFieldCustom {...defaultProps} label="New Label" />);
188
-
189
- expect(screen.getByLabelText('New Label')).toBeInTheDocument();
190
- });
191
-
192
- it('updates constraints when min/max props change', () => {
193
- const { rerender } = render(<NumberTextFieldCustom {...defaultProps} value={5} min={1} max={10} />);
194
-
195
- rerender(<NumberTextFieldCustom {...defaultProps} value={5} min={1} max={8} />);
196
-
197
- expect(screen.getByRole('spinbutton')).toBeInTheDocument();
198
- });
199
- });
200
-
201
- describe('text alignment', () => {
202
- it('renders with center alignment (default)', () => {
203
- render(<NumberTextFieldCustom {...defaultProps} value={5} />);
204
- expect(screen.getByRole('spinbutton')).toBeInTheDocument();
205
- });
206
-
207
- it('renders with custom left alignment', () => {
208
- render(<NumberTextFieldCustom {...defaultProps} value={5} textAlign="left" />);
209
- expect(screen.getByRole('spinbutton')).toBeInTheDocument();
210
- });
211
-
212
- it('renders with right alignment', () => {
213
- render(<NumberTextFieldCustom {...defaultProps} value={5} textAlign="right" />);
214
- expect(screen.getByRole('spinbutton')).toBeInTheDocument();
215
- });
216
- });
217
-
218
- describe('type property', () => {
219
- it('renders as number type by default', () => {
220
- const { container } = render(<NumberTextFieldCustom {...defaultProps} value={5} />);
221
- const input = container.querySelector('input[type="number"]');
222
- expect(input).toBeInTheDocument();
223
- });
224
-
225
- it('can render with custom type', () => {
226
- const { container } = render(<NumberTextFieldCustom {...defaultProps} value={5} type="text" />);
227
- const input = container.querySelector('input');
228
- expect(input).toBeInTheDocument();
229
- });
230
- });
231
-
232
- describe('accessibility', () => {
233
- it('renders as a spinbutton', () => {
234
- render(<NumberTextFieldCustom {...defaultProps} />);
235
- expect(screen.getByRole('spinbutton')).toBeInTheDocument();
236
- });
237
-
238
- it('has proper label association', () => {
239
- render(<NumberTextFieldCustom {...defaultProps} label="Price" />);
240
- expect(screen.getByLabelText('Price')).toBeInTheDocument();
241
- });
242
-
243
- it('supports keyboard navigation', async () => {
244
- const user = userEvent.setup();
245
- render(<NumberTextFieldCustom {...defaultProps} value={5} />);
246
-
247
- const input = screen.getByRole('spinbutton');
248
- input.focus();
249
- expect(input).toHaveFocus();
250
-
251
- await user.keyboard('{ArrowUp}');
252
- expect(input).toHaveFocus();
253
- });
254
- });
255
- });