@akinon/akiform-builder 1.0.0 → 1.0.2
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/dist/cjs/__tests__/akiform-builder.test.js +257 -83
- package/dist/cjs/__tests__/field-builder.test.js +48 -3
- package/dist/cjs/index.css +10 -0
- package/dist/cjs/src/akiform-builder.d.ts.map +1 -1
- package/dist/cjs/src/akiform-builder.js +230 -63
- package/dist/cjs/src/field-builder.d.ts +22 -5
- package/dist/cjs/src/field-builder.d.ts.map +1 -1
- package/dist/cjs/src/field-builder.js +81 -22
- package/dist/cjs/src/i18n/translations/en.d.ts +7 -0
- package/dist/cjs/src/i18n/translations/en.d.ts.map +1 -1
- package/dist/cjs/src/i18n/translations/en.js +8 -1
- package/dist/cjs/src/i18n/translations/tr.d.ts +7 -0
- package/dist/cjs/src/i18n/translations/tr.d.ts.map +1 -1
- package/dist/cjs/src/i18n/translations/tr.js +8 -1
- package/dist/cjs/src/types.d.ts +27 -5
- package/dist/cjs/src/types.d.ts.map +1 -1
- package/dist/esm/__tests__/akiform-builder.test.js +257 -83
- package/dist/esm/__tests__/field-builder.test.js +48 -3
- package/dist/esm/index.css +10 -0
- package/dist/esm/src/akiform-builder.d.ts.map +1 -1
- package/dist/esm/src/akiform-builder.js +231 -64
- package/dist/esm/src/field-builder.d.ts +22 -5
- package/dist/esm/src/field-builder.d.ts.map +1 -1
- package/dist/esm/src/field-builder.js +81 -22
- package/dist/esm/src/i18n/translations/en.d.ts +7 -0
- package/dist/esm/src/i18n/translations/en.d.ts.map +1 -1
- package/dist/esm/src/i18n/translations/en.js +8 -1
- package/dist/esm/src/i18n/translations/tr.d.ts +7 -0
- package/dist/esm/src/i18n/translations/tr.d.ts.map +1 -1
- package/dist/esm/src/i18n/translations/tr.js +8 -1
- package/dist/esm/src/types.d.ts +27 -5
- package/dist/esm/src/types.d.ts.map +1 -1
- package/package.json +19 -16
|
@@ -21,6 +21,13 @@ describe('AkiformBuilder', () => {
|
|
|
21
21
|
const mockOnSubmit = vi.fn();
|
|
22
22
|
const mockOnReset = vi.fn();
|
|
23
23
|
const mockOnValueChange = vi.fn();
|
|
24
|
+
const expandCollapsable = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
25
|
+
const user = utils_1.userEvent.setup();
|
|
26
|
+
const expandIcons = (yield utils_1.screen.findAllByRole('button')).filter(el => el.className.includes('akinon-collapse-expand-icon'));
|
|
27
|
+
for (const expandIcon of expandIcons) {
|
|
28
|
+
yield user.click(expandIcon);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
24
31
|
const defaultFields = [
|
|
25
32
|
{
|
|
26
33
|
key: 'name',
|
|
@@ -32,7 +39,8 @@ describe('AkiformBuilder', () => {
|
|
|
32
39
|
key: 'age',
|
|
33
40
|
label: 'Age',
|
|
34
41
|
type: 'number',
|
|
35
|
-
placeholder: 'Enter your age'
|
|
42
|
+
placeholder: 'Enter your age',
|
|
43
|
+
help: 'Description text 2'
|
|
36
44
|
}
|
|
37
45
|
];
|
|
38
46
|
beforeEach(() => {
|
|
@@ -40,13 +48,100 @@ describe('AkiformBuilder', () => {
|
|
|
40
48
|
});
|
|
41
49
|
describe('AkiformBuilder in uncontrolled mode', () => {
|
|
42
50
|
it('renders form fields correctly', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
|
+
const newDefaultFields = defaultFields.map((field, key) => (Object.assign(Object.assign({}, field), { help: `Description text ${key}`, labelDescription: `Label description text ${key}` })));
|
|
43
52
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
|
-
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields:
|
|
53
|
+
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: newDefaultFields, onSubmit: mockOnSubmit }));
|
|
45
54
|
}));
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
for (const field of newDefaultFields) {
|
|
56
|
+
if (field.label) {
|
|
57
|
+
expect(utils_1.screen.getByText(field.label)).toBeInTheDocument();
|
|
58
|
+
}
|
|
59
|
+
if (field.placeholder) {
|
|
60
|
+
expect(utils_1.screen.getByPlaceholderText(field.placeholder)).toBeInTheDocument();
|
|
61
|
+
}
|
|
62
|
+
expect(utils_1.screen.getByText(field.help)).toBeInTheDocument();
|
|
63
|
+
expect(utils_1.screen.getByText(field.labelDescription)).toBeInTheDocument();
|
|
64
|
+
}
|
|
65
|
+
}));
|
|
66
|
+
it('renders form fields correctly with row and column fields', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
67
|
+
const newDefaultFields = [
|
|
68
|
+
{
|
|
69
|
+
type: 'row',
|
|
70
|
+
key: 'mainrow',
|
|
71
|
+
rowProps: {
|
|
72
|
+
align: 'middle'
|
|
73
|
+
},
|
|
74
|
+
columnFields: [
|
|
75
|
+
{
|
|
76
|
+
type: 'column',
|
|
77
|
+
key: 'col1',
|
|
78
|
+
columnProps: {
|
|
79
|
+
span: '24'
|
|
80
|
+
},
|
|
81
|
+
fields: [
|
|
82
|
+
{
|
|
83
|
+
type: 'row',
|
|
84
|
+
key: 'row1',
|
|
85
|
+
columnFields: [
|
|
86
|
+
{
|
|
87
|
+
type: 'column',
|
|
88
|
+
key: 'col1_1',
|
|
89
|
+
fields: [
|
|
90
|
+
{
|
|
91
|
+
type: 'text',
|
|
92
|
+
key: 'test1',
|
|
93
|
+
label: 'Test Field 1'
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
type: 'row',
|
|
101
|
+
key: 'row2',
|
|
102
|
+
columnFields: [
|
|
103
|
+
{
|
|
104
|
+
type: 'column',
|
|
105
|
+
key: 'col2_1',
|
|
106
|
+
fields: [
|
|
107
|
+
{
|
|
108
|
+
type: 'text',
|
|
109
|
+
key: 'test2',
|
|
110
|
+
label: 'Test Field 2'
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
type: 'column',
|
|
116
|
+
key: 'col2_2',
|
|
117
|
+
fields: [
|
|
118
|
+
{
|
|
119
|
+
type: 'text',
|
|
120
|
+
key: 'test3',
|
|
121
|
+
label: 'Test Field 3'
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
];
|
|
132
|
+
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
133
|
+
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: newDefaultFields, onSubmit: mockOnSubmit }));
|
|
134
|
+
}));
|
|
135
|
+
// Check fields
|
|
136
|
+
expect(utils_1.screen.getByLabelText('Test Field 1')).toBeInTheDocument();
|
|
137
|
+
expect(utils_1.screen.getByLabelText('Test Field 2')).toBeInTheDocument();
|
|
138
|
+
expect(utils_1.screen.getByLabelText('Test Field 3')).toBeInTheDocument();
|
|
139
|
+
// Check row and column count
|
|
140
|
+
expect(document.querySelectorAll('.akinon-col')).toHaveLength(11);
|
|
141
|
+
expect(document.querySelectorAll('.akinon-row')).toHaveLength(7);
|
|
142
|
+
// Check props
|
|
143
|
+
expect(document.querySelector('.akinon-row-middle')).toBeInTheDocument();
|
|
144
|
+
expect(document.querySelector('.akinon-col-24')).toBeInTheDocument();
|
|
50
145
|
}));
|
|
51
146
|
it('handles form with custom field and onChange', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
52
147
|
const CustomComponent = ({ field, control }) => {
|
|
@@ -168,7 +263,14 @@ describe('AkiformBuilder', () => {
|
|
|
168
263
|
}));
|
|
169
264
|
it('renders different field types correctly', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
170
265
|
const fields = [
|
|
171
|
-
{
|
|
266
|
+
{
|
|
267
|
+
key: 'name',
|
|
268
|
+
label: 'Name',
|
|
269
|
+
type: 'text',
|
|
270
|
+
help: 'Help text',
|
|
271
|
+
labelDescription: 'Label description text',
|
|
272
|
+
placeholder: 'Enter your name'
|
|
273
|
+
},
|
|
172
274
|
{ key: 'age', label: 'Age', type: 'number' },
|
|
173
275
|
{
|
|
174
276
|
key: 'gender',
|
|
@@ -186,7 +288,9 @@ describe('AkiformBuilder', () => {
|
|
|
186
288
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
187
289
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: mockOnSubmit }));
|
|
188
290
|
}));
|
|
189
|
-
expect(utils_1.screen.
|
|
291
|
+
expect(utils_1.screen.getByPlaceholderText('Enter your name')).toHaveAttribute('type', 'text');
|
|
292
|
+
expect(utils_1.screen.getByText('Help text')).toBeInTheDocument();
|
|
293
|
+
expect(utils_1.screen.getByText('Label description text')).toBeInTheDocument();
|
|
190
294
|
expect(utils_1.screen.getByLabelText('Age')).toHaveClass('akinon-input-number-input');
|
|
191
295
|
expect(utils_1.screen.getByLabelText('Gender')).toBeInTheDocument();
|
|
192
296
|
expect(utils_1.screen.getByLabelText('Subscribe')).toHaveAttribute('type', 'checkbox');
|
|
@@ -194,29 +298,38 @@ describe('AkiformBuilder', () => {
|
|
|
194
298
|
expect(utils_1.screen.getByLabelText('Biography')).toBeInTheDocument();
|
|
195
299
|
}));
|
|
196
300
|
it('renders field array correctly', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
301
|
+
const user = utils_1.userEvent.setup();
|
|
197
302
|
const fields = [
|
|
198
|
-
|
|
199
|
-
key
|
|
200
|
-
label
|
|
201
|
-
type
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
303
|
+
(0, field_builder_1.field)()
|
|
304
|
+
.key('addresses')
|
|
305
|
+
.label('Addresses')
|
|
306
|
+
.type('fieldArray')
|
|
307
|
+
.defaultExpanded(true)
|
|
308
|
+
.fields([
|
|
309
|
+
(0, field_builder_1.field)()
|
|
310
|
+
.key('street')
|
|
311
|
+
.label('Street')
|
|
312
|
+
.type('text')
|
|
313
|
+
.help('Help text')
|
|
314
|
+
.labelDescription('Label description text')
|
|
315
|
+
.build(),
|
|
316
|
+
(0, field_builder_1.field)().key('city').label('City').type('text').build()
|
|
317
|
+
])
|
|
318
|
+
.build()
|
|
207
319
|
];
|
|
208
320
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
209
321
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: mockOnSubmit }));
|
|
210
322
|
}));
|
|
211
|
-
expect(utils_1.screen.getByText('Add')).toBeInTheDocument();
|
|
212
|
-
yield (
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
expect(utils_1.screen.
|
|
216
|
-
expect(utils_1.screen.
|
|
217
|
-
expect(utils_1.screen.getByText('
|
|
323
|
+
expect(utils_1.screen.getByText('Add Addresses')).toBeInTheDocument();
|
|
324
|
+
yield user.click(utils_1.screen.getByTestId('addresses-add-button'));
|
|
325
|
+
yield expandCollapsable();
|
|
326
|
+
expect(utils_1.screen.getAllByText('Street')).toHaveLength(1);
|
|
327
|
+
expect(utils_1.screen.getAllByText('City')).toHaveLength(1);
|
|
328
|
+
expect(utils_1.screen.getByText('Help text')).toBeInTheDocument();
|
|
329
|
+
expect(utils_1.screen.getByText('Label description text')).toBeInTheDocument();
|
|
218
330
|
}));
|
|
219
331
|
it('handles form with field array and nested validation', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
332
|
+
const user = utils_1.userEvent.setup();
|
|
220
333
|
const fields = [
|
|
221
334
|
{
|
|
222
335
|
key: 'items',
|
|
@@ -243,25 +356,24 @@ describe('AkiformBuilder', () => {
|
|
|
243
356
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: onSubmitMock }));
|
|
244
357
|
}));
|
|
245
358
|
// Add an item
|
|
246
|
-
yield (
|
|
247
|
-
utils_1.fireEvent.click(utils_1.screen.getByText('Add'));
|
|
248
|
-
}));
|
|
359
|
+
yield user.click(utils_1.screen.getByTestId('items-add-button'));
|
|
249
360
|
// Try to submit without filling required fields
|
|
250
361
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
251
362
|
utils_1.fireEvent.submit(utils_1.screen.getByTestId('akiform-builder'));
|
|
252
363
|
}));
|
|
253
364
|
yield (0, utils_1.waitFor)(() => {
|
|
254
|
-
expect(utils_1.screen.getByText('
|
|
365
|
+
expect(utils_1.screen.getByText('An error occurred in here')).toBeInTheDocument();
|
|
255
366
|
expect(onSubmitMock).not.toHaveBeenCalled();
|
|
256
367
|
});
|
|
368
|
+
yield expandCollapsable();
|
|
257
369
|
// Fill in valid data
|
|
258
370
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
259
|
-
utils_1.
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Quantity'), {
|
|
263
|
-
target: { value: '2' }
|
|
371
|
+
const nameInput = utils_1.screen.getByRole('textbox', { name: /item name/i });
|
|
372
|
+
const quantityInput = utils_1.screen.getByRole('spinbutton', {
|
|
373
|
+
name: /quantity/i
|
|
264
374
|
});
|
|
375
|
+
yield utils_1.userEvent.type(nameInput, 'Test Item');
|
|
376
|
+
yield utils_1.userEvent.type(quantityInput, '2');
|
|
265
377
|
}));
|
|
266
378
|
// Submit the form
|
|
267
379
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -274,6 +386,7 @@ describe('AkiformBuilder', () => {
|
|
|
274
386
|
});
|
|
275
387
|
}));
|
|
276
388
|
it('handles field array operations correctly', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
389
|
+
const user = utils_1.userEvent.setup();
|
|
277
390
|
const fields = [
|
|
278
391
|
{
|
|
279
392
|
key: 'items',
|
|
@@ -297,9 +410,8 @@ describe('AkiformBuilder', () => {
|
|
|
297
410
|
(0, utils_1.render)(React.createElement(TestComponent, null));
|
|
298
411
|
}));
|
|
299
412
|
// Add an item
|
|
300
|
-
yield (
|
|
301
|
-
|
|
302
|
-
}));
|
|
413
|
+
yield user.click(utils_1.screen.getByTestId('items-add-button'));
|
|
414
|
+
yield expandCollapsable();
|
|
303
415
|
// Fill in the fields
|
|
304
416
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
305
417
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Item Name'), {
|
|
@@ -381,7 +493,7 @@ describe('AkiformBuilder', () => {
|
|
|
381
493
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: mockOnSubmit }));
|
|
382
494
|
}));
|
|
383
495
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
384
|
-
utils_1.fireEvent.change(utils_1.screen.
|
|
496
|
+
utils_1.fireEvent.change(utils_1.screen.getByRole('textbox', { name: /email/i }), {
|
|
385
497
|
target: { value: 'invalid-email' }
|
|
386
498
|
});
|
|
387
499
|
utils_1.fireEvent.submit(utils_1.screen.getByTestId('akiform-builder'));
|
|
@@ -495,6 +607,8 @@ describe('AkiformBuilder', () => {
|
|
|
495
607
|
key: 'customField',
|
|
496
608
|
label: 'Custom Field',
|
|
497
609
|
type: 'custom',
|
|
610
|
+
help: 'Help text',
|
|
611
|
+
labelDescription: 'Label description text',
|
|
498
612
|
render: ({ field }) => (React.createElement(CustomComponent, { field: field }))
|
|
499
613
|
}
|
|
500
614
|
];
|
|
@@ -502,6 +616,8 @@ describe('AkiformBuilder', () => {
|
|
|
502
616
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
503
617
|
}));
|
|
504
618
|
expect(utils_1.screen.getByTestId('custom-field')).toHaveTextContent('Custom Field');
|
|
619
|
+
expect(utils_1.screen.getByText('Help text')).toBeInTheDocument();
|
|
620
|
+
expect(utils_1.screen.getByText('Label description text')).toBeInTheDocument();
|
|
505
621
|
}));
|
|
506
622
|
it('cleans up throttle timeout on unmount', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
507
623
|
vi.useFakeTimers();
|
|
@@ -536,6 +652,33 @@ describe('AkiformBuilder', () => {
|
|
|
536
652
|
// The form should still be rendered
|
|
537
653
|
expect(utils_1.screen.getByTestId('akiform-builder')).toBeInTheDocument();
|
|
538
654
|
}));
|
|
655
|
+
it('renders custom submit and reset button props', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
656
|
+
const submitButtonProps = {
|
|
657
|
+
className: 'custom-submit-btn',
|
|
658
|
+
children: 'submit button'
|
|
659
|
+
};
|
|
660
|
+
const resetButtonProps = {
|
|
661
|
+
className: 'custom-reset-btn',
|
|
662
|
+
children: 'reset button'
|
|
663
|
+
};
|
|
664
|
+
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
665
|
+
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: defaultFields, onSubmit: mockOnSubmit, showResetButton: true, onReset: mockOnReset, submitButtonProps: submitButtonProps, resetButtonProps: resetButtonProps }));
|
|
666
|
+
}));
|
|
667
|
+
const submitButton = utils_1.screen
|
|
668
|
+
.getByText(submitButtonProps.children)
|
|
669
|
+
.closest('button');
|
|
670
|
+
const resetButton = utils_1.screen
|
|
671
|
+
.getByText(resetButtonProps.children)
|
|
672
|
+
.closest('button');
|
|
673
|
+
expect(submitButton).toBeInTheDocument();
|
|
674
|
+
expect(resetButton).toBeInTheDocument();
|
|
675
|
+
expect(submitButton).toHaveClass(submitButtonProps.className);
|
|
676
|
+
expect(resetButton).toHaveClass(resetButtonProps.className);
|
|
677
|
+
yield utils_1.userEvent.click(resetButton);
|
|
678
|
+
expect(mockOnReset).toHaveBeenCalled();
|
|
679
|
+
yield utils_1.userEvent.click(submitButton);
|
|
680
|
+
expect(mockOnSubmit).toHaveBeenCalled();
|
|
681
|
+
}));
|
|
539
682
|
});
|
|
540
683
|
describe('AkiformBuilder in controlled mode', () => {
|
|
541
684
|
it('uses provided values in controlled mode', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -632,11 +775,12 @@ describe('AkiformBuilder', () => {
|
|
|
632
775
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
633
776
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn(), initialValues: initialValues }));
|
|
634
777
|
}));
|
|
778
|
+
yield expandCollapsable();
|
|
635
779
|
expect(utils_1.screen.getAllByLabelText('Item Name')).toHaveLength(2);
|
|
636
780
|
expect(utils_1.screen.getAllByLabelText('Quantity')).toHaveLength(2);
|
|
637
|
-
expect(utils_1.screen.getAllByText('Remove')).toHaveLength(2);
|
|
638
781
|
}));
|
|
639
782
|
it('adds and removes field array items', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
783
|
+
const user = utils_1.userEvent.setup();
|
|
640
784
|
const fields = [
|
|
641
785
|
{
|
|
642
786
|
key: 'items',
|
|
@@ -649,22 +793,20 @@ describe('AkiformBuilder', () => {
|
|
|
649
793
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
650
794
|
}));
|
|
651
795
|
// Add an item
|
|
652
|
-
yield (
|
|
653
|
-
|
|
654
|
-
}));
|
|
796
|
+
yield user.click(utils_1.screen.getByTestId('items-add-button'));
|
|
797
|
+
yield expandCollapsable();
|
|
655
798
|
expect(utils_1.screen.getByLabelText('Item Name')).toBeInTheDocument();
|
|
656
799
|
// Add another item
|
|
657
|
-
yield (
|
|
658
|
-
|
|
659
|
-
}));
|
|
800
|
+
yield user.click(utils_1.screen.getByLabelText('Add Items'));
|
|
801
|
+
yield expandCollapsable();
|
|
660
802
|
expect(utils_1.screen.getAllByLabelText('Item Name')).toHaveLength(2);
|
|
661
803
|
// Remove an item
|
|
662
|
-
yield (
|
|
663
|
-
|
|
664
|
-
}));
|
|
804
|
+
yield user.click(utils_1.screen.getAllByLabelText('Remove Items')[0]);
|
|
805
|
+
yield expandCollapsable();
|
|
665
806
|
expect(utils_1.screen.getAllByLabelText('Item Name')).toHaveLength(1);
|
|
666
807
|
}));
|
|
667
808
|
it('handles field array with conditional fields', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
809
|
+
const user = utils_1.userEvent.setup();
|
|
668
810
|
const fields = [
|
|
669
811
|
{
|
|
670
812
|
key: 'items',
|
|
@@ -684,10 +826,10 @@ describe('AkiformBuilder', () => {
|
|
|
684
826
|
}
|
|
685
827
|
];
|
|
686
828
|
const { rerender } = (0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
829
|
+
yield expandCollapsable();
|
|
687
830
|
// Add an item
|
|
688
|
-
yield (
|
|
689
|
-
|
|
690
|
-
}));
|
|
831
|
+
yield user.click(utils_1.screen.getByLabelText('Add Items'));
|
|
832
|
+
yield expandCollapsable();
|
|
691
833
|
// Description should not be visible initially
|
|
692
834
|
expect(utils_1.screen.queryByLabelText('Description')).not.toBeInTheDocument();
|
|
693
835
|
// Enter a name longer than 5 characters
|
|
@@ -718,9 +860,10 @@ describe('AkiformBuilder', () => {
|
|
|
718
860
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
719
861
|
}));
|
|
720
862
|
// The field array should be rendered with an "Add" button
|
|
721
|
-
expect(utils_1.screen.
|
|
863
|
+
expect(utils_1.screen.getByTestId('emptyFieldArray-add-button')).toBeInTheDocument();
|
|
722
864
|
}));
|
|
723
865
|
it('handles form submission with field array', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
866
|
+
const user = utils_1.userEvent.setup();
|
|
724
867
|
const fields = [
|
|
725
868
|
{
|
|
726
869
|
key: 'items',
|
|
@@ -737,10 +880,9 @@ describe('AkiformBuilder', () => {
|
|
|
737
880
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: onSubmitMock }));
|
|
738
881
|
}));
|
|
739
882
|
// Add two items
|
|
740
|
-
yield (
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
}));
|
|
883
|
+
yield user.click(utils_1.screen.getByTestId('items-add-button'));
|
|
884
|
+
yield user.click(utils_1.screen.getByLabelText('Add Items'));
|
|
885
|
+
yield expandCollapsable();
|
|
744
886
|
// Fill in the fields
|
|
745
887
|
const itemNames = utils_1.screen.getAllByLabelText('Item Name');
|
|
746
888
|
const quantities = utils_1.screen.getAllByLabelText('Quantity');
|
|
@@ -798,7 +940,7 @@ describe('AkiformBuilder', () => {
|
|
|
798
940
|
expect(utils_1.screen.getByLabelText('Checkbox')).toBeInTheDocument();
|
|
799
941
|
expect(utils_1.screen.getByLabelText('Date')).toBeInTheDocument();
|
|
800
942
|
expect(utils_1.screen.getByLabelText('Textarea')).toBeInTheDocument();
|
|
801
|
-
expect(utils_1.screen.
|
|
943
|
+
expect(utils_1.screen.getByTestId('fieldArray-add-button')).toBeInTheDocument(); // For field array
|
|
802
944
|
expect(utils_1.screen.getByTestId('custom-field')).toBeInTheDocument();
|
|
803
945
|
}));
|
|
804
946
|
it('handles form with inline layout', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -827,6 +969,8 @@ describe('AkiformBuilder', () => {
|
|
|
827
969
|
.label('Name')
|
|
828
970
|
.type('text')
|
|
829
971
|
.placeholder('Enter your name')
|
|
972
|
+
.help('Help text')
|
|
973
|
+
.labelDescription('Label description text')
|
|
830
974
|
.build(),
|
|
831
975
|
(0, field_builder_1.field)()
|
|
832
976
|
.key('age')
|
|
@@ -854,7 +998,9 @@ describe('AkiformBuilder', () => {
|
|
|
854
998
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
855
999
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
856
1000
|
}));
|
|
857
|
-
expect(utils_1.screen.
|
|
1001
|
+
expect(utils_1.screen.getByText('Name')).toBeInTheDocument();
|
|
1002
|
+
expect(utils_1.screen.getByText('Label description text')).toBeInTheDocument();
|
|
1003
|
+
expect(utils_1.screen.getByText('Help text')).toBeInTheDocument();
|
|
858
1004
|
expect(utils_1.screen.getByLabelText('Age')).toBeInTheDocument();
|
|
859
1005
|
expect(utils_1.screen.getByLabelText('Country')).toBeInTheDocument();
|
|
860
1006
|
expect(utils_1.screen.getByLabelText('Subscribe to newsletter')).toBeInTheDocument();
|
|
@@ -881,10 +1027,10 @@ describe('AkiformBuilder', () => {
|
|
|
881
1027
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: onSubmitMock }));
|
|
882
1028
|
}));
|
|
883
1029
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
884
|
-
utils_1.fireEvent.change(utils_1.screen.
|
|
1030
|
+
utils_1.fireEvent.change(utils_1.screen.getByRole('textbox', { name: /name/i }), {
|
|
885
1031
|
target: { value: 'John Doe' }
|
|
886
1032
|
});
|
|
887
|
-
utils_1.fireEvent.change(utils_1.screen.
|
|
1033
|
+
utils_1.fireEvent.change(utils_1.screen.getByRole('spinbutton', { name: /age/i }), {
|
|
888
1034
|
target: { value: '25' }
|
|
889
1035
|
});
|
|
890
1036
|
utils_1.fireEvent.submit(utils_1.screen.getByTestId('akiform-builder'));
|
|
@@ -903,6 +1049,8 @@ describe('AkiformBuilder', () => {
|
|
|
903
1049
|
.key('customField')
|
|
904
1050
|
.label('Custom Field')
|
|
905
1051
|
.type('custom')
|
|
1052
|
+
.help('Help text')
|
|
1053
|
+
.labelDescription('Label description text')
|
|
906
1054
|
.render(({ field }) => React.createElement(CustomComponent, { field: field }))
|
|
907
1055
|
.build()
|
|
908
1056
|
];
|
|
@@ -910,15 +1058,25 @@ describe('AkiformBuilder', () => {
|
|
|
910
1058
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
911
1059
|
}));
|
|
912
1060
|
expect(utils_1.screen.getByTestId('custom-field')).toHaveTextContent('Custom Field');
|
|
1061
|
+
expect(utils_1.screen.getByText('Help text')).toBeInTheDocument();
|
|
1062
|
+
expect(utils_1.screen.getByText('Label description text')).toBeInTheDocument();
|
|
913
1063
|
}));
|
|
914
1064
|
it('handles form with field array created by FieldBuilder', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1065
|
+
const user = utils_1.userEvent.setup();
|
|
915
1066
|
const fields = [
|
|
916
1067
|
(0, field_builder_1.field)()
|
|
917
1068
|
.key('addresses')
|
|
918
1069
|
.label('Addresses')
|
|
919
1070
|
.type('fieldArray')
|
|
920
1071
|
.fields([
|
|
921
|
-
(0, field_builder_1.field)()
|
|
1072
|
+
(0, field_builder_1.field)()
|
|
1073
|
+
.key('street')
|
|
1074
|
+
.label('Street')
|
|
1075
|
+
.type('text')
|
|
1076
|
+
.help('Help text')
|
|
1077
|
+
.labelDescription('Label description text')
|
|
1078
|
+
.placeholder('Enter your street')
|
|
1079
|
+
.build(),
|
|
922
1080
|
(0, field_builder_1.field)().key('city').label('City').type('text').build()
|
|
923
1081
|
])
|
|
924
1082
|
.build()
|
|
@@ -928,12 +1086,16 @@ describe('AkiformBuilder', () => {
|
|
|
928
1086
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: onSubmitMock }));
|
|
929
1087
|
}));
|
|
930
1088
|
// Add an address
|
|
931
|
-
yield (
|
|
932
|
-
|
|
933
|
-
|
|
1089
|
+
yield user.click(utils_1.screen.getByTestId('addresses-add-button'));
|
|
1090
|
+
yield expandCollapsable();
|
|
1091
|
+
//Check rendered fields
|
|
1092
|
+
expect(utils_1.screen.getByText('Street')).toBeInTheDocument();
|
|
1093
|
+
expect(utils_1.screen.getByText('Help text')).toBeInTheDocument();
|
|
1094
|
+
expect(utils_1.screen.getByText('Label description text')).toBeInTheDocument();
|
|
1095
|
+
expect(utils_1.screen.getByLabelText('City')).toBeInTheDocument();
|
|
934
1096
|
// Fill in the fields
|
|
935
1097
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
936
|
-
utils_1.fireEvent.change(utils_1.screen.
|
|
1098
|
+
utils_1.fireEvent.change(utils_1.screen.getByPlaceholderText('Enter your street'), {
|
|
937
1099
|
target: { value: '123 Main St' }
|
|
938
1100
|
});
|
|
939
1101
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('City'), {
|
|
@@ -1000,10 +1162,10 @@ describe('AkiformBuilder', () => {
|
|
|
1000
1162
|
}));
|
|
1001
1163
|
const form = utils_1.screen.getByRole('form');
|
|
1002
1164
|
expect(form).toHaveAttribute('aria-label', 'Form');
|
|
1003
|
-
const nameInput = utils_1.screen.
|
|
1165
|
+
const nameInput = utils_1.screen.getByRole('textbox', { name: /name/i });
|
|
1004
1166
|
expect(nameInput).toHaveAttribute('aria-required', 'true');
|
|
1005
1167
|
expect(nameInput).toHaveAttribute('aria-invalid', 'false');
|
|
1006
|
-
const ageInput = utils_1.screen.
|
|
1168
|
+
const ageInput = utils_1.screen.getByRole('spinbutton', { name: /age/i });
|
|
1007
1169
|
expect(ageInput).toHaveAttribute('aria-required', 'false');
|
|
1008
1170
|
expect(ageInput).toHaveAttribute('aria-invalid', 'false');
|
|
1009
1171
|
}));
|
|
@@ -1019,7 +1181,7 @@ describe('AkiformBuilder', () => {
|
|
|
1019
1181
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
1020
1182
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
1021
1183
|
}));
|
|
1022
|
-
const nameInput = utils_1.screen.
|
|
1184
|
+
const nameInput = utils_1.screen.getByRole('textbox', { name: /name/i });
|
|
1023
1185
|
expect(nameInput).toHaveAttribute('aria-invalid', 'false');
|
|
1024
1186
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
1025
1187
|
utils_1.fireEvent.submit(utils_1.screen.getByRole('form'));
|
|
@@ -1030,6 +1192,7 @@ describe('AkiformBuilder', () => {
|
|
|
1030
1192
|
});
|
|
1031
1193
|
}));
|
|
1032
1194
|
it('renders field array with proper ARIA attributes', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1195
|
+
const user = utils_1.userEvent.setup();
|
|
1033
1196
|
const fields = [
|
|
1034
1197
|
{
|
|
1035
1198
|
key: 'addresses',
|
|
@@ -1044,16 +1207,15 @@ describe('AkiformBuilder', () => {
|
|
|
1044
1207
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
1045
1208
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
1046
1209
|
}));
|
|
1210
|
+
yield user.click(utils_1.screen.getByTestId('addresses-add-button'));
|
|
1211
|
+
yield expandCollapsable();
|
|
1047
1212
|
const fieldArrayGroup = utils_1.screen.getByRole('group', { name: 'Addresses' });
|
|
1048
1213
|
expect(fieldArrayGroup).toBeInTheDocument();
|
|
1049
|
-
const addButton = utils_1.screen.
|
|
1214
|
+
const addButton = utils_1.screen.getByLabelText('Add Addresses');
|
|
1050
1215
|
expect(addButton).toBeInTheDocument();
|
|
1051
|
-
yield
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
const removeButton = utils_1.screen.getByRole('button', {
|
|
1055
|
-
name: 'Remove Addresses 1'
|
|
1056
|
-
});
|
|
1216
|
+
yield user.click(addButton);
|
|
1217
|
+
yield expandCollapsable();
|
|
1218
|
+
const removeButton = utils_1.screen.getAllByLabelText('Remove Addresses')[1];
|
|
1057
1219
|
expect(removeButton).toBeInTheDocument();
|
|
1058
1220
|
}));
|
|
1059
1221
|
it('supports keyboard navigation', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -1087,15 +1249,24 @@ describe('AkiformBuilder', () => {
|
|
|
1087
1249
|
.label('Personal Information')
|
|
1088
1250
|
.type('section')
|
|
1089
1251
|
.fields([
|
|
1090
|
-
(0, field_builder_1.field)()
|
|
1252
|
+
(0, field_builder_1.field)()
|
|
1253
|
+
.key('name')
|
|
1254
|
+
.label('Name')
|
|
1255
|
+
.type('text')
|
|
1256
|
+
.help('Help text')
|
|
1257
|
+
.labelDescription('Label description text')
|
|
1258
|
+
.build(),
|
|
1091
1259
|
(0, field_builder_1.field)().key('age').label('Age').type('number').build()
|
|
1092
1260
|
])
|
|
1261
|
+
.collapsible(true)
|
|
1093
1262
|
.defaultExpanded(true)
|
|
1094
1263
|
.build(),
|
|
1095
1264
|
(0, field_builder_1.field)()
|
|
1096
1265
|
.key('contactInfo')
|
|
1097
1266
|
.label('Contact Information')
|
|
1098
1267
|
.type('section')
|
|
1268
|
+
.collapsible(true)
|
|
1269
|
+
.defaultExpanded(false)
|
|
1099
1270
|
.fields([
|
|
1100
1271
|
(0, field_builder_1.field)().key('email').label('Email').type('text').build(),
|
|
1101
1272
|
(0, field_builder_1.field)().key('phone').label('Phone').type('text').build()
|
|
@@ -1107,10 +1278,12 @@ describe('AkiformBuilder', () => {
|
|
|
1107
1278
|
}));
|
|
1108
1279
|
expect(utils_1.screen.getByText('Personal Information')).toBeInTheDocument();
|
|
1109
1280
|
expect(utils_1.screen.getByText('Contact Information')).toBeInTheDocument();
|
|
1110
|
-
expect(utils_1.screen.
|
|
1281
|
+
expect(utils_1.screen.getByText('Name')).toBeInTheDocument();
|
|
1282
|
+
expect(utils_1.screen.getByText('Help text')).toBeInTheDocument();
|
|
1283
|
+
expect(utils_1.screen.getByText('Label description text')).toBeInTheDocument();
|
|
1111
1284
|
expect(utils_1.screen.getByLabelText('Age')).toBeInTheDocument();
|
|
1112
1285
|
// Check if the first section is expanded by default
|
|
1113
|
-
expect(utils_1.screen.
|
|
1286
|
+
expect(utils_1.screen.getByText('Name').closest('label')).toBeVisible();
|
|
1114
1287
|
// Check if the second section is collapsed by default
|
|
1115
1288
|
expect(utils_1.screen.queryByLabelText('Email')).not.toBeInTheDocument();
|
|
1116
1289
|
// Expand the second section
|
|
@@ -1166,18 +1339,19 @@ describe('AkiformBuilder', () => {
|
|
|
1166
1339
|
delay: 1
|
|
1167
1340
|
});
|
|
1168
1341
|
// Wait for submit button to become interactable
|
|
1342
|
+
const submitButton = utils_1.screen.getByRole('button', { name: /submit/i });
|
|
1169
1343
|
yield (0, utils_1.waitFor)(() => {
|
|
1170
|
-
expect(
|
|
1344
|
+
expect(submitButton).toBeEnabled();
|
|
1171
1345
|
});
|
|
1172
1346
|
// Submit the form
|
|
1173
|
-
yield utils_1.userEvent.click(
|
|
1347
|
+
yield utils_1.userEvent.click(submitButton);
|
|
1174
1348
|
// Validate submission
|
|
1175
1349
|
expect(onSubmitMock).toHaveBeenCalledWith({
|
|
1176
1350
|
name: 'John Doe',
|
|
1177
1351
|
age: 30,
|
|
1178
1352
|
email: 'john@example.com'
|
|
1179
1353
|
}, expect.anything());
|
|
1180
|
-
})
|
|
1354
|
+
}));
|
|
1181
1355
|
it('handles conditional rendering within sections', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1182
1356
|
const fields = [
|
|
1183
1357
|
(0, field_builder_1.field)()
|
|
@@ -1214,7 +1388,7 @@ describe('AkiformBuilder', () => {
|
|
|
1214
1388
|
.key('name')
|
|
1215
1389
|
.label('Name')
|
|
1216
1390
|
.type('text')
|
|
1217
|
-
.tooltip({ title: 'Enter your full name' })
|
|
1391
|
+
.tooltip({ title: 'Enter your full name', defaultOpen: true })
|
|
1218
1392
|
.build()
|
|
1219
1393
|
];
|
|
1220
1394
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -1237,7 +1411,7 @@ describe('AkiformBuilder', () => {
|
|
|
1237
1411
|
.key('email')
|
|
1238
1412
|
.label('Email')
|
|
1239
1413
|
.type('text')
|
|
1240
|
-
.tooltip('Enter your
|
|
1414
|
+
.tooltip({ title: 'Enter your full name', defaultOpen: true })
|
|
1241
1415
|
.build()
|
|
1242
1416
|
];
|
|
1243
1417
|
yield (0, react_1.act)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -1251,7 +1425,7 @@ describe('AkiformBuilder', () => {
|
|
|
1251
1425
|
}));
|
|
1252
1426
|
// Wait for the tooltip to appear
|
|
1253
1427
|
yield (0, utils_1.waitFor)(() => {
|
|
1254
|
-
expect(utils_1.screen.getByText('Enter your
|
|
1428
|
+
expect(utils_1.screen.getByText('Enter your full name')).toBeInTheDocument();
|
|
1255
1429
|
});
|
|
1256
1430
|
}));
|
|
1257
1431
|
});
|