@centreon/js-config 24.9.1 → 24.10.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 +39 -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 +225 -0
- package/cypress/e2e/commands.ts +629 -149
- package/cypress/e2e/configuration.ts +46 -40
- package/cypress/e2e/esbuild-preprocessor.ts +26 -0
- package/cypress/e2e/plugins.ts +52 -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 +4 -8
- 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,98 @@ 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 ExecInContainerOptions {
|
|
316
|
+
log: boolean;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
interface ExecInContainerResult {
|
|
320
|
+
exitCode: number;
|
|
321
|
+
output: string;
|
|
322
|
+
}
|
|
323
|
+
|
|
179
324
|
Cypress.Commands.add(
|
|
180
325
|
'execInContainer',
|
|
181
|
-
({ command, name }:
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
326
|
+
({ command, name }, { log = true } = { log: true }): Cypress.Chainable => {
|
|
327
|
+
const commands =
|
|
328
|
+
typeof command === 'string' || command instanceof String
|
|
329
|
+
? [command]
|
|
330
|
+
: command;
|
|
331
|
+
|
|
332
|
+
const results = commands.reduce(
|
|
333
|
+
(acc, runCommand) => {
|
|
334
|
+
cy.task<ExecInContainerResult>(
|
|
335
|
+
'execInContainer',
|
|
336
|
+
{ command: runCommand, name },
|
|
337
|
+
{ log, timeout: 600000 }
|
|
338
|
+
).then((result) => {
|
|
339
|
+
const displayedOutput = log ? result.output : 'hidden command output';
|
|
340
|
+
const displayedRunCommand = log ? runCommand : 'hidden run command';
|
|
341
|
+
|
|
342
|
+
if (result.exitCode) {
|
|
343
|
+
cy.log(displayedOutput);
|
|
344
|
+
|
|
345
|
+
// output will not be truncated
|
|
346
|
+
throw new Error(`
|
|
347
|
+
Execution of "${displayedRunCommand}" failed
|
|
348
|
+
Exit code: ${result.exitCode}
|
|
349
|
+
Output:\n${displayedOutput}`);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
acc.output = `${acc.output}${displayedOutput}`;
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
return acc;
|
|
356
|
+
},
|
|
357
|
+
{ exitCode: 0, output: '' }
|
|
358
|
+
);
|
|
193
359
|
|
|
194
|
-
|
|
195
|
-
|
|
360
|
+
return cy.wrap(results);
|
|
361
|
+
}
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
interface RequestOnDatabaseProps {
|
|
365
|
+
database: string;
|
|
366
|
+
query: string;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
Cypress.Commands.add(
|
|
370
|
+
'requestOnDatabase',
|
|
371
|
+
({ database, query }: RequestOnDatabaseProps): Cypress.Chainable => {
|
|
372
|
+
return cy.task('requestOnDatabase', { database, query });
|
|
373
|
+
}
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
interface SetUserTokenApiV1Props {
|
|
377
|
+
login?: string;
|
|
378
|
+
password?: string;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
Cypress.Commands.add(
|
|
382
|
+
'setUserTokenApiV1',
|
|
383
|
+
({
|
|
384
|
+
login = 'admin',
|
|
385
|
+
password = 'Centreon!2021'
|
|
386
|
+
}: SetUserTokenApiV1Props = {}): Cypress.Chainable => {
|
|
387
|
+
return cy
|
|
388
|
+
.request({
|
|
389
|
+
body: {
|
|
390
|
+
password,
|
|
391
|
+
username: login
|
|
392
|
+
},
|
|
393
|
+
headers: {
|
|
394
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
395
|
+
},
|
|
396
|
+
method: 'POST',
|
|
397
|
+
url: `${apiActionV1}?action=authenticate`
|
|
398
|
+
})
|
|
399
|
+
.then(({ body }) =>
|
|
400
|
+
window.localStorage.setItem('userTokenApiV1', body.authToken)
|
|
401
|
+
);
|
|
196
402
|
}
|
|
197
403
|
);
|
|
198
404
|
|
|
@@ -202,6 +408,7 @@ interface PortBinding {
|
|
|
202
408
|
}
|
|
203
409
|
|
|
204
410
|
interface StartContainerProps {
|
|
411
|
+
command?: string;
|
|
205
412
|
image: string;
|
|
206
413
|
name: string;
|
|
207
414
|
portBindings: Array<PortBinding>;
|
|
@@ -209,174 +416,447 @@ interface StartContainerProps {
|
|
|
209
416
|
|
|
210
417
|
Cypress.Commands.add(
|
|
211
418
|
'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
|
-
);
|
|
419
|
+
({
|
|
420
|
+
command,
|
|
421
|
+
name,
|
|
422
|
+
image,
|
|
423
|
+
portBindings
|
|
424
|
+
}: StartContainerProps): Cypress.Chainable => {
|
|
425
|
+
cy.log(`Starting container ${name} from image ${image}`);
|
|
426
|
+
|
|
427
|
+
return cy.task(
|
|
428
|
+
'startContainer',
|
|
429
|
+
{ command, image, name, portBindings },
|
|
430
|
+
{ timeout: 600000 } // 10 minutes because docker pull can be very slow
|
|
431
|
+
);
|
|
236
432
|
}
|
|
237
433
|
);
|
|
238
434
|
|
|
239
|
-
interface
|
|
240
|
-
|
|
241
|
-
|
|
435
|
+
interface StartContainersProps {
|
|
436
|
+
composeFile?: string;
|
|
437
|
+
databaseImage?: string;
|
|
438
|
+
moduleName?: string;
|
|
439
|
+
openidImage?: string;
|
|
440
|
+
profiles?: Array<string>;
|
|
441
|
+
samlImage?: string;
|
|
242
442
|
useSlim?: boolean;
|
|
243
|
-
|
|
443
|
+
webOs?: string;
|
|
444
|
+
webVersion?: string;
|
|
244
445
|
}
|
|
245
446
|
|
|
246
447
|
Cypress.Commands.add(
|
|
247
|
-
'
|
|
448
|
+
'startContainers',
|
|
248
449
|
({
|
|
249
|
-
|
|
250
|
-
|
|
450
|
+
composeFile,
|
|
451
|
+
databaseImage = Cypress.env('DATABASE_IMAGE'),
|
|
452
|
+
moduleName = 'centreon-web',
|
|
453
|
+
openidImage = `docker.centreon.com/centreon/keycloak:${Cypress.env(
|
|
454
|
+
'OPENID_IMAGE_VERSION'
|
|
455
|
+
)}`,
|
|
456
|
+
profiles = [],
|
|
457
|
+
samlImage = `docker.centreon.com/centreon/keycloak:${Cypress.env(
|
|
458
|
+
'SAML_IMAGE_VERSION'
|
|
459
|
+
)}`,
|
|
251
460
|
useSlim = true,
|
|
252
|
-
|
|
253
|
-
|
|
461
|
+
webOs = Cypress.env('WEB_IMAGE_OS'),
|
|
462
|
+
webVersion = Cypress.env('WEB_IMAGE_VERSION')
|
|
463
|
+
}: StartContainersProps = {}): Cypress.Chainable => {
|
|
464
|
+
cy.log('Starting containers ...');
|
|
465
|
+
|
|
466
|
+
let composeFilePath = composeFile;
|
|
467
|
+
if (!composeFile) {
|
|
468
|
+
const cypressDir = path.dirname(Cypress.config('configFile'));
|
|
469
|
+
composeFilePath = `${cypressDir}/../../../.github/docker/docker-compose.yml`;
|
|
470
|
+
}
|
|
471
|
+
|
|
254
472
|
const slimSuffix = useSlim ? '-slim' : '';
|
|
255
473
|
|
|
256
|
-
const
|
|
474
|
+
const webImage = `docker.centreon.com/centreon/${moduleName}${slimSuffix}-${webOs}:${webVersion}`;
|
|
257
475
|
|
|
258
476
|
return cy
|
|
259
|
-
.
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
477
|
+
.task(
|
|
478
|
+
'startContainers',
|
|
479
|
+
{
|
|
480
|
+
composeFile: composeFilePath,
|
|
481
|
+
databaseImage,
|
|
482
|
+
openidImage,
|
|
483
|
+
profiles,
|
|
484
|
+
samlImage,
|
|
485
|
+
webImage
|
|
486
|
+
},
|
|
487
|
+
{ timeout: 600000 } // 10 minutes because docker pull can be very slow
|
|
488
|
+
)
|
|
264
489
|
.then(() => {
|
|
265
|
-
const baseUrl = 'http://
|
|
490
|
+
const baseUrl = 'http://127.0.0.1:4000';
|
|
266
491
|
|
|
267
492
|
Cypress.config('baseUrl', baseUrl);
|
|
268
493
|
|
|
269
|
-
return cy.
|
|
270
|
-
`npx wait-on ${baseUrl}/centreon/api/latest/platform/installation/status`
|
|
271
|
-
);
|
|
494
|
+
return cy.wrap(null);
|
|
272
495
|
})
|
|
273
496
|
.visit('/') // this is necessary to refresh browser cause baseUrl has changed (flash appears in video)
|
|
274
497
|
.setUserTokenApiV1();
|
|
275
498
|
}
|
|
276
499
|
);
|
|
277
500
|
|
|
278
|
-
interface
|
|
279
|
-
name
|
|
501
|
+
interface StopContainerProps {
|
|
502
|
+
name: string;
|
|
280
503
|
}
|
|
281
504
|
|
|
282
505
|
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
|
-
)}`;
|
|
506
|
+
'stopContainer',
|
|
507
|
+
({ name }: StopContainerProps): Cypress.Chainable => {
|
|
508
|
+
cy.log(`Stopping container ${name}`);
|
|
294
509
|
|
|
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 });
|
|
510
|
+
return cy.task('stopContainer', { name });
|
|
317
511
|
}
|
|
318
512
|
);
|
|
319
513
|
|
|
320
|
-
|
|
514
|
+
Cypress.Commands.add('stopContainers', (): Cypress.Chainable => {
|
|
515
|
+
cy.log('Stopping containers ...');
|
|
516
|
+
|
|
517
|
+
const logDirectory = `results/logs/${Cypress.spec.name.replace(
|
|
518
|
+
artifactIllegalCharactersMatcher,
|
|
519
|
+
'_'
|
|
520
|
+
)}/${Cypress.currentTest.title.replace(
|
|
521
|
+
artifactIllegalCharactersMatcher,
|
|
522
|
+
'_'
|
|
523
|
+
)}`;
|
|
524
|
+
|
|
525
|
+
const name = 'web';
|
|
526
|
+
|
|
527
|
+
return cy
|
|
528
|
+
.visitEmptyPage()
|
|
529
|
+
.createDirectory(logDirectory)
|
|
530
|
+
.getContainersLogs()
|
|
531
|
+
.then((containersLogs: Array<Array<string>>) => {
|
|
532
|
+
if (!containersLogs) {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
Object.entries(containersLogs).forEach(([containerName, logs]) => {
|
|
537
|
+
cy.writeFile(
|
|
538
|
+
`results/logs/${Cypress.spec.name.replace(
|
|
539
|
+
artifactIllegalCharactersMatcher,
|
|
540
|
+
'_'
|
|
541
|
+
)}/${Cypress.currentTest.title.replace(
|
|
542
|
+
artifactIllegalCharactersMatcher,
|
|
543
|
+
'_'
|
|
544
|
+
)}/container-${containerName}.log`,
|
|
545
|
+
logs
|
|
546
|
+
);
|
|
547
|
+
});
|
|
548
|
+
})
|
|
549
|
+
.copyFromContainer({
|
|
550
|
+
destination: `${logDirectory}/broker`,
|
|
551
|
+
name,
|
|
552
|
+
source: '/var/log/centreon-broker'
|
|
553
|
+
})
|
|
554
|
+
.copyFromContainer({
|
|
555
|
+
destination: `${logDirectory}/engine`,
|
|
556
|
+
name,
|
|
557
|
+
source: '/var/log/centreon-engine'
|
|
558
|
+
})
|
|
559
|
+
.copyFromContainer({
|
|
560
|
+
destination: `${logDirectory}/centreon`,
|
|
561
|
+
name,
|
|
562
|
+
source: '/var/log/centreon'
|
|
563
|
+
})
|
|
564
|
+
.copyFromContainer({
|
|
565
|
+
destination: `${logDirectory}/centreon-gorgone`,
|
|
566
|
+
name,
|
|
567
|
+
source: '/var/log/centreon-gorgone'
|
|
568
|
+
})
|
|
569
|
+
.then(() => {
|
|
570
|
+
if (Cypress.env('WEB_IMAGE_OS').includes('alma')) {
|
|
571
|
+
return cy.copyFromContainer({
|
|
572
|
+
destination: `${logDirectory}/php`,
|
|
573
|
+
name,
|
|
574
|
+
source: '/var/log/php-fpm'
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
return cy.copyFromContainer(
|
|
579
|
+
{
|
|
580
|
+
destination: `${logDirectory}/php8.1-fpm-centreon-error.log`,
|
|
581
|
+
name,
|
|
582
|
+
source: '/var/log/php8.1-fpm-centreon-error.log'
|
|
583
|
+
},
|
|
584
|
+
{ failOnNonZeroExit: false }
|
|
585
|
+
);
|
|
586
|
+
})
|
|
587
|
+
.then(() => {
|
|
588
|
+
if (Cypress.env('WEB_IMAGE_OS').includes('alma')) {
|
|
589
|
+
return cy.copyFromContainer({
|
|
590
|
+
destination: `${logDirectory}/httpd`,
|
|
591
|
+
name,
|
|
592
|
+
source: '/var/log/httpd'
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
return cy.copyFromContainer(
|
|
597
|
+
{
|
|
598
|
+
destination: `${logDirectory}/apache2`,
|
|
599
|
+
name,
|
|
600
|
+
source: '/var/log/apache2'
|
|
601
|
+
},
|
|
602
|
+
{ failOnNonZeroExit: false }
|
|
603
|
+
);
|
|
604
|
+
})
|
|
605
|
+
.exec(`chmod -R 755 "${logDirectory}"`)
|
|
606
|
+
.task(
|
|
607
|
+
'stopContainers',
|
|
608
|
+
{},
|
|
609
|
+
{ timeout: 600000 } // 10 minutes because docker pull can be very slow
|
|
610
|
+
);
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
Cypress.Commands.add(
|
|
614
|
+
'createDirectory',
|
|
615
|
+
(directoryPath: string): Cypress.Chainable => {
|
|
616
|
+
return cy.task('createDirectory', directoryPath);
|
|
617
|
+
}
|
|
618
|
+
);
|
|
619
|
+
|
|
620
|
+
interface Dashboard {
|
|
621
|
+
description?: string;
|
|
321
622
|
name: string;
|
|
322
623
|
}
|
|
323
624
|
|
|
324
625
|
Cypress.Commands.add(
|
|
325
|
-
'
|
|
326
|
-
(
|
|
327
|
-
cy.
|
|
328
|
-
cy.
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
'_'
|
|
335
|
-
)}/container-${name}.log`,
|
|
336
|
-
stdout
|
|
626
|
+
'insertDashboardList',
|
|
627
|
+
(fixtureFile: string): Cypress.Chainable => {
|
|
628
|
+
return cy.fixture(fixtureFile).then((dashboardList) => {
|
|
629
|
+
cy.wrap(
|
|
630
|
+
Promise.all(
|
|
631
|
+
dashboardList.map((dashboardBody: Dashboard) =>
|
|
632
|
+
cy.insertDashboard({ ...dashboardBody })
|
|
633
|
+
)
|
|
634
|
+
)
|
|
337
635
|
);
|
|
338
636
|
});
|
|
637
|
+
}
|
|
638
|
+
);
|
|
339
639
|
|
|
340
|
-
|
|
640
|
+
Cypress.Commands.add(
|
|
641
|
+
'insertDashboard',
|
|
642
|
+
(dashboardBody: Dashboard): Cypress.Chainable => {
|
|
643
|
+
return cy.request({
|
|
644
|
+
body: {
|
|
645
|
+
...dashboardBody
|
|
646
|
+
},
|
|
647
|
+
method: 'POST',
|
|
648
|
+
url: '/centreon/api/latest/configuration/dashboards'
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
);
|
|
652
|
+
|
|
653
|
+
Cypress.Commands.add(
|
|
654
|
+
'insertDashboardWithWidget',
|
|
655
|
+
(dashboardBody, patchBody) => {
|
|
656
|
+
cy.request({
|
|
657
|
+
body: {
|
|
658
|
+
...dashboardBody
|
|
659
|
+
},
|
|
660
|
+
method: 'POST',
|
|
661
|
+
url: '/centreon/api/latest/configuration/dashboards'
|
|
662
|
+
}).then((response) => {
|
|
663
|
+
const dashboardId = response.body.id;
|
|
664
|
+
cy.waitUntil(
|
|
665
|
+
() => {
|
|
666
|
+
return cy
|
|
667
|
+
.request({
|
|
668
|
+
method: 'GET',
|
|
669
|
+
url: `/centreon/api/latest/configuration/dashboards/${dashboardId}`
|
|
670
|
+
})
|
|
671
|
+
.then((getResponse) => {
|
|
672
|
+
return getResponse.body && getResponse.body.id === dashboardId;
|
|
673
|
+
});
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
timeout: 10000
|
|
677
|
+
}
|
|
678
|
+
);
|
|
679
|
+
cy.request({
|
|
680
|
+
body: patchBody,
|
|
681
|
+
method: 'PATCH',
|
|
682
|
+
url: `/centreon/api/latest/configuration/dashboards/${dashboardId}`
|
|
683
|
+
});
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
);
|
|
687
|
+
|
|
688
|
+
interface ShareDashboardToUserProps {
|
|
689
|
+
dashboardName: string;
|
|
690
|
+
role: string;
|
|
691
|
+
userName: string;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
interface ListingRequestResult {
|
|
695
|
+
body: {
|
|
696
|
+
result: Array<{
|
|
697
|
+
id: number;
|
|
698
|
+
}>;
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
interface PatchDashboardBody {
|
|
703
|
+
panels: Array<{
|
|
704
|
+
layout: {
|
|
705
|
+
height: number;
|
|
706
|
+
min_height: number;
|
|
707
|
+
min_width: number;
|
|
708
|
+
width: number;
|
|
709
|
+
x: number;
|
|
710
|
+
y: number;
|
|
711
|
+
};
|
|
712
|
+
name: string;
|
|
713
|
+
widget_settings: {
|
|
714
|
+
options: {
|
|
715
|
+
description: {
|
|
716
|
+
content: string;
|
|
717
|
+
enabled: boolean;
|
|
718
|
+
};
|
|
719
|
+
name: string;
|
|
720
|
+
};
|
|
721
|
+
};
|
|
722
|
+
widget_type: string;
|
|
723
|
+
}>;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
Cypress.Commands.add(
|
|
727
|
+
'shareDashboardToUser',
|
|
728
|
+
({ dashboardName, userName, role }: ShareDashboardToUserProps): void => {
|
|
729
|
+
Promise.all([
|
|
730
|
+
cy.request({
|
|
731
|
+
method: 'GET',
|
|
732
|
+
url: `/centreon/api/latest/configuration/users?search={"name":"${userName}"}`
|
|
733
|
+
}),
|
|
734
|
+
cy.request({
|
|
735
|
+
method: 'GET',
|
|
736
|
+
url: `/centreon/api/latest/configuration/dashboards?search={"name":"${dashboardName}"}`
|
|
737
|
+
})
|
|
738
|
+
]).then(
|
|
739
|
+
([retrievedUser, retrievedDashboard]: [
|
|
740
|
+
ListingRequestResult,
|
|
741
|
+
ListingRequestResult
|
|
742
|
+
]) => {
|
|
743
|
+
const userId = retrievedUser.body.result[0].id;
|
|
744
|
+
const dashboardId = retrievedDashboard.body.result[0].id;
|
|
745
|
+
|
|
746
|
+
cy.request({
|
|
747
|
+
body: {
|
|
748
|
+
id: userId,
|
|
749
|
+
role: `${role}`
|
|
750
|
+
},
|
|
751
|
+
method: 'POST',
|
|
752
|
+
url: `/centreon/api/latest/configuration/dashboards/${dashboardId}/access_rights/contacts`
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
);
|
|
341
756
|
}
|
|
342
757
|
);
|
|
343
758
|
|
|
759
|
+
Cypress.Commands.add('getTimeFromHeader', (): Cypress.Chainable => {
|
|
760
|
+
return cy
|
|
761
|
+
.get('header div[data-cy="clock"]', { timeout: 20000 })
|
|
762
|
+
.should('be.visible')
|
|
763
|
+
.then(($time) => {
|
|
764
|
+
const headerTime = $time.children()[1].textContent;
|
|
765
|
+
if (headerTime?.match(/\d+:\d+/)) {
|
|
766
|
+
cy.log(`header time is : ${headerTime}`);
|
|
767
|
+
|
|
768
|
+
return cy.wrap(headerTime);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
throw new Error(`header time is not displayed`);
|
|
772
|
+
});
|
|
773
|
+
});
|
|
774
|
+
|
|
344
775
|
declare global {
|
|
345
776
|
namespace Cypress {
|
|
346
777
|
interface Chainable {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
778
|
+
clickSubRootMenuItem: (page: string) => Cypress.Chainable;
|
|
779
|
+
copyFromContainer: (
|
|
780
|
+
props: CopyFromContainerProps,
|
|
781
|
+
options?: Partial<Cypress.ExecOptions>
|
|
782
|
+
) => Cypress.Chainable;
|
|
783
|
+
copyToContainer: (
|
|
784
|
+
props: CopyToContainerProps,
|
|
785
|
+
options?: Partial<Cypress.ExecOptions>
|
|
786
|
+
) => Cypress.Chainable;
|
|
787
|
+
createDirectory: (directoryPath: string) => Cypress.Chainable;
|
|
788
|
+
execInContainer: (
|
|
789
|
+
props: ExecInContainerProps,
|
|
790
|
+
options?: ExecInContainerOptions
|
|
791
|
+
) => Cypress.Chainable;
|
|
792
|
+
getByLabel: ({
|
|
793
|
+
patternType,
|
|
794
|
+
tag,
|
|
795
|
+
label
|
|
796
|
+
}: GetByLabelProps) => Cypress.Chainable;
|
|
797
|
+
getByTestId: ({
|
|
798
|
+
patternType,
|
|
799
|
+
tag,
|
|
800
|
+
testId
|
|
801
|
+
}: GetByTestIdProps) => Cypress.Chainable;
|
|
802
|
+
getContainerId: (containerName: string) => Cypress.Chainable;
|
|
803
|
+
getContainerIpAddress: (containerName: string) => Cypress.Chainable;
|
|
804
|
+
getContainersLogs: () => Cypress.Chainable;
|
|
353
805
|
getIframeBody: () => Cypress.Chainable;
|
|
806
|
+
getTimeFromHeader: () => Cypress.Chainable;
|
|
354
807
|
getWebVersion: () => Cypress.Chainable;
|
|
355
808
|
hoverRootMenuItem: (rootItemNumber: number) => Cypress.Chainable;
|
|
809
|
+
insertDashboard: (dashboard: Dashboard) => Cypress.Chainable;
|
|
810
|
+
insertDashboardList: (fixtureFile: string) => Cypress.Chainable;
|
|
811
|
+
insertDashboardWithWidget: (
|
|
812
|
+
dashboard: Dashboard,
|
|
813
|
+
patch: PatchDashboardBody
|
|
814
|
+
) => Cypress.Chainable;
|
|
815
|
+
loginAsAdminViaApiV2: () => Cypress.Chainable;
|
|
356
816
|
loginByTypeOfUser: ({
|
|
357
|
-
jsonName
|
|
358
|
-
loginViaApi
|
|
817
|
+
jsonName,
|
|
818
|
+
loginViaApi
|
|
359
819
|
}: LoginByTypeOfUserProps) => Cypress.Chainable;
|
|
820
|
+
logout: () => void;
|
|
821
|
+
logoutViaAPI: () => Cypress.Chainable;
|
|
360
822
|
moveSortableElement: (direction: string) => Cypress.Chainable;
|
|
361
823
|
navigateTo: ({
|
|
362
824
|
page,
|
|
363
825
|
rootItemNumber,
|
|
364
826
|
subMenu
|
|
365
827
|
}: NavigateToProps) => Cypress.Chainable;
|
|
828
|
+
requestOnDatabase: ({
|
|
829
|
+
database,
|
|
830
|
+
query
|
|
831
|
+
}: RequestOnDatabaseProps) => Cypress.Chainable;
|
|
832
|
+
setUserTokenApiV1: ({
|
|
833
|
+
login,
|
|
834
|
+
password
|
|
835
|
+
}?: SetUserTokenApiV1Props) => Cypress.Chainable;
|
|
836
|
+
shareDashboardToUser: ({
|
|
837
|
+
dashboardName,
|
|
838
|
+
userName,
|
|
839
|
+
role
|
|
840
|
+
}: ShareDashboardToUserProps) => Cypress.Chainable;
|
|
366
841
|
startContainer: ({
|
|
842
|
+
command,
|
|
367
843
|
name,
|
|
368
|
-
image
|
|
844
|
+
image,
|
|
845
|
+
portBindings
|
|
369
846
|
}: StartContainerProps) => Cypress.Chainable;
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
847
|
+
startContainers: ({
|
|
848
|
+
composeFile,
|
|
849
|
+
databaseImage,
|
|
850
|
+
moduleName,
|
|
851
|
+
openidImage,
|
|
852
|
+
profiles,
|
|
373
853
|
useSlim,
|
|
374
|
-
|
|
375
|
-
|
|
854
|
+
webOs,
|
|
855
|
+
webVersion
|
|
856
|
+
}?: StartContainersProps) => Cypress.Chainable;
|
|
376
857
|
stopContainer: ({ name }: StopContainerProps) => Cypress.Chainable;
|
|
377
|
-
|
|
858
|
+
stopContainers: () => Cypress.Chainable;
|
|
378
859
|
visitEmptyPage: () => Cypress.Chainable;
|
|
379
|
-
waitForContainerAndSetToken: () => Cypress.Chainable;
|
|
380
860
|
}
|
|
381
861
|
}
|
|
382
862
|
}
|