@centreon/ui 26.12.1 → 26.12.3
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/package.json +6 -3
- package/public/mockServiceWorker.js +31 -8
- package/src/Dashboard/Dashboard.browser.test.tsx +107 -0
- package/src/Form/CollapsibleGroup.tsx +6 -33
- package/src/Form/Form.browser.test.tsx +553 -0
- package/src/Form/Inputs/ExclusiveCheckboxGroup.browser.test.tsx +304 -0
- package/src/Form/Inputs/Grid.tsx +1 -2
- package/src/Form/Inputs/SegmentedButtons.browser.test.tsx +113 -0
- package/src/Form/Inputs/index.tsx +10 -52
- package/src/InputField/Number/Number.browser.test.tsx +109 -0
- package/src/InputField/Select/Autocomplete/Connected/Multi/MultiConnectedAutocompleteField.browser.test.tsx +250 -0
- package/src/Listing/Listing.browser.test.tsx +476 -0
- package/src/Module/Module.browser.test.tsx +145 -0
- package/src/Pagination/Pagination.browser.test.tsx +184 -0
- package/src/RichTextEditor/RichTextEditor.browser.test.tsx +567 -0
- package/src/RichTextEditor/plugins/FloatingLinkEditorPlugin.tsx +3 -1
- package/src/TimePeriods/ResolutionTimePeriod.browser.test.tsx +143 -0
- package/src/TimePeriods/TimePeriods.browser.test.tsx +468 -0
- package/src/Typography/FluidTypography/FluidTypography.browser.test.tsx +54 -0
- package/src/api/useMutationQuery/useMutationQuery.browser.test.tsx +154 -0
- package/src/components/CollapsibleItem/CollapsibleItem.browser.test.tsx +120 -0
- package/src/components/CopyCommand/CopyCommand.browser.test.tsx +287 -0
- package/src/components/CrudPage/CrudPage.browser.test.tsx +659 -0
- package/src/components/DataTable/DataTable.browser.test.tsx +257 -0
- package/src/components/Form/AccessRights/AccessRights.browser.test.tsx +527 -0
- package/src/components/ItemComposition/ItemComposition.browser.test.tsx +172 -0
- package/src/components/Layout/PageLayout.browser.test.tsx +114 -0
- package/src/components/Modal/ConfirmationModal/ConfirmationModal.browser.test.tsx +237 -0
- package/src/components/SortableEntriesList/SortableEntriesList.browser.test.tsx +981 -0
- package/src/components/Tabs/Tabs.browser.test.tsx +115 -0
- package/src/utils/useFullscreen/Fullscreen.browser.test.tsx +176 -0
- package/src/utils/useLocale/useLocale.browser.test.tsx +49 -0
- package/src/utils/useLocaleTimezoneDate/{LocaleTimezoneDate.cypress.spec.tsx → LocaleTimezoneDate.browser.test.tsx} +24 -11
- package/src/Dashboard/Dashboard.cypress.spec.tsx +0 -71
- package/src/Form/Form.cypress.spec.tsx +0 -306
- package/src/Form/Inputs/ExclusiveCheckboxGroup.cypress.spec.tsx +0 -236
- package/src/Form/Inputs/SegmentedButtons.cypress.spec.tsx +0 -101
- package/src/InputField/Number/Number.cypress.spec.tsx +0 -89
- package/src/InputField/Select/Autocomplete/Connected/Multi/MultiConnectedAutocompleteField.cypress.spec.tsx +0 -182
- package/src/Listing/Listing.cypress.spec.tsx +0 -349
- package/src/Module/Module.cypress.spec.tsx +0 -127
- package/src/Pagination/Pagination.cypress.spec.tsx +0 -140
- package/src/RichTextEditor/RichTextEditor.cypress.spec.tsx +0 -408
- package/src/TimePeriods/ResolutionTimePeriod.cypress.spec.tsx +0 -74
- package/src/TimePeriods/TimePeriods.cypress.spec.tsx +0 -488
- package/src/Typography/FluidTypography/FluidTypography.cypress.spec.tsx +0 -27
- package/src/api/useMutationQuery/useMutationQuery.cypress.spec.tsx +0 -93
- package/src/components/CollapsibleItem/CollapsibleItem.cypress.spec.tsx +0 -76
- package/src/components/CopyCommand/CopyCommand.cypress.spec.tsx +0 -167
- package/src/components/CrudPage/CrudPage.cypress.spec.tsx +0 -561
- package/src/components/DataTable/DataTable.cypress.spec.tsx +0 -174
- package/src/components/Form/AccessRights/AccessRights.cypress.spec.tsx +0 -376
- package/src/components/ItemComposition/ItemComposition.cypress.spec.tsx +0 -112
- package/src/components/Layout/PageLayout.cypress.spec.tsx +0 -64
- package/src/components/Modal/ConfirmationModal/ConfirmationModal.cypress.spec.tsx +0 -171
- package/src/components/SortableEntriesList/SortableEntriesList.cypress.spec.tsx +0 -792
- package/src/components/Tabs/Tabs.cypress.spec.tsx +0 -69
- package/src/utils/useFullscreen/Fullscreen.cypress.spec.tsx +0 -130
- package/src/utils/useLocale/useLocale.cypress.spec.tsx +0 -40
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
import { Typography } from '@mui/material';
|
|
2
|
+
|
|
3
|
+
import { ThemeMode, userAtom } from '@centreon/ui-context';
|
|
4
|
+
|
|
5
|
+
import { faker } from '@faker-js/faker';
|
|
6
|
+
import { rs } from '@rstest/core';
|
|
7
|
+
import { render } from '@test-setup/render';
|
|
8
|
+
import { screen, waitFor, within } from '@testing-library/react';
|
|
9
|
+
import userEvent from '@testing-library/user-event';
|
|
10
|
+
import { useFormikContext } from 'formik';
|
|
11
|
+
import { createStore, Provider } from 'jotai';
|
|
12
|
+
import { object } from 'yup';
|
|
13
|
+
|
|
14
|
+
import type { SelectEntry } from '..';
|
|
15
|
+
import { Button } from '../components';
|
|
16
|
+
import ThemeProvider from '../ThemeProvider';
|
|
17
|
+
import { Form } from './Form';
|
|
18
|
+
import { type InputProps, InputType } from './Inputs/models';
|
|
19
|
+
|
|
20
|
+
faker.seed(42);
|
|
21
|
+
|
|
22
|
+
interface Item {
|
|
23
|
+
alias: string;
|
|
24
|
+
id: number;
|
|
25
|
+
name: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface ListValues {
|
|
29
|
+
list: Array<Item>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const AddItem = ({
|
|
33
|
+
addItem
|
|
34
|
+
}: {
|
|
35
|
+
addItem: (item: SelectEntry) => void;
|
|
36
|
+
}): JSX.Element => {
|
|
37
|
+
const { values } = useFormikContext<ListValues>();
|
|
38
|
+
const add = (): void => {
|
|
39
|
+
addItem({
|
|
40
|
+
alias: faker.company.name(),
|
|
41
|
+
id: values.list.length,
|
|
42
|
+
name: faker.person.firstName()
|
|
43
|
+
} as SelectEntry);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Button onClick={add} variant="ghost">
|
|
48
|
+
Add item
|
|
49
|
+
</Button>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const SortContent = ({
|
|
54
|
+
name,
|
|
55
|
+
alias
|
|
56
|
+
}: {
|
|
57
|
+
alias: string;
|
|
58
|
+
name: string;
|
|
59
|
+
}): JSX.Element => (
|
|
60
|
+
<Typography>
|
|
61
|
+
{name} ({alias})
|
|
62
|
+
</Typography>
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const initializeFormList = (): void => {
|
|
66
|
+
render(
|
|
67
|
+
<Form
|
|
68
|
+
initialValues={{
|
|
69
|
+
list: []
|
|
70
|
+
}}
|
|
71
|
+
inputs={[
|
|
72
|
+
{
|
|
73
|
+
fieldName: 'list',
|
|
74
|
+
group: '',
|
|
75
|
+
label: '',
|
|
76
|
+
list: {
|
|
77
|
+
AddItem,
|
|
78
|
+
addItemLabel: 'Add an item to the list',
|
|
79
|
+
itemProps: ['id', 'name', 'alias'],
|
|
80
|
+
SortContent: SortContent as React.ComponentType<object>,
|
|
81
|
+
sortLabel: 'Sort items'
|
|
82
|
+
},
|
|
83
|
+
type: InputType.List
|
|
84
|
+
}
|
|
85
|
+
]}
|
|
86
|
+
submit={rs.fn()}
|
|
87
|
+
validationSchema={object()}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// A keyboard drag of the handle: space to pick the item up, an arrow to move
|
|
93
|
+
// it one place, space to drop it. dnd-kit handles a key once the previous one
|
|
94
|
+
// took effect, so each step is awaited: the item pressed once picked up, the
|
|
95
|
+
// other item making way after the arrow, no item pressed once dropped.
|
|
96
|
+
const moveSortableElementUsingAriaLabel = async ({
|
|
97
|
+
ariaLabel,
|
|
98
|
+
direction
|
|
99
|
+
}: {
|
|
100
|
+
ariaLabel: string;
|
|
101
|
+
direction: 'down' | 'up';
|
|
102
|
+
}): Promise<void> => {
|
|
103
|
+
const handle = screen.getByLabelText(ariaLabel);
|
|
104
|
+
const item = handle.closest('[aria-roledescription]') as HTMLElement;
|
|
105
|
+
const isShifted = (element: Element): boolean =>
|
|
106
|
+
/translate3d\(0px, -?[1-9]/.test((element as HTMLElement).style.transform);
|
|
107
|
+
|
|
108
|
+
handle.focus();
|
|
109
|
+
await userEvent.keyboard(' ');
|
|
110
|
+
await waitFor(() => {
|
|
111
|
+
expect(item).toHaveAttribute('aria-pressed', 'true');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
await userEvent.keyboard(direction === 'down' ? '{ArrowDown}' : '{ArrowUp}');
|
|
115
|
+
await waitFor(() => {
|
|
116
|
+
expect(
|
|
117
|
+
Array.from(document.querySelectorAll('[aria-roledescription]')).some(
|
|
118
|
+
(other) => other !== item && isShifted(other)
|
|
119
|
+
)
|
|
120
|
+
).toBe(true);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
await userEvent.keyboard(' ');
|
|
124
|
+
await waitFor(() => {
|
|
125
|
+
expect(document.querySelector('[aria-pressed="true"]')).toBeNull();
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const getItemTexts = (): Array<string | null> =>
|
|
130
|
+
Array.from(document.querySelectorAll('[aria-label^="sort-"]')).map(
|
|
131
|
+
(handle) => handle.parentElement?.textContent ?? null
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
const getSaveButton = (): HTMLElement => screen.getByLabelText('save button');
|
|
135
|
+
|
|
136
|
+
const expectFormButtons = (): void => {
|
|
137
|
+
expect(screen.getByRole('button', { name: 'Reset' })).toBeVisible();
|
|
138
|
+
expect(getSaveButton()).toBeVisible();
|
|
139
|
+
expect(getSaveButton()).toHaveTextContent('Save');
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
describe('Form list', () => {
|
|
143
|
+
beforeEach(() => {
|
|
144
|
+
expect.hasAssertions();
|
|
145
|
+
});
|
|
146
|
+
beforeEach(initializeFormList);
|
|
147
|
+
|
|
148
|
+
it('adds an element to the list', async () => {
|
|
149
|
+
expect(await screen.findByText('Add an item to the list')).toBeVisible();
|
|
150
|
+
expect(screen.getByText('Sort items')).toBeVisible();
|
|
151
|
+
|
|
152
|
+
await userEvent.click(screen.getByText('Add item'));
|
|
153
|
+
|
|
154
|
+
expect(await screen.findByLabelText('sort-0')).toBeVisible();
|
|
155
|
+
expect(screen.getByLabelText('delete-0')).toBeVisible();
|
|
156
|
+
expect(await screen.findByText('Lavinia (Wiegand LLC)')).toBeVisible();
|
|
157
|
+
|
|
158
|
+
expect(getItemTexts()).toEqual(['Lavinia (Wiegand LLC)']);
|
|
159
|
+
expectFormButtons();
|
|
160
|
+
await waitFor(() => {
|
|
161
|
+
expect(getSaveButton()).toBeEnabled();
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('sorts elements in the list', async () => {
|
|
166
|
+
expect(await screen.findByText('Add an item to the list')).toBeVisible();
|
|
167
|
+
expect(screen.getByText('Sort items')).toBeVisible();
|
|
168
|
+
|
|
169
|
+
await userEvent.click(screen.getByText('Add item'));
|
|
170
|
+
await userEvent.click(screen.getByText('Add item'));
|
|
171
|
+
|
|
172
|
+
expect(await screen.findByLabelText('sort-0')).toBeVisible();
|
|
173
|
+
expect(screen.getByLabelText('delete-0')).toBeVisible();
|
|
174
|
+
expect(await screen.findByText('Sammie (Crist - Beer)')).toBeVisible();
|
|
175
|
+
expect(await screen.findByLabelText('sort-1')).toBeVisible();
|
|
176
|
+
expect(screen.getByLabelText('delete-1')).toBeVisible();
|
|
177
|
+
expect(await screen.findByText('Waino (Quigley Group)')).toBeVisible();
|
|
178
|
+
|
|
179
|
+
expect(getItemTexts()).toEqual([
|
|
180
|
+
'Sammie (Crist - Beer)',
|
|
181
|
+
'Waino (Quigley Group)'
|
|
182
|
+
]);
|
|
183
|
+
|
|
184
|
+
await moveSortableElementUsingAriaLabel({
|
|
185
|
+
ariaLabel: 'sort-0',
|
|
186
|
+
direction: 'down'
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
expect(await screen.findByText('Waino (Quigley Group)')).toBeVisible();
|
|
190
|
+
expect(screen.getAllByText('Sammie (Crist - Beer)')[0]).toBeVisible();
|
|
191
|
+
|
|
192
|
+
// The moved item is below the other one.
|
|
193
|
+
await waitFor(() => {
|
|
194
|
+
expect(getItemTexts()).toEqual([
|
|
195
|
+
'Waino (Quigley Group)',
|
|
196
|
+
'Sammie (Crist - Beer)'
|
|
197
|
+
]);
|
|
198
|
+
});
|
|
199
|
+
expectFormButtons();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('removes an element from the list', async () => {
|
|
203
|
+
expect(await screen.findByText('Add an item to the list')).toBeVisible();
|
|
204
|
+
expect(screen.getByText('Sort items')).toBeVisible();
|
|
205
|
+
|
|
206
|
+
await userEvent.click(screen.getByText('Add item'));
|
|
207
|
+
await userEvent.click(screen.getByText('Add item'));
|
|
208
|
+
|
|
209
|
+
expect(await screen.findByLabelText('sort-0')).toBeVisible();
|
|
210
|
+
expect(screen.getByLabelText('delete-0')).toBeVisible();
|
|
211
|
+
expect(
|
|
212
|
+
await screen.findByText('Elliott (Effertz, Deckow and Deckow)')
|
|
213
|
+
).toBeVisible();
|
|
214
|
+
expect(await screen.findByLabelText('sort-1')).toBeVisible();
|
|
215
|
+
expect(screen.getByLabelText('delete-1')).toBeVisible();
|
|
216
|
+
expect(await screen.findByText('Leopoldo (Kemmer Inc)')).toBeVisible();
|
|
217
|
+
|
|
218
|
+
await userEvent.click(screen.getByLabelText('delete-0'));
|
|
219
|
+
|
|
220
|
+
await waitFor(() => {
|
|
221
|
+
expect(
|
|
222
|
+
screen.queryByText('Elliott (Effertz, Deckow and Deckow)')
|
|
223
|
+
).not.toBeInTheDocument();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
expect(getItemTexts()).toEqual(['Leopoldo (Kemmer Inc)']);
|
|
227
|
+
expectFormButtons();
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// The rstest viewport (1000px tall) fits the whole form: the spacer keeps the
|
|
232
|
+
// page scrollable for the scroll-to-section test.
|
|
233
|
+
const initializeFormWithSections = (): void => {
|
|
234
|
+
render(
|
|
235
|
+
<>
|
|
236
|
+
<Form
|
|
237
|
+
groups={[
|
|
238
|
+
{
|
|
239
|
+
name: 'First group',
|
|
240
|
+
order: 1
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
name: 'Third group',
|
|
244
|
+
order: 3
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: 'Second group',
|
|
248
|
+
order: 2
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
name: 'Fourth group',
|
|
252
|
+
order: 4
|
|
253
|
+
}
|
|
254
|
+
]}
|
|
255
|
+
initialValues={{
|
|
256
|
+
list: []
|
|
257
|
+
}}
|
|
258
|
+
inputs={[
|
|
259
|
+
{
|
|
260
|
+
fieldName: 'First name',
|
|
261
|
+
group: 'First group',
|
|
262
|
+
label: 'Name',
|
|
263
|
+
type: InputType.Text
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
fieldName: 'Divider',
|
|
267
|
+
group: 'First group',
|
|
268
|
+
label: 'Divider',
|
|
269
|
+
type: InputType.Divider
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
fieldName: 'Second name',
|
|
273
|
+
group: 'First group',
|
|
274
|
+
label: 'Name',
|
|
275
|
+
type: InputType.Text
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
fieldName: 'Third name',
|
|
279
|
+
group: 'First group',
|
|
280
|
+
label: 'Name',
|
|
281
|
+
type: InputType.Text
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
fieldName: 'Fourth name',
|
|
285
|
+
group: 'First group',
|
|
286
|
+
label: 'Name',
|
|
287
|
+
type: InputType.Text
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
fieldName: 'Fifth name',
|
|
291
|
+
group: 'First group',
|
|
292
|
+
label: 'Name',
|
|
293
|
+
type: InputType.Text
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
fieldName: 'Sixth name',
|
|
297
|
+
group: 'First group',
|
|
298
|
+
label: 'Name',
|
|
299
|
+
type: InputType.Text
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
fieldName: 'Seventh name',
|
|
303
|
+
group: 'First group',
|
|
304
|
+
label: 'Name',
|
|
305
|
+
type: InputType.Text
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
fieldName: 'Eighth name',
|
|
309
|
+
group: 'First group',
|
|
310
|
+
label: 'Name',
|
|
311
|
+
type: InputType.Text
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
fieldName: 'Ninth name',
|
|
315
|
+
group: 'First group',
|
|
316
|
+
label: 'Name',
|
|
317
|
+
type: InputType.Text
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
fieldName: 'First second group name',
|
|
321
|
+
group: 'Second group',
|
|
322
|
+
label: 'Name',
|
|
323
|
+
type: InputType.Text
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
fieldName: 'First third group name',
|
|
327
|
+
group: 'Third group',
|
|
328
|
+
label: 'Name',
|
|
329
|
+
type: InputType.Text
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
fieldName: 'First fourth group name',
|
|
333
|
+
group: 'Fourth group',
|
|
334
|
+
label: 'Name',
|
|
335
|
+
type: InputType.Text
|
|
336
|
+
}
|
|
337
|
+
]}
|
|
338
|
+
isCollapsible
|
|
339
|
+
submit={rs.fn()}
|
|
340
|
+
validationSchema={object()}
|
|
341
|
+
/>
|
|
342
|
+
<div style={{ height: 1000 }} />
|
|
343
|
+
</>
|
|
344
|
+
);
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
const initializeFile = (): void => {
|
|
348
|
+
render(
|
|
349
|
+
<Form
|
|
350
|
+
initialValues={{
|
|
351
|
+
list: []
|
|
352
|
+
}}
|
|
353
|
+
inputs={[
|
|
354
|
+
{
|
|
355
|
+
fieldName: 'list',
|
|
356
|
+
// No custom drop zone content: the default one is shown.
|
|
357
|
+
file: {
|
|
358
|
+
accept: '.json'
|
|
359
|
+
} as InputProps['file'],
|
|
360
|
+
group: '',
|
|
361
|
+
label: 'json',
|
|
362
|
+
type: InputType.File
|
|
363
|
+
}
|
|
364
|
+
]}
|
|
365
|
+
submit={rs.fn()}
|
|
366
|
+
validationSchema={object()}
|
|
367
|
+
/>
|
|
368
|
+
);
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
describe('File', () => {
|
|
372
|
+
beforeEach(() => {
|
|
373
|
+
expect.hasAssertions();
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
it('uploads a file when a file is selected', async () => {
|
|
377
|
+
initializeFile();
|
|
378
|
+
|
|
379
|
+
expect(await screen.findByText('Drop or select a file')).toBeVisible();
|
|
380
|
+
await userEvent.upload(
|
|
381
|
+
screen.getByLabelText('select a file'),
|
|
382
|
+
new File(['{}'], 'package.json', { type: 'application/json' })
|
|
383
|
+
);
|
|
384
|
+
expect(await screen.findByText('package.json')).toBeVisible();
|
|
385
|
+
|
|
386
|
+
// The field label above the drop zone, and the selected
|
|
387
|
+
// file listed with a file icon.
|
|
388
|
+
expect(screen.getByRole('heading', { name: 'json' })).toBeVisible();
|
|
389
|
+
expect(
|
|
390
|
+
within(
|
|
391
|
+
screen.getByText('package.json').parentElement as HTMLElement
|
|
392
|
+
).getByTestId('DescriptionOutlinedIcon')
|
|
393
|
+
).toBeVisible();
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
describe('Form with sections', () => {
|
|
398
|
+
beforeEach(() => {
|
|
399
|
+
expect.hasAssertions();
|
|
400
|
+
});
|
|
401
|
+
beforeEach(initializeFormWithSections);
|
|
402
|
+
|
|
403
|
+
it('displays sections when correct amount of sections', async () => {
|
|
404
|
+
expect((await screen.findAllByText('First group'))[0]).toBeVisible();
|
|
405
|
+
expect(screen.getAllByText('Second group')[0]).toBeVisible();
|
|
406
|
+
expect(screen.getAllByText('Third group')[0]).toBeVisible();
|
|
407
|
+
expect(screen.getAllByText('Fourth group')[0]).toBeVisible();
|
|
408
|
+
|
|
409
|
+
// The section tabs sorted by group order, the first one
|
|
410
|
+
// selected, and the first group expanded with its nine fields.
|
|
411
|
+
expect(screen.getAllByRole('tab').map((tab) => tab.textContent)).toEqual([
|
|
412
|
+
'First group',
|
|
413
|
+
'Second group',
|
|
414
|
+
'Third group',
|
|
415
|
+
'Fourth group'
|
|
416
|
+
]);
|
|
417
|
+
expect(screen.getByRole('tab', { name: 'First group' })).toHaveAttribute(
|
|
418
|
+
'aria-selected',
|
|
419
|
+
'true'
|
|
420
|
+
);
|
|
421
|
+
expect(
|
|
422
|
+
screen
|
|
423
|
+
.getAllByLabelText('Name')
|
|
424
|
+
.filter((input) => input.tagName === 'INPUT')
|
|
425
|
+
.filter(
|
|
426
|
+
(input) =>
|
|
427
|
+
input.checkVisibility() &&
|
|
428
|
+
getComputedStyle(input).visibility !== 'hidden'
|
|
429
|
+
)
|
|
430
|
+
).toHaveLength(9);
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
it('scrolls correctly to section', async () => {
|
|
434
|
+
const initialScrollY = window.scrollY;
|
|
435
|
+
|
|
436
|
+
await userEvent.click(
|
|
437
|
+
await screen.findByRole('tab', { name: 'Third group' })
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
await waitFor(() => {
|
|
441
|
+
expect(window.scrollY).toBeGreaterThan(initialScrollY);
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
expect(screen.getByRole('tab', { name: 'Third group' })).toHaveAttribute(
|
|
445
|
+
'aria-selected',
|
|
446
|
+
'true'
|
|
447
|
+
);
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// The theme mode comes from the user atom, and the Tailwind tokens from the
|
|
452
|
+
// `dark` class on the document.
|
|
453
|
+
const initializeFormTitles = (themeMode: ThemeMode): void => {
|
|
454
|
+
const store = createStore();
|
|
455
|
+
store.set(userAtom, { ...store.get(userAtom), themeMode });
|
|
456
|
+
|
|
457
|
+
document.documentElement.classList.toggle(
|
|
458
|
+
'dark',
|
|
459
|
+
themeMode === ThemeMode.dark
|
|
460
|
+
);
|
|
461
|
+
|
|
462
|
+
render(
|
|
463
|
+
<Provider store={store}>
|
|
464
|
+
<ThemeProvider>
|
|
465
|
+
<Form
|
|
466
|
+
areGroupsOpen
|
|
467
|
+
groups={[{ name: 'Titles section', order: 1 }]}
|
|
468
|
+
initialValues={{ gridField: '', topLevelField: '' }}
|
|
469
|
+
inputs={[
|
|
470
|
+
{
|
|
471
|
+
additionalLabel: 'Top level block title',
|
|
472
|
+
fieldName: 'topLevelField',
|
|
473
|
+
group: 'Titles section',
|
|
474
|
+
label: 'Top level field',
|
|
475
|
+
type: InputType.Text
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
fieldName: '',
|
|
479
|
+
grid: {
|
|
480
|
+
columns: [
|
|
481
|
+
{
|
|
482
|
+
additionalLabel: 'Grid block title',
|
|
483
|
+
fieldName: 'gridField',
|
|
484
|
+
label: 'Grid field',
|
|
485
|
+
type: InputType.Text
|
|
486
|
+
}
|
|
487
|
+
]
|
|
488
|
+
},
|
|
489
|
+
group: 'Titles section',
|
|
490
|
+
label: 'Grid',
|
|
491
|
+
type: InputType.Grid
|
|
492
|
+
}
|
|
493
|
+
]}
|
|
494
|
+
isCollapsible
|
|
495
|
+
submit={rs.fn()}
|
|
496
|
+
validationSchema={object()}
|
|
497
|
+
/>
|
|
498
|
+
</ThemeProvider>
|
|
499
|
+
</Provider>
|
|
500
|
+
);
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
const textPrimaryColor = {
|
|
504
|
+
[ThemeMode.dark]: 'rgb(255, 255, 255)',
|
|
505
|
+
[ThemeMode.light]: 'rgb(0, 0, 0)'
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
[ThemeMode.light, ThemeMode.dark].forEach((themeMode) => {
|
|
509
|
+
describe(`Form titles in ${themeMode} mode`, () => {
|
|
510
|
+
beforeEach(() => {
|
|
511
|
+
expect.hasAssertions();
|
|
512
|
+
});
|
|
513
|
+
beforeEach(() => initializeFormTitles(themeMode));
|
|
514
|
+
|
|
515
|
+
afterEach(() => {
|
|
516
|
+
document.documentElement.classList.remove('dark');
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
it('displays the section title in 16px medium on a 24px line', async () => {
|
|
520
|
+
const title = await screen.findByText('Titles section');
|
|
521
|
+
|
|
522
|
+
expect(title).toHaveStyle({
|
|
523
|
+
fontSize: '16px',
|
|
524
|
+
fontWeight: '500',
|
|
525
|
+
lineHeight: '24px'
|
|
526
|
+
});
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
it('rounds the collapsible section header with an 8px radius', async () => {
|
|
530
|
+
expect(await screen.findByLabelText('Titles section')).toHaveStyle({
|
|
531
|
+
borderRadius: '8px'
|
|
532
|
+
});
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
it('displays the grid block title in 16px bold with the text colour', async () => {
|
|
536
|
+
expect(await screen.findByText('Grid block title')).toHaveStyle({
|
|
537
|
+
color: textPrimaryColor[themeMode],
|
|
538
|
+
fontSize: '16px',
|
|
539
|
+
fontWeight: '700',
|
|
540
|
+
lineHeight: '24px'
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
it('displays the top level block title like the grid block title', async () => {
|
|
545
|
+
expect(await screen.findByText('Top level block title')).toHaveStyle({
|
|
546
|
+
color: textPrimaryColor[themeMode],
|
|
547
|
+
fontSize: '16px',
|
|
548
|
+
fontWeight: '700',
|
|
549
|
+
lineHeight: '24px'
|
|
550
|
+
});
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
});
|