@evoke-platform/ui-components 1.9.1-testing.1 → 1.10.0-dev.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/published/components/custom/FormV2/FormRenderer.d.ts +20 -6
- package/dist/published/components/custom/FormV2/FormRenderer.js +142 -128
- package/dist/published/components/custom/FormV2/FormRendererContainer.d.ts +21 -2
- package/dist/published/components/custom/FormV2/FormRendererContainer.js +44 -46
- package/dist/published/components/custom/FormV2/components/Body.d.ts +18 -0
- package/dist/published/components/custom/FormV2/components/Body.js +27 -0
- package/dist/published/components/custom/FormV2/components/Footer.d.ts +15 -0
- package/dist/published/components/custom/FormV2/components/Footer.js +77 -0
- package/dist/published/components/custom/FormV2/components/FormContext.d.ts +2 -2
- package/dist/published/components/custom/FormV2/components/FormContext.js +1 -1
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/ActionDialog.d.ts +1 -1
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/ActionDialog.js +64 -22
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/RepeatableField.js +18 -16
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.js +7 -7
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/InstanceLookup.d.ts +0 -1
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/InstanceLookup.js +25 -20
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/ObjectPropertyInput.js +38 -49
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/RelatedObjectInstance.d.ts +2 -1
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/RelatedObjectInstance.js +95 -51
- package/dist/published/components/custom/FormV2/components/Header.d.ts +29 -0
- package/dist/published/components/custom/FormV2/components/Header.js +63 -0
- package/dist/published/components/custom/FormV2/components/RecursiveEntryRenderer.js +3 -3
- package/dist/published/components/custom/FormV2/components/ValidationFiles/ValidationErrors.d.ts +9 -0
- package/dist/published/components/custom/FormV2/components/ValidationFiles/{ValidationErrorDisplay.js → ValidationErrors.js} +11 -8
- package/dist/published/components/custom/FormV2/components/types.d.ts +1 -7
- package/dist/published/components/custom/FormV2/index.d.ts +3 -0
- package/dist/published/components/custom/FormV2/tests/FormRenderer.test.js +711 -78
- package/dist/published/components/custom/FormV2/tests/FormRendererContainer.test.js +4 -3
- package/dist/published/components/custom/index.d.ts +1 -1
- package/dist/published/components/custom/index.js +1 -1
- package/dist/published/index.d.ts +1 -1
- package/dist/published/stories/FormRenderer.stories.d.ts +24 -16
- package/dist/published/stories/FormRenderer.stories.js +2 -10
- package/dist/published/stories/FormRendererContainer.stories.d.ts +40 -10
- package/dist/published/theme/hooks.d.ts +12 -3
- package/package.json +1 -1
- package/dist/published/components/custom/FormV2/components/ActionButtons.d.ts +0 -17
- package/dist/published/components/custom/FormV2/components/ActionButtons.js +0 -111
- package/dist/published/components/custom/FormV2/components/ValidationFiles/ValidationErrorDisplay.d.ts +0 -11
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as matchers from '@testing-library/jest-dom/matchers';
|
|
2
|
-
import { render, screen, waitFor, within } from '@testing-library/react';
|
|
2
|
+
import { render as baseRender, screen, waitFor, within } from '@testing-library/react';
|
|
3
3
|
import userEvent from '@testing-library/user-event';
|
|
4
|
-
import { isEqual, set } from 'lodash';
|
|
4
|
+
import { isEmpty, isEqual, set } from 'lodash';
|
|
5
5
|
import { http, HttpResponse } from 'msw';
|
|
6
6
|
import { setupServer } from 'msw/node';
|
|
7
7
|
import React from 'react';
|
|
@@ -16,13 +16,10 @@ global.ResizeObserver = class ResizeObserver {
|
|
|
16
16
|
unobserve() { }
|
|
17
17
|
disconnect() { }
|
|
18
18
|
};
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
portalSelectors.forEach((selector) => {
|
|
22
|
-
// eslint-disable-next-line testing-library/no-node-access
|
|
23
|
-
document.querySelectorAll(selector).forEach((el) => el.remove());
|
|
24
|
-
});
|
|
19
|
+
const WithProviders = ({ children }) => {
|
|
20
|
+
return React.createElement(MemoryRouter, null, children);
|
|
25
21
|
};
|
|
22
|
+
const render = (ui, options) => baseRender(ui, { wrapper: WithProviders, ...options });
|
|
26
23
|
describe('Form component', () => {
|
|
27
24
|
let server;
|
|
28
25
|
beforeAll(() => {
|
|
@@ -46,7 +43,7 @@ describe('Form component', () => {
|
|
|
46
43
|
if (sanitizedVersion === 'true') {
|
|
47
44
|
return HttpResponse.json(accessibility508Object);
|
|
48
45
|
}
|
|
49
|
-
}), http.get('/data/objects/license/effective', () => HttpResponse.json(licenseObject)), http.get('/api/data/objects/license/instances', () => {
|
|
46
|
+
}), http.get('/api/data/objects/license/effective', () => HttpResponse.json(licenseObject)), http.get('/api/data/objects/license/instances', () => {
|
|
50
47
|
return HttpResponse.json([rnLicense, npLicense]);
|
|
51
48
|
}), http.get('/api/data/objects/specialtyType/instances', (req) => {
|
|
52
49
|
const filter = new URL(req.request.url).searchParams.get('filter');
|
|
@@ -55,7 +52,7 @@ describe('Form component', () => {
|
|
|
55
52
|
// The two objects in the array of conditions in the "where" filter represent the potential filters that can be applied when retrieving "specialty" instances.
|
|
56
53
|
// The first object is for the the validation criteria, but it is empty if the "license" field, which is referenced in the validation criteria, hasn't been filled out yet.
|
|
57
54
|
// The second object is for the search criteria which the user enters in the "specialty" field, but it is empty if no search text has been entered.
|
|
58
|
-
if (isEqual(whereFilter, { and: [{}, {}] }))
|
|
55
|
+
if (isEqual(whereFilter, { and: [{}, {}] }) || isEmpty(whereFilter))
|
|
59
56
|
return HttpResponse.json([
|
|
60
57
|
rnSpecialtyType1,
|
|
61
58
|
rnSpecialtyType2,
|
|
@@ -75,7 +72,6 @@ describe('Form component', () => {
|
|
|
75
72
|
});
|
|
76
73
|
afterEach(() => {
|
|
77
74
|
server.resetHandlers();
|
|
78
|
-
removePoppers();
|
|
79
75
|
});
|
|
80
76
|
describe('validation criteria', () => {
|
|
81
77
|
it(`filters related object field with validation criteria that references a related object's nested data`, async () => {
|
|
@@ -103,8 +99,7 @@ describe('Form component', () => {
|
|
|
103
99
|
return React.createElement("div", null, "Render error");
|
|
104
100
|
}
|
|
105
101
|
};
|
|
106
|
-
render(React.createElement(
|
|
107
|
-
React.createElement(FormWithState, null)));
|
|
102
|
+
render(React.createElement(FormWithState, null));
|
|
108
103
|
const license = await screen.findByRole('combobox', { name: 'License' });
|
|
109
104
|
// Step 1: Open Specialty Type and verify all options
|
|
110
105
|
await user.click(await screen.findByRole('combobox', { name: 'Specialty Type' }));
|
|
@@ -134,23 +129,21 @@ describe('Form component', () => {
|
|
|
134
129
|
describe('visibility configuration', () => {
|
|
135
130
|
it('shows fields based on instance data using JsonLogic', async () => {
|
|
136
131
|
server.use(http.get('/data/objects/license/instances/rnLicense', () => HttpResponse.json(rnLicense)));
|
|
137
|
-
render(React.createElement(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
} })));
|
|
132
|
+
render(React.createElement(FormRenderer, { form: jsonLogicDisplayTestSpecialtyForm, onChange: () => { }, instance: {
|
|
133
|
+
id: '123',
|
|
134
|
+
objectId: 'specialty',
|
|
135
|
+
name: 'Test Specialty Object Instance',
|
|
136
|
+
} }));
|
|
143
137
|
// Validate that specialty type dropdown renders
|
|
144
138
|
await screen.findByRole('combobox', { name: 'Specialty Type' });
|
|
145
139
|
});
|
|
146
140
|
it('hides fields based on instance data using JsonLogic', async () => {
|
|
147
141
|
server.use(http.get('/data/objects/license/instances/rnLicense', () => HttpResponse.json(rnLicense)));
|
|
148
|
-
render(React.createElement(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
} })));
|
|
142
|
+
render(React.createElement(FormRenderer, { form: jsonLogicDisplayTestSpecialtyForm, onChange: () => { }, instance: {
|
|
143
|
+
id: '123',
|
|
144
|
+
objectId: 'specialty',
|
|
145
|
+
name: 'Test Specialty Object Instance -- hidden',
|
|
146
|
+
} }));
|
|
154
147
|
// Validate that license dropdown renders
|
|
155
148
|
await screen.findByRole('combobox', { name: 'License' });
|
|
156
149
|
// Validate that specialty type dropdown does not render
|
|
@@ -158,23 +151,21 @@ describe('Form component', () => {
|
|
|
158
151
|
});
|
|
159
152
|
it('shows fields based on instance data using simple conditions', async () => {
|
|
160
153
|
server.use(http.get('/data/objects/license/instances/rnLicense', () => HttpResponse.json(rnLicense)));
|
|
161
|
-
render(React.createElement(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
} })));
|
|
154
|
+
render(React.createElement(FormRenderer, { form: simpleConditionDisplayTestSpecialtyForm, onChange: () => { }, instance: {
|
|
155
|
+
id: '123',
|
|
156
|
+
objectId: 'specialty',
|
|
157
|
+
name: 'Test Specialty Object Instance',
|
|
158
|
+
} }));
|
|
167
159
|
// Validate that specialty type dropdown renders
|
|
168
160
|
await screen.findByRole('combobox', { name: 'Specialty Type' });
|
|
169
161
|
});
|
|
170
162
|
it('hides fields based on instance data using simple conditions', async () => {
|
|
171
163
|
server.use(http.get('/data/objects/license/instances/rnLicense', () => HttpResponse.json(rnLicense)));
|
|
172
|
-
render(React.createElement(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
} })));
|
|
164
|
+
render(React.createElement(FormRenderer, { form: simpleConditionDisplayTestSpecialtyForm, onChange: () => { }, instance: {
|
|
165
|
+
id: '123',
|
|
166
|
+
objectId: 'specialty',
|
|
167
|
+
name: 'Test Specialty Object Instance -- hidden',
|
|
168
|
+
} }));
|
|
178
169
|
// Validate that license dropdown renders
|
|
179
170
|
await screen.findByRole('combobox', { name: 'License' });
|
|
180
171
|
// Validate that specialty type dropdown does not render
|
|
@@ -185,9 +176,7 @@ describe('Form component', () => {
|
|
|
185
176
|
describe('508 accessibility compliance', () => {
|
|
186
177
|
it('supports keyboard navigation back and forth through Related Object dropdowns', async () => {
|
|
187
178
|
const user = userEvent.setup();
|
|
188
|
-
render(React.createElement(
|
|
189
|
-
React.createElement(FormRenderer, { form: UpdateAccessibilityFormOne, onChange: () => { } }),
|
|
190
|
-
","));
|
|
179
|
+
render(React.createElement(FormRenderer, { form: UpdateAccessibilityFormOne, onChange: () => { } }));
|
|
191
180
|
await waitFor(() => {
|
|
192
181
|
expect(screen.getByLabelText('Name')).toBeInTheDocument();
|
|
193
182
|
});
|
|
@@ -203,9 +192,7 @@ describe('Form component', () => {
|
|
|
203
192
|
});
|
|
204
193
|
it('supports keyboard navigation back and forth through User dropdowns', async () => {
|
|
205
194
|
const user = userEvent.setup();
|
|
206
|
-
render(React.createElement(
|
|
207
|
-
React.createElement(FormRenderer, { form: UpdateAccessibilityFormTwo, onChange: () => { } }),
|
|
208
|
-
","));
|
|
195
|
+
render(React.createElement(FormRenderer, { form: UpdateAccessibilityFormTwo, onChange: () => { } }));
|
|
209
196
|
await waitFor(() => {
|
|
210
197
|
expect(screen.getByLabelText('Name')).toBeInTheDocument();
|
|
211
198
|
});
|
|
@@ -223,9 +210,7 @@ describe('Form component', () => {
|
|
|
223
210
|
});
|
|
224
211
|
it('supports keyboard selection of dropdown values using Enter key on Related Objects', async () => {
|
|
225
212
|
const user = userEvent.setup();
|
|
226
|
-
render(React.createElement(
|
|
227
|
-
React.createElement(FormRenderer, { form: UpdateAccessibilityFormOne, onChange: () => { } }),
|
|
228
|
-
","));
|
|
213
|
+
render(React.createElement(FormRenderer, { form: UpdateAccessibilityFormOne, onChange: () => { } }));
|
|
229
214
|
await waitFor(() => {
|
|
230
215
|
expect(screen.getByLabelText('Name')).toBeInTheDocument();
|
|
231
216
|
});
|
|
@@ -234,6 +219,8 @@ describe('Form component', () => {
|
|
|
234
219
|
await user.tab();
|
|
235
220
|
// Open dropdown with Enter
|
|
236
221
|
await user.keyboard('{Enter}');
|
|
222
|
+
// Wait for options to load
|
|
223
|
+
await screen.findByText('RN License');
|
|
237
224
|
// Navigate to first option
|
|
238
225
|
await user.keyboard('{ArrowDown}');
|
|
239
226
|
// Select option with Enter
|
|
@@ -244,9 +231,7 @@ describe('Form component', () => {
|
|
|
244
231
|
});
|
|
245
232
|
it('supports keyboard selection of dropdown values using Enter key on Users', async () => {
|
|
246
233
|
const user = userEvent.setup();
|
|
247
|
-
render(React.createElement(
|
|
248
|
-
React.createElement(FormRenderer, { form: UpdateAccessibilityFormTwo, onChange: () => { } }),
|
|
249
|
-
","));
|
|
234
|
+
render(React.createElement(FormRenderer, { form: UpdateAccessibilityFormTwo, onChange: () => { } }));
|
|
250
235
|
await waitFor(() => {
|
|
251
236
|
expect(screen.getByLabelText('Name')).toBeInTheDocument();
|
|
252
237
|
});
|
|
@@ -266,9 +251,7 @@ describe('Form component', () => {
|
|
|
266
251
|
});
|
|
267
252
|
it('supports navigating between dropdown options using arrow keys on Related Objects', async () => {
|
|
268
253
|
const user = userEvent.setup();
|
|
269
|
-
render(React.createElement(
|
|
270
|
-
React.createElement(FormRenderer, { form: UpdateAccessibilityFormOne, onChange: () => { } }),
|
|
271
|
-
","));
|
|
254
|
+
render(React.createElement(FormRenderer, { form: UpdateAccessibilityFormOne, onChange: () => { } }));
|
|
272
255
|
await waitFor(() => {
|
|
273
256
|
expect(screen.getByLabelText('License')).toBeInTheDocument();
|
|
274
257
|
});
|
|
@@ -288,9 +271,7 @@ describe('Form component', () => {
|
|
|
288
271
|
});
|
|
289
272
|
it('supports navigating between dropdown options using arrow keys on User dropdowns', async () => {
|
|
290
273
|
const user = userEvent.setup();
|
|
291
|
-
render(React.createElement(
|
|
292
|
-
React.createElement(FormRenderer, { form: UpdateAccessibilityFormTwo, onChange: () => { } }),
|
|
293
|
-
","));
|
|
274
|
+
render(React.createElement(FormRenderer, { form: UpdateAccessibilityFormTwo, onChange: () => { } }));
|
|
294
275
|
await waitFor(() => {
|
|
295
276
|
expect(screen.getByLabelText('Name')).toBeInTheDocument();
|
|
296
277
|
});
|
|
@@ -308,16 +289,15 @@ describe('Form component', () => {
|
|
|
308
289
|
});
|
|
309
290
|
it('supports clearing selection with the clear button on Related Objects', async () => {
|
|
310
291
|
const user = userEvent.setup();
|
|
311
|
-
render(React.createElement(
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
} })));
|
|
292
|
+
render(React.createElement(FormRenderer, { form: UpdateAccessibilityFormOne, onChange: () => { }, value: {
|
|
293
|
+
id: '123',
|
|
294
|
+
objectId: 'accessibility508Object',
|
|
295
|
+
name: 'Test Accessibility 508 Object Instance',
|
|
296
|
+
license: {
|
|
297
|
+
id: 'rnLicense',
|
|
298
|
+
name: 'RN License',
|
|
299
|
+
},
|
|
300
|
+
} }));
|
|
321
301
|
// Set up a selection first
|
|
322
302
|
await waitFor(() => {
|
|
323
303
|
expect(screen.getByLabelText('Name')).toBeInTheDocument();
|
|
@@ -337,16 +317,15 @@ describe('Form component', () => {
|
|
|
337
317
|
});
|
|
338
318
|
it('supports clearing selection with the clear button on User dropdowns', async () => {
|
|
339
319
|
const user = userEvent.setup();
|
|
340
|
-
render(React.createElement(
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
} })));
|
|
320
|
+
render(React.createElement(FormRenderer, { form: UpdateAccessibilityFormTwo, onChange: () => { }, value: {
|
|
321
|
+
id: '123',
|
|
322
|
+
objectId: 'accessibility508Object',
|
|
323
|
+
name: 'Test Accessibility 508 Object Instance',
|
|
324
|
+
user: {
|
|
325
|
+
id: 'user1',
|
|
326
|
+
name: 'User 1',
|
|
327
|
+
},
|
|
328
|
+
} }));
|
|
350
329
|
// Set up a selection first
|
|
351
330
|
await waitFor(() => {
|
|
352
331
|
expect(screen.getByLabelText('Name')).toBeInTheDocument();
|
|
@@ -368,9 +347,7 @@ describe('Form component', () => {
|
|
|
368
347
|
});
|
|
369
348
|
it('supports navigating to Add New option with arrow keys and opens modal', async () => {
|
|
370
349
|
const user = userEvent.setup();
|
|
371
|
-
render(React.createElement(
|
|
372
|
-
React.createElement(FormRenderer, { form: UpdateAccessibilityFormOne, onChange: () => { } }),
|
|
373
|
-
","));
|
|
350
|
+
render(React.createElement(FormRenderer, { form: UpdateAccessibilityFormOne, onChange: () => { } }));
|
|
374
351
|
await waitFor(() => {
|
|
375
352
|
expect(screen.getByLabelText('Name')).toBeInTheDocument();
|
|
376
353
|
});
|
|
@@ -388,4 +365,660 @@ describe('Form component', () => {
|
|
|
388
365
|
});
|
|
389
366
|
});
|
|
390
367
|
});
|
|
368
|
+
describe('when passed a related object entry', () => {
|
|
369
|
+
const setupTestMocks = (object, form, instances) => {
|
|
370
|
+
server.use(http.get(`/api/data/objects/${object.id}/effective`, () => HttpResponse.json(object)), http.get(`/api/data/forms/${form.id}`, () => HttpResponse.json(form)), http.get(`/api/data/forms?filter={"where":{"actionId":"${form.actionId}","objectId":"${object.id}"}}`, () => HttpResponse.json([form])), http.get(`/api/data/objects/${object.id}/instances`, () => HttpResponse.json(instances || [])));
|
|
371
|
+
};
|
|
372
|
+
describe('when in table view', () => {
|
|
373
|
+
describe('when mode is existing records only', () => {
|
|
374
|
+
const form = {
|
|
375
|
+
id: 'relatedObjectTestForm',
|
|
376
|
+
name: 'Related Object Test Form',
|
|
377
|
+
entries: [
|
|
378
|
+
{
|
|
379
|
+
type: 'input',
|
|
380
|
+
parameterId: 'specialtyType',
|
|
381
|
+
display: {
|
|
382
|
+
label: 'Speciality Type',
|
|
383
|
+
mode: 'existingOnly',
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
],
|
|
387
|
+
actionId: '_update',
|
|
388
|
+
objectId: 'relatedObjectTestForm',
|
|
389
|
+
};
|
|
390
|
+
beforeEach(() => {
|
|
391
|
+
const relatedObjectTestFormObject = {
|
|
392
|
+
id: 'relatedObjectTestForm',
|
|
393
|
+
name: 'Related Object Test Form',
|
|
394
|
+
actions: [
|
|
395
|
+
{
|
|
396
|
+
id: '_update',
|
|
397
|
+
name: 'Update',
|
|
398
|
+
type: 'update',
|
|
399
|
+
parameters: [
|
|
400
|
+
{
|
|
401
|
+
id: 'specialtyType',
|
|
402
|
+
name: 'Related Object',
|
|
403
|
+
type: 'object',
|
|
404
|
+
objectId: 'specialtyType',
|
|
405
|
+
},
|
|
406
|
+
],
|
|
407
|
+
outputEvent: 'updated',
|
|
408
|
+
},
|
|
409
|
+
],
|
|
410
|
+
properties: [
|
|
411
|
+
{
|
|
412
|
+
id: 'specialtyType',
|
|
413
|
+
name: 'Related Object',
|
|
414
|
+
type: 'object',
|
|
415
|
+
},
|
|
416
|
+
],
|
|
417
|
+
};
|
|
418
|
+
setupTestMocks(relatedObjectTestFormObject, form);
|
|
419
|
+
const specialtyTypeObject = {
|
|
420
|
+
id: 'specialtyType',
|
|
421
|
+
name: 'Specialty Type',
|
|
422
|
+
actions: [
|
|
423
|
+
{
|
|
424
|
+
id: '_create',
|
|
425
|
+
name: 'Create',
|
|
426
|
+
type: 'create',
|
|
427
|
+
parameters: [],
|
|
428
|
+
outputEvent: 'created',
|
|
429
|
+
defaultFormId: 'specialtyType',
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
id: '_update',
|
|
433
|
+
name: 'Update',
|
|
434
|
+
type: 'update',
|
|
435
|
+
parameters: [],
|
|
436
|
+
outputEvent: 'updated',
|
|
437
|
+
},
|
|
438
|
+
],
|
|
439
|
+
properties: [],
|
|
440
|
+
};
|
|
441
|
+
const specialtyTypeForm = {
|
|
442
|
+
id: 'specialtyTypeForm',
|
|
443
|
+
name: 'Specialty Type Form',
|
|
444
|
+
entries: [],
|
|
445
|
+
actionId: '_update',
|
|
446
|
+
objectId: 'specialtyType',
|
|
447
|
+
};
|
|
448
|
+
setupTestMocks(specialtyTypeObject, specialtyTypeForm);
|
|
449
|
+
});
|
|
450
|
+
it('does not display radio buttons if mode is existing records only', async () => {
|
|
451
|
+
const user = userEvent.setup();
|
|
452
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
453
|
+
await user.click(await screen.findByRole('button', { name: 'Add' }));
|
|
454
|
+
// Make sure dialog loads
|
|
455
|
+
await screen.findByRole('dialog');
|
|
456
|
+
expect(screen.queryByRole('radiogroup', { name: 'Relation Type' })).not.toBeInTheDocument();
|
|
457
|
+
});
|
|
458
|
+
});
|
|
459
|
+
describe('when object has no searchable properties', () => {
|
|
460
|
+
const form = {
|
|
461
|
+
id: 'relatedObjectTestForm',
|
|
462
|
+
name: 'Related Object Test Form',
|
|
463
|
+
entries: [
|
|
464
|
+
{
|
|
465
|
+
type: 'input',
|
|
466
|
+
parameterId: 'specialtyType',
|
|
467
|
+
display: {
|
|
468
|
+
label: 'Speciality Type',
|
|
469
|
+
},
|
|
470
|
+
},
|
|
471
|
+
],
|
|
472
|
+
actionId: '_update',
|
|
473
|
+
objectId: 'relatedObjectTestForm',
|
|
474
|
+
};
|
|
475
|
+
beforeEach(async () => {
|
|
476
|
+
const relatedObjectTestFormObject = {
|
|
477
|
+
id: 'relatedObjectTestForm',
|
|
478
|
+
name: 'Related Object Test Form',
|
|
479
|
+
actions: [
|
|
480
|
+
{
|
|
481
|
+
id: '_update',
|
|
482
|
+
name: 'Update',
|
|
483
|
+
type: 'update',
|
|
484
|
+
parameters: [
|
|
485
|
+
{
|
|
486
|
+
id: 'specialtyType',
|
|
487
|
+
name: 'Related Object',
|
|
488
|
+
type: 'object',
|
|
489
|
+
objectId: 'specialtyType',
|
|
490
|
+
},
|
|
491
|
+
],
|
|
492
|
+
outputEvent: 'updated',
|
|
493
|
+
},
|
|
494
|
+
],
|
|
495
|
+
properties: [
|
|
496
|
+
{
|
|
497
|
+
id: 'specialtyType',
|
|
498
|
+
name: 'Related Object',
|
|
499
|
+
type: 'object',
|
|
500
|
+
},
|
|
501
|
+
],
|
|
502
|
+
};
|
|
503
|
+
setupTestMocks(relatedObjectTestFormObject, form);
|
|
504
|
+
const specialtyTypeObject = {
|
|
505
|
+
id: 'specialtyType',
|
|
506
|
+
name: 'Specialty Type',
|
|
507
|
+
actions: [
|
|
508
|
+
{
|
|
509
|
+
id: '_create',
|
|
510
|
+
name: 'Create',
|
|
511
|
+
type: 'create',
|
|
512
|
+
parameters: [],
|
|
513
|
+
outputEvent: 'created',
|
|
514
|
+
defaultFormId: 'specialtyType',
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
id: '_update',
|
|
518
|
+
name: 'Update',
|
|
519
|
+
type: 'update',
|
|
520
|
+
parameters: [],
|
|
521
|
+
outputEvent: 'updated',
|
|
522
|
+
},
|
|
523
|
+
],
|
|
524
|
+
properties: [],
|
|
525
|
+
};
|
|
526
|
+
const specialtyTypeForm = {
|
|
527
|
+
id: 'specialtyTypeForm',
|
|
528
|
+
name: 'Specialty Type Form',
|
|
529
|
+
entries: [],
|
|
530
|
+
actionId: '_update',
|
|
531
|
+
objectId: 'specialtyType',
|
|
532
|
+
};
|
|
533
|
+
setupTestMocks(specialtyTypeObject, specialtyTypeForm);
|
|
534
|
+
});
|
|
535
|
+
it("displays an error message if there aren't any searchable properties on a related object", async () => {
|
|
536
|
+
const user = userEvent.setup();
|
|
537
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
538
|
+
await user.click(await screen.findByRole('button', { name: 'Add' }));
|
|
539
|
+
await screen.findByRole('dialog');
|
|
540
|
+
await waitFor(() => {
|
|
541
|
+
expect(screen.getByText('There are no searchable properties configured for this object')).toBeInTheDocument();
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
});
|
|
545
|
+
describe('when object has searchable properties', () => {
|
|
546
|
+
const form = {
|
|
547
|
+
id: 'relatedObjectTestForm',
|
|
548
|
+
name: 'Related Object Test Form',
|
|
549
|
+
entries: [
|
|
550
|
+
{
|
|
551
|
+
type: 'input',
|
|
552
|
+
parameterId: 'specialtyType',
|
|
553
|
+
display: {
|
|
554
|
+
label: 'Speciality Type',
|
|
555
|
+
relatedObjectDisplay: 'dialogBox',
|
|
556
|
+
mode: 'existingOnly',
|
|
557
|
+
},
|
|
558
|
+
},
|
|
559
|
+
],
|
|
560
|
+
actionId: '_update',
|
|
561
|
+
objectId: 'relatedObjectTestForm',
|
|
562
|
+
};
|
|
563
|
+
beforeEach(async () => {
|
|
564
|
+
const relatedObjectTestFormObject = {
|
|
565
|
+
id: 'relatedObjectTestForm',
|
|
566
|
+
name: 'Related Object Test Form',
|
|
567
|
+
actions: [
|
|
568
|
+
{
|
|
569
|
+
id: '_update',
|
|
570
|
+
name: 'Update',
|
|
571
|
+
type: 'update',
|
|
572
|
+
parameters: [
|
|
573
|
+
{
|
|
574
|
+
id: 'specialtyType',
|
|
575
|
+
name: 'Related Object',
|
|
576
|
+
type: 'object',
|
|
577
|
+
objectId: 'specialtyType',
|
|
578
|
+
},
|
|
579
|
+
],
|
|
580
|
+
outputEvent: 'updated',
|
|
581
|
+
},
|
|
582
|
+
],
|
|
583
|
+
properties: [
|
|
584
|
+
{
|
|
585
|
+
id: 'specialtyType',
|
|
586
|
+
name: 'Related Object',
|
|
587
|
+
type: 'object',
|
|
588
|
+
},
|
|
589
|
+
],
|
|
590
|
+
};
|
|
591
|
+
setupTestMocks(relatedObjectTestFormObject, form);
|
|
592
|
+
const specialtyTypeObject = {
|
|
593
|
+
id: 'specialtyType',
|
|
594
|
+
name: 'Specialty Type',
|
|
595
|
+
actions: [
|
|
596
|
+
{
|
|
597
|
+
id: '_create',
|
|
598
|
+
name: 'Create',
|
|
599
|
+
type: 'create',
|
|
600
|
+
parameters: [],
|
|
601
|
+
outputEvent: 'created',
|
|
602
|
+
defaultFormId: 'specialtyType',
|
|
603
|
+
},
|
|
604
|
+
],
|
|
605
|
+
properties: [
|
|
606
|
+
{
|
|
607
|
+
id: 'name',
|
|
608
|
+
name: 'Name',
|
|
609
|
+
type: 'string',
|
|
610
|
+
searchable: true,
|
|
611
|
+
},
|
|
612
|
+
],
|
|
613
|
+
};
|
|
614
|
+
const specialtyTypeForm = {
|
|
615
|
+
id: 'specialtyTypeForm',
|
|
616
|
+
name: 'Specialty Type Form',
|
|
617
|
+
entries: [
|
|
618
|
+
{
|
|
619
|
+
type: 'input',
|
|
620
|
+
parameterId: 'specialtyType',
|
|
621
|
+
display: {
|
|
622
|
+
label: 'Speciality Type',
|
|
623
|
+
relatedObjectDisplay: 'dialogBox',
|
|
624
|
+
mode: 'existingOnly',
|
|
625
|
+
},
|
|
626
|
+
},
|
|
627
|
+
],
|
|
628
|
+
actionId: '_update',
|
|
629
|
+
objectId: 'specialtyType',
|
|
630
|
+
};
|
|
631
|
+
setupTestMocks(specialtyTypeObject, specialtyTypeForm);
|
|
632
|
+
});
|
|
633
|
+
it('displays message to refine search if no search results are found', async () => {
|
|
634
|
+
const user = userEvent.setup();
|
|
635
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
636
|
+
await user.click(await screen.findByRole('button', { name: 'Add' }));
|
|
637
|
+
await screen.findByRole('dialog');
|
|
638
|
+
const searchField = screen.getByRole('textbox', { name: 'Search' });
|
|
639
|
+
await user.type(searchField, 'Nonexistent Instance');
|
|
640
|
+
await screen.findByText(/refine your search/i);
|
|
641
|
+
});
|
|
642
|
+
});
|
|
643
|
+
describe('when mode is default (allows both new and existing)', () => {
|
|
644
|
+
const form = {
|
|
645
|
+
id: 'relatedObjectTestForm',
|
|
646
|
+
name: 'Related Object Test Form',
|
|
647
|
+
entries: [
|
|
648
|
+
{
|
|
649
|
+
type: 'input',
|
|
650
|
+
parameterId: 'specialtyType',
|
|
651
|
+
display: {
|
|
652
|
+
label: 'Speciality Type',
|
|
653
|
+
},
|
|
654
|
+
},
|
|
655
|
+
],
|
|
656
|
+
actionId: '_update',
|
|
657
|
+
objectId: 'relatedObjectTestForm',
|
|
658
|
+
};
|
|
659
|
+
beforeEach(async () => {
|
|
660
|
+
const relatedObjectTestFormObject = {
|
|
661
|
+
id: 'relatedObjectTestForm',
|
|
662
|
+
name: 'Related Object Test Form',
|
|
663
|
+
actions: [
|
|
664
|
+
{
|
|
665
|
+
id: '_update',
|
|
666
|
+
name: 'Update',
|
|
667
|
+
type: 'update',
|
|
668
|
+
parameters: [
|
|
669
|
+
{
|
|
670
|
+
id: 'specialtyType',
|
|
671
|
+
name: 'Related Object',
|
|
672
|
+
type: 'object',
|
|
673
|
+
objectId: 'specialtyType',
|
|
674
|
+
},
|
|
675
|
+
],
|
|
676
|
+
outputEvent: 'updated',
|
|
677
|
+
},
|
|
678
|
+
],
|
|
679
|
+
properties: [
|
|
680
|
+
{
|
|
681
|
+
id: 'specialtyType',
|
|
682
|
+
name: 'Related Object',
|
|
683
|
+
type: 'object',
|
|
684
|
+
},
|
|
685
|
+
],
|
|
686
|
+
};
|
|
687
|
+
setupTestMocks(relatedObjectTestFormObject, form);
|
|
688
|
+
const specialtyTypeForm = {
|
|
689
|
+
id: 'specialtyTypeForm',
|
|
690
|
+
name: 'Specialty Type Form',
|
|
691
|
+
entries: [
|
|
692
|
+
{
|
|
693
|
+
type: 'content',
|
|
694
|
+
html: '<div>Specialty Type Form Content</div>',
|
|
695
|
+
},
|
|
696
|
+
],
|
|
697
|
+
actionId: '_create',
|
|
698
|
+
objectId: 'specialtyType',
|
|
699
|
+
};
|
|
700
|
+
const specialtyTypeObject = {
|
|
701
|
+
id: 'specialtyType',
|
|
702
|
+
name: 'Specialty Type',
|
|
703
|
+
actions: [
|
|
704
|
+
{
|
|
705
|
+
id: '_create',
|
|
706
|
+
name: 'Create',
|
|
707
|
+
type: 'create',
|
|
708
|
+
parameters: [],
|
|
709
|
+
outputEvent: 'created',
|
|
710
|
+
defaultFormId: 'specialtyTypeForm',
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
id: '_update',
|
|
714
|
+
name: 'Update',
|
|
715
|
+
type: 'update',
|
|
716
|
+
parameters: [],
|
|
717
|
+
outputEvent: 'updated',
|
|
718
|
+
},
|
|
719
|
+
],
|
|
720
|
+
properties: [],
|
|
721
|
+
};
|
|
722
|
+
setupTestMocks(specialtyTypeObject, specialtyTypeForm);
|
|
723
|
+
});
|
|
724
|
+
it('displays an add button for related object fields', async () => {
|
|
725
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
726
|
+
await screen.findByRole('button', { name: 'Add' });
|
|
727
|
+
});
|
|
728
|
+
it('shows a close icon in instance lookup mode', async () => {
|
|
729
|
+
const user = userEvent.setup();
|
|
730
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
731
|
+
await user.click(await screen.findByRole('button', { name: 'Add' }));
|
|
732
|
+
await screen.findByRole('button', { name: 'Close' });
|
|
733
|
+
});
|
|
734
|
+
it('allows users to close modal using close icon in instance lookup mode', async () => {
|
|
735
|
+
const user = userEvent.setup();
|
|
736
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
737
|
+
await user.click(await screen.findByRole('button', { name: 'Add' }));
|
|
738
|
+
const dialog = await screen.findByRole('dialog');
|
|
739
|
+
await user.click(await screen.findByRole('button', { name: 'Close' }));
|
|
740
|
+
await waitFor(() => expect(dialog).not.toBeInTheDocument());
|
|
741
|
+
});
|
|
742
|
+
it('shows a cancel button in instance lookup mode', async () => {
|
|
743
|
+
const user = userEvent.setup();
|
|
744
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
745
|
+
await user.click(await screen.findByRole('button', { name: 'Add' }));
|
|
746
|
+
await screen.findByRole('button', { name: 'Cancel' });
|
|
747
|
+
});
|
|
748
|
+
it('closes dialog in instance lookup mode when clicking cancel', async () => {
|
|
749
|
+
const user = userEvent.setup();
|
|
750
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
751
|
+
await user.click(await screen.findByRole('button', { name: 'Add' }));
|
|
752
|
+
const dialog = await screen.findByRole('dialog');
|
|
753
|
+
await user.click(await screen.findByRole('button', { name: 'Cancel' }));
|
|
754
|
+
await waitFor(() => expect(dialog).not.toBeInTheDocument());
|
|
755
|
+
});
|
|
756
|
+
it('displays radio buttons for new or existing record selection', async () => {
|
|
757
|
+
const user = userEvent.setup();
|
|
758
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
759
|
+
await user.click(await screen.findByRole('button', { name: 'Add' }));
|
|
760
|
+
await screen.findByRole('radiogroup', { name: 'Relation Type' });
|
|
761
|
+
});
|
|
762
|
+
it('closes dialog if cancel button is clicked when creating a new record', async () => {
|
|
763
|
+
const user = userEvent.setup();
|
|
764
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
765
|
+
await user.click(await screen.findByRole('button', { name: 'Add' }));
|
|
766
|
+
const dialog = await screen.findByRole('dialog');
|
|
767
|
+
await screen.findByRole('radiogroup', { name: 'Relation Type' });
|
|
768
|
+
const existingRecordButton = await screen.findByRole('radio', { name: /existing/i });
|
|
769
|
+
expect(existingRecordButton).toBeChecked();
|
|
770
|
+
const newRecordButton = await screen.findByRole('radio', { name: /new/i });
|
|
771
|
+
await user.click(newRecordButton);
|
|
772
|
+
const cancelButton = screen.getByRole('button', { name: 'Cancel' });
|
|
773
|
+
await user.click(cancelButton);
|
|
774
|
+
await waitFor(() => expect(dialog).not.toBeInTheDocument());
|
|
775
|
+
});
|
|
776
|
+
it('displays form if user switches to creating a new record', async () => {
|
|
777
|
+
const user = userEvent.setup();
|
|
778
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
779
|
+
await user.click(await screen.findByRole('button', { name: 'Add' }));
|
|
780
|
+
await screen.findByRole('radiogroup', { name: 'Relation Type' });
|
|
781
|
+
const existingRecordButton = await screen.findByRole('radio', { name: /existing/i });
|
|
782
|
+
expect(existingRecordButton).toBeChecked();
|
|
783
|
+
const newRecordButton = await screen.findByRole('radio', { name: /new/i });
|
|
784
|
+
await user.click(newRecordButton);
|
|
785
|
+
await screen.findByText('Specialty Type Form Content');
|
|
786
|
+
});
|
|
787
|
+
it('displays a close icon in record creation mode', async () => {
|
|
788
|
+
const user = userEvent.setup();
|
|
789
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
790
|
+
await user.click(await screen.findByRole('button', { name: 'Add' }));
|
|
791
|
+
const newRecordButton = await screen.findByRole('radio', { name: /new/i });
|
|
792
|
+
await user.click(newRecordButton);
|
|
793
|
+
await screen.findByText('Specialty Type Form Content');
|
|
794
|
+
await screen.findByRole('button', { name: 'Close' });
|
|
795
|
+
});
|
|
796
|
+
it('displays a cancel button in record creation mode', async () => {
|
|
797
|
+
const user = userEvent.setup();
|
|
798
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
799
|
+
await user.click(await screen.findByRole('button', { name: 'Add' }));
|
|
800
|
+
const newRecordButton = await screen.findByRole('radio', { name: /new/i });
|
|
801
|
+
await user.click(newRecordButton);
|
|
802
|
+
await screen.findByText('Specialty Type Form Content');
|
|
803
|
+
await screen.findByRole('button', { name: 'Cancel' });
|
|
804
|
+
});
|
|
805
|
+
it('displays a not found error in record creation mode if a form could not be found', async () => {
|
|
806
|
+
const user = userEvent.setup();
|
|
807
|
+
server.use(http.get('/api/data/forms/specialtyTypeForm', () => {
|
|
808
|
+
return HttpResponse.json({ error: 'Not found' }, { status: 404 });
|
|
809
|
+
}));
|
|
810
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
811
|
+
await user.click(await screen.findByRole('button', { name: 'Add' }));
|
|
812
|
+
const newRecordButton = await screen.findByRole('radio', { name: /new/i });
|
|
813
|
+
await user.click(newRecordButton);
|
|
814
|
+
await screen.findByText(/not found/i);
|
|
815
|
+
});
|
|
816
|
+
});
|
|
817
|
+
});
|
|
818
|
+
describe('when in dropdown view', () => {
|
|
819
|
+
describe('when mode is existing records only', () => {
|
|
820
|
+
const form = {
|
|
821
|
+
id: 'relatedObjectTestForm',
|
|
822
|
+
name: 'Related Object Test Form',
|
|
823
|
+
entries: [
|
|
824
|
+
{
|
|
825
|
+
type: 'input',
|
|
826
|
+
parameterId: 'specialtyType',
|
|
827
|
+
display: {
|
|
828
|
+
label: 'Speciality Type',
|
|
829
|
+
relatedObjectDisplay: 'dropdown',
|
|
830
|
+
mode: 'existingOnly',
|
|
831
|
+
},
|
|
832
|
+
},
|
|
833
|
+
],
|
|
834
|
+
actionId: '_update',
|
|
835
|
+
objectId: 'relatedObjectTestForm',
|
|
836
|
+
};
|
|
837
|
+
beforeEach(() => {
|
|
838
|
+
const relatedObjectTestFormObject = {
|
|
839
|
+
id: 'relatedObjectTestForm',
|
|
840
|
+
name: 'Related Object Test Form',
|
|
841
|
+
actions: [
|
|
842
|
+
{
|
|
843
|
+
id: '_update',
|
|
844
|
+
name: 'Update',
|
|
845
|
+
type: 'update',
|
|
846
|
+
parameters: [
|
|
847
|
+
{
|
|
848
|
+
id: 'specialtyType',
|
|
849
|
+
name: 'Related Object',
|
|
850
|
+
type: 'object',
|
|
851
|
+
objectId: 'specialtyType',
|
|
852
|
+
},
|
|
853
|
+
],
|
|
854
|
+
outputEvent: 'updated',
|
|
855
|
+
},
|
|
856
|
+
],
|
|
857
|
+
properties: [
|
|
858
|
+
{
|
|
859
|
+
id: 'specialtyType',
|
|
860
|
+
name: 'Related Object',
|
|
861
|
+
type: 'object',
|
|
862
|
+
},
|
|
863
|
+
],
|
|
864
|
+
};
|
|
865
|
+
setupTestMocks(relatedObjectTestFormObject, form);
|
|
866
|
+
const specialtyTypeObject = {
|
|
867
|
+
id: 'specialtyType',
|
|
868
|
+
name: 'Specialty Type',
|
|
869
|
+
actions: [
|
|
870
|
+
{
|
|
871
|
+
id: '_create',
|
|
872
|
+
name: 'Create',
|
|
873
|
+
type: 'create',
|
|
874
|
+
parameters: [],
|
|
875
|
+
outputEvent: 'created',
|
|
876
|
+
defaultFormId: 'specialtyType',
|
|
877
|
+
},
|
|
878
|
+
],
|
|
879
|
+
properties: [],
|
|
880
|
+
};
|
|
881
|
+
const specialtyTypeForm = {
|
|
882
|
+
id: 'specialtyTypeForm',
|
|
883
|
+
name: 'Specialty Type Form',
|
|
884
|
+
entries: [
|
|
885
|
+
{
|
|
886
|
+
type: 'content',
|
|
887
|
+
html: '<div>Specialty Type Form Content</div>',
|
|
888
|
+
},
|
|
889
|
+
],
|
|
890
|
+
actionId: '_update',
|
|
891
|
+
objectId: 'specialtyType',
|
|
892
|
+
};
|
|
893
|
+
setupTestMocks(specialtyTypeObject, specialtyTypeForm, [
|
|
894
|
+
{
|
|
895
|
+
id: 'rnSpecialtyType1',
|
|
896
|
+
name: 'RN Specialty Type #1',
|
|
897
|
+
objectId: 'specialtyType',
|
|
898
|
+
},
|
|
899
|
+
]);
|
|
900
|
+
});
|
|
901
|
+
it('does not provide option to add new object instances if mode is set to existing only', async () => {
|
|
902
|
+
const user = userEvent.setup();
|
|
903
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
904
|
+
// Navigate to and open dropdown
|
|
905
|
+
const dropdown = await screen.findByRole('combobox', { name: 'Speciality Type' });
|
|
906
|
+
await user.click(dropdown);
|
|
907
|
+
await screen.findByRole('listbox');
|
|
908
|
+
// Verify that the existing option is present
|
|
909
|
+
await screen.findByRole('option', { name: 'RN Specialty Type #1' });
|
|
910
|
+
// Verify that the "Add New" option is not present
|
|
911
|
+
expect(screen.queryByText('+ Add New')).not.toBeInTheDocument();
|
|
912
|
+
});
|
|
913
|
+
});
|
|
914
|
+
describe('when mode is default (allows both new and existing)', () => {
|
|
915
|
+
const form = {
|
|
916
|
+
id: 'relatedObjectTestForm',
|
|
917
|
+
name: 'Related Object Test Form',
|
|
918
|
+
entries: [
|
|
919
|
+
{
|
|
920
|
+
type: 'input',
|
|
921
|
+
parameterId: 'specialtyType',
|
|
922
|
+
display: {
|
|
923
|
+
label: 'Speciality Type',
|
|
924
|
+
relatedObjectDisplay: 'dropdown',
|
|
925
|
+
},
|
|
926
|
+
},
|
|
927
|
+
],
|
|
928
|
+
actionId: '_update',
|
|
929
|
+
objectId: 'relatedObjectTestForm',
|
|
930
|
+
};
|
|
931
|
+
beforeEach(() => {
|
|
932
|
+
const relatedObjectTestFormObject = {
|
|
933
|
+
id: 'relatedObjectTestForm',
|
|
934
|
+
name: 'Related Object Test Form',
|
|
935
|
+
actions: [
|
|
936
|
+
{
|
|
937
|
+
id: '_update',
|
|
938
|
+
name: 'Update',
|
|
939
|
+
type: 'update',
|
|
940
|
+
parameters: [
|
|
941
|
+
{
|
|
942
|
+
id: 'specialtyType',
|
|
943
|
+
name: 'Related Object',
|
|
944
|
+
type: 'object',
|
|
945
|
+
objectId: 'specialtyType',
|
|
946
|
+
},
|
|
947
|
+
],
|
|
948
|
+
outputEvent: 'updated',
|
|
949
|
+
},
|
|
950
|
+
],
|
|
951
|
+
properties: [
|
|
952
|
+
{
|
|
953
|
+
id: 'specialtyType',
|
|
954
|
+
name: 'Related Object',
|
|
955
|
+
type: 'object',
|
|
956
|
+
},
|
|
957
|
+
],
|
|
958
|
+
};
|
|
959
|
+
setupTestMocks(relatedObjectTestFormObject, form);
|
|
960
|
+
const specialtyTypeObject = {
|
|
961
|
+
id: 'specialtyType',
|
|
962
|
+
name: 'Specialty Type',
|
|
963
|
+
actions: [
|
|
964
|
+
{
|
|
965
|
+
id: '_create',
|
|
966
|
+
name: 'Create',
|
|
967
|
+
type: 'create',
|
|
968
|
+
parameters: [],
|
|
969
|
+
outputEvent: 'created',
|
|
970
|
+
defaultFormId: 'specialtyTypeForm',
|
|
971
|
+
},
|
|
972
|
+
],
|
|
973
|
+
properties: [],
|
|
974
|
+
};
|
|
975
|
+
const specialtyTypeForm = {
|
|
976
|
+
id: 'specialtyTypeForm',
|
|
977
|
+
name: 'Specialty Type Form',
|
|
978
|
+
entries: [
|
|
979
|
+
{
|
|
980
|
+
type: 'content',
|
|
981
|
+
html: '<div>Specialty Type Form Content</div>',
|
|
982
|
+
},
|
|
983
|
+
],
|
|
984
|
+
actionId: '_create',
|
|
985
|
+
objectId: 'specialtyType',
|
|
986
|
+
};
|
|
987
|
+
setupTestMocks(specialtyTypeObject, specialtyTypeForm, [
|
|
988
|
+
{
|
|
989
|
+
id: 'rnSpecialtyType1',
|
|
990
|
+
name: 'RN Specialty Type #1',
|
|
991
|
+
objectId: 'specialtyType',
|
|
992
|
+
},
|
|
993
|
+
]);
|
|
994
|
+
});
|
|
995
|
+
it('provides option to add new object instances', async () => {
|
|
996
|
+
const user = userEvent.setup();
|
|
997
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
998
|
+
// Navigate to and open dropdown
|
|
999
|
+
const dropdown = await screen.findByRole('combobox', { name: 'Speciality Type' });
|
|
1000
|
+
await user.click(dropdown);
|
|
1001
|
+
await waitFor(() => {
|
|
1002
|
+
expect(screen.getByText('+ Add New')).toBeInTheDocument();
|
|
1003
|
+
});
|
|
1004
|
+
await user.click(screen.getByText('+ Add New'));
|
|
1005
|
+
await screen.findByRole('dialog');
|
|
1006
|
+
await screen.findByText('Specialty Type Form Content');
|
|
1007
|
+
});
|
|
1008
|
+
it('allows related object instance selection', async () => {
|
|
1009
|
+
const user = userEvent.setup();
|
|
1010
|
+
render(React.createElement(FormRenderer, { form: form, onChange: () => { } }));
|
|
1011
|
+
// Navigate to and open dropdown
|
|
1012
|
+
const dropdown = await screen.findByRole('combobox', { name: 'Speciality Type' });
|
|
1013
|
+
await user.click(dropdown);
|
|
1014
|
+
const option = await screen.findByRole('option', { name: 'RN Specialty Type #1' });
|
|
1015
|
+
await user.click(option);
|
|
1016
|
+
// Verify option has been removed from the document
|
|
1017
|
+
expect(option).not.toBeInTheDocument();
|
|
1018
|
+
// Verify selection
|
|
1019
|
+
screen.getByText('RN Specialty Type #1');
|
|
1020
|
+
});
|
|
1021
|
+
});
|
|
1022
|
+
});
|
|
1023
|
+
});
|
|
391
1024
|
});
|