@centreon/ui 26.10.8 → 26.10.10
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/Form.stories.tsx +102 -1
- package/src/Form/Form.tsx +4 -3
- package/src/Form/Inputs/ExclusiveCheckboxGroup.browser.test.tsx +304 -0
- package/src/Form/Inputs/Grid.browser.test.tsx +186 -0
- package/src/Form/Inputs/Grid.tsx +59 -12
- package/src/Form/Inputs/PasswordInput.browser.test.tsx +80 -0
- package/src/Form/Inputs/SegmentedButtons.browser.test.tsx +197 -0
- package/src/Form/Inputs/SegmentedButtons.tsx +38 -29
- package/src/Form/Inputs/Text.tsx +13 -1
- package/src/Form/Inputs/index.tsx +10 -52
- package/src/Form/Inputs/models.ts +6 -0
- package/src/Form/Section/FormSection.browser.test.tsx +174 -0
- package/src/Form/Section/FormSection.tsx +20 -6
- package/src/Form/Section/navigateToSection.ts +26 -8
- package/src/Form/Section/useActiveSection.ts +213 -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/InputField/Select/Autocomplete/Connected/index.test.tsx +37 -0
- package/src/InputField/Select/Autocomplete/Connected/index.tsx +56 -45
- package/src/Listing/Cell/DataCell.tsx +0 -2
- 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/Header/PageHeader/PageHeader.stories.tsx +9 -0
- package/src/components/Header/PageHeader/PageHeaderMain.tsx +4 -2
- package/src/components/Header/PageHeader/PageHeaderTitle.tsx +61 -18
- 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/components/Tabs/Tabs.tsx +7 -1
- 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 -304
- 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,145 @@
|
|
|
1
|
+
import { interceptAPIRequest, waitForRequest } from '@test-setup/api';
|
|
2
|
+
import { render } from '@test-setup/render';
|
|
3
|
+
import { screen, waitFor } from '@testing-library/react';
|
|
4
|
+
import { createStore } from 'jotai';
|
|
5
|
+
|
|
6
|
+
import { Method } from '..';
|
|
7
|
+
import Module from '.';
|
|
8
|
+
import LicensedModule from './LicensedModule';
|
|
9
|
+
|
|
10
|
+
const initializeModule = (): void => {
|
|
11
|
+
render(
|
|
12
|
+
<Module seedName="seed" store={createStore()}>
|
|
13
|
+
<p>Module</p>
|
|
14
|
+
</Module>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const initializeModuleWithValidLicense = (
|
|
19
|
+
isFederatedComponent = false
|
|
20
|
+
): void => {
|
|
21
|
+
interceptAPIRequest({
|
|
22
|
+
alias: 'getValidLicense',
|
|
23
|
+
method: Method.GET,
|
|
24
|
+
path: './api/internal.php?object=centreon_license_manager&action=licenseValid&productName=valid',
|
|
25
|
+
response: {
|
|
26
|
+
success: true
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
render(
|
|
31
|
+
<div style={{ height: '100vh' }}>
|
|
32
|
+
<LicensedModule
|
|
33
|
+
isFederatedComponent={isFederatedComponent}
|
|
34
|
+
moduleName="valid"
|
|
35
|
+
seedName="seed"
|
|
36
|
+
store={createStore()}
|
|
37
|
+
>
|
|
38
|
+
<p>Module</p>
|
|
39
|
+
</LicensedModule>
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const initializeModuleWithInvalidLicense = (
|
|
45
|
+
isFederatedComponent = false
|
|
46
|
+
): void => {
|
|
47
|
+
interceptAPIRequest({
|
|
48
|
+
alias: 'getInvalidLicense',
|
|
49
|
+
method: Method.GET,
|
|
50
|
+
path: './api/internal.php?object=centreon_license_manager&action=licenseValid&productName=invalid',
|
|
51
|
+
response: {
|
|
52
|
+
success: false
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
render(
|
|
57
|
+
<div style={{ height: '100vh' }}>
|
|
58
|
+
<LicensedModule
|
|
59
|
+
isFederatedComponent={isFederatedComponent}
|
|
60
|
+
moduleName="invalid"
|
|
61
|
+
seedName="seed"
|
|
62
|
+
store={createStore()}
|
|
63
|
+
>
|
|
64
|
+
<p>Module</p>
|
|
65
|
+
</LicensedModule>
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
describe('Module', () => {
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
expect.hasAssertions();
|
|
73
|
+
});
|
|
74
|
+
beforeEach(() => {
|
|
75
|
+
initializeModule();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('displays the content of the module', async () => {
|
|
79
|
+
expect(await screen.findByText('Module')).toBeVisible();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('Valid license module', () => {
|
|
84
|
+
beforeEach(() => {
|
|
85
|
+
expect.hasAssertions();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('displays the content of the page when the license is valid license', async () => {
|
|
89
|
+
initializeModuleWithValidLicense();
|
|
90
|
+
const { request } = await waitForRequest('@getValidLicense');
|
|
91
|
+
|
|
92
|
+
expect(await screen.findByText('Module')).toBeVisible();
|
|
93
|
+
|
|
94
|
+
// The license is checked for the module given.
|
|
95
|
+
expect(request.url.searchParams.get('productName')).toBe('valid');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('displays the content of the component when the license is valid license', async () => {
|
|
99
|
+
initializeModuleWithValidLicense(true);
|
|
100
|
+
|
|
101
|
+
expect(await screen.findByText('Module')).toBeVisible();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe('Invalid license module', () => {
|
|
106
|
+
beforeEach(() => {
|
|
107
|
+
expect.hasAssertions();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('displays the content of the page when the license is invalid license', async () => {
|
|
111
|
+
initializeModuleWithInvalidLicense();
|
|
112
|
+
await waitForRequest('@getInvalidLicense');
|
|
113
|
+
|
|
114
|
+
expect(await screen.findByText('Oops !')).toBeVisible();
|
|
115
|
+
expect(screen.queryByText('Module')).not.toBeInTheDocument();
|
|
116
|
+
|
|
117
|
+
expect(screen.getByText('License invalid or expired !')).toBeVisible();
|
|
118
|
+
expect(
|
|
119
|
+
screen.getByText('Please contact your administrator.')
|
|
120
|
+
).toBeVisible();
|
|
121
|
+
// The images are shown once loaded.
|
|
122
|
+
await waitFor(() => {
|
|
123
|
+
expect(
|
|
124
|
+
document.querySelector('img[alt="License invalid or expired !"]')
|
|
125
|
+
).toBeVisible();
|
|
126
|
+
});
|
|
127
|
+
await waitFor(() => {
|
|
128
|
+
expect(document.querySelector('img[alt="Centreon Logo"]')).toBeVisible();
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('displays the content of the module when the license is invalid license', async () => {
|
|
133
|
+
initializeModuleWithInvalidLicense(true);
|
|
134
|
+
// No request to wait for: the previous test left the license of this
|
|
135
|
+
// module in the shared query cache. Once no skeleton is left, the page is
|
|
136
|
+
// empty: neither the fallback page nor a skeleton.
|
|
137
|
+
await waitFor(() => {
|
|
138
|
+
expect(
|
|
139
|
+
document.querySelector('.MuiSkeleton-root')
|
|
140
|
+
).not.toBeInTheDocument();
|
|
141
|
+
});
|
|
142
|
+
expect(screen.queryByText('Module')).not.toBeInTheDocument();
|
|
143
|
+
expect(screen.queryByText('Oops !')).not.toBeInTheDocument();
|
|
144
|
+
});
|
|
145
|
+
});
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { interceptAPIRequest, waitForRequest } from '@test-setup/api';
|
|
2
|
+
import { render } from '@test-setup/render';
|
|
3
|
+
import { screen, waitFor } from '@testing-library/react';
|
|
4
|
+
import userEvent from '@testing-library/user-event';
|
|
5
|
+
|
|
6
|
+
import TestQueryProvider from '../api/TestQueryProvider';
|
|
7
|
+
import { Method } from '../api/useMutationQuery';
|
|
8
|
+
import { labelNextPage, labelPreviousPage } from '../Listing/translatedLabels';
|
|
9
|
+
import Pagination from './Pagination';
|
|
10
|
+
import { generateItems } from './utils';
|
|
11
|
+
|
|
12
|
+
const defaultTotalItems = 25;
|
|
13
|
+
const itemsPerPage = 6;
|
|
14
|
+
const totalPages = Math.ceil(defaultTotalItems / itemsPerPage);
|
|
15
|
+
|
|
16
|
+
interface InitializeProps {
|
|
17
|
+
currentPage?: number;
|
|
18
|
+
total?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const initialize = ({
|
|
22
|
+
total = defaultTotalItems,
|
|
23
|
+
currentPage = 1
|
|
24
|
+
}: InitializeProps): void => {
|
|
25
|
+
interceptAPIRequest({
|
|
26
|
+
alias: 'list',
|
|
27
|
+
method: Method.GET,
|
|
28
|
+
path: '**/listing**',
|
|
29
|
+
response: {
|
|
30
|
+
meta: {
|
|
31
|
+
limit: itemsPerPage,
|
|
32
|
+
page: currentPage,
|
|
33
|
+
total
|
|
34
|
+
},
|
|
35
|
+
result: generateItems(itemsPerPage)
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
render(
|
|
40
|
+
<div
|
|
41
|
+
style={{
|
|
42
|
+
alignItems: 'center',
|
|
43
|
+
display: 'flex',
|
|
44
|
+
height: '100vh',
|
|
45
|
+
justifyContent: 'center',
|
|
46
|
+
width: '100%'
|
|
47
|
+
}}
|
|
48
|
+
>
|
|
49
|
+
<div
|
|
50
|
+
style={{
|
|
51
|
+
boxShadow: '2px 2px 4px rgba(0, 0, 0, 0.2)',
|
|
52
|
+
height: '176px'
|
|
53
|
+
}}
|
|
54
|
+
>
|
|
55
|
+
<TestQueryProvider>
|
|
56
|
+
<Pagination
|
|
57
|
+
api={{ baseEndpoint: '/test/listing', queryKey: ['test'] }}
|
|
58
|
+
/>
|
|
59
|
+
</TestQueryProvider>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// The six items of the page, in order.
|
|
66
|
+
const expectItems = async (): Promise<void> => {
|
|
67
|
+
expect(await screen.findByText('Item Item Item 0')).toBeVisible();
|
|
68
|
+
|
|
69
|
+
expect(
|
|
70
|
+
screen.getAllByText(/^Item Item Item \d$/).map((item) => item.textContent)
|
|
71
|
+
).toEqual(generateItems(itemsPerPage).map(({ name }) => name));
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const getRequestedPage = (url: URL): number =>
|
|
75
|
+
Number(url.searchParams.get('page'));
|
|
76
|
+
|
|
77
|
+
describe('Pagination Component', () => {
|
|
78
|
+
beforeEach(() => {
|
|
79
|
+
expect.hasAssertions();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('render with correct initial state', async () => {
|
|
83
|
+
initialize({});
|
|
84
|
+
const { request } = await waitForRequest('@list');
|
|
85
|
+
|
|
86
|
+
expect(await screen.findByTestId(labelPreviousPage)).toBeDisabled();
|
|
87
|
+
|
|
88
|
+
expect(screen.getByTestId(labelNextPage)).toBeEnabled();
|
|
89
|
+
|
|
90
|
+
expect(await screen.findByText(`Page 1/${totalPages}`)).toBeVisible();
|
|
91
|
+
|
|
92
|
+
expect(getRequestedPage(request.url)).toBe(1);
|
|
93
|
+
await expectItems();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('hides pagination controls when only one page exists', async () => {
|
|
97
|
+
initialize({ total: itemsPerPage });
|
|
98
|
+
await waitForRequest('@list');
|
|
99
|
+
// The items first, so the controls are checked once the answer is
|
|
100
|
+
// applied (before, the page shows no controls either). The shared query
|
|
101
|
+
// client may first show the page a previous test left in its cache.
|
|
102
|
+
await expectItems();
|
|
103
|
+
|
|
104
|
+
await waitFor(() => {
|
|
105
|
+
expect(screen.queryByTestId(labelPreviousPage)).not.toBeInTheDocument();
|
|
106
|
+
});
|
|
107
|
+
expect(screen.queryByTestId(labelNextPage)).not.toBeInTheDocument();
|
|
108
|
+
expect(screen.queryByText(/Page \d+\/\d+/)).not.toBeInTheDocument();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('navigates forward through pages correctly', async () => {
|
|
112
|
+
initialize({});
|
|
113
|
+
await waitForRequest('@list');
|
|
114
|
+
|
|
115
|
+
expect(await screen.findByText(`Page 1/${totalPages}`)).toBeVisible();
|
|
116
|
+
|
|
117
|
+
for (let index = 0; index < totalPages - 1; index += 1) {
|
|
118
|
+
await userEvent.click(screen.getByTestId(labelNextPage));
|
|
119
|
+
const { request } = await waitForRequest('@list');
|
|
120
|
+
|
|
121
|
+
expect(
|
|
122
|
+
await screen.findByText(`Page ${index + 2}/${totalPages}`)
|
|
123
|
+
).toBeVisible();
|
|
124
|
+
expect(getRequestedPage(request.url)).toBe(index + 2);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
await waitFor(() => {
|
|
128
|
+
expect(screen.getByTestId(labelNextPage)).toBeDisabled();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
expect(screen.getByTestId(labelPreviousPage)).toBeEnabled();
|
|
132
|
+
await expectItems();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('navigates backward through pages correctly', async () => {
|
|
136
|
+
initialize({});
|
|
137
|
+
|
|
138
|
+
await waitForRequest('@list');
|
|
139
|
+
|
|
140
|
+
for (let index = 0; index < totalPages - 1; index += 1) {
|
|
141
|
+
await screen.findByText(`Page ${index + 1}/${totalPages}`);
|
|
142
|
+
await userEvent.click(screen.getByTestId(labelNextPage));
|
|
143
|
+
|
|
144
|
+
await waitForRequest('@list');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
await screen.findByText(`Page ${totalPages}/${totalPages}`);
|
|
148
|
+
|
|
149
|
+
for (let index = 0; index < totalPages - 1; index += 1) {
|
|
150
|
+
await userEvent.click(screen.getByTestId(labelPreviousPage));
|
|
151
|
+
const { request } = await waitForRequest('@list');
|
|
152
|
+
|
|
153
|
+
expect(
|
|
154
|
+
await screen.findByText(`Page ${totalPages - index - 1}/${totalPages}`)
|
|
155
|
+
).toBeVisible();
|
|
156
|
+
expect(getRequestedPage(request.url)).toBe(totalPages - index - 1);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
await waitFor(() => {
|
|
160
|
+
expect(screen.getByTestId(labelPreviousPage)).toBeDisabled();
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
expect(screen.getByTestId(labelNextPage)).toBeEnabled();
|
|
164
|
+
await expectItems();
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('enables both buttons when on middle page', async () => {
|
|
168
|
+
initialize({});
|
|
169
|
+
|
|
170
|
+
await waitForRequest('@list');
|
|
171
|
+
|
|
172
|
+
await userEvent.click(await screen.findByTestId(labelNextPage));
|
|
173
|
+
|
|
174
|
+
await waitForRequest('@list');
|
|
175
|
+
|
|
176
|
+
await waitFor(() => {
|
|
177
|
+
expect(screen.getByTestId(labelPreviousPage)).toBeEnabled();
|
|
178
|
+
});
|
|
179
|
+
expect(screen.getByTestId(labelNextPage)).toBeEnabled();
|
|
180
|
+
|
|
181
|
+
expect(await screen.findByText(`Page 2/${totalPages}`)).toBeVisible();
|
|
182
|
+
await expectItems();
|
|
183
|
+
});
|
|
184
|
+
});
|