@akinon/akiform-builder 1.3.4 → 1.3.5-next.1
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 +345 -354
- package/dist/cjs/constants.d.ts +14 -14
- package/dist/cjs/constants.d.ts.map +1 -1
- package/dist/cjs/constants.js +14 -15
- package/dist/cjs/field-builder.d.ts +2 -2
- package/dist/cjs/field-builder.d.ts.map +1 -1
- package/dist/cjs/src/akiform-builder.d.ts +1 -1
- package/dist/cjs/src/akiform-builder.d.ts.map +1 -1
- package/dist/cjs/src/akiform-builder.js +1 -1
- package/dist/cjs/src/field-builder.d.ts +3 -3
- package/dist/cjs/src/field-builder.d.ts.map +1 -1
- package/dist/cjs/src/i18n/index.d.ts +1 -4
- package/dist/cjs/src/i18n/index.d.ts.map +1 -1
- package/dist/cjs/src/types.d.ts +4 -4
- package/dist/cjs/src/types.d.ts.map +1 -1
- package/dist/cjs/types.d.ts +12 -12
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/esm/__tests__/akiform-builder.test.js +345 -354
- package/dist/esm/constants.d.ts +14 -14
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/constants.js +13 -14
- package/dist/esm/field-builder.d.ts +2 -2
- package/dist/esm/field-builder.d.ts.map +1 -1
- package/dist/esm/src/akiform-builder.d.ts +1 -1
- package/dist/esm/src/akiform-builder.d.ts.map +1 -1
- package/dist/esm/src/akiform-builder.js +1 -1
- package/dist/esm/src/field-builder.d.ts +3 -3
- package/dist/esm/src/field-builder.d.ts.map +1 -1
- package/dist/esm/src/i18n/index.d.ts +1 -4
- package/dist/esm/src/i18n/index.d.ts.map +1 -1
- package/dist/esm/src/types.d.ts +4 -4
- package/dist/esm/src/types.d.ts.map +1 -1
- package/dist/esm/types.d.ts +12 -12
- package/dist/esm/types.d.ts.map +1 -1
- package/package.json +17 -17
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
13
4
|
const akiform_1 = require("@akinon/akiform");
|
|
@@ -21,13 +12,13 @@ describe('AkiformBuilder', () => {
|
|
|
21
12
|
const mockOnSubmit = vi.fn();
|
|
22
13
|
const mockOnReset = vi.fn();
|
|
23
14
|
const mockOnValueChange = vi.fn();
|
|
24
|
-
const expandCollapsable = () =>
|
|
15
|
+
const expandCollapsable = async () => {
|
|
25
16
|
const user = utils_1.userEvent.setup();
|
|
26
|
-
const expandIcons = (
|
|
17
|
+
const expandIcons = (await utils_1.screen.findAllByRole('button')).filter(el => el.className.includes('akinon-collapse-expand-icon'));
|
|
27
18
|
for (const expandIcon of expandIcons) {
|
|
28
|
-
|
|
19
|
+
await user.click(expandIcon);
|
|
29
20
|
}
|
|
30
|
-
}
|
|
21
|
+
};
|
|
31
22
|
const defaultFields = [
|
|
32
23
|
{
|
|
33
24
|
key: 'name',
|
|
@@ -47,11 +38,11 @@ describe('AkiformBuilder', () => {
|
|
|
47
38
|
vi.clearAllMocks();
|
|
48
39
|
});
|
|
49
40
|
describe('AkiformBuilder in uncontrolled mode', () => {
|
|
50
|
-
it('renders form fields correctly', () =>
|
|
41
|
+
it('renders form fields correctly', async () => {
|
|
51
42
|
const newDefaultFields = defaultFields.map((field, key) => (Object.assign(Object.assign({}, field), { help: `Description text ${key}`, labelDescription: `Label description text ${key}` })));
|
|
52
|
-
|
|
43
|
+
await (0, react_1.act)(async () => {
|
|
53
44
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: newDefaultFields, onSubmit: mockOnSubmit }));
|
|
54
|
-
})
|
|
45
|
+
});
|
|
55
46
|
for (const field of newDefaultFields) {
|
|
56
47
|
if (field.label) {
|
|
57
48
|
expect(utils_1.screen.getByText(field.label)).toBeInTheDocument();
|
|
@@ -62,8 +53,8 @@ describe('AkiformBuilder', () => {
|
|
|
62
53
|
expect(utils_1.screen.getByText(field.help)).toBeInTheDocument();
|
|
63
54
|
expect(utils_1.screen.getByText(field.labelDescription)).toBeInTheDocument();
|
|
64
55
|
}
|
|
65
|
-
})
|
|
66
|
-
it('renders form fields correctly with row and column fields', () =>
|
|
56
|
+
});
|
|
57
|
+
it('renders form fields correctly with row and column fields', async () => {
|
|
67
58
|
const newDefaultFields = [
|
|
68
59
|
{
|
|
69
60
|
type: 'row',
|
|
@@ -129,9 +120,9 @@ describe('AkiformBuilder', () => {
|
|
|
129
120
|
]
|
|
130
121
|
}
|
|
131
122
|
];
|
|
132
|
-
|
|
123
|
+
await (0, react_1.act)(async () => {
|
|
133
124
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: newDefaultFields, onSubmit: mockOnSubmit }));
|
|
134
|
-
})
|
|
125
|
+
});
|
|
135
126
|
// Check fields
|
|
136
127
|
expect(utils_1.screen.getByLabelText('Test Field 1')).toBeInTheDocument();
|
|
137
128
|
expect(utils_1.screen.getByLabelText('Test Field 2')).toBeInTheDocument();
|
|
@@ -142,8 +133,8 @@ describe('AkiformBuilder', () => {
|
|
|
142
133
|
// Check props
|
|
143
134
|
expect(document.querySelector('.akinon-row-middle')).toBeInTheDocument();
|
|
144
135
|
expect(document.querySelector('.akinon-col-24')).toBeInTheDocument();
|
|
145
|
-
})
|
|
146
|
-
it('handles form with custom field and onChange', () =>
|
|
136
|
+
});
|
|
137
|
+
it('handles form with custom field and onChange', async () => {
|
|
147
138
|
const CustomComponent = ({ field, control }) => {
|
|
148
139
|
const { field: controllerField } = (0, akiform_1.useController)({
|
|
149
140
|
name: field.key,
|
|
@@ -160,25 +151,25 @@ describe('AkiformBuilder', () => {
|
|
|
160
151
|
}
|
|
161
152
|
];
|
|
162
153
|
const onValueChangeMock = vi.fn();
|
|
163
|
-
|
|
154
|
+
await (0, react_1.act)(async () => {
|
|
164
155
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: mockOnSubmit, onValueChange: onValueChangeMock }));
|
|
165
|
-
})
|
|
156
|
+
});
|
|
166
157
|
const customInput = utils_1.screen.getByTestId('custom-input');
|
|
167
158
|
expect(customInput).toBeInTheDocument();
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
})
|
|
171
|
-
|
|
159
|
+
await (0, react_1.act)(async () => {
|
|
160
|
+
await utils_1.userEvent.type(customInput, 'test value');
|
|
161
|
+
});
|
|
162
|
+
await (0, utils_1.waitFor)(() => {
|
|
172
163
|
expect(onValueChangeMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
173
164
|
customField: 'test value'
|
|
174
165
|
}));
|
|
175
166
|
});
|
|
176
|
-
})
|
|
177
|
-
it('resets form when reset button is clicked', () =>
|
|
178
|
-
|
|
167
|
+
});
|
|
168
|
+
it('resets form when reset button is clicked', async () => {
|
|
169
|
+
await (0, react_1.act)(async () => {
|
|
179
170
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: defaultFields, onSubmit: mockOnSubmit, onReset: mockOnReset, showResetButton: true }));
|
|
180
|
-
})
|
|
181
|
-
|
|
171
|
+
});
|
|
172
|
+
await (0, react_1.act)(async () => {
|
|
182
173
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Name'), {
|
|
183
174
|
target: { value: 'John Doe' }
|
|
184
175
|
});
|
|
@@ -186,82 +177,82 @@ describe('AkiformBuilder', () => {
|
|
|
186
177
|
target: { value: '30' }
|
|
187
178
|
});
|
|
188
179
|
utils_1.fireEvent.click(utils_1.screen.getByText('RESET'));
|
|
189
|
-
})
|
|
190
|
-
|
|
180
|
+
});
|
|
181
|
+
await (0, utils_1.waitFor)(() => {
|
|
191
182
|
expect(mockOnReset).toHaveBeenCalled();
|
|
192
183
|
expect(utils_1.screen.getByLabelText('Name')).toHaveValue('');
|
|
193
184
|
expect(utils_1.screen.getByLabelText('Age')).toHaveValue('');
|
|
194
185
|
});
|
|
195
|
-
})
|
|
196
|
-
it('exposes reset method through ref', () =>
|
|
186
|
+
});
|
|
187
|
+
it('exposes reset method through ref', async () => {
|
|
197
188
|
const ref = React.createRef();
|
|
198
189
|
const onResetMock = vi.fn();
|
|
199
|
-
|
|
190
|
+
await (0, react_1.act)(async () => {
|
|
200
191
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { ref: ref, fields: defaultFields, onSubmit: mockOnSubmit, onReset: onResetMock }));
|
|
201
|
-
})
|
|
192
|
+
});
|
|
202
193
|
// Fill in some values
|
|
203
|
-
|
|
194
|
+
await (0, react_1.act)(async () => {
|
|
204
195
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Name'), {
|
|
205
196
|
target: { value: 'John Doe' }
|
|
206
197
|
});
|
|
207
|
-
})
|
|
198
|
+
});
|
|
208
199
|
// Call reset through ref
|
|
209
|
-
|
|
200
|
+
await (0, react_1.act)(async () => {
|
|
210
201
|
var _a;
|
|
211
202
|
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.reset();
|
|
212
|
-
})
|
|
203
|
+
});
|
|
213
204
|
// Check if form is reset and onReset is called
|
|
214
205
|
expect(utils_1.screen.getByLabelText('Name')).toHaveValue('');
|
|
215
206
|
expect(onResetMock).toHaveBeenCalled();
|
|
216
207
|
// Test partial reset
|
|
217
|
-
|
|
208
|
+
await (0, react_1.act)(async () => {
|
|
218
209
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Name'), {
|
|
219
210
|
target: { value: 'John Doe' }
|
|
220
211
|
});
|
|
221
212
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Age'), {
|
|
222
213
|
target: { value: '30' }
|
|
223
214
|
});
|
|
224
|
-
})
|
|
225
|
-
|
|
215
|
+
});
|
|
216
|
+
await (0, react_1.act)(async () => {
|
|
226
217
|
var _a;
|
|
227
218
|
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.reset({ name: 'Jane Doe' });
|
|
228
|
-
})
|
|
219
|
+
});
|
|
229
220
|
expect(utils_1.screen.getByLabelText('Name')).toHaveValue('Jane Doe');
|
|
230
221
|
expect(utils_1.screen.getByLabelText('Age')).toHaveValue('30');
|
|
231
|
-
})
|
|
232
|
-
it('calls onValueChange when form values change in uncontrolled mode', () =>
|
|
233
|
-
|
|
222
|
+
});
|
|
223
|
+
it('calls onValueChange when form values change in uncontrolled mode', async () => {
|
|
224
|
+
await (0, react_1.act)(async () => {
|
|
234
225
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: defaultFields, onSubmit: mockOnSubmit, onValueChange: mockOnValueChange }));
|
|
235
|
-
})
|
|
236
|
-
|
|
226
|
+
});
|
|
227
|
+
await (0, react_1.act)(async () => {
|
|
237
228
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Name'), {
|
|
238
229
|
target: { value: 'John Doe' }
|
|
239
230
|
});
|
|
240
|
-
})
|
|
241
|
-
|
|
231
|
+
});
|
|
232
|
+
await (0, utils_1.waitFor)(() => {
|
|
242
233
|
expect(mockOnValueChange).toHaveBeenCalledWith(expect.objectContaining({
|
|
243
234
|
name: 'John Doe'
|
|
244
235
|
}));
|
|
245
236
|
});
|
|
246
|
-
})
|
|
247
|
-
it('applies throttling in uncontrolled mode', () =>
|
|
237
|
+
});
|
|
238
|
+
it('applies throttling in uncontrolled mode', async () => {
|
|
248
239
|
vi.useFakeTimers();
|
|
249
|
-
|
|
240
|
+
await (0, react_1.act)(async () => {
|
|
250
241
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: defaultFields, onSubmit: mockOnSubmit, onValueChange: mockOnValueChange }));
|
|
251
|
-
})
|
|
252
|
-
|
|
242
|
+
});
|
|
243
|
+
await (0, react_1.act)(async () => {
|
|
253
244
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Name'), {
|
|
254
245
|
target: { value: 'John Doe' }
|
|
255
246
|
});
|
|
256
|
-
})
|
|
247
|
+
});
|
|
257
248
|
expect(mockOnValueChange).not.toHaveBeenCalled();
|
|
258
|
-
|
|
249
|
+
await (0, react_1.act)(async () => {
|
|
259
250
|
vi.advanceTimersByTime(akiform_builder_1.THROTTLE_DELAY);
|
|
260
|
-
})
|
|
251
|
+
});
|
|
261
252
|
expect(mockOnValueChange).toHaveBeenCalledWith(expect.objectContaining({ name: 'John Doe' }));
|
|
262
253
|
vi.useRealTimers();
|
|
263
|
-
})
|
|
264
|
-
it('renders different field types correctly', () =>
|
|
254
|
+
});
|
|
255
|
+
it('renders different field types correctly', async () => {
|
|
265
256
|
const fields = [
|
|
266
257
|
{
|
|
267
258
|
key: 'name',
|
|
@@ -285,9 +276,9 @@ describe('AkiformBuilder', () => {
|
|
|
285
276
|
{ key: 'birthdate', label: 'Birth Date', type: 'date' },
|
|
286
277
|
{ key: 'bio', label: 'Biography', type: 'textarea' }
|
|
287
278
|
];
|
|
288
|
-
|
|
279
|
+
await (0, react_1.act)(async () => {
|
|
289
280
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: mockOnSubmit }));
|
|
290
|
-
})
|
|
281
|
+
});
|
|
291
282
|
expect(utils_1.screen.getByPlaceholderText('Enter your name')).toHaveAttribute('type', 'text');
|
|
292
283
|
expect(utils_1.screen.getByText('Help text')).toBeInTheDocument();
|
|
293
284
|
expect(utils_1.screen.getByText('Label description text')).toBeInTheDocument();
|
|
@@ -296,8 +287,8 @@ describe('AkiformBuilder', () => {
|
|
|
296
287
|
expect(utils_1.screen.getByLabelText('Subscribe')).toHaveAttribute('type', 'checkbox');
|
|
297
288
|
expect(utils_1.screen.getByLabelText('Birth Date')).toBeInTheDocument();
|
|
298
289
|
expect(utils_1.screen.getByLabelText('Biography')).toBeInTheDocument();
|
|
299
|
-
})
|
|
300
|
-
it('renders field array correctly', () =>
|
|
290
|
+
});
|
|
291
|
+
it('renders field array correctly', async () => {
|
|
301
292
|
const user = utils_1.userEvent.setup();
|
|
302
293
|
const fields = [
|
|
303
294
|
(0, field_builder_1.field)()
|
|
@@ -317,18 +308,18 @@ describe('AkiformBuilder', () => {
|
|
|
317
308
|
])
|
|
318
309
|
.build()
|
|
319
310
|
];
|
|
320
|
-
|
|
311
|
+
await (0, react_1.act)(async () => {
|
|
321
312
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: mockOnSubmit }));
|
|
322
|
-
})
|
|
313
|
+
});
|
|
323
314
|
expect(utils_1.screen.getByText('Add Addresses')).toBeInTheDocument();
|
|
324
|
-
|
|
325
|
-
|
|
315
|
+
await user.click(utils_1.screen.getByTestId('addresses-add-button'));
|
|
316
|
+
await expandCollapsable();
|
|
326
317
|
expect(utils_1.screen.getAllByText('Street')).toHaveLength(1);
|
|
327
318
|
expect(utils_1.screen.getAllByText('City')).toHaveLength(1);
|
|
328
319
|
expect(utils_1.screen.getByText('Help text')).toBeInTheDocument();
|
|
329
320
|
expect(utils_1.screen.getByText('Label description text')).toBeInTheDocument();
|
|
330
|
-
})
|
|
331
|
-
it('handles form with field array and nested validation', () =>
|
|
321
|
+
});
|
|
322
|
+
it('handles form with field array and nested validation', async () => {
|
|
332
323
|
const user = utils_1.userEvent.setup();
|
|
333
324
|
const fields = [
|
|
334
325
|
{
|
|
@@ -352,40 +343,40 @@ describe('AkiformBuilder', () => {
|
|
|
352
343
|
}
|
|
353
344
|
];
|
|
354
345
|
const onSubmitMock = vi.fn();
|
|
355
|
-
|
|
346
|
+
await (0, react_1.act)(async () => {
|
|
356
347
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: onSubmitMock }));
|
|
357
|
-
})
|
|
348
|
+
});
|
|
358
349
|
// Add an item
|
|
359
|
-
|
|
350
|
+
await user.click(utils_1.screen.getByTestId('items-add-button'));
|
|
360
351
|
// Try to submit without filling required fields
|
|
361
|
-
|
|
352
|
+
await (0, react_1.act)(async () => {
|
|
362
353
|
utils_1.fireEvent.submit(utils_1.screen.getByTestId('akiform-builder'));
|
|
363
|
-
})
|
|
364
|
-
|
|
354
|
+
});
|
|
355
|
+
await (0, utils_1.waitFor)(() => {
|
|
365
356
|
expect(utils_1.screen.getByText('An error occurred in here')).toBeInTheDocument();
|
|
366
357
|
expect(onSubmitMock).not.toHaveBeenCalled();
|
|
367
358
|
});
|
|
368
|
-
|
|
359
|
+
await expandCollapsable();
|
|
369
360
|
// Fill in valid data
|
|
370
|
-
|
|
361
|
+
await (0, react_1.act)(async () => {
|
|
371
362
|
const nameInput = utils_1.screen.getByRole('textbox', { name: /item name/i });
|
|
372
363
|
const quantityInput = utils_1.screen.getByRole('spinbutton', {
|
|
373
364
|
name: /quantity/i
|
|
374
365
|
});
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
})
|
|
366
|
+
await utils_1.userEvent.type(nameInput, 'Test Item');
|
|
367
|
+
await utils_1.userEvent.type(quantityInput, '2');
|
|
368
|
+
});
|
|
378
369
|
// Submit the form
|
|
379
|
-
|
|
370
|
+
await (0, react_1.act)(async () => {
|
|
380
371
|
utils_1.fireEvent.submit(utils_1.screen.getByTestId('akiform-builder'));
|
|
381
|
-
})
|
|
382
|
-
|
|
372
|
+
});
|
|
373
|
+
await (0, utils_1.waitFor)(() => {
|
|
383
374
|
expect(onSubmitMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
384
375
|
items: [{ name: 'Test Item', quantity: 2 }]
|
|
385
376
|
}), expect.anything());
|
|
386
377
|
});
|
|
387
|
-
})
|
|
388
|
-
it('handles field array operations correctly', () =>
|
|
378
|
+
});
|
|
379
|
+
it('handles field array operations correctly', async () => {
|
|
389
380
|
const user = utils_1.userEvent.setup();
|
|
390
381
|
const fields = [
|
|
391
382
|
{
|
|
@@ -406,25 +397,25 @@ describe('AkiformBuilder', () => {
|
|
|
406
397
|
} }),
|
|
407
398
|
React.createElement("div", { "data-testid": "form-values" }, JSON.stringify(formValues))));
|
|
408
399
|
};
|
|
409
|
-
|
|
400
|
+
await (0, react_1.act)(async () => {
|
|
410
401
|
(0, utils_1.render)(React.createElement(TestComponent, null));
|
|
411
|
-
})
|
|
402
|
+
});
|
|
412
403
|
// Add an item
|
|
413
|
-
|
|
414
|
-
|
|
404
|
+
await user.click(utils_1.screen.getByTestId('items-add-button'));
|
|
405
|
+
await expandCollapsable();
|
|
415
406
|
// Fill in the fields
|
|
416
|
-
|
|
407
|
+
await (0, react_1.act)(async () => {
|
|
417
408
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Item Name'), {
|
|
418
409
|
target: { value: 'Test Item' }
|
|
419
410
|
});
|
|
420
|
-
})
|
|
421
|
-
|
|
411
|
+
});
|
|
412
|
+
await (0, react_1.act)(async () => {
|
|
422
413
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Quantity'), {
|
|
423
414
|
target: { value: '5' }
|
|
424
415
|
});
|
|
425
|
-
})
|
|
416
|
+
});
|
|
426
417
|
// Wait for the form values to update
|
|
427
|
-
|
|
418
|
+
await (0, utils_1.waitFor)(() => {
|
|
428
419
|
const formValuesElement = utils_1.screen.getByTestId('form-values');
|
|
429
420
|
const formValues = JSON.parse(formValuesElement.textContent || '{}');
|
|
430
421
|
expect(formValues).toEqual(expect.objectContaining({
|
|
@@ -432,24 +423,24 @@ describe('AkiformBuilder', () => {
|
|
|
432
423
|
}));
|
|
433
424
|
});
|
|
434
425
|
// Submit the form
|
|
435
|
-
|
|
426
|
+
await (0, react_1.act)(async () => {
|
|
436
427
|
utils_1.fireEvent.submit(utils_1.screen.getByTestId('akiform-builder'));
|
|
437
|
-
})
|
|
428
|
+
});
|
|
438
429
|
// Check the submitted values
|
|
439
|
-
|
|
430
|
+
await (0, utils_1.waitFor)(() => {
|
|
440
431
|
expect(mockOnSubmit).toHaveBeenCalledWith(expect.objectContaining({
|
|
441
432
|
items: [{ name: 'Test Item', quantity: 5 }]
|
|
442
433
|
}), expect.anything());
|
|
443
434
|
});
|
|
444
|
-
})
|
|
445
|
-
it('applies layout options correctly', () =>
|
|
446
|
-
|
|
435
|
+
});
|
|
436
|
+
it('applies layout options correctly', async () => {
|
|
437
|
+
await (0, react_1.act)(async () => {
|
|
447
438
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: defaultFields, onSubmit: mockOnSubmit, layout: "horizontal", layoutOptions: { labelCol: { span: 8 }, wrapperCol: { span: 16 } } }));
|
|
448
|
-
})
|
|
439
|
+
});
|
|
449
440
|
const form = utils_1.screen.getByTestId('akiform-builder');
|
|
450
441
|
expect(form).toHaveClass('akinon-form-horizontal');
|
|
451
|
-
})
|
|
452
|
-
it('conditionally renders and disables fields', () =>
|
|
442
|
+
});
|
|
443
|
+
it('conditionally renders and disables fields', async () => {
|
|
453
444
|
const fields = [
|
|
454
445
|
{ key: 'showField', label: 'Show Field', type: 'checkbox' },
|
|
455
446
|
{
|
|
@@ -466,21 +457,21 @@ describe('AkiformBuilder', () => {
|
|
|
466
457
|
config: { disabled: values => !values.enableField }
|
|
467
458
|
}
|
|
468
459
|
];
|
|
469
|
-
|
|
460
|
+
await (0, react_1.act)(async () => {
|
|
470
461
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: mockOnSubmit }));
|
|
471
|
-
})
|
|
462
|
+
});
|
|
472
463
|
expect(utils_1.screen.queryByLabelText('Conditional Field')).not.toBeInTheDocument();
|
|
473
|
-
|
|
464
|
+
await (0, react_1.act)(async () => {
|
|
474
465
|
utils_1.fireEvent.click(utils_1.screen.getByLabelText('Show Field'));
|
|
475
|
-
})
|
|
466
|
+
});
|
|
476
467
|
expect(utils_1.screen.getByLabelText('Conditional Field')).toBeInTheDocument();
|
|
477
468
|
expect(utils_1.screen.getByLabelText('Disableable Field')).toBeDisabled();
|
|
478
|
-
|
|
469
|
+
await (0, react_1.act)(async () => {
|
|
479
470
|
utils_1.fireEvent.click(utils_1.screen.getByLabelText('Enable Field'));
|
|
480
|
-
})
|
|
471
|
+
});
|
|
481
472
|
expect(utils_1.screen.getByLabelText('Disableable Field')).not.toBeDisabled();
|
|
482
|
-
})
|
|
483
|
-
it('applies custom validation', () =>
|
|
473
|
+
});
|
|
474
|
+
it('applies custom validation', async () => {
|
|
484
475
|
const fields = [
|
|
485
476
|
{
|
|
486
477
|
key: 'email',
|
|
@@ -489,40 +480,40 @@ describe('AkiformBuilder', () => {
|
|
|
489
480
|
validation: akival_1.akival.string().email('Invalid email format')
|
|
490
481
|
}
|
|
491
482
|
];
|
|
492
|
-
|
|
483
|
+
await (0, react_1.act)(async () => {
|
|
493
484
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: mockOnSubmit }));
|
|
494
|
-
})
|
|
495
|
-
|
|
485
|
+
});
|
|
486
|
+
await (0, react_1.act)(async () => {
|
|
496
487
|
utils_1.fireEvent.change(utils_1.screen.getByRole('textbox', { name: /email/i }), {
|
|
497
488
|
target: { value: 'invalid-email' }
|
|
498
489
|
});
|
|
499
490
|
utils_1.fireEvent.submit(utils_1.screen.getByTestId('akiform-builder'));
|
|
500
|
-
})
|
|
501
|
-
|
|
491
|
+
});
|
|
492
|
+
await (0, utils_1.waitFor)(() => {
|
|
502
493
|
expect(utils_1.screen.getByText('Invalid email format')).toBeInTheDocument();
|
|
503
494
|
});
|
|
504
|
-
})
|
|
505
|
-
it('resets form using ref', () =>
|
|
495
|
+
});
|
|
496
|
+
it('resets form using ref', async () => {
|
|
506
497
|
const ref = React.createRef();
|
|
507
|
-
|
|
498
|
+
await (0, react_1.act)(async () => {
|
|
508
499
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { ref: ref, fields: defaultFields, onSubmit: mockOnSubmit }));
|
|
509
|
-
})
|
|
510
|
-
|
|
500
|
+
});
|
|
501
|
+
await (0, react_1.act)(async () => {
|
|
511
502
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Name'), {
|
|
512
503
|
target: { value: 'John Doe' }
|
|
513
504
|
});
|
|
514
505
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Age'), {
|
|
515
506
|
target: { value: '30' }
|
|
516
507
|
});
|
|
517
|
-
})
|
|
518
|
-
|
|
508
|
+
});
|
|
509
|
+
await (0, react_1.act)(async () => {
|
|
519
510
|
var _a;
|
|
520
511
|
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.reset();
|
|
521
|
-
})
|
|
512
|
+
});
|
|
522
513
|
expect(utils_1.screen.getByLabelText('Name')).toHaveValue('');
|
|
523
514
|
expect(utils_1.screen.getByLabelText('Age')).toHaveValue('');
|
|
524
|
-
})
|
|
525
|
-
it('displays error states', () =>
|
|
515
|
+
});
|
|
516
|
+
it('displays error states', async () => {
|
|
526
517
|
const fields = [
|
|
527
518
|
{
|
|
528
519
|
key: 'name',
|
|
@@ -531,22 +522,22 @@ describe('AkiformBuilder', () => {
|
|
|
531
522
|
validation: akival_1.akival.string().required('Name is required')
|
|
532
523
|
}
|
|
533
524
|
];
|
|
534
|
-
|
|
525
|
+
await (0, react_1.act)(async () => {
|
|
535
526
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: mockOnSubmit }));
|
|
536
|
-
})
|
|
537
|
-
|
|
527
|
+
});
|
|
528
|
+
await (0, react_1.act)(async () => {
|
|
538
529
|
utils_1.fireEvent.submit(utils_1.screen.getByTestId('akiform-builder'));
|
|
539
|
-
})
|
|
540
|
-
|
|
530
|
+
});
|
|
531
|
+
await (0, utils_1.waitFor)(() => {
|
|
541
532
|
expect(utils_1.screen.getByText('Name is required')).toBeInTheDocument();
|
|
542
533
|
});
|
|
543
|
-
})
|
|
544
|
-
it('handles form submission', () =>
|
|
534
|
+
});
|
|
535
|
+
it('handles form submission', async () => {
|
|
545
536
|
const onSubmit = vi.fn();
|
|
546
|
-
|
|
537
|
+
await (0, react_1.act)(async () => {
|
|
547
538
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: defaultFields, onSubmit: onSubmit }));
|
|
548
|
-
})
|
|
549
|
-
|
|
539
|
+
});
|
|
540
|
+
await (0, react_1.act)(async () => {
|
|
550
541
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Name'), {
|
|
551
542
|
target: { value: 'John Doe' }
|
|
552
543
|
});
|
|
@@ -554,15 +545,15 @@ describe('AkiformBuilder', () => {
|
|
|
554
545
|
target: { value: '30' }
|
|
555
546
|
});
|
|
556
547
|
utils_1.fireEvent.submit(utils_1.screen.getByTestId('akiform-builder'));
|
|
557
|
-
})
|
|
558
|
-
|
|
548
|
+
});
|
|
549
|
+
await (0, utils_1.waitFor)(() => {
|
|
559
550
|
expect(onSubmit).toHaveBeenCalledWith(expect.objectContaining({
|
|
560
551
|
name: 'John Doe',
|
|
561
552
|
age: 30
|
|
562
553
|
}), expect.anything());
|
|
563
554
|
});
|
|
564
|
-
})
|
|
565
|
-
it('handles form submission with errors', () =>
|
|
555
|
+
});
|
|
556
|
+
it('handles form submission with errors', async () => {
|
|
566
557
|
const fields = [
|
|
567
558
|
{
|
|
568
559
|
key: 'name',
|
|
@@ -572,35 +563,35 @@ describe('AkiformBuilder', () => {
|
|
|
572
563
|
}
|
|
573
564
|
];
|
|
574
565
|
const onSubmit = vi.fn();
|
|
575
|
-
|
|
566
|
+
await (0, react_1.act)(async () => {
|
|
576
567
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: onSubmit }));
|
|
577
|
-
})
|
|
578
|
-
|
|
568
|
+
});
|
|
569
|
+
await (0, react_1.act)(async () => {
|
|
579
570
|
utils_1.fireEvent.submit(utils_1.screen.getByTestId('akiform-builder'));
|
|
580
|
-
})
|
|
581
|
-
|
|
571
|
+
});
|
|
572
|
+
await (0, utils_1.waitFor)(() => {
|
|
582
573
|
expect(utils_1.screen.getByText('Name is required')).toBeInTheDocument();
|
|
583
574
|
expect(onSubmit).not.toHaveBeenCalled();
|
|
584
575
|
});
|
|
585
|
-
})
|
|
586
|
-
it('handles form with initial values', () =>
|
|
576
|
+
});
|
|
577
|
+
it('handles form with initial values', async () => {
|
|
587
578
|
const initialValues = { name: 'John Doe', age: 30 };
|
|
588
|
-
|
|
579
|
+
await (0, react_1.act)(async () => {
|
|
589
580
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: defaultFields, onSubmit: mockOnSubmit, initialValues: initialValues }));
|
|
590
|
-
})
|
|
591
|
-
|
|
581
|
+
});
|
|
582
|
+
await (0, utils_1.waitFor)(() => {
|
|
592
583
|
expect(utils_1.screen.getByLabelText('Name')).toHaveValue('John Doe');
|
|
593
584
|
expect(utils_1.screen.getByLabelText('Age')).toHaveValue('30');
|
|
594
585
|
});
|
|
595
|
-
})
|
|
596
|
-
it('handles form with custom layout', () =>
|
|
597
|
-
|
|
586
|
+
});
|
|
587
|
+
it('handles form with custom layout', async () => {
|
|
588
|
+
await (0, react_1.act)(async () => {
|
|
598
589
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: defaultFields, onSubmit: mockOnSubmit, layout: "vertical" }));
|
|
599
|
-
})
|
|
590
|
+
});
|
|
600
591
|
const form = utils_1.screen.getByTestId('akiform-builder');
|
|
601
592
|
expect(form).toHaveClass('akinon-form-vertical');
|
|
602
|
-
})
|
|
603
|
-
it('renders custom field correctly', () =>
|
|
593
|
+
});
|
|
594
|
+
it('renders custom field correctly', async () => {
|
|
604
595
|
const CustomComponent = ({ field }) => (React.createElement("div", { "data-testid": "custom-field" }, field.label));
|
|
605
596
|
const fields = [
|
|
606
597
|
{
|
|
@@ -612,30 +603,30 @@ describe('AkiformBuilder', () => {
|
|
|
612
603
|
render: ({ field }) => (React.createElement(CustomComponent, { field: field }))
|
|
613
604
|
}
|
|
614
605
|
];
|
|
615
|
-
|
|
606
|
+
await (0, react_1.act)(async () => {
|
|
616
607
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
617
|
-
})
|
|
608
|
+
});
|
|
618
609
|
expect(utils_1.screen.getByTestId('custom-field')).toHaveTextContent('Custom Field');
|
|
619
610
|
expect(utils_1.screen.getByText('Help text')).toBeInTheDocument();
|
|
620
611
|
expect(utils_1.screen.getByText('Label description text')).toBeInTheDocument();
|
|
621
|
-
})
|
|
622
|
-
it('cleans up throttle timeout on unmount', () =>
|
|
612
|
+
});
|
|
613
|
+
it('cleans up throttle timeout on unmount', async () => {
|
|
623
614
|
vi.useFakeTimers();
|
|
624
615
|
const { unmount } = (0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: defaultFields, onSubmit: mockOnSubmit, onValueChange: mockOnValueChange }));
|
|
625
|
-
|
|
616
|
+
await (0, react_1.act)(async () => {
|
|
626
617
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Name'), {
|
|
627
618
|
target: { value: 'John Doe' }
|
|
628
619
|
});
|
|
629
|
-
})
|
|
620
|
+
});
|
|
630
621
|
unmount();
|
|
631
622
|
// Advance timers and ensure onValueChange is not called
|
|
632
|
-
|
|
623
|
+
await (0, react_1.act)(async () => {
|
|
633
624
|
vi.advanceTimersByTime(akiform_builder_1.THROTTLE_DELAY + 100);
|
|
634
|
-
})
|
|
625
|
+
});
|
|
635
626
|
expect(mockOnValueChange).not.toHaveBeenCalled();
|
|
636
627
|
vi.useRealTimers();
|
|
637
|
-
})
|
|
638
|
-
it('handles custom field with undefined render prop', () =>
|
|
628
|
+
});
|
|
629
|
+
it('handles custom field with undefined render prop', async () => {
|
|
639
630
|
const fields = [
|
|
640
631
|
{
|
|
641
632
|
key: 'customField',
|
|
@@ -644,15 +635,15 @@ describe('AkiformBuilder', () => {
|
|
|
644
635
|
render: undefined
|
|
645
636
|
}
|
|
646
637
|
];
|
|
647
|
-
|
|
638
|
+
await (0, react_1.act)(async () => {
|
|
648
639
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
649
|
-
})
|
|
640
|
+
});
|
|
650
641
|
// The custom field should not be rendered, but the form should not crash
|
|
651
642
|
expect(utils_1.screen.queryByLabelText('Custom Field')).not.toBeInTheDocument();
|
|
652
643
|
// The form should still be rendered
|
|
653
644
|
expect(utils_1.screen.getByTestId('akiform-builder')).toBeInTheDocument();
|
|
654
|
-
})
|
|
655
|
-
it('renders custom submit and reset button props', () =>
|
|
645
|
+
});
|
|
646
|
+
it('renders custom submit and reset button props', async () => {
|
|
656
647
|
const submitButtonProps = {
|
|
657
648
|
className: 'custom-submit-btn',
|
|
658
649
|
children: 'submit button'
|
|
@@ -661,9 +652,9 @@ describe('AkiformBuilder', () => {
|
|
|
661
652
|
className: 'custom-reset-btn',
|
|
662
653
|
children: 'reset button'
|
|
663
654
|
};
|
|
664
|
-
|
|
655
|
+
await (0, react_1.act)(async () => {
|
|
665
656
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: defaultFields, onSubmit: mockOnSubmit, showResetButton: true, onReset: mockOnReset, submitButtonProps: submitButtonProps, resetButtonProps: resetButtonProps }));
|
|
666
|
-
})
|
|
657
|
+
});
|
|
667
658
|
const submitButton = utils_1.screen
|
|
668
659
|
.getByText(submitButtonProps.children)
|
|
669
660
|
.closest('button');
|
|
@@ -674,51 +665,51 @@ describe('AkiformBuilder', () => {
|
|
|
674
665
|
expect(resetButton).toBeInTheDocument();
|
|
675
666
|
expect(submitButton).toHaveClass(submitButtonProps.className);
|
|
676
667
|
expect(resetButton).toHaveClass(resetButtonProps.className);
|
|
677
|
-
|
|
668
|
+
await utils_1.userEvent.click(resetButton);
|
|
678
669
|
expect(mockOnReset).toHaveBeenCalled();
|
|
679
|
-
|
|
670
|
+
await utils_1.userEvent.click(submitButton);
|
|
680
671
|
expect(mockOnSubmit).toHaveBeenCalled();
|
|
681
|
-
})
|
|
672
|
+
});
|
|
682
673
|
});
|
|
683
674
|
describe('AkiformBuilder in controlled mode', () => {
|
|
684
|
-
it('uses provided values in controlled mode', () =>
|
|
675
|
+
it('uses provided values in controlled mode', async () => {
|
|
685
676
|
const fields = [
|
|
686
677
|
{ key: 'name', label: 'Name', type: 'text' },
|
|
687
678
|
{ key: 'age', label: 'Age', type: 'number' }
|
|
688
679
|
];
|
|
689
680
|
const controlledValues = { name: 'John Doe', age: 30 };
|
|
690
681
|
const onChangeMock = vi.fn();
|
|
691
|
-
|
|
682
|
+
await (0, react_1.act)(async () => {
|
|
692
683
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn(), controlled: true, values: controlledValues, onValueChange: onChangeMock }));
|
|
693
|
-
})
|
|
684
|
+
});
|
|
694
685
|
expect(utils_1.screen.getByLabelText('Name')).toHaveValue('John Doe');
|
|
695
686
|
expect(utils_1.screen.getByLabelText('Age')).toHaveValue('30');
|
|
696
|
-
})
|
|
697
|
-
it('calls onValueChange when form values change in controlled mode', () =>
|
|
687
|
+
});
|
|
688
|
+
it('calls onValueChange when form values change in controlled mode', async () => {
|
|
698
689
|
const fields = [
|
|
699
690
|
{ key: 'name', label: 'Name', type: 'text' }
|
|
700
691
|
];
|
|
701
692
|
const onChangeMock = vi.fn();
|
|
702
|
-
|
|
693
|
+
await (0, react_1.act)(async () => {
|
|
703
694
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn(), controlled: true, values: { name: '' }, onValueChange: onChangeMock }));
|
|
704
|
-
})
|
|
705
|
-
|
|
695
|
+
});
|
|
696
|
+
await (0, react_1.act)(async () => {
|
|
706
697
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Name'), {
|
|
707
698
|
target: { value: 'Jane Doe' }
|
|
708
699
|
});
|
|
709
|
-
})
|
|
710
|
-
|
|
700
|
+
});
|
|
701
|
+
await (0, utils_1.waitFor)(() => {
|
|
711
702
|
expect(onChangeMock).toHaveBeenCalledWith(expect.objectContaining({ name: 'Jane Doe' }));
|
|
712
703
|
});
|
|
713
|
-
})
|
|
714
|
-
it('calls onValueChange immediately in controlled mode', () =>
|
|
704
|
+
});
|
|
705
|
+
it('calls onValueChange immediately in controlled mode', async () => {
|
|
715
706
|
const onValueChangeMock = vi.fn();
|
|
716
|
-
|
|
707
|
+
await (0, react_1.act)(async () => {
|
|
717
708
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: defaultFields, onSubmit: mockOnSubmit, controlled: true, values: { name: 'John Doe', age: 30 }, onValueChange: onValueChangeMock }));
|
|
718
|
-
})
|
|
709
|
+
});
|
|
719
710
|
expect(onValueChangeMock).toHaveBeenCalledWith(expect.objectContaining({ name: 'John Doe', age: 30 }));
|
|
720
|
-
})
|
|
721
|
-
it('handles conditional rendering and disabling of fields', () =>
|
|
711
|
+
});
|
|
712
|
+
it('handles conditional rendering and disabling of fields', async () => {
|
|
722
713
|
const fields = [
|
|
723
714
|
{ key: 'showField', label: 'Show Field', type: 'checkbox' },
|
|
724
715
|
{
|
|
@@ -736,25 +727,25 @@ describe('AkiformBuilder', () => {
|
|
|
736
727
|
}
|
|
737
728
|
];
|
|
738
729
|
const onValueChangeMock = vi.fn();
|
|
739
|
-
|
|
730
|
+
await (0, react_1.act)(async () => {
|
|
740
731
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn(), controlled: true, values: { showField: false, enableField: false }, onValueChange: onValueChangeMock }));
|
|
741
|
-
})
|
|
732
|
+
});
|
|
742
733
|
expect(utils_1.screen.queryByLabelText('Conditional Field')).not.toBeInTheDocument();
|
|
743
734
|
expect(utils_1.screen.getByLabelText('Disableable Field')).toBeDisabled();
|
|
744
|
-
|
|
735
|
+
await (0, react_1.act)(async () => {
|
|
745
736
|
utils_1.fireEvent.click(utils_1.screen.getByLabelText('Show Field'));
|
|
746
737
|
utils_1.fireEvent.click(utils_1.screen.getByLabelText('Enable Field'));
|
|
747
|
-
})
|
|
738
|
+
});
|
|
748
739
|
expect(utils_1.screen.getByLabelText('Conditional Field')).toBeInTheDocument();
|
|
749
740
|
expect(utils_1.screen.getByLabelText('Disableable Field')).not.toBeDisabled();
|
|
750
741
|
expect(onValueChangeMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
751
742
|
showField: true,
|
|
752
743
|
enableField: true
|
|
753
744
|
}));
|
|
754
|
-
})
|
|
745
|
+
});
|
|
755
746
|
});
|
|
756
747
|
describe('FieldArrayComponent', () => {
|
|
757
|
-
it('renders field array with initial values', () =>
|
|
748
|
+
it('renders field array with initial values', async () => {
|
|
758
749
|
const fields = [
|
|
759
750
|
{
|
|
760
751
|
key: 'items',
|
|
@@ -772,14 +763,14 @@ describe('AkiformBuilder', () => {
|
|
|
772
763
|
{ name: 'Item 2', quantity: 2 }
|
|
773
764
|
]
|
|
774
765
|
};
|
|
775
|
-
|
|
766
|
+
await (0, react_1.act)(async () => {
|
|
776
767
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn(), initialValues: initialValues }));
|
|
777
|
-
})
|
|
778
|
-
|
|
768
|
+
});
|
|
769
|
+
await expandCollapsable();
|
|
779
770
|
expect(utils_1.screen.getAllByLabelText('Item Name')).toHaveLength(2);
|
|
780
771
|
expect(utils_1.screen.getAllByLabelText('Quantity')).toHaveLength(2);
|
|
781
|
-
})
|
|
782
|
-
it('adds and removes field array items', () =>
|
|
772
|
+
});
|
|
773
|
+
it('adds and removes field array items', async () => {
|
|
783
774
|
const user = utils_1.userEvent.setup();
|
|
784
775
|
const fields = [
|
|
785
776
|
{
|
|
@@ -789,23 +780,23 @@ describe('AkiformBuilder', () => {
|
|
|
789
780
|
fields: [{ key: 'name', label: 'Item Name', type: 'text' }]
|
|
790
781
|
}
|
|
791
782
|
];
|
|
792
|
-
|
|
783
|
+
await (0, react_1.act)(async () => {
|
|
793
784
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
794
|
-
})
|
|
785
|
+
});
|
|
795
786
|
// Add an item
|
|
796
|
-
|
|
797
|
-
|
|
787
|
+
await user.click(utils_1.screen.getByTestId('items-add-button'));
|
|
788
|
+
await expandCollapsable();
|
|
798
789
|
expect(utils_1.screen.getByLabelText('Item Name')).toBeInTheDocument();
|
|
799
790
|
// Add another item
|
|
800
|
-
|
|
801
|
-
|
|
791
|
+
await user.click(utils_1.screen.getByLabelText('Add Items'));
|
|
792
|
+
await expandCollapsable();
|
|
802
793
|
expect(utils_1.screen.getAllByLabelText('Item Name')).toHaveLength(2);
|
|
803
794
|
// Remove an item
|
|
804
|
-
|
|
805
|
-
|
|
795
|
+
await user.click(utils_1.screen.getAllByLabelText('Remove Items')[0]);
|
|
796
|
+
await expandCollapsable();
|
|
806
797
|
expect(utils_1.screen.getAllByLabelText('Item Name')).toHaveLength(1);
|
|
807
|
-
})
|
|
808
|
-
it('handles field array with conditional fields', () =>
|
|
798
|
+
});
|
|
799
|
+
it('handles field array with conditional fields', async () => {
|
|
809
800
|
const user = utils_1.userEvent.setup();
|
|
810
801
|
const fields = [
|
|
811
802
|
{
|
|
@@ -826,28 +817,28 @@ describe('AkiformBuilder', () => {
|
|
|
826
817
|
}
|
|
827
818
|
];
|
|
828
819
|
const { rerender } = (0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
829
|
-
|
|
820
|
+
await expandCollapsable();
|
|
830
821
|
// Add an item
|
|
831
|
-
|
|
832
|
-
|
|
822
|
+
await user.click(utils_1.screen.getByLabelText('Add Items'));
|
|
823
|
+
await expandCollapsable();
|
|
833
824
|
// Description should not be visible initially
|
|
834
825
|
expect(utils_1.screen.queryByLabelText('Description')).not.toBeInTheDocument();
|
|
835
826
|
// Enter a name longer than 5 characters
|
|
836
|
-
|
|
827
|
+
await (0, react_1.act)(async () => {
|
|
837
828
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('Item Name'), {
|
|
838
829
|
target: { value: 'Long Name' }
|
|
839
830
|
});
|
|
840
|
-
})
|
|
831
|
+
});
|
|
841
832
|
// Force a re-render to trigger the conditional rendering
|
|
842
833
|
rerender(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
843
834
|
// Description should now be visible
|
|
844
|
-
|
|
835
|
+
await (0, utils_1.waitFor)(() => {
|
|
845
836
|
expect(utils_1.screen.getByLabelText('Description')).toBeInTheDocument();
|
|
846
837
|
});
|
|
847
|
-
})
|
|
838
|
+
});
|
|
848
839
|
});
|
|
849
840
|
describe('Edge cases and uncovered scenarios', () => {
|
|
850
|
-
it('handles field array with no fields', () =>
|
|
841
|
+
it('handles field array with no fields', async () => {
|
|
851
842
|
const fields = [
|
|
852
843
|
{
|
|
853
844
|
key: 'emptyFieldArray',
|
|
@@ -856,13 +847,13 @@ describe('AkiformBuilder', () => {
|
|
|
856
847
|
fields: []
|
|
857
848
|
}
|
|
858
849
|
];
|
|
859
|
-
|
|
850
|
+
await (0, react_1.act)(async () => {
|
|
860
851
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
861
|
-
})
|
|
852
|
+
});
|
|
862
853
|
// The field array should be rendered with an "Add" button
|
|
863
854
|
expect(utils_1.screen.getByTestId('emptyFieldArray-add-button')).toBeInTheDocument();
|
|
864
|
-
})
|
|
865
|
-
it('handles form submission with field array', () =>
|
|
855
|
+
});
|
|
856
|
+
it('handles form submission with field array', async () => {
|
|
866
857
|
const user = utils_1.userEvent.setup();
|
|
867
858
|
const fields = [
|
|
868
859
|
{
|
|
@@ -876,27 +867,27 @@ describe('AkiformBuilder', () => {
|
|
|
876
867
|
}
|
|
877
868
|
];
|
|
878
869
|
const onSubmitMock = vi.fn();
|
|
879
|
-
|
|
870
|
+
await (0, react_1.act)(async () => {
|
|
880
871
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: onSubmitMock }));
|
|
881
|
-
})
|
|
872
|
+
});
|
|
882
873
|
// Add two items
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
874
|
+
await user.click(utils_1.screen.getByTestId('items-add-button'));
|
|
875
|
+
await user.click(utils_1.screen.getByLabelText('Add Items'));
|
|
876
|
+
await expandCollapsable();
|
|
886
877
|
// Fill in the fields
|
|
887
878
|
const itemNames = utils_1.screen.getAllByLabelText('Item Name');
|
|
888
879
|
const quantities = utils_1.screen.getAllByLabelText('Quantity');
|
|
889
|
-
|
|
880
|
+
await (0, react_1.act)(async () => {
|
|
890
881
|
utils_1.fireEvent.change(itemNames[0], { target: { value: 'Item 1' } });
|
|
891
882
|
utils_1.fireEvent.change(quantities[0], { target: { value: '5' } });
|
|
892
883
|
utils_1.fireEvent.change(itemNames[1], { target: { value: 'Item 2' } });
|
|
893
884
|
utils_1.fireEvent.change(quantities[1], { target: { value: '10' } });
|
|
894
|
-
})
|
|
885
|
+
});
|
|
895
886
|
// Submit the form
|
|
896
|
-
|
|
887
|
+
await (0, react_1.act)(async () => {
|
|
897
888
|
utils_1.fireEvent.submit(utils_1.screen.getByTestId('akiform-builder'));
|
|
898
|
-
})
|
|
899
|
-
|
|
889
|
+
});
|
|
890
|
+
await (0, utils_1.waitFor)(() => {
|
|
900
891
|
expect(onSubmitMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
901
892
|
items: [
|
|
902
893
|
{ name: 'Item 1', quantity: 5 },
|
|
@@ -904,8 +895,8 @@ describe('AkiformBuilder', () => {
|
|
|
904
895
|
]
|
|
905
896
|
}), expect.anything());
|
|
906
897
|
});
|
|
907
|
-
})
|
|
908
|
-
it('handles form with all field types', () =>
|
|
898
|
+
});
|
|
899
|
+
it('handles form with all field types', async () => {
|
|
909
900
|
const fields = [
|
|
910
901
|
{ key: 'text', label: 'Text', type: 'text' },
|
|
911
902
|
{ key: 'number', label: 'Number', type: 'number' },
|
|
@@ -931,9 +922,9 @@ describe('AkiformBuilder', () => {
|
|
|
931
922
|
render: () => React.createElement("div", { "data-testid": "custom-field" }, "Custom Field")
|
|
932
923
|
}
|
|
933
924
|
];
|
|
934
|
-
|
|
925
|
+
await (0, react_1.act)(async () => {
|
|
935
926
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
936
|
-
})
|
|
927
|
+
});
|
|
937
928
|
expect(utils_1.screen.getByLabelText('Text')).toBeInTheDocument();
|
|
938
929
|
expect(utils_1.screen.getByLabelText('Number')).toBeInTheDocument();
|
|
939
930
|
expect(utils_1.screen.getByLabelText('Select')).toBeInTheDocument();
|
|
@@ -942,27 +933,27 @@ describe('AkiformBuilder', () => {
|
|
|
942
933
|
expect(utils_1.screen.getByLabelText('Textarea')).toBeInTheDocument();
|
|
943
934
|
expect(utils_1.screen.getByTestId('fieldArray-add-button')).toBeInTheDocument(); // For field array
|
|
944
935
|
expect(utils_1.screen.getByTestId('custom-field')).toBeInTheDocument();
|
|
945
|
-
})
|
|
946
|
-
it('handles form with inline layout', () =>
|
|
947
|
-
|
|
936
|
+
});
|
|
937
|
+
it('handles form with inline layout', async () => {
|
|
938
|
+
await (0, react_1.act)(async () => {
|
|
948
939
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: defaultFields, onSubmit: vi.fn(), layout: "inline" }));
|
|
949
|
-
})
|
|
940
|
+
});
|
|
950
941
|
const form = utils_1.screen.getByTestId('akiform-builder');
|
|
951
942
|
expect(form).toHaveClass('akinon-form-inline');
|
|
952
|
-
})
|
|
953
|
-
it('handles form reset with custom reset handler', () =>
|
|
943
|
+
});
|
|
944
|
+
it('handles form reset with custom reset handler', async () => {
|
|
954
945
|
const onResetMock = vi.fn();
|
|
955
|
-
|
|
946
|
+
await (0, react_1.act)(async () => {
|
|
956
947
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: defaultFields, onSubmit: vi.fn(), onReset: onResetMock, showResetButton: true }));
|
|
957
|
-
})
|
|
958
|
-
|
|
948
|
+
});
|
|
949
|
+
await (0, react_1.act)(async () => {
|
|
959
950
|
utils_1.fireEvent.click(utils_1.screen.getByText('RESET'));
|
|
960
|
-
})
|
|
951
|
+
});
|
|
961
952
|
expect(onResetMock).toHaveBeenCalled();
|
|
962
|
-
})
|
|
953
|
+
});
|
|
963
954
|
});
|
|
964
955
|
describe('AkiformBuilder with FieldBuilder', () => {
|
|
965
|
-
it('renders form fields created with FieldBuilder', () =>
|
|
956
|
+
it('renders form fields created with FieldBuilder', async () => {
|
|
966
957
|
const fields = [
|
|
967
958
|
(0, field_builder_1.field)()
|
|
968
959
|
.key('name')
|
|
@@ -995,9 +986,9 @@ describe('AkiformBuilder', () => {
|
|
|
995
986
|
(0, field_builder_1.field)().key('birthdate').label('Birth Date').type('date').build(),
|
|
996
987
|
(0, field_builder_1.field)().key('description').label('Description').type('textarea').build()
|
|
997
988
|
];
|
|
998
|
-
|
|
989
|
+
await (0, react_1.act)(async () => {
|
|
999
990
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
1000
|
-
})
|
|
991
|
+
});
|
|
1001
992
|
expect(utils_1.screen.getByText('Name')).toBeInTheDocument();
|
|
1002
993
|
expect(utils_1.screen.getByText('Label description text')).toBeInTheDocument();
|
|
1003
994
|
expect(utils_1.screen.getByText('Help text')).toBeInTheDocument();
|
|
@@ -1006,8 +997,8 @@ describe('AkiformBuilder', () => {
|
|
|
1006
997
|
expect(utils_1.screen.getByLabelText('Subscribe to newsletter')).toBeInTheDocument();
|
|
1007
998
|
expect(utils_1.screen.getByLabelText('Birth Date')).toBeInTheDocument();
|
|
1008
999
|
expect(utils_1.screen.getByLabelText('Description')).toBeInTheDocument();
|
|
1009
|
-
})
|
|
1010
|
-
it('handles form submission with fields created by FieldBuilder', () =>
|
|
1000
|
+
});
|
|
1001
|
+
it('handles form submission with fields created by FieldBuilder', async () => {
|
|
1011
1002
|
const fields = [
|
|
1012
1003
|
(0, field_builder_1.field)()
|
|
1013
1004
|
.key('name')
|
|
@@ -1023,10 +1014,10 @@ describe('AkiformBuilder', () => {
|
|
|
1023
1014
|
.build()
|
|
1024
1015
|
];
|
|
1025
1016
|
const onSubmitMock = vi.fn();
|
|
1026
|
-
|
|
1017
|
+
await (0, react_1.act)(async () => {
|
|
1027
1018
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: onSubmitMock }));
|
|
1028
|
-
})
|
|
1029
|
-
|
|
1019
|
+
});
|
|
1020
|
+
await (0, react_1.act)(async () => {
|
|
1030
1021
|
utils_1.fireEvent.change(utils_1.screen.getByRole('textbox', { name: /name/i }), {
|
|
1031
1022
|
target: { value: 'John Doe' }
|
|
1032
1023
|
});
|
|
@@ -1034,15 +1025,15 @@ describe('AkiformBuilder', () => {
|
|
|
1034
1025
|
target: { value: '25' }
|
|
1035
1026
|
});
|
|
1036
1027
|
utils_1.fireEvent.submit(utils_1.screen.getByTestId('akiform-builder'));
|
|
1037
|
-
})
|
|
1038
|
-
|
|
1028
|
+
});
|
|
1029
|
+
await (0, utils_1.waitFor)(() => {
|
|
1039
1030
|
expect(onSubmitMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
1040
1031
|
name: 'John Doe',
|
|
1041
1032
|
age: 25
|
|
1042
1033
|
}), expect.anything());
|
|
1043
1034
|
});
|
|
1044
|
-
})
|
|
1045
|
-
it('handles form with custom field created by FieldBuilder', () =>
|
|
1035
|
+
});
|
|
1036
|
+
it('handles form with custom field created by FieldBuilder', async () => {
|
|
1046
1037
|
const CustomComponent = ({ field }) => (React.createElement("div", { "data-testid": "custom-field" }, field.label));
|
|
1047
1038
|
const fields = [
|
|
1048
1039
|
(0, field_builder_1.field)()
|
|
@@ -1054,14 +1045,14 @@ describe('AkiformBuilder', () => {
|
|
|
1054
1045
|
.render(({ field }) => React.createElement(CustomComponent, { field: field }))
|
|
1055
1046
|
.build()
|
|
1056
1047
|
];
|
|
1057
|
-
|
|
1048
|
+
await (0, react_1.act)(async () => {
|
|
1058
1049
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
1059
|
-
})
|
|
1050
|
+
});
|
|
1060
1051
|
expect(utils_1.screen.getByTestId('custom-field')).toHaveTextContent('Custom Field');
|
|
1061
1052
|
expect(utils_1.screen.getByText('Help text')).toBeInTheDocument();
|
|
1062
1053
|
expect(utils_1.screen.getByText('Label description text')).toBeInTheDocument();
|
|
1063
|
-
})
|
|
1064
|
-
it('handles form with field array created by FieldBuilder', () =>
|
|
1054
|
+
});
|
|
1055
|
+
it('handles form with field array created by FieldBuilder', async () => {
|
|
1065
1056
|
const user = utils_1.userEvent.setup();
|
|
1066
1057
|
const fields = [
|
|
1067
1058
|
(0, field_builder_1.field)()
|
|
@@ -1082,37 +1073,37 @@ describe('AkiformBuilder', () => {
|
|
|
1082
1073
|
.build()
|
|
1083
1074
|
];
|
|
1084
1075
|
const onSubmitMock = vi.fn();
|
|
1085
|
-
|
|
1076
|
+
await (0, react_1.act)(async () => {
|
|
1086
1077
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: onSubmitMock }));
|
|
1087
|
-
})
|
|
1078
|
+
});
|
|
1088
1079
|
// Add an address
|
|
1089
|
-
|
|
1090
|
-
|
|
1080
|
+
await user.click(utils_1.screen.getByTestId('addresses-add-button'));
|
|
1081
|
+
await expandCollapsable();
|
|
1091
1082
|
//Check rendered fields
|
|
1092
1083
|
expect(utils_1.screen.getByText('Street')).toBeInTheDocument();
|
|
1093
1084
|
expect(utils_1.screen.getByText('Help text')).toBeInTheDocument();
|
|
1094
1085
|
expect(utils_1.screen.getByText('Label description text')).toBeInTheDocument();
|
|
1095
1086
|
expect(utils_1.screen.getByLabelText('City')).toBeInTheDocument();
|
|
1096
1087
|
// Fill in the fields
|
|
1097
|
-
|
|
1088
|
+
await (0, react_1.act)(async () => {
|
|
1098
1089
|
utils_1.fireEvent.change(utils_1.screen.getByPlaceholderText('Enter your street'), {
|
|
1099
1090
|
target: { value: '123 Main St' }
|
|
1100
1091
|
});
|
|
1101
1092
|
utils_1.fireEvent.change(utils_1.screen.getByLabelText('City'), {
|
|
1102
1093
|
target: { value: 'Anytown' }
|
|
1103
1094
|
});
|
|
1104
|
-
})
|
|
1095
|
+
});
|
|
1105
1096
|
// Submit the form
|
|
1106
|
-
|
|
1097
|
+
await (0, react_1.act)(async () => {
|
|
1107
1098
|
utils_1.fireEvent.submit(utils_1.screen.getByTestId('akiform-builder'));
|
|
1108
|
-
})
|
|
1109
|
-
|
|
1099
|
+
});
|
|
1100
|
+
await (0, utils_1.waitFor)(() => {
|
|
1110
1101
|
expect(onSubmitMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
1111
1102
|
addresses: [{ street: '123 Main St', city: 'Anytown' }]
|
|
1112
1103
|
}), expect.anything());
|
|
1113
1104
|
});
|
|
1114
|
-
})
|
|
1115
|
-
it('handles conditional rendering with FieldBuilder', () =>
|
|
1105
|
+
});
|
|
1106
|
+
it('handles conditional rendering with FieldBuilder', async () => {
|
|
1116
1107
|
const fields = [
|
|
1117
1108
|
(0, field_builder_1.field)().key('showField').label('Show Field').type('checkbox').build(),
|
|
1118
1109
|
(0, field_builder_1.field)()
|
|
@@ -1122,16 +1113,16 @@ describe('AkiformBuilder', () => {
|
|
|
1122
1113
|
.config({ visible: (values) => values.showField })
|
|
1123
1114
|
.build()
|
|
1124
1115
|
];
|
|
1125
|
-
|
|
1116
|
+
await (0, react_1.act)(async () => {
|
|
1126
1117
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
1127
|
-
})
|
|
1118
|
+
});
|
|
1128
1119
|
expect(utils_1.screen.queryByLabelText('Conditional Field')).not.toBeInTheDocument();
|
|
1129
|
-
|
|
1120
|
+
await (0, react_1.act)(async () => {
|
|
1130
1121
|
utils_1.fireEvent.click(utils_1.screen.getByLabelText('Show Field'));
|
|
1131
|
-
})
|
|
1122
|
+
});
|
|
1132
1123
|
expect(utils_1.screen.getByLabelText('Conditional Field')).toBeInTheDocument();
|
|
1133
|
-
})
|
|
1134
|
-
it('handles disabled fields with FieldBuilder', () =>
|
|
1124
|
+
});
|
|
1125
|
+
it('handles disabled fields with FieldBuilder', async () => {
|
|
1135
1126
|
const fields = [
|
|
1136
1127
|
(0, field_builder_1.field)()
|
|
1137
1128
|
.key('disabledField')
|
|
@@ -1140,14 +1131,14 @@ describe('AkiformBuilder', () => {
|
|
|
1140
1131
|
.config({ disabled: true })
|
|
1141
1132
|
.build()
|
|
1142
1133
|
];
|
|
1143
|
-
|
|
1134
|
+
await (0, react_1.act)(async () => {
|
|
1144
1135
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
1145
|
-
})
|
|
1136
|
+
});
|
|
1146
1137
|
expect(utils_1.screen.getByLabelText('Disabled Field')).toBeDisabled();
|
|
1147
|
-
})
|
|
1138
|
+
});
|
|
1148
1139
|
});
|
|
1149
1140
|
describe('Accessibility features', () => {
|
|
1150
|
-
it('renders form with proper ARIA attributes', () =>
|
|
1141
|
+
it('renders form with proper ARIA attributes', async () => {
|
|
1151
1142
|
const fields = [
|
|
1152
1143
|
{
|
|
1153
1144
|
key: 'name',
|
|
@@ -1157,9 +1148,9 @@ describe('AkiformBuilder', () => {
|
|
|
1157
1148
|
},
|
|
1158
1149
|
{ key: 'age', label: 'Age', type: 'number' }
|
|
1159
1150
|
];
|
|
1160
|
-
|
|
1151
|
+
await (0, react_1.act)(async () => {
|
|
1161
1152
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
1162
|
-
})
|
|
1153
|
+
});
|
|
1163
1154
|
const form = utils_1.screen.getByRole('form');
|
|
1164
1155
|
expect(form).toHaveAttribute('aria-label', 'Form');
|
|
1165
1156
|
const nameInput = utils_1.screen.getByRole('textbox', { name: /name/i });
|
|
@@ -1168,8 +1159,8 @@ describe('AkiformBuilder', () => {
|
|
|
1168
1159
|
const ageInput = utils_1.screen.getByRole('spinbutton', { name: /age/i });
|
|
1169
1160
|
expect(ageInput).toHaveAttribute('aria-required', 'false');
|
|
1170
1161
|
expect(ageInput).toHaveAttribute('aria-invalid', 'false');
|
|
1171
|
-
})
|
|
1172
|
-
it('updates aria-invalid attribute when form is submitted with errors', () =>
|
|
1162
|
+
});
|
|
1163
|
+
it('updates aria-invalid attribute when form is submitted with errors', async () => {
|
|
1173
1164
|
const fields = [
|
|
1174
1165
|
{
|
|
1175
1166
|
key: 'name',
|
|
@@ -1178,20 +1169,20 @@ describe('AkiformBuilder', () => {
|
|
|
1178
1169
|
validation: akival_1.akival.string().required('Name is required')
|
|
1179
1170
|
}
|
|
1180
1171
|
];
|
|
1181
|
-
|
|
1172
|
+
await (0, react_1.act)(async () => {
|
|
1182
1173
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
1183
|
-
})
|
|
1174
|
+
});
|
|
1184
1175
|
const nameInput = utils_1.screen.getByRole('textbox', { name: /name/i });
|
|
1185
1176
|
expect(nameInput).toHaveAttribute('aria-invalid', 'false');
|
|
1186
|
-
|
|
1177
|
+
await (0, react_1.act)(async () => {
|
|
1187
1178
|
utils_1.fireEvent.submit(utils_1.screen.getByRole('form'));
|
|
1188
|
-
})
|
|
1189
|
-
|
|
1179
|
+
});
|
|
1180
|
+
await (0, utils_1.waitFor)(() => {
|
|
1190
1181
|
expect(nameInput).toHaveAttribute('aria-invalid', 'true');
|
|
1191
1182
|
expect(utils_1.screen.getByText('Name is required')).toBeInTheDocument();
|
|
1192
1183
|
});
|
|
1193
|
-
})
|
|
1194
|
-
it('renders field array with proper ARIA attributes', () =>
|
|
1184
|
+
});
|
|
1185
|
+
it('renders field array with proper ARIA attributes', async () => {
|
|
1195
1186
|
const user = utils_1.userEvent.setup();
|
|
1196
1187
|
const fields = [
|
|
1197
1188
|
{
|
|
@@ -1204,45 +1195,45 @@ describe('AkiformBuilder', () => {
|
|
|
1204
1195
|
]
|
|
1205
1196
|
}
|
|
1206
1197
|
];
|
|
1207
|
-
|
|
1198
|
+
await (0, react_1.act)(async () => {
|
|
1208
1199
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
1209
|
-
})
|
|
1210
|
-
|
|
1211
|
-
|
|
1200
|
+
});
|
|
1201
|
+
await user.click(utils_1.screen.getByTestId('addresses-add-button'));
|
|
1202
|
+
await expandCollapsable();
|
|
1212
1203
|
const fieldArrayGroup = utils_1.screen.getByRole('group', { name: 'Addresses' });
|
|
1213
1204
|
expect(fieldArrayGroup).toBeInTheDocument();
|
|
1214
1205
|
const addButton = utils_1.screen.getByLabelText('Add Addresses');
|
|
1215
1206
|
expect(addButton).toBeInTheDocument();
|
|
1216
|
-
|
|
1217
|
-
|
|
1207
|
+
await user.click(addButton);
|
|
1208
|
+
await expandCollapsable();
|
|
1218
1209
|
const removeButton = utils_1.screen.getAllByLabelText('Remove Addresses')[1];
|
|
1219
1210
|
expect(removeButton).toBeInTheDocument();
|
|
1220
|
-
})
|
|
1221
|
-
it('supports keyboard navigation', () =>
|
|
1211
|
+
});
|
|
1212
|
+
it('supports keyboard navigation', async () => {
|
|
1222
1213
|
const user = utils_1.userEvent.setup();
|
|
1223
1214
|
const fields = [
|
|
1224
1215
|
{ key: 'name', label: 'Name', type: 'text' },
|
|
1225
1216
|
{ key: 'age', label: 'Age', type: 'number' }
|
|
1226
1217
|
];
|
|
1227
|
-
|
|
1218
|
+
await (0, react_1.act)(async () => {
|
|
1228
1219
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn(), showResetButton: true }));
|
|
1229
|
-
})
|
|
1220
|
+
});
|
|
1230
1221
|
const nameInput = utils_1.screen.getByLabelText('Name');
|
|
1231
1222
|
const ageInput = utils_1.screen.getByLabelText('Age');
|
|
1232
1223
|
const submitButton = utils_1.screen.getByRole('button', { name: 'SUBMIT' });
|
|
1233
1224
|
const resetButton = utils_1.screen.getByRole('button', { name: 'RESET' });
|
|
1234
|
-
|
|
1225
|
+
await user.tab();
|
|
1235
1226
|
expect(document.activeElement).toBe(nameInput);
|
|
1236
|
-
|
|
1227
|
+
await user.tab();
|
|
1237
1228
|
expect(document.activeElement).toBe(ageInput);
|
|
1238
|
-
|
|
1229
|
+
await user.tab();
|
|
1239
1230
|
expect(document.activeElement).toBe(submitButton);
|
|
1240
|
-
|
|
1231
|
+
await user.tab();
|
|
1241
1232
|
expect(document.activeElement).toBe(resetButton);
|
|
1242
|
-
})
|
|
1233
|
+
});
|
|
1243
1234
|
});
|
|
1244
1235
|
describe('AkiformBuilder with sections', () => {
|
|
1245
|
-
it('renders form with sections', () =>
|
|
1236
|
+
it('renders form with sections', async () => {
|
|
1246
1237
|
const fields = [
|
|
1247
1238
|
(0, field_builder_1.field)()
|
|
1248
1239
|
.key('personalInfo')
|
|
@@ -1273,9 +1264,9 @@ describe('AkiformBuilder', () => {
|
|
|
1273
1264
|
])
|
|
1274
1265
|
.build()
|
|
1275
1266
|
];
|
|
1276
|
-
|
|
1267
|
+
await (0, react_1.act)(async () => {
|
|
1277
1268
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
1278
|
-
})
|
|
1269
|
+
});
|
|
1279
1270
|
expect(utils_1.screen.getByText('Personal Information')).toBeInTheDocument();
|
|
1280
1271
|
expect(utils_1.screen.getByText('Contact Information')).toBeInTheDocument();
|
|
1281
1272
|
expect(utils_1.screen.getByText('Name')).toBeInTheDocument();
|
|
@@ -1288,9 +1279,9 @@ describe('AkiformBuilder', () => {
|
|
|
1288
1279
|
expect(utils_1.screen.queryByLabelText('Email')).not.toBeInTheDocument();
|
|
1289
1280
|
// Expand the second section
|
|
1290
1281
|
const contactInfoSection = utils_1.screen.getByText('Contact Information');
|
|
1291
|
-
|
|
1282
|
+
await utils_1.userEvent.click(contactInfoSection);
|
|
1292
1283
|
// Wait for the section to expand
|
|
1293
|
-
|
|
1284
|
+
await (0, utils_1.waitFor)(() => {
|
|
1294
1285
|
expect(utils_1.screen.getByLabelText('Email')).toBeInTheDocument();
|
|
1295
1286
|
});
|
|
1296
1287
|
// Check if the Email field is now visible
|
|
@@ -1304,8 +1295,8 @@ describe('AkiformBuilder', () => {
|
|
|
1304
1295
|
// 'Email input visibility:',
|
|
1305
1296
|
// window.getComputedStyle(emailInput).display
|
|
1306
1297
|
// );
|
|
1307
|
-
})
|
|
1308
|
-
it('handles form submission with sections', () =>
|
|
1298
|
+
});
|
|
1299
|
+
it('handles form submission with sections', async () => {
|
|
1309
1300
|
const onSubmitMock = vi.fn();
|
|
1310
1301
|
const fields = [
|
|
1311
1302
|
(0, field_builder_1.field)()
|
|
@@ -1324,35 +1315,35 @@ describe('AkiformBuilder', () => {
|
|
|
1324
1315
|
.fields([(0, field_builder_1.field)().key('email').label('Email').type('text').build()])
|
|
1325
1316
|
.build()
|
|
1326
1317
|
];
|
|
1327
|
-
|
|
1318
|
+
await (0, react_1.act)(async () => {
|
|
1328
1319
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: onSubmitMock }));
|
|
1329
|
-
})
|
|
1320
|
+
});
|
|
1330
1321
|
// Expand both sections
|
|
1331
|
-
|
|
1332
|
-
|
|
1322
|
+
await utils_1.userEvent.click(utils_1.screen.getByText('Personal Information'));
|
|
1323
|
+
await utils_1.userEvent.click(utils_1.screen.getByText('Contact Information'));
|
|
1333
1324
|
// Fill in the form
|
|
1334
|
-
|
|
1325
|
+
await utils_1.userEvent.type(utils_1.screen.getByLabelText('Name'), 'John Doe', {
|
|
1335
1326
|
delay: 1
|
|
1336
1327
|
});
|
|
1337
|
-
|
|
1338
|
-
|
|
1328
|
+
await utils_1.userEvent.type(utils_1.screen.getByLabelText('Age'), '30', { delay: 1 });
|
|
1329
|
+
await utils_1.userEvent.type(utils_1.screen.getByLabelText('Email'), 'john@example.com', {
|
|
1339
1330
|
delay: 1
|
|
1340
1331
|
});
|
|
1341
1332
|
// Wait for submit button to become interactable
|
|
1342
1333
|
const submitButton = utils_1.screen.getByRole('button', { name: /submit/i });
|
|
1343
|
-
|
|
1334
|
+
await (0, utils_1.waitFor)(() => {
|
|
1344
1335
|
expect(submitButton).toBeEnabled();
|
|
1345
1336
|
});
|
|
1346
1337
|
// Submit the form
|
|
1347
|
-
|
|
1338
|
+
await utils_1.userEvent.click(submitButton);
|
|
1348
1339
|
// Validate submission
|
|
1349
1340
|
expect(onSubmitMock).toHaveBeenCalledWith({
|
|
1350
1341
|
name: 'John Doe',
|
|
1351
1342
|
age: 30,
|
|
1352
1343
|
email: 'john@example.com'
|
|
1353
1344
|
}, expect.anything());
|
|
1354
|
-
})
|
|
1355
|
-
it('handles conditional rendering within sections', () =>
|
|
1345
|
+
});
|
|
1346
|
+
it('handles conditional rendering within sections', async () => {
|
|
1356
1347
|
const fields = [
|
|
1357
1348
|
(0, field_builder_1.field)()
|
|
1358
1349
|
.key('personalInfo')
|
|
@@ -1371,18 +1362,18 @@ describe('AkiformBuilder', () => {
|
|
|
1371
1362
|
.defaultExpanded(true)
|
|
1372
1363
|
.build()
|
|
1373
1364
|
];
|
|
1374
|
-
|
|
1365
|
+
await (0, react_1.act)(async () => {
|
|
1375
1366
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
1376
|
-
})
|
|
1367
|
+
});
|
|
1377
1368
|
expect(utils_1.screen.getByLabelText('Name')).toBeInTheDocument();
|
|
1378
1369
|
expect(utils_1.screen.getByLabelText('Show Age')).toBeInTheDocument();
|
|
1379
1370
|
expect(utils_1.screen.queryByLabelText('Age')).not.toBeInTheDocument();
|
|
1380
|
-
|
|
1381
|
-
expect(
|
|
1382
|
-
})
|
|
1371
|
+
await utils_1.userEvent.click(utils_1.screen.getByLabelText('Show Age'));
|
|
1372
|
+
expect(await utils_1.screen.findByLabelText('Age')).toBeInTheDocument();
|
|
1373
|
+
});
|
|
1383
1374
|
});
|
|
1384
1375
|
describe('AkiformBuilder with tooltip', () => {
|
|
1385
|
-
it('renders form field with tooltip as TooltipProps', () =>
|
|
1376
|
+
it('renders form field with tooltip as TooltipProps', async () => {
|
|
1386
1377
|
const fields = [
|
|
1387
1378
|
(0, field_builder_1.field)()
|
|
1388
1379
|
.key('name')
|
|
@@ -1391,21 +1382,21 @@ describe('AkiformBuilder', () => {
|
|
|
1391
1382
|
.tooltip({ title: 'Enter your full name', defaultOpen: true })
|
|
1392
1383
|
.build()
|
|
1393
1384
|
];
|
|
1394
|
-
|
|
1385
|
+
await (0, react_1.act)(async () => {
|
|
1395
1386
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
1396
|
-
})
|
|
1387
|
+
});
|
|
1397
1388
|
const tooltipTrigger = utils_1.screen.getByLabelText('Name');
|
|
1398
1389
|
expect(tooltipTrigger).toBeInTheDocument();
|
|
1399
1390
|
// Simulate hovering over the field to show the tooltip
|
|
1400
|
-
|
|
1391
|
+
await (0, react_1.act)(async () => {
|
|
1401
1392
|
utils_1.fireEvent.mouseEnter(tooltipTrigger);
|
|
1402
|
-
})
|
|
1393
|
+
});
|
|
1403
1394
|
// Wait for the tooltip to appear
|
|
1404
|
-
|
|
1395
|
+
await (0, utils_1.waitFor)(() => {
|
|
1405
1396
|
expect(utils_1.screen.getByText('Enter your full name')).toBeInTheDocument();
|
|
1406
1397
|
});
|
|
1407
|
-
})
|
|
1408
|
-
it('renders form field with tooltip as string', () =>
|
|
1398
|
+
});
|
|
1399
|
+
it('renders form field with tooltip as string', async () => {
|
|
1409
1400
|
const fields = [
|
|
1410
1401
|
(0, field_builder_1.field)()
|
|
1411
1402
|
.key('email')
|
|
@@ -1414,19 +1405,19 @@ describe('AkiformBuilder', () => {
|
|
|
1414
1405
|
.tooltip({ title: 'Enter your full name', defaultOpen: true })
|
|
1415
1406
|
.build()
|
|
1416
1407
|
];
|
|
1417
|
-
|
|
1408
|
+
await (0, react_1.act)(async () => {
|
|
1418
1409
|
(0, utils_1.render)(React.createElement(akiform_builder_1.AkiformBuilder, { fields: fields, onSubmit: vi.fn() }));
|
|
1419
|
-
})
|
|
1410
|
+
});
|
|
1420
1411
|
const tooltipTrigger = utils_1.screen.getByLabelText('Email');
|
|
1421
1412
|
expect(tooltipTrigger).toBeInTheDocument();
|
|
1422
1413
|
// Simulate hovering over the field to show the tooltip
|
|
1423
|
-
|
|
1414
|
+
await (0, react_1.act)(async () => {
|
|
1424
1415
|
utils_1.fireEvent.mouseEnter(tooltipTrigger);
|
|
1425
|
-
})
|
|
1416
|
+
});
|
|
1426
1417
|
// Wait for the tooltip to appear
|
|
1427
|
-
|
|
1418
|
+
await (0, utils_1.waitFor)(() => {
|
|
1428
1419
|
expect(utils_1.screen.getByText('Enter your full name')).toBeInTheDocument();
|
|
1429
1420
|
});
|
|
1430
|
-
})
|
|
1421
|
+
});
|
|
1431
1422
|
});
|
|
1432
1423
|
});
|