@centreon/ui 26.10.7 → 26.10.9

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.
Files changed (64) hide show
  1. package/package.json +6 -3
  2. package/public/mockServiceWorker.js +31 -8
  3. package/src/Dashboard/Dashboard.browser.test.tsx +107 -0
  4. package/src/Form/Form.browser.test.tsx +445 -0
  5. package/src/Form/Inputs/ConnectedAutocomplete.tsx +12 -4
  6. package/src/Form/Inputs/ExclusiveCheckboxGroup.browser.test.tsx +304 -0
  7. package/src/Form/Inputs/ExclusiveCheckboxGroup.tsx +60 -15
  8. package/src/Form/Inputs/LoadingSkeleton.tsx +4 -0
  9. package/src/Form/Inputs/SegmentedButtons.browser.test.tsx +113 -0
  10. package/src/Form/Inputs/SegmentedButtons.tsx +71 -0
  11. package/src/Form/Inputs/index.tsx +5 -0
  12. package/src/Form/Inputs/models.ts +16 -1
  13. package/src/InputField/Number/Number.browser.test.tsx +109 -0
  14. package/src/InputField/Select/Autocomplete/Connected/Multi/MultiConnectedAutocompleteField.browser.test.tsx +250 -0
  15. package/src/InputField/Select/Autocomplete/Connected/index.test.tsx +37 -0
  16. package/src/InputField/Select/Autocomplete/Connected/index.tsx +59 -45
  17. package/src/Listing/Cell/DataCell.tsx +0 -2
  18. package/src/Listing/Listing.browser.test.tsx +476 -0
  19. package/src/Module/Module.browser.test.tsx +145 -0
  20. package/src/Pagination/Pagination.browser.test.tsx +184 -0
  21. package/src/RichTextEditor/RichTextEditor.browser.test.tsx +567 -0
  22. package/src/RichTextEditor/plugins/FloatingLinkEditorPlugin.tsx +3 -1
  23. package/src/TimePeriods/ResolutionTimePeriod.browser.test.tsx +143 -0
  24. package/src/TimePeriods/TimePeriods.browser.test.tsx +468 -0
  25. package/src/Typography/FluidTypography/FluidTypography.browser.test.tsx +54 -0
  26. package/src/api/useMutationQuery/useMutationQuery.browser.test.tsx +154 -0
  27. package/src/components/CollapsibleItem/CollapsibleItem.browser.test.tsx +120 -0
  28. package/src/components/CopyCommand/CopyCommand.browser.test.tsx +287 -0
  29. package/src/components/CrudPage/CrudPage.browser.test.tsx +659 -0
  30. package/src/components/DataTable/DataTable.browser.test.tsx +257 -0
  31. package/src/components/Form/AccessRights/AccessRights.browser.test.tsx +527 -0
  32. package/src/components/ItemComposition/ItemComposition.browser.test.tsx +172 -0
  33. package/src/components/Layout/PageLayout.browser.test.tsx +114 -0
  34. package/src/components/Modal/ConfirmationModal/ConfirmationModal.browser.test.tsx +237 -0
  35. package/src/components/SortableEntriesList/SortableEntriesList.browser.test.tsx +981 -0
  36. package/src/components/Tabs/Tabs.browser.test.tsx +115 -0
  37. package/src/utils/useFullscreen/Fullscreen.browser.test.tsx +176 -0
  38. package/src/utils/useLocale/useLocale.browser.test.tsx +49 -0
  39. package/src/utils/useLocaleTimezoneDate/{LocaleTimezoneDate.cypress.spec.tsx → LocaleTimezoneDate.browser.test.tsx} +24 -11
  40. package/src/Dashboard/Dashboard.cypress.spec.tsx +0 -71
  41. package/src/Form/Form.cypress.spec.tsx +0 -306
  42. package/src/Form/Inputs/ExclusiveCheckboxGroup.cypress.spec.tsx +0 -174
  43. package/src/InputField/Number/Number.cypress.spec.tsx +0 -89
  44. package/src/InputField/Select/Autocomplete/Connected/Multi/MultiConnectedAutocompleteField.cypress.spec.tsx +0 -182
  45. package/src/Listing/Listing.cypress.spec.tsx +0 -304
  46. package/src/Module/Module.cypress.spec.tsx +0 -127
  47. package/src/Pagination/Pagination.cypress.spec.tsx +0 -140
  48. package/src/RichTextEditor/RichTextEditor.cypress.spec.tsx +0 -408
  49. package/src/TimePeriods/ResolutionTimePeriod.cypress.spec.tsx +0 -74
  50. package/src/TimePeriods/TimePeriods.cypress.spec.tsx +0 -488
  51. package/src/Typography/FluidTypography/FluidTypography.cypress.spec.tsx +0 -27
  52. package/src/api/useMutationQuery/useMutationQuery.cypress.spec.tsx +0 -93
  53. package/src/components/CollapsibleItem/CollapsibleItem.cypress.spec.tsx +0 -76
  54. package/src/components/CopyCommand/CopyCommand.cypress.spec.tsx +0 -167
  55. package/src/components/CrudPage/CrudPage.cypress.spec.tsx +0 -561
  56. package/src/components/DataTable/DataTable.cypress.spec.tsx +0 -174
  57. package/src/components/Form/AccessRights/AccessRights.cypress.spec.tsx +0 -376
  58. package/src/components/ItemComposition/ItemComposition.cypress.spec.tsx +0 -112
  59. package/src/components/Layout/PageLayout.cypress.spec.tsx +0 -64
  60. package/src/components/Modal/ConfirmationModal/ConfirmationModal.cypress.spec.tsx +0 -171
  61. package/src/components/SortableEntriesList/SortableEntriesList.cypress.spec.tsx +0 -792
  62. package/src/components/Tabs/Tabs.cypress.spec.tsx +0 -69
  63. package/src/utils/useFullscreen/Fullscreen.cypress.spec.tsx +0 -130
  64. package/src/utils/useLocale/useLocale.cypress.spec.tsx +0 -40
@@ -0,0 +1,114 @@
1
+ import { rs } from '@rstest/core';
2
+ import { render } from '@test-setup/render';
3
+ import { screen, within } from '@testing-library/react';
4
+ import userEvent from '@testing-library/user-event';
5
+ import { T } from 'ramda';
6
+
7
+ import { PageHeader } from '..';
8
+ import { PageLayout } from '.';
9
+ import { AreaIndicator } from './AreaIndicator';
10
+
11
+ const initialize = (): void => {
12
+ render(
13
+ <PageLayout>
14
+ <PageLayout.Header>
15
+ <PageHeader>
16
+ <PageHeader.Menu>
17
+ <PageLayout.QuickAccess
18
+ create={rs.fn()}
19
+ elements={[
20
+ {
21
+ id: 1,
22
+ name: 'Entity'
23
+ }
24
+ ]}
25
+ goBack={rs.fn()}
26
+ isActive={T}
27
+ labels={{
28
+ create: 'Create',
29
+ goBack: 'Go back'
30
+ }}
31
+ navigateToElement={rs.fn()}
32
+ />
33
+ </PageHeader.Menu>
34
+ <PageHeader.Main>
35
+ <PageHeader.Title description="Description" title="Title" />
36
+ </PageHeader.Main>
37
+ <PageHeader.Actions>Actions</PageHeader.Actions>
38
+ </PageHeader>
39
+ </PageLayout.Header>
40
+ <PageLayout.Body>
41
+ <PageLayout.Actions>
42
+ <AreaIndicator name="Body actions" />
43
+ </PageLayout.Actions>
44
+ <h1>Content</h1>
45
+ </PageLayout.Body>
46
+ </PageLayout>
47
+ );
48
+ };
49
+
50
+ describe('Page layout', () => {
51
+ beforeEach(() => {
52
+ expect.hasAssertions();
53
+ initialize();
54
+ });
55
+
56
+ it('displays the page layout', async () => {
57
+ // The header (quick access button, title, description, actions) above
58
+ // the body (actions area, then content), and the quick access menu closed.
59
+ const header = document.querySelector('#header') as HTMLElement;
60
+ const body = document.querySelector('#page-body') as HTMLElement;
61
+
62
+ const title = await within(header).findByRole('heading', {
63
+ name: 'page header title'
64
+ });
65
+
66
+ expect(title).toBeVisible();
67
+ expect(title).toHaveTextContent(/^Title$/);
68
+ expect(within(header).getByText('Description')).toBeVisible();
69
+ expect(within(header).getByText('Actions')).toBeVisible();
70
+ expect(within(header).getByTestId('quickaccess')).toBeVisible();
71
+ expect(within(header).getByTestId('quickaccess')).toHaveAttribute(
72
+ 'data-is-active',
73
+ 'false'
74
+ );
75
+
76
+ const bodyActions = within(body).getByText('Body actions');
77
+ const content = within(body).getByRole('heading', { name: 'Content' });
78
+
79
+ expect(bodyActions).toBeVisible();
80
+ expect(content).toBeVisible();
81
+ expect(header.getBoundingClientRect().bottom).toBeLessThanOrEqual(
82
+ body.getBoundingClientRect().top
83
+ );
84
+ expect(bodyActions.getBoundingClientRect().bottom).toBeLessThanOrEqual(
85
+ content.getBoundingClientRect().top
86
+ );
87
+ expect(screen.queryByText('Entity')).not.toBeInTheDocument();
88
+ });
89
+
90
+ it('opens the quick access poppin when the corresponding logo is displayed', async () => {
91
+ await userEvent.click(await screen.findByTestId('quickaccess'));
92
+
93
+ expect(await screen.findByText('Entity')).toBeVisible();
94
+ expect(await screen.findByText('Create')).toBeVisible();
95
+ expect(await screen.findByText('Go back')).toBeVisible();
96
+
97
+ // The button shown as open, the active element selected, and "Go back"
98
+ // before "Create".
99
+ expect(screen.getByTestId('quickaccess')).toHaveAttribute(
100
+ 'data-is-active',
101
+ 'true'
102
+ );
103
+ expect(screen.getByRole('menuitem', { name: 'Entity' })).toHaveClass(
104
+ 'Mui-selected'
105
+ );
106
+ expect(
107
+ screen.getByRole('button', { name: 'Go back' }).getBoundingClientRect()
108
+ .right
109
+ ).toBeLessThanOrEqual(
110
+ screen.getByRole('button', { name: 'Create' }).getBoundingClientRect()
111
+ .left
112
+ );
113
+ });
114
+ });
@@ -0,0 +1,237 @@
1
+ import { Button } from '@mui/material';
2
+
3
+ import { rs } from '@rstest/core';
4
+ import { render } from '@test-setup/render';
5
+ import { screen, waitFor } from '@testing-library/react';
6
+ import userEvent from '@testing-library/user-event';
7
+ import { atom, createStore, Provider, useSetAtom } from 'jotai';
8
+
9
+ import {
10
+ ConfirmationModal,
11
+ type ConfirmationModalProps
12
+ } from './ConfirmationModal';
13
+
14
+ const testAtom = atom<string | null>(null);
15
+
16
+ const buttonLabel = 'Click to open modal';
17
+
18
+ const TestComponent = (args: ConfirmationModalProps<string>): JSX.Element => {
19
+ const setAtom = useSetAtom(testAtom);
20
+
21
+ return (
22
+ <>
23
+ <Button onClick={() => setAtom('John')}>{buttonLabel}</Button>
24
+ <ConfirmationModal<string> {...args} />
25
+ </>
26
+ );
27
+ };
28
+
29
+ const staticLabels = {
30
+ cancel: 'Cancel',
31
+ confirm: 'Confirm',
32
+ description: 'Description',
33
+ title: 'Title'
34
+ };
35
+
36
+ const dynamicLabels = {
37
+ cancel: 'Cancel',
38
+ confirm: 'Confirm',
39
+ description: (data: string | null): string => `Description ${data}`,
40
+ title: (data: string | null): string => `Hello ${data}`
41
+ };
42
+
43
+ type InitializeProps = Pick<
44
+ ConfirmationModalProps<string>,
45
+ 'labels' | 'disabled' | 'hasCloseButton' | 'isDanger'
46
+ >;
47
+
48
+ interface InitializeResult {
49
+ cancel: ReturnType<typeof rs.fn>;
50
+ confirm: ReturnType<typeof rs.fn>;
51
+ }
52
+
53
+ const initialize = (props: InitializeProps): InitializeResult => {
54
+ const store = createStore();
55
+
56
+ const cancel = rs.fn();
57
+ const confirm = rs.fn();
58
+
59
+ render(
60
+ <Provider store={store}>
61
+ <TestComponent
62
+ {...props}
63
+ atom={testAtom}
64
+ onCancel={cancel}
65
+ onConfirm={confirm}
66
+ />
67
+ </Provider>
68
+ );
69
+
70
+ return {
71
+ cancel,
72
+ confirm
73
+ };
74
+ };
75
+
76
+ const openModal = async (): Promise<void> => {
77
+ await userEvent.click(screen.getByText(buttonLabel));
78
+ };
79
+
80
+ // The open modal: the title, the description, then the Cancel and Confirm
81
+ // buttons, in that order.
82
+ const expectModalContent = async ({
83
+ description,
84
+ title
85
+ }: {
86
+ description: string;
87
+ title: string;
88
+ }): Promise<void> => {
89
+ const dialog = await screen.findByRole('dialog');
90
+
91
+ expect(screen.getByTestId('modal-header')).toHaveTextContent(
92
+ new RegExp(`^${title}$`)
93
+ );
94
+ expect(dialog).toHaveTextContent(description);
95
+ expect(screen.getByTestId('cancel')).toBeVisible();
96
+ expect(screen.getByTestId('cancel')).toHaveTextContent(/^Cancel$/);
97
+ expect(screen.getByTestId('confirm')).toBeVisible();
98
+ expect(screen.getByTestId('confirm')).toHaveTextContent(/^Confirm$/);
99
+ expect(
100
+ screen
101
+ .getByTestId('cancel')
102
+ .compareDocumentPosition(screen.getByTestId('confirm'))
103
+ ).toBe(Node.DOCUMENT_POSITION_FOLLOWING);
104
+ };
105
+
106
+ const expectModalClosed = async (): Promise<void> => {
107
+ await waitFor(() => {
108
+ expect(screen.queryByText('Title')).not.toBeInTheDocument();
109
+ });
110
+ expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
111
+ expect(screen.getByText(buttonLabel)).toBeVisible();
112
+ };
113
+
114
+ describe('Confirmation modal', () => {
115
+ beforeEach(() => {
116
+ expect.hasAssertions();
117
+ });
118
+
119
+ it('displays the modal with static labels', async () => {
120
+ initialize({ labels: staticLabels });
121
+
122
+ await openModal();
123
+
124
+ expect(await screen.findByText('Title')).toBeVisible();
125
+ expect(screen.getByText('Description')).toBeVisible();
126
+ expect(screen.getByLabelText('close')).toBeVisible();
127
+
128
+ await expectModalContent({ description: 'Description', title: 'Title' });
129
+ expect(screen.getByTestId('confirm')).toBeEnabled();
130
+ expect(screen.getByTestId('confirm')).toHaveAttribute(
131
+ 'data-is-danger',
132
+ 'false'
133
+ );
134
+ });
135
+
136
+ it('displays the modal with dynamic labels', async () => {
137
+ initialize({ labels: dynamicLabels });
138
+
139
+ await openModal();
140
+
141
+ expect(await screen.findByText('Hello John')).toBeVisible();
142
+ expect(screen.getByText('Description John')).toBeVisible();
143
+
144
+ await expectModalContent({
145
+ description: 'Description John',
146
+ title: 'Hello John'
147
+ });
148
+ expect(screen.getByLabelText('close')).toBeVisible();
149
+ });
150
+
151
+ it('displays the confirm button as disabled when a prop is set', async () => {
152
+ initialize({ disabled: true, labels: staticLabels });
153
+
154
+ await openModal();
155
+
156
+ expect(await screen.findByText('Confirm')).toBeVisible();
157
+ expect(screen.getByTestId('confirm')).toBeDisabled();
158
+
159
+ await expectModalContent({ description: 'Description', title: 'Title' });
160
+ expect(screen.getByTestId('cancel')).toBeEnabled();
161
+ });
162
+
163
+ it('displays the confirm button as danger when a prop is set', async () => {
164
+ initialize({ isDanger: true, labels: staticLabels });
165
+
166
+ await openModal();
167
+
168
+ expect(await screen.findByText('Confirm')).toBeVisible();
169
+ expect(screen.getByTestId('confirm')).toHaveAttribute(
170
+ 'data-is-danger',
171
+ 'true'
172
+ );
173
+
174
+ await expectModalContent({ description: 'Description', title: 'Title' });
175
+
176
+ // A red Confirm button: its background is the theme's error colour.
177
+ const errorColorProbe = document.createElement('div');
178
+ errorColorProbe.style.backgroundColor = 'var(--color-error-main)';
179
+ document.body.appendChild(errorColorProbe);
180
+ const errorColor = getComputedStyle(errorColorProbe).backgroundColor;
181
+ errorColorProbe.remove();
182
+
183
+ expect(errorColor).not.toBe('rgba(0, 0, 0, 0)');
184
+ expect(
185
+ getComputedStyle(screen.getByTestId('confirm')).backgroundColor
186
+ ).toBe(errorColor);
187
+ });
188
+
189
+ it('displays the modal without the close button when a prop is set', async () => {
190
+ initialize({ hasCloseButton: false, labels: staticLabels });
191
+
192
+ await openModal();
193
+
194
+ await expectModalContent({ description: 'Description', title: 'Title' });
195
+ expect(screen.queryByLabelText('close')).not.toBeInTheDocument();
196
+ });
197
+
198
+ it('closes the modal when the close button is clicked', async () => {
199
+ initialize({ labels: staticLabels });
200
+
201
+ await openModal();
202
+
203
+ expect(await screen.findByText('Title')).toBeVisible();
204
+
205
+ await userEvent.click(screen.getByLabelText('close'));
206
+
207
+ await expectModalClosed();
208
+ });
209
+
210
+ it('closes the modal when the cancel button is clicked', async () => {
211
+ const { cancel } = initialize({ labels: staticLabels });
212
+
213
+ await openModal();
214
+
215
+ expect(await screen.findByText('Title')).toBeVisible();
216
+
217
+ await userEvent.click(screen.getByText('Cancel'));
218
+
219
+ expect(cancel).toHaveBeenCalledWith('John');
220
+
221
+ await expectModalClosed();
222
+ });
223
+
224
+ it('closes the modal when the confirm button is clicked', async () => {
225
+ const { confirm } = initialize({ labels: staticLabels });
226
+
227
+ await openModal();
228
+
229
+ expect(await screen.findByText('Title')).toBeVisible();
230
+
231
+ await userEvent.click(screen.getByText('Confirm'));
232
+
233
+ expect(confirm).toHaveBeenCalledWith('John');
234
+
235
+ await expectModalClosed();
236
+ });
237
+ });