@centreon/ui 26.12.0 → 26.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -3
- package/public/mockServiceWorker.js +31 -8
- package/src/Dashboard/Dashboard.browser.test.tsx +107 -0
- package/src/Form/Form.browser.test.tsx +445 -0
- package/src/Form/Inputs/ExclusiveCheckboxGroup.browser.test.tsx +304 -0
- package/src/Form/Inputs/SegmentedButtons.browser.test.tsx +113 -0
- 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/Panel/Section/index.test.tsx +1 -1
- 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,250 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Method,
|
|
3
|
+
MultiConnectedAutocompleteField,
|
|
4
|
+
type SelectEntry,
|
|
5
|
+
TestQueryProvider
|
|
6
|
+
} from '@centreon/ui';
|
|
7
|
+
|
|
8
|
+
import { interceptAPIRequest, waitForRequest } from '@test-setup/api';
|
|
9
|
+
import { render } from '@test-setup/render';
|
|
10
|
+
import { screen, waitFor, within } from '@testing-library/react';
|
|
11
|
+
import userEvent from '@testing-library/user-event';
|
|
12
|
+
import i18next from 'i18next';
|
|
13
|
+
import { useState } from 'react';
|
|
14
|
+
import { initReactI18next } from 'react-i18next';
|
|
15
|
+
|
|
16
|
+
import { labelSelectAll, labelUnSelectAll } from '../../../../translatedLabels';
|
|
17
|
+
import { baseEndpoint, getEndpoint, label, placeholder } from './utils';
|
|
18
|
+
|
|
19
|
+
const optionOne = 'My Option 1';
|
|
20
|
+
|
|
21
|
+
// The option list and search result the endpoint mocks return.
|
|
22
|
+
const listOptions = {
|
|
23
|
+
meta: { limit: 5, page: 1, total: 5 },
|
|
24
|
+
result: [
|
|
25
|
+
{ id: 0, name: 'My Option 1' },
|
|
26
|
+
{ id: 1, name: 'My Option 2' },
|
|
27
|
+
{ id: 2, name: 'My Option 3' },
|
|
28
|
+
{ id: 3, name: 'My Option 4' },
|
|
29
|
+
{ id: 4, name: 'My Option 5' }
|
|
30
|
+
]
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const searchedOption = {
|
|
34
|
+
meta: { limit: 1, page: 1, total: 1 },
|
|
35
|
+
result: [{ id: 0, name: 'My Option 1' }]
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const optionNames = listOptions.result.map(({ name }) => name);
|
|
39
|
+
|
|
40
|
+
// Passed down to the multi autocomplete, though the connected field's type
|
|
41
|
+
// does not declare it.
|
|
42
|
+
const multiAutocompleteProps: Record<string, unknown> = {
|
|
43
|
+
disableSelectAll: false
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const Component = (): JSX.Element => {
|
|
47
|
+
const [values, setValues] = useState<Array<SelectEntry>>([]);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<TestQueryProvider>
|
|
51
|
+
<div style={{ paddingTop: 20 }}>
|
|
52
|
+
<MultiConnectedAutocompleteField
|
|
53
|
+
{...multiAutocompleteProps}
|
|
54
|
+
field="host.name"
|
|
55
|
+
getEndpoint={getEndpoint}
|
|
56
|
+
label={label}
|
|
57
|
+
onChange={(_, item) => setValues(item as Array<SelectEntry>)}
|
|
58
|
+
placeholder={placeholder}
|
|
59
|
+
value={values}
|
|
60
|
+
/>
|
|
61
|
+
</div>
|
|
62
|
+
</TestQueryProvider>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const getInput = (): HTMLInputElement =>
|
|
67
|
+
document.querySelector(
|
|
68
|
+
'[data-testid="Multi Connected Autocomplete"]'
|
|
69
|
+
) as HTMLInputElement;
|
|
70
|
+
|
|
71
|
+
// The last one: a closing list can still be in the page.
|
|
72
|
+
const findListOptions = async (): Promise<HTMLElement> =>
|
|
73
|
+
(await screen.findAllByRole('presentation')).at(-1) as HTMLElement;
|
|
74
|
+
|
|
75
|
+
const getOptionTexts = (listOptionsElement: HTMLElement): Array<string> =>
|
|
76
|
+
within(listOptionsElement)
|
|
77
|
+
.queryAllByText(/^My Option \d$/)
|
|
78
|
+
.map((option) => option.textContent ?? '');
|
|
79
|
+
|
|
80
|
+
const getOptionCheckboxes = (listOptionsElement: HTMLElement) =>
|
|
81
|
+
within(listOptionsElement).getAllByRole('checkbox');
|
|
82
|
+
|
|
83
|
+
describe('Multi connected autocomplete', () => {
|
|
84
|
+
beforeEach(() => {
|
|
85
|
+
expect.hasAssertions();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
beforeEach(() => {
|
|
89
|
+
i18next.use(initReactI18next).init({
|
|
90
|
+
lng: 'en',
|
|
91
|
+
resources: {}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
interceptAPIRequest({
|
|
95
|
+
alias: 'getListOptions',
|
|
96
|
+
method: Method.GET,
|
|
97
|
+
path: `${baseEndpoint}**`,
|
|
98
|
+
response: listOptions
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
interceptAPIRequest({
|
|
102
|
+
alias: 'getSearchedOption',
|
|
103
|
+
method: Method.GET,
|
|
104
|
+
path: `${baseEndpoint}**`,
|
|
105
|
+
query: {
|
|
106
|
+
name: 'search',
|
|
107
|
+
value: JSON.stringify({
|
|
108
|
+
$and: [{ $and: [{ 'host.name': { $lk: `%${optionOne}%` } }] }]
|
|
109
|
+
})
|
|
110
|
+
},
|
|
111
|
+
response: searchedOption
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
render(<Component />);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('displays and hides the list when the user double-clicks on the input', async () => {
|
|
118
|
+
expect((await screen.findAllByText(label))[0]).toBeVisible();
|
|
119
|
+
|
|
120
|
+
const input = getInput();
|
|
121
|
+
|
|
122
|
+
await userEvent.click(input);
|
|
123
|
+
|
|
124
|
+
await waitForRequest('@getListOptions');
|
|
125
|
+
|
|
126
|
+
expect(input).toHaveAttribute('placeholder', placeholder);
|
|
127
|
+
|
|
128
|
+
const listOptionsElement = await findListOptions();
|
|
129
|
+
|
|
130
|
+
expect(listOptionsElement).toBeVisible();
|
|
131
|
+
|
|
132
|
+
// The list re-renders its options: compared by text, not by element.
|
|
133
|
+
await waitFor(() => {
|
|
134
|
+
expect(getOptionTexts(listOptionsElement)).toEqual(optionNames);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// The count of options, the select all button and the five options
|
|
138
|
+
// unchecked.
|
|
139
|
+
expect(
|
|
140
|
+
within(listOptionsElement).getByText('5 element(s) found')
|
|
141
|
+
).toBeVisible();
|
|
142
|
+
expect(within(listOptionsElement).getByText(labelSelectAll)).toBeVisible();
|
|
143
|
+
getOptionCheckboxes(listOptionsElement).forEach((checkbox) => {
|
|
144
|
+
expect(checkbox).not.toBeChecked();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
await userEvent.click(input);
|
|
148
|
+
|
|
149
|
+
await waitFor(() => {
|
|
150
|
+
expect(listOptionsElement).not.toBeInTheDocument();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// No option list, and nothing selected.
|
|
154
|
+
expect(screen.queryByRole('presentation')).not.toBeInTheDocument();
|
|
155
|
+
expect(screen.queryByTestId('CancelIcon')).not.toBeInTheDocument();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('displays all options on the list when the user searches for and selects an option', async () => {
|
|
159
|
+
const input = getInput();
|
|
160
|
+
|
|
161
|
+
await userEvent.click(input);
|
|
162
|
+
|
|
163
|
+
await waitForRequest('@getListOptions');
|
|
164
|
+
|
|
165
|
+
const listOptionsElement = await findListOptions();
|
|
166
|
+
|
|
167
|
+
expect(listOptionsElement).toBeVisible();
|
|
168
|
+
|
|
169
|
+
await userEvent.type(input, optionOne);
|
|
170
|
+
|
|
171
|
+
await waitForRequest('@getSearchedOption');
|
|
172
|
+
|
|
173
|
+
await waitFor(() => {
|
|
174
|
+
expect(listOptionsElement.querySelectorAll('li')).toHaveLength(6);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
await userEvent.click(document.querySelectorAll('[type="checkbox"]')[0]);
|
|
178
|
+
|
|
179
|
+
const inputContainer = input.parentElement as HTMLElement;
|
|
180
|
+
|
|
181
|
+
expect(await within(inputContainer).findByText(optionOne)).toBeVisible();
|
|
182
|
+
expect(within(inputContainer).getByTestId('CancelIcon')).toBeVisible();
|
|
183
|
+
|
|
184
|
+
await waitForRequest('@getListOptions');
|
|
185
|
+
|
|
186
|
+
await waitFor(() => {
|
|
187
|
+
expect(listOptionsElement.querySelectorAll('li')).toHaveLength(
|
|
188
|
+
listOptions.result.length + 1
|
|
189
|
+
);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// The list re-renders its options: compared by text, not by element.
|
|
193
|
+
await waitFor(() => {
|
|
194
|
+
expect(getOptionTexts(listOptionsElement)).toEqual(optionNames);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('checks all options when Select all button is clicked', async () => {
|
|
199
|
+
const input = getInput();
|
|
200
|
+
|
|
201
|
+
await userEvent.click(input);
|
|
202
|
+
|
|
203
|
+
expect(await screen.findByText('5 element(s) found')).toBeInTheDocument();
|
|
204
|
+
|
|
205
|
+
await waitForRequest('@getListOptions');
|
|
206
|
+
|
|
207
|
+
await userEvent.click(await screen.findByText(labelSelectAll));
|
|
208
|
+
|
|
209
|
+
expect(await screen.findByText(labelUnSelectAll)).toBeVisible();
|
|
210
|
+
|
|
211
|
+
await waitFor(() => {
|
|
212
|
+
expect(screen.getAllByTestId('CancelIcon')).toHaveLength(5);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// A chip per option in the field, in order, and every option checked.
|
|
216
|
+
expect(
|
|
217
|
+
within(input.parentElement as HTMLElement)
|
|
218
|
+
.getAllByText(/^My Option \d$/)
|
|
219
|
+
.map((chip) => chip.textContent)
|
|
220
|
+
).toEqual(optionNames);
|
|
221
|
+
getOptionCheckboxes(await findListOptions()).forEach((checkbox) => {
|
|
222
|
+
expect(checkbox).toBeChecked();
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('unchecks all options when unSelect all button is clicked', async () => {
|
|
227
|
+
const input = getInput();
|
|
228
|
+
|
|
229
|
+
await userEvent.click(input);
|
|
230
|
+
|
|
231
|
+
expect(await screen.findByText('5 element(s) found')).toBeInTheDocument();
|
|
232
|
+
|
|
233
|
+
await waitForRequest('@getListOptions');
|
|
234
|
+
|
|
235
|
+
await userEvent.click(await screen.findByText(labelSelectAll));
|
|
236
|
+
await userEvent.click(await screen.findByText(labelUnSelectAll));
|
|
237
|
+
|
|
238
|
+
expect(await screen.findByText(labelSelectAll)).toBeVisible();
|
|
239
|
+
|
|
240
|
+
await waitFor(() => {
|
|
241
|
+
expect(screen.queryAllByTestId('CancelIcon')).toHaveLength(0);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// The field is empty and every option unchecked.
|
|
245
|
+
expect(input).toHaveAttribute('placeholder', placeholder);
|
|
246
|
+
getOptionCheckboxes(await findListOptions()).forEach((checkbox) => {
|
|
247
|
+
expect(checkbox).not.toBeChecked();
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
});
|