@centreon/js-config 24.7.4 → 24.8.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/biome/base.json +224 -0
- package/cypress/component/commands.tsx +82 -22
- package/cypress/component/configuration.js +40 -16
- package/cypress/component/disableCssTransitions.ts +19 -0
- package/cypress/component/enableVisualTesting.ts +1 -1
- package/cypress/component/excludeNodeModulesFromCoverage.js +36 -0
- package/cypress/e2e/commands/configuration.ts +330 -1
- package/cypress/e2e/commands/monitoring.ts +117 -0
- package/cypress/e2e/commands.ts +617 -144
- package/cypress/e2e/configuration.ts +45 -40
- package/cypress/e2e/esbuild-preprocessor.ts +26 -0
- package/cypress/e2e/plugins.ts +53 -114
- package/cypress/e2e/reporter-config.js +13 -0
- package/cypress/e2e/tasks.ts +259 -0
- package/eslint/base.typescript.eslintrc.js +15 -3
- package/eslint/lambda/typescript.eslintrc.js +48 -0
- package/jest/index.js +5 -2
- package/jest/lambda/typescript.js +49 -0
- package/package.json +57 -45
- package/rspack/base/globalConfig.js +71 -0
- package/rspack/base/index.js +89 -0
- package/rspack/patch/dev.js +12 -0
- package/{webpack → rspack}/patch/devServer.js +3 -5
- package/rspack/patch/module.js +13 -0
- package/rspack/plugins/TransformPreloadScript.js +37 -0
- package/rspack/plugins/WriteRemoteEntryNameToModuleFederation.js +30 -0
- package/tsconfig/index.json +5 -4
- package/tsconfig/lambda/node20.tsconfig.json +12 -0
- package/tsconfig/lambda/tsconfig.json +14 -0
- package/tsconfig.json +21 -0
- package/webpack/base/index.js +0 -130
- package/webpack/patch/dev.js +0 -24
- package/webpack/patch/module.js +0 -46
package/cypress/e2e/commands.ts
CHANGED
|
@@ -1,11 +1,64 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-namespace */
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import 'cypress-wait-until';
|
|
2
4
|
|
|
3
5
|
import './commands/configuration';
|
|
6
|
+
import './commands/monitoring';
|
|
4
7
|
|
|
8
|
+
import installLogsCollector from 'cypress-terminal-report/src/installLogsCollector';
|
|
9
|
+
|
|
10
|
+
installLogsCollector({
|
|
11
|
+
commandTimings: 'seconds',
|
|
12
|
+
enableExtendedCollector: true
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const apiBase = '/centreon/api';
|
|
16
|
+
const apiActionV1 = `${apiBase}/index.php`;
|
|
5
17
|
const apiLoginV2 = '/centreon/authentication/providers/configurations/local';
|
|
6
18
|
|
|
7
19
|
const artifactIllegalCharactersMatcher = /[,\s/|<>*?:"]/g;
|
|
8
20
|
|
|
21
|
+
export enum PatternType {
|
|
22
|
+
contains = '*',
|
|
23
|
+
endsWith = '$',
|
|
24
|
+
equals = '',
|
|
25
|
+
startsWith = '^'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface GetByLabelProps {
|
|
29
|
+
label: string;
|
|
30
|
+
patternType?: PatternType;
|
|
31
|
+
tag?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
Cypress.Commands.add(
|
|
35
|
+
'getByLabel',
|
|
36
|
+
({
|
|
37
|
+
tag = '',
|
|
38
|
+
patternType = PatternType.equals,
|
|
39
|
+
label
|
|
40
|
+
}: GetByLabelProps): Cypress.Chainable => {
|
|
41
|
+
return cy.get(`${tag}[aria-label${patternType}="${label}"]`);
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
interface GetByTestIdProps {
|
|
46
|
+
patternType?: PatternType;
|
|
47
|
+
tag?: string;
|
|
48
|
+
testId: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
Cypress.Commands.add(
|
|
52
|
+
'getByTestId',
|
|
53
|
+
({
|
|
54
|
+
tag = '',
|
|
55
|
+
patternType = PatternType.equals,
|
|
56
|
+
testId
|
|
57
|
+
}: GetByTestIdProps): Cypress.Chainable => {
|
|
58
|
+
return cy.get(`${tag}[data-testid${patternType}="${testId}"]`);
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
|
|
9
62
|
Cypress.Commands.add('getWebVersion', (): Cypress.Chainable => {
|
|
10
63
|
return cy
|
|
11
64
|
.exec(
|
|
@@ -23,7 +76,7 @@ Cypress.Commands.add('getWebVersion', (): Cypress.Chainable => {
|
|
|
23
76
|
|
|
24
77
|
Cypress.Commands.add('getIframeBody', (): Cypress.Chainable => {
|
|
25
78
|
return cy
|
|
26
|
-
.get('iframe#main-content')
|
|
79
|
+
.get('iframe#main-content', { timeout: 10000 })
|
|
27
80
|
.its('0.contentDocument.body')
|
|
28
81
|
.should('not.be.empty')
|
|
29
82
|
.then(cy.wrap);
|
|
@@ -39,6 +92,13 @@ Cypress.Commands.add(
|
|
|
39
92
|
}
|
|
40
93
|
);
|
|
41
94
|
|
|
95
|
+
Cypress.Commands.add(
|
|
96
|
+
'clickSubRootMenuItem',
|
|
97
|
+
(page: string): Cypress.Chainable => {
|
|
98
|
+
return cy.get('div[data-cy="collapse"]').eq(1).contains(page).click();
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
|
|
42
102
|
interface NavigateToProps {
|
|
43
103
|
page: string;
|
|
44
104
|
rootItemNumber: number;
|
|
@@ -47,12 +107,17 @@ interface NavigateToProps {
|
|
|
47
107
|
|
|
48
108
|
Cypress.Commands.add(
|
|
49
109
|
'navigateTo',
|
|
50
|
-
({ rootItemNumber, subMenu, page }): void => {
|
|
110
|
+
({ rootItemNumber, subMenu, page }: NavigateToProps): void => {
|
|
51
111
|
if (subMenu) {
|
|
52
112
|
cy.hoverRootMenuItem(rootItemNumber)
|
|
53
113
|
.contains(subMenu)
|
|
54
|
-
.trigger('mouseover'
|
|
55
|
-
|
|
114
|
+
.trigger('mouseover')
|
|
115
|
+
.get('.MuiCollapse-wrapper')
|
|
116
|
+
.find('div[data-cy="collapse"]')
|
|
117
|
+
.should('be.visible')
|
|
118
|
+
.and('contain', page);
|
|
119
|
+
|
|
120
|
+
cy.clickSubRootMenuItem(page);
|
|
56
121
|
|
|
57
122
|
return;
|
|
58
123
|
}
|
|
@@ -83,34 +148,80 @@ Cypress.Commands.add(
|
|
|
83
148
|
}
|
|
84
149
|
);
|
|
85
150
|
|
|
151
|
+
Cypress.Commands.add('getContainerId', (containerName: string) => {
|
|
152
|
+
cy.log(`Getting container id of ${containerName}`);
|
|
153
|
+
|
|
154
|
+
return cy.task('getContainerId', containerName);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
Cypress.Commands.add('getContainerIpAddress', (containerName: string) => {
|
|
158
|
+
cy.log(`Getting container ip address of ${containerName}`);
|
|
159
|
+
|
|
160
|
+
return cy.task('getContainerIpAddress', containerName);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
Cypress.Commands.add('getContainersLogs', () => {
|
|
164
|
+
cy.log('Getting containers logs');
|
|
165
|
+
|
|
166
|
+
return cy.task('getContainersLogs');
|
|
167
|
+
});
|
|
168
|
+
|
|
86
169
|
interface CopyFromContainerProps {
|
|
87
170
|
destination: string;
|
|
171
|
+
name?: string;
|
|
88
172
|
source: string;
|
|
89
173
|
}
|
|
90
174
|
|
|
91
175
|
Cypress.Commands.add(
|
|
92
176
|
'copyFromContainer',
|
|
93
|
-
({ source, destination }: CopyFromContainerProps) => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
177
|
+
({ name = 'web', source, destination }: CopyFromContainerProps) => {
|
|
178
|
+
cy.log(`Copy content from ${name}:${source} to ${destination}`);
|
|
179
|
+
|
|
180
|
+
return cy.task('copyFromContainer', {
|
|
181
|
+
destination,
|
|
182
|
+
serviceName: name,
|
|
183
|
+
source
|
|
184
|
+
});
|
|
97
185
|
}
|
|
98
186
|
);
|
|
99
187
|
|
|
188
|
+
export enum CopyToContainerContentType {
|
|
189
|
+
Directory = 'directory',
|
|
190
|
+
File = 'file'
|
|
191
|
+
}
|
|
192
|
+
|
|
100
193
|
interface CopyToContainerProps {
|
|
101
194
|
destination: string;
|
|
195
|
+
name?: string;
|
|
102
196
|
source: string;
|
|
197
|
+
type: CopyToContainerContentType;
|
|
103
198
|
}
|
|
104
199
|
|
|
105
200
|
Cypress.Commands.add(
|
|
106
201
|
'copyToContainer',
|
|
107
|
-
({ source, destination }: CopyToContainerProps) => {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
202
|
+
({ name = 'web', source, destination, type }: CopyToContainerProps) => {
|
|
203
|
+
cy.log(`Copy content from ${source} to ${name}:${destination}`);
|
|
204
|
+
|
|
205
|
+
return cy.task('copyToContainer', {
|
|
206
|
+
destination,
|
|
207
|
+
serviceName: name,
|
|
208
|
+
source,
|
|
209
|
+
type
|
|
210
|
+
});
|
|
111
211
|
}
|
|
112
212
|
);
|
|
113
213
|
|
|
214
|
+
Cypress.Commands.add('loginAsAdminViaApiV2', (): Cypress.Chainable => {
|
|
215
|
+
return cy.request({
|
|
216
|
+
body: {
|
|
217
|
+
login: 'admin',
|
|
218
|
+
password: 'Centreon!2021'
|
|
219
|
+
},
|
|
220
|
+
method: 'POST',
|
|
221
|
+
url: apiLoginV2
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
114
225
|
interface LoginByTypeOfUserProps {
|
|
115
226
|
jsonName?: string;
|
|
116
227
|
loginViaApi?: boolean;
|
|
@@ -118,7 +229,7 @@ interface LoginByTypeOfUserProps {
|
|
|
118
229
|
|
|
119
230
|
Cypress.Commands.add(
|
|
120
231
|
'loginByTypeOfUser',
|
|
121
|
-
({ jsonName, loginViaApi }): Cypress.Chainable => {
|
|
232
|
+
({ jsonName = 'admin', loginViaApi = false }): Cypress.Chainable => {
|
|
122
233
|
if (loginViaApi) {
|
|
123
234
|
return cy
|
|
124
235
|
.fixture(`users/${jsonName}.json`)
|
|
@@ -135,27 +246,56 @@ Cypress.Commands.add(
|
|
|
135
246
|
.visit(`${Cypress.config().baseUrl}`)
|
|
136
247
|
.wait('@getNavigationList');
|
|
137
248
|
}
|
|
249
|
+
|
|
138
250
|
cy.visit(`${Cypress.config().baseUrl}`)
|
|
139
251
|
.fixture(`users/${jsonName}.json`)
|
|
140
252
|
.then((credential) => {
|
|
141
|
-
cy.getByLabel({ label: 'Alias', tag: 'input' }).type(
|
|
253
|
+
cy.getByLabel({ label: 'Alias', tag: 'input' }).type(
|
|
254
|
+
`{selectAll}{backspace}${credential.login}`
|
|
255
|
+
);
|
|
142
256
|
cy.getByLabel({ label: 'Password', tag: 'input' }).type(
|
|
143
|
-
credential.password
|
|
257
|
+
`{selectAll}{backspace}${credential.password}`
|
|
144
258
|
);
|
|
145
259
|
})
|
|
146
260
|
.getByLabel({ label: 'Connect', tag: 'button' })
|
|
147
261
|
.click();
|
|
148
262
|
|
|
149
|
-
return cy
|
|
150
|
-
.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
});
|
|
263
|
+
return cy.get('.MuiAlert-message').then(($snackbar) => {
|
|
264
|
+
if ($snackbar.text().includes('Login succeeded')) {
|
|
265
|
+
cy.wait('@getNavigationList');
|
|
266
|
+
cy.get('.MuiAlert-message').should('not.be.visible');
|
|
267
|
+
}
|
|
268
|
+
});
|
|
156
269
|
}
|
|
157
270
|
);
|
|
158
271
|
|
|
272
|
+
Cypress.Commands.add('logout', (): void => {
|
|
273
|
+
cy.getByLabel({ label: 'Profile' }).should('exist').click();
|
|
274
|
+
|
|
275
|
+
cy.intercept({
|
|
276
|
+
method: 'GET',
|
|
277
|
+
times: 1,
|
|
278
|
+
url: '/centreon/api/latest/authentication/logout'
|
|
279
|
+
}).as('logout');
|
|
280
|
+
|
|
281
|
+
cy.contains(/^Logout$/).click();
|
|
282
|
+
|
|
283
|
+
cy.wait('@logout').its('response.statusCode').should('eq', 302);
|
|
284
|
+
|
|
285
|
+
// https://github.com/cypress-io/cypress/issues/25841
|
|
286
|
+
cy.clearAllCookies();
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
Cypress.Commands.add('logoutViaAPI', (): Cypress.Chainable => {
|
|
290
|
+
return cy
|
|
291
|
+
.request({
|
|
292
|
+
method: 'GET',
|
|
293
|
+
url: '/centreon/authentication/logout'
|
|
294
|
+
})
|
|
295
|
+
.visit('/')
|
|
296
|
+
.getByLabel({ label: 'Alias', tag: 'input' });
|
|
297
|
+
});
|
|
298
|
+
|
|
159
299
|
Cypress.Commands.add(
|
|
160
300
|
'visitEmptyPage',
|
|
161
301
|
(): Cypress.Chainable =>
|
|
@@ -167,32 +307,91 @@ Cypress.Commands.add(
|
|
|
167
307
|
.visit('/waiting-page')
|
|
168
308
|
);
|
|
169
309
|
|
|
170
|
-
Cypress.Commands.add('waitForContainerAndSetToken', (): Cypress.Chainable => {
|
|
171
|
-
return cy.setUserTokenApiV1();
|
|
172
|
-
});
|
|
173
|
-
|
|
174
310
|
interface ExecInContainerProps {
|
|
175
|
-
command: string
|
|
311
|
+
command: string | Array<string>;
|
|
176
312
|
name: string;
|
|
177
313
|
}
|
|
178
314
|
|
|
315
|
+
interface ExecInContainerResult {
|
|
316
|
+
exitCode: number;
|
|
317
|
+
output: string;
|
|
318
|
+
}
|
|
319
|
+
|
|
179
320
|
Cypress.Commands.add(
|
|
180
321
|
'execInContainer',
|
|
181
322
|
({ command, name }: ExecInContainerProps): Cypress.Chainable => {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
323
|
+
const commands =
|
|
324
|
+
typeof command === 'string' || command instanceof String
|
|
325
|
+
? [command]
|
|
326
|
+
: command;
|
|
327
|
+
|
|
328
|
+
const results = commands.reduce(
|
|
329
|
+
(acc, runCommand) => {
|
|
330
|
+
cy.task<ExecInContainerResult>(
|
|
331
|
+
'execInContainer',
|
|
332
|
+
{ command: runCommand, name },
|
|
333
|
+
{ timeout: 600000 }
|
|
334
|
+
).then((result) => {
|
|
335
|
+
if (result.exitCode) {
|
|
336
|
+
cy.log(result.output);
|
|
337
|
+
|
|
338
|
+
// output will not be truncated
|
|
339
|
+
throw new Error(`
|
|
340
|
+
Execution of "${runCommand}" failed
|
|
341
|
+
Exit code: ${result.exitCode}
|
|
342
|
+
Output:\n${result.output}`);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
acc.output = `${acc.output}${result.output}`;
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
return acc;
|
|
349
|
+
},
|
|
350
|
+
{ exitCode: 0, output: '' }
|
|
351
|
+
);
|
|
193
352
|
|
|
194
|
-
|
|
195
|
-
|
|
353
|
+
return cy.wrap(results);
|
|
354
|
+
}
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
interface RequestOnDatabaseProps {
|
|
358
|
+
database: string;
|
|
359
|
+
query: string;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
Cypress.Commands.add(
|
|
363
|
+
'requestOnDatabase',
|
|
364
|
+
({ database, query }: RequestOnDatabaseProps): Cypress.Chainable => {
|
|
365
|
+
return cy.task('requestOnDatabase', { database, query });
|
|
366
|
+
}
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
interface SetUserTokenApiV1Props {
|
|
370
|
+
login?: string;
|
|
371
|
+
password?: string;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
Cypress.Commands.add(
|
|
375
|
+
'setUserTokenApiV1',
|
|
376
|
+
({
|
|
377
|
+
login = 'admin',
|
|
378
|
+
password = 'Centreon!2021'
|
|
379
|
+
}: SetUserTokenApiV1Props = {}): Cypress.Chainable => {
|
|
380
|
+
return cy
|
|
381
|
+
.request({
|
|
382
|
+
body: {
|
|
383
|
+
password,
|
|
384
|
+
username: login
|
|
385
|
+
},
|
|
386
|
+
headers: {
|
|
387
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
388
|
+
},
|
|
389
|
+
method: 'POST',
|
|
390
|
+
url: `${apiActionV1}?action=authenticate`
|
|
391
|
+
})
|
|
392
|
+
.then(({ body }) =>
|
|
393
|
+
window.localStorage.setItem('userTokenApiV1', body.authToken)
|
|
394
|
+
);
|
|
196
395
|
}
|
|
197
396
|
);
|
|
198
397
|
|
|
@@ -202,6 +401,7 @@ interface PortBinding {
|
|
|
202
401
|
}
|
|
203
402
|
|
|
204
403
|
interface StartContainerProps {
|
|
404
|
+
command?: string;
|
|
205
405
|
image: string;
|
|
206
406
|
name: string;
|
|
207
407
|
portBindings: Array<PortBinding>;
|
|
@@ -209,174 +409,447 @@ interface StartContainerProps {
|
|
|
209
409
|
|
|
210
410
|
Cypress.Commands.add(
|
|
211
411
|
'startContainer',
|
|
212
|
-
({
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
return cy.wrap(image);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
cy.log(`Pulling remote docker image : ${image}`);
|
|
230
|
-
|
|
231
|
-
return cy.exec(`docker pull ${image}`).then(() => cy.wrap(image));
|
|
232
|
-
})
|
|
233
|
-
.then((imageName) =>
|
|
234
|
-
cy.task('startContainer', { image: imageName, name, portBindings })
|
|
235
|
-
);
|
|
412
|
+
({
|
|
413
|
+
command,
|
|
414
|
+
name,
|
|
415
|
+
image,
|
|
416
|
+
portBindings
|
|
417
|
+
}: StartContainerProps): Cypress.Chainable => {
|
|
418
|
+
cy.log(`Starting container ${name} from image ${image}`);
|
|
419
|
+
|
|
420
|
+
return cy.task(
|
|
421
|
+
'startContainer',
|
|
422
|
+
{ command, image, name, portBindings },
|
|
423
|
+
{ timeout: 600000 } // 10 minutes because docker pull can be very slow
|
|
424
|
+
);
|
|
236
425
|
}
|
|
237
426
|
);
|
|
238
427
|
|
|
239
|
-
interface
|
|
240
|
-
|
|
241
|
-
|
|
428
|
+
interface StartContainersProps {
|
|
429
|
+
composeFile?: string;
|
|
430
|
+
databaseImage?: string;
|
|
431
|
+
moduleName?: string;
|
|
432
|
+
openidImage?: string;
|
|
433
|
+
profiles?: Array<string>;
|
|
434
|
+
samlImage?: string;
|
|
242
435
|
useSlim?: boolean;
|
|
243
|
-
|
|
436
|
+
webOs?: string;
|
|
437
|
+
webVersion?: string;
|
|
244
438
|
}
|
|
245
439
|
|
|
246
440
|
Cypress.Commands.add(
|
|
247
|
-
'
|
|
441
|
+
'startContainers',
|
|
248
442
|
({
|
|
249
|
-
|
|
250
|
-
|
|
443
|
+
composeFile,
|
|
444
|
+
databaseImage = Cypress.env('DATABASE_IMAGE'),
|
|
445
|
+
moduleName = 'centreon-web',
|
|
446
|
+
openidImage = `docker.centreon.com/centreon/keycloak:${Cypress.env(
|
|
447
|
+
'OPENID_IMAGE_VERSION'
|
|
448
|
+
)}`,
|
|
449
|
+
profiles = [],
|
|
450
|
+
samlImage = `docker.centreon.com/centreon/keycloak:${Cypress.env(
|
|
451
|
+
'SAML_IMAGE_VERSION'
|
|
452
|
+
)}`,
|
|
251
453
|
useSlim = true,
|
|
252
|
-
|
|
253
|
-
|
|
454
|
+
webOs = Cypress.env('WEB_IMAGE_OS'),
|
|
455
|
+
webVersion = Cypress.env('WEB_IMAGE_VERSION')
|
|
456
|
+
}: StartContainersProps = {}): Cypress.Chainable => {
|
|
457
|
+
cy.log('Starting containers ...');
|
|
458
|
+
|
|
459
|
+
let composeFilePath = composeFile;
|
|
460
|
+
if (!composeFile) {
|
|
461
|
+
const cypressDir = path.dirname(Cypress.config('configFile'));
|
|
462
|
+
composeFilePath = `${cypressDir}/../../../.github/docker/docker-compose.yml`;
|
|
463
|
+
}
|
|
464
|
+
|
|
254
465
|
const slimSuffix = useSlim ? '-slim' : '';
|
|
255
466
|
|
|
256
|
-
const
|
|
467
|
+
const webImage = `docker.centreon.com/centreon/${moduleName}${slimSuffix}-${webOs}:${webVersion}`;
|
|
257
468
|
|
|
258
469
|
return cy
|
|
259
|
-
.
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
470
|
+
.task(
|
|
471
|
+
'startContainers',
|
|
472
|
+
{
|
|
473
|
+
composeFile: composeFilePath,
|
|
474
|
+
databaseImage,
|
|
475
|
+
openidImage,
|
|
476
|
+
profiles,
|
|
477
|
+
samlImage,
|
|
478
|
+
webImage
|
|
479
|
+
},
|
|
480
|
+
{ timeout: 600000 } // 10 minutes because docker pull can be very slow
|
|
481
|
+
)
|
|
264
482
|
.then(() => {
|
|
265
|
-
const baseUrl = 'http://
|
|
483
|
+
const baseUrl = 'http://127.0.0.1:4000';
|
|
266
484
|
|
|
267
485
|
Cypress.config('baseUrl', baseUrl);
|
|
268
486
|
|
|
269
|
-
return cy.
|
|
270
|
-
`npx wait-on ${baseUrl}/centreon/api/latest/platform/installation/status`
|
|
271
|
-
);
|
|
487
|
+
return cy.wrap(null);
|
|
272
488
|
})
|
|
273
489
|
.visit('/') // this is necessary to refresh browser cause baseUrl has changed (flash appears in video)
|
|
274
490
|
.setUserTokenApiV1();
|
|
275
491
|
}
|
|
276
492
|
);
|
|
277
493
|
|
|
278
|
-
interface
|
|
279
|
-
name
|
|
494
|
+
interface StopContainerProps {
|
|
495
|
+
name: string;
|
|
280
496
|
}
|
|
281
497
|
|
|
282
498
|
Cypress.Commands.add(
|
|
283
|
-
'
|
|
284
|
-
({
|
|
285
|
-
|
|
286
|
-
}: StopWebContainerProps = {}): Cypress.Chainable => {
|
|
287
|
-
const logDirectory = `cypress/results/logs/${Cypress.spec.name.replace(
|
|
288
|
-
artifactIllegalCharactersMatcher,
|
|
289
|
-
'_'
|
|
290
|
-
)}/${Cypress.currentTest.title.replace(
|
|
291
|
-
artifactIllegalCharactersMatcher,
|
|
292
|
-
'_'
|
|
293
|
-
)}`;
|
|
499
|
+
'stopContainer',
|
|
500
|
+
({ name }: StopContainerProps): Cypress.Chainable => {
|
|
501
|
+
cy.log(`Stopping container ${name}`);
|
|
294
502
|
|
|
295
|
-
return cy
|
|
296
|
-
.visitEmptyPage()
|
|
297
|
-
.exec(`mkdir -p "${logDirectory}"`)
|
|
298
|
-
.copyFromContainer({
|
|
299
|
-
destination: `${logDirectory}/broker`,
|
|
300
|
-
source: '/var/log/centreon-broker'
|
|
301
|
-
})
|
|
302
|
-
.copyFromContainer({
|
|
303
|
-
destination: `${logDirectory}/engine`,
|
|
304
|
-
source: '/var/log/centreon-engine'
|
|
305
|
-
})
|
|
306
|
-
.execInContainer({
|
|
307
|
-
command: `bash -e <<EOF
|
|
308
|
-
chmod 777 /var/log/centreon/centreon-web.log > /dev/null 2>&1 || :
|
|
309
|
-
EOF`,
|
|
310
|
-
name
|
|
311
|
-
})
|
|
312
|
-
.copyFromContainer({
|
|
313
|
-
destination: `${logDirectory}/centreon`,
|
|
314
|
-
source: '/var/log/centreon'
|
|
315
|
-
})
|
|
316
|
-
.stopContainer({ name });
|
|
503
|
+
return cy.task('stopContainer', { name });
|
|
317
504
|
}
|
|
318
505
|
);
|
|
319
506
|
|
|
320
|
-
|
|
507
|
+
Cypress.Commands.add('stopContainers', (): Cypress.Chainable => {
|
|
508
|
+
cy.log('Stopping containers ...');
|
|
509
|
+
|
|
510
|
+
const logDirectory = `results/logs/${Cypress.spec.name.replace(
|
|
511
|
+
artifactIllegalCharactersMatcher,
|
|
512
|
+
'_'
|
|
513
|
+
)}/${Cypress.currentTest.title.replace(
|
|
514
|
+
artifactIllegalCharactersMatcher,
|
|
515
|
+
'_'
|
|
516
|
+
)}`;
|
|
517
|
+
|
|
518
|
+
const name = 'web';
|
|
519
|
+
|
|
520
|
+
return cy
|
|
521
|
+
.visitEmptyPage()
|
|
522
|
+
.createDirectory(logDirectory)
|
|
523
|
+
.getContainersLogs()
|
|
524
|
+
.then((containersLogs: Array<Array<string>>) => {
|
|
525
|
+
if (!containersLogs) {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
Object.entries(containersLogs).forEach(([containerName, logs]) => {
|
|
530
|
+
cy.writeFile(
|
|
531
|
+
`results/logs/${Cypress.spec.name.replace(
|
|
532
|
+
artifactIllegalCharactersMatcher,
|
|
533
|
+
'_'
|
|
534
|
+
)}/${Cypress.currentTest.title.replace(
|
|
535
|
+
artifactIllegalCharactersMatcher,
|
|
536
|
+
'_'
|
|
537
|
+
)}/container-${containerName}.log`,
|
|
538
|
+
logs
|
|
539
|
+
);
|
|
540
|
+
});
|
|
541
|
+
})
|
|
542
|
+
.copyFromContainer({
|
|
543
|
+
destination: `${logDirectory}/broker`,
|
|
544
|
+
name,
|
|
545
|
+
source: '/var/log/centreon-broker'
|
|
546
|
+
})
|
|
547
|
+
.copyFromContainer({
|
|
548
|
+
destination: `${logDirectory}/engine`,
|
|
549
|
+
name,
|
|
550
|
+
source: '/var/log/centreon-engine'
|
|
551
|
+
})
|
|
552
|
+
.copyFromContainer({
|
|
553
|
+
destination: `${logDirectory}/centreon`,
|
|
554
|
+
name,
|
|
555
|
+
source: '/var/log/centreon'
|
|
556
|
+
})
|
|
557
|
+
.copyFromContainer({
|
|
558
|
+
destination: `${logDirectory}/centreon-gorgone`,
|
|
559
|
+
name,
|
|
560
|
+
source: '/var/log/centreon-gorgone'
|
|
561
|
+
})
|
|
562
|
+
.then(() => {
|
|
563
|
+
if (Cypress.env('WEB_IMAGE_OS').includes('alma')) {
|
|
564
|
+
return cy.copyFromContainer({
|
|
565
|
+
destination: `${logDirectory}/php`,
|
|
566
|
+
name,
|
|
567
|
+
source: '/var/log/php-fpm'
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
return cy.copyFromContainer(
|
|
572
|
+
{
|
|
573
|
+
destination: `${logDirectory}/php8.1-fpm-centreon-error.log`,
|
|
574
|
+
name,
|
|
575
|
+
source: '/var/log/php8.1-fpm-centreon-error.log'
|
|
576
|
+
},
|
|
577
|
+
{ failOnNonZeroExit: false }
|
|
578
|
+
);
|
|
579
|
+
})
|
|
580
|
+
.then(() => {
|
|
581
|
+
if (Cypress.env('WEB_IMAGE_OS').includes('alma')) {
|
|
582
|
+
return cy.copyFromContainer({
|
|
583
|
+
destination: `${logDirectory}/httpd`,
|
|
584
|
+
name,
|
|
585
|
+
source: '/var/log/httpd'
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
return cy.copyFromContainer(
|
|
590
|
+
{
|
|
591
|
+
destination: `${logDirectory}/apache2`,
|
|
592
|
+
name,
|
|
593
|
+
source: '/var/log/apache2'
|
|
594
|
+
},
|
|
595
|
+
{ failOnNonZeroExit: false }
|
|
596
|
+
);
|
|
597
|
+
})
|
|
598
|
+
.exec(`chmod -R 755 "${logDirectory}"`)
|
|
599
|
+
.task(
|
|
600
|
+
'stopContainers',
|
|
601
|
+
{},
|
|
602
|
+
{ timeout: 600000 } // 10 minutes because docker pull can be very slow
|
|
603
|
+
);
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
Cypress.Commands.add(
|
|
607
|
+
'createDirectory',
|
|
608
|
+
(directoryPath: string): Cypress.Chainable => {
|
|
609
|
+
return cy.task('createDirectory', directoryPath);
|
|
610
|
+
}
|
|
611
|
+
);
|
|
612
|
+
|
|
613
|
+
interface Dashboard {
|
|
614
|
+
description?: string;
|
|
321
615
|
name: string;
|
|
322
616
|
}
|
|
323
617
|
|
|
324
618
|
Cypress.Commands.add(
|
|
325
|
-
'
|
|
326
|
-
(
|
|
327
|
-
cy.
|
|
328
|
-
cy.
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
'_'
|
|
335
|
-
)}/container-${name}.log`,
|
|
336
|
-
stdout
|
|
619
|
+
'insertDashboardList',
|
|
620
|
+
(fixtureFile: string): Cypress.Chainable => {
|
|
621
|
+
return cy.fixture(fixtureFile).then((dashboardList) => {
|
|
622
|
+
cy.wrap(
|
|
623
|
+
Promise.all(
|
|
624
|
+
dashboardList.map((dashboardBody: Dashboard) =>
|
|
625
|
+
cy.insertDashboard({ ...dashboardBody })
|
|
626
|
+
)
|
|
627
|
+
)
|
|
337
628
|
);
|
|
338
629
|
});
|
|
630
|
+
}
|
|
631
|
+
);
|
|
339
632
|
|
|
340
|
-
|
|
633
|
+
Cypress.Commands.add(
|
|
634
|
+
'insertDashboard',
|
|
635
|
+
(dashboardBody: Dashboard): Cypress.Chainable => {
|
|
636
|
+
return cy.request({
|
|
637
|
+
body: {
|
|
638
|
+
...dashboardBody
|
|
639
|
+
},
|
|
640
|
+
method: 'POST',
|
|
641
|
+
url: '/centreon/api/latest/configuration/dashboards'
|
|
642
|
+
});
|
|
341
643
|
}
|
|
342
644
|
);
|
|
343
645
|
|
|
646
|
+
Cypress.Commands.add(
|
|
647
|
+
'insertDashboardWithWidget',
|
|
648
|
+
(dashboardBody, patchBody) => {
|
|
649
|
+
cy.request({
|
|
650
|
+
body: {
|
|
651
|
+
...dashboardBody
|
|
652
|
+
},
|
|
653
|
+
method: 'POST',
|
|
654
|
+
url: '/centreon/api/latest/configuration/dashboards'
|
|
655
|
+
}).then((response) => {
|
|
656
|
+
const dashboardId = response.body.id;
|
|
657
|
+
cy.waitUntil(
|
|
658
|
+
() => {
|
|
659
|
+
return cy
|
|
660
|
+
.request({
|
|
661
|
+
method: 'GET',
|
|
662
|
+
url: `/centreon/api/latest/configuration/dashboards/${dashboardId}`
|
|
663
|
+
})
|
|
664
|
+
.then((getResponse) => {
|
|
665
|
+
return getResponse.body && getResponse.body.id === dashboardId;
|
|
666
|
+
});
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
timeout: 10000
|
|
670
|
+
}
|
|
671
|
+
);
|
|
672
|
+
cy.request({
|
|
673
|
+
body: patchBody,
|
|
674
|
+
method: 'PATCH',
|
|
675
|
+
url: `/centreon/api/latest/configuration/dashboards/${dashboardId}`
|
|
676
|
+
});
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
);
|
|
680
|
+
|
|
681
|
+
interface ShareDashboardToUserProps {
|
|
682
|
+
dashboardName: string;
|
|
683
|
+
role: string;
|
|
684
|
+
userName: string;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
interface ListingRequestResult {
|
|
688
|
+
body: {
|
|
689
|
+
result: Array<{
|
|
690
|
+
id: number;
|
|
691
|
+
}>;
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
interface PatchDashboardBody {
|
|
696
|
+
panels: Array<{
|
|
697
|
+
layout: {
|
|
698
|
+
height: number;
|
|
699
|
+
min_height: number;
|
|
700
|
+
min_width: number;
|
|
701
|
+
width: number;
|
|
702
|
+
x: number;
|
|
703
|
+
y: number;
|
|
704
|
+
};
|
|
705
|
+
name: string;
|
|
706
|
+
widget_settings: {
|
|
707
|
+
options: {
|
|
708
|
+
description: {
|
|
709
|
+
content: string;
|
|
710
|
+
enabled: boolean;
|
|
711
|
+
};
|
|
712
|
+
name: string;
|
|
713
|
+
};
|
|
714
|
+
};
|
|
715
|
+
widget_type: string;
|
|
716
|
+
}>;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
Cypress.Commands.add(
|
|
720
|
+
'shareDashboardToUser',
|
|
721
|
+
({ dashboardName, userName, role }: ShareDashboardToUserProps): void => {
|
|
722
|
+
Promise.all([
|
|
723
|
+
cy.request({
|
|
724
|
+
method: 'GET',
|
|
725
|
+
url: `/centreon/api/latest/configuration/users?search={"name":"${userName}"}`
|
|
726
|
+
}),
|
|
727
|
+
cy.request({
|
|
728
|
+
method: 'GET',
|
|
729
|
+
url: `/centreon/api/latest/configuration/dashboards?search={"name":"${dashboardName}"}`
|
|
730
|
+
})
|
|
731
|
+
]).then(
|
|
732
|
+
([retrievedUser, retrievedDashboard]: [
|
|
733
|
+
ListingRequestResult,
|
|
734
|
+
ListingRequestResult
|
|
735
|
+
]) => {
|
|
736
|
+
const userId = retrievedUser.body.result[0].id;
|
|
737
|
+
const dashboardId = retrievedDashboard.body.result[0].id;
|
|
738
|
+
|
|
739
|
+
cy.request({
|
|
740
|
+
body: {
|
|
741
|
+
id: userId,
|
|
742
|
+
role: `${role}`
|
|
743
|
+
},
|
|
744
|
+
method: 'POST',
|
|
745
|
+
url: `/centreon/api/latest/configuration/dashboards/${dashboardId}/access_rights/contacts`
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
);
|
|
751
|
+
|
|
752
|
+
Cypress.Commands.add('getTimeFromHeader', (): Cypress.Chainable => {
|
|
753
|
+
return cy
|
|
754
|
+
.get('header div[data-cy="clock"]', { timeout: 20000 })
|
|
755
|
+
.should('be.visible')
|
|
756
|
+
.then(($time) => {
|
|
757
|
+
const headerTime = $time.children()[1].textContent;
|
|
758
|
+
if (headerTime?.match(/\d+:\d+/)) {
|
|
759
|
+
cy.log(`header time is : ${headerTime}`);
|
|
760
|
+
|
|
761
|
+
return cy.wrap(headerTime);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
throw new Error(`header time is not displayed`);
|
|
765
|
+
});
|
|
766
|
+
});
|
|
767
|
+
|
|
344
768
|
declare global {
|
|
345
769
|
namespace Cypress {
|
|
346
770
|
interface Chainable {
|
|
347
|
-
|
|
348
|
-
|
|
771
|
+
clickSubRootMenuItem: (page: string) => Cypress.Chainable;
|
|
772
|
+
copyFromContainer: (
|
|
773
|
+
props: CopyFromContainerProps,
|
|
774
|
+
options?: Partial<Cypress.ExecOptions>
|
|
775
|
+
) => Cypress.Chainable;
|
|
776
|
+
copyToContainer: (
|
|
777
|
+
props: CopyToContainerProps,
|
|
778
|
+
options?: Partial<Cypress.ExecOptions>
|
|
779
|
+
) => Cypress.Chainable;
|
|
780
|
+
createDirectory: (directoryPath: string) => Cypress.Chainable;
|
|
349
781
|
execInContainer: ({
|
|
350
782
|
command,
|
|
351
783
|
name
|
|
352
784
|
}: ExecInContainerProps) => Cypress.Chainable;
|
|
785
|
+
getByLabel: ({
|
|
786
|
+
patternType,
|
|
787
|
+
tag,
|
|
788
|
+
label
|
|
789
|
+
}: GetByLabelProps) => Cypress.Chainable;
|
|
790
|
+
getByTestId: ({
|
|
791
|
+
patternType,
|
|
792
|
+
tag,
|
|
793
|
+
testId
|
|
794
|
+
}: GetByTestIdProps) => Cypress.Chainable;
|
|
795
|
+
getContainerId: (containerName: string) => Cypress.Chainable;
|
|
796
|
+
getContainerIpAddress: (containerName: string) => Cypress.Chainable;
|
|
797
|
+
getContainersLogs: () => Cypress.Chainable;
|
|
353
798
|
getIframeBody: () => Cypress.Chainable;
|
|
799
|
+
getTimeFromHeader: () => Cypress.Chainable;
|
|
354
800
|
getWebVersion: () => Cypress.Chainable;
|
|
355
801
|
hoverRootMenuItem: (rootItemNumber: number) => Cypress.Chainable;
|
|
802
|
+
insertDashboard: (dashboard: Dashboard) => Cypress.Chainable;
|
|
803
|
+
insertDashboardList: (fixtureFile: string) => Cypress.Chainable;
|
|
804
|
+
insertDashboardWithWidget: (
|
|
805
|
+
dashboard: Dashboard,
|
|
806
|
+
patch: PatchDashboardBody
|
|
807
|
+
) => Cypress.Chainable;
|
|
808
|
+
loginAsAdminViaApiV2: () => Cypress.Chainable;
|
|
356
809
|
loginByTypeOfUser: ({
|
|
357
|
-
jsonName
|
|
358
|
-
loginViaApi
|
|
810
|
+
jsonName,
|
|
811
|
+
loginViaApi
|
|
359
812
|
}: LoginByTypeOfUserProps) => Cypress.Chainable;
|
|
813
|
+
logout: () => void;
|
|
814
|
+
logoutViaAPI: () => Cypress.Chainable;
|
|
360
815
|
moveSortableElement: (direction: string) => Cypress.Chainable;
|
|
361
816
|
navigateTo: ({
|
|
362
817
|
page,
|
|
363
818
|
rootItemNumber,
|
|
364
819
|
subMenu
|
|
365
820
|
}: NavigateToProps) => Cypress.Chainable;
|
|
821
|
+
requestOnDatabase: ({
|
|
822
|
+
database,
|
|
823
|
+
query
|
|
824
|
+
}: RequestOnDatabaseProps) => Cypress.Chainable;
|
|
825
|
+
setUserTokenApiV1: ({
|
|
826
|
+
login,
|
|
827
|
+
password
|
|
828
|
+
}?: SetUserTokenApiV1Props) => Cypress.Chainable;
|
|
829
|
+
shareDashboardToUser: ({
|
|
830
|
+
dashboardName,
|
|
831
|
+
userName,
|
|
832
|
+
role
|
|
833
|
+
}: ShareDashboardToUserProps) => Cypress.Chainable;
|
|
366
834
|
startContainer: ({
|
|
835
|
+
command,
|
|
367
836
|
name,
|
|
368
|
-
image
|
|
837
|
+
image,
|
|
838
|
+
portBindings
|
|
369
839
|
}: StartContainerProps) => Cypress.Chainable;
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
840
|
+
startContainers: ({
|
|
841
|
+
composeFile,
|
|
842
|
+
databaseImage,
|
|
843
|
+
moduleName,
|
|
844
|
+
openidImage,
|
|
845
|
+
profiles,
|
|
373
846
|
useSlim,
|
|
374
|
-
|
|
375
|
-
|
|
847
|
+
webOs,
|
|
848
|
+
webVersion
|
|
849
|
+
}?: StartContainersProps) => Cypress.Chainable;
|
|
376
850
|
stopContainer: ({ name }: StopContainerProps) => Cypress.Chainable;
|
|
377
|
-
|
|
851
|
+
stopContainers: () => Cypress.Chainable;
|
|
378
852
|
visitEmptyPage: () => Cypress.Chainable;
|
|
379
|
-
waitForContainerAndSetToken: () => Cypress.Chainable;
|
|
380
853
|
}
|
|
381
854
|
}
|
|
382
855
|
}
|