@centreon/js-config 24.4.20 → 24.4.22
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/cypress/e2e/commands.ts +392 -166
- package/cypress/e2e/configuration.ts +5 -5
- package/cypress/e2e/plugins.ts +1 -1
- package/cypress/e2e/tasks.ts +206 -53
- package/package.json +13 -10
package/cypress/e2e/commands.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
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';
|
|
4
6
|
import './commands/monitoring';
|
|
@@ -7,10 +9,53 @@ import installLogsCollector from 'cypress-terminal-report/src/installLogsCollect
|
|
|
7
9
|
|
|
8
10
|
installLogsCollector({ enableExtendedCollector: true });
|
|
9
11
|
|
|
12
|
+
const apiBase = '/centreon/api';
|
|
13
|
+
const apiActionV1 = `${apiBase}/index.php`;
|
|
10
14
|
const apiLoginV2 = '/centreon/authentication/providers/configurations/local';
|
|
11
15
|
|
|
12
16
|
const artifactIllegalCharactersMatcher = /[,\s/|<>*?:"]/g;
|
|
13
17
|
|
|
18
|
+
export enum PatternType {
|
|
19
|
+
contains = '*',
|
|
20
|
+
endsWith = '$',
|
|
21
|
+
equals = '',
|
|
22
|
+
startsWith = '^'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface GetByLabelProps {
|
|
26
|
+
label: string;
|
|
27
|
+
patternType?: PatternType;
|
|
28
|
+
tag?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Cypress.Commands.add(
|
|
32
|
+
'getByLabel',
|
|
33
|
+
({
|
|
34
|
+
tag = '',
|
|
35
|
+
patternType = PatternType.equals,
|
|
36
|
+
label
|
|
37
|
+
}: GetByLabelProps): Cypress.Chainable => {
|
|
38
|
+
return cy.get(`${tag}[aria-label${patternType}="${label}"]`);
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
interface GetByTestIdProps {
|
|
43
|
+
patternType?: PatternType;
|
|
44
|
+
tag?: string;
|
|
45
|
+
testId: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Cypress.Commands.add(
|
|
49
|
+
'getByTestId',
|
|
50
|
+
({
|
|
51
|
+
tag = '',
|
|
52
|
+
patternType = PatternType.equals,
|
|
53
|
+
testId
|
|
54
|
+
}: GetByTestIdProps): Cypress.Chainable => {
|
|
55
|
+
return cy.get(`${tag}[data-testid${patternType}="${testId}"]`);
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
|
|
14
59
|
Cypress.Commands.add('getWebVersion', (): Cypress.Chainable => {
|
|
15
60
|
return cy
|
|
16
61
|
.exec(
|
|
@@ -59,7 +104,7 @@ interface NavigateToProps {
|
|
|
59
104
|
|
|
60
105
|
Cypress.Commands.add(
|
|
61
106
|
'navigateTo',
|
|
62
|
-
({ rootItemNumber, subMenu, page }): void => {
|
|
107
|
+
({ rootItemNumber, subMenu, page }: NavigateToProps): void => {
|
|
63
108
|
if (subMenu) {
|
|
64
109
|
cy.hoverRootMenuItem(rootItemNumber)
|
|
65
110
|
.contains(subMenu)
|
|
@@ -100,6 +145,24 @@ Cypress.Commands.add(
|
|
|
100
145
|
}
|
|
101
146
|
);
|
|
102
147
|
|
|
148
|
+
Cypress.Commands.add('getContainerId', (containerName: string) => {
|
|
149
|
+
cy.log(`Getting container id of ${containerName}`);
|
|
150
|
+
|
|
151
|
+
return cy.task('getContainerId', containerName);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
Cypress.Commands.add('getContainerIpAddress', (containerName: string) => {
|
|
155
|
+
cy.log(`Getting container ip address of ${containerName}`);
|
|
156
|
+
|
|
157
|
+
return cy.task('getContainerIpAddress', containerName);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
Cypress.Commands.add('getContainersLogs', () => {
|
|
161
|
+
cy.log('Getting containers logs');
|
|
162
|
+
|
|
163
|
+
return cy.task('getContainersLogs');
|
|
164
|
+
});
|
|
165
|
+
|
|
103
166
|
interface CopyFromContainerProps {
|
|
104
167
|
destination: string;
|
|
105
168
|
name?: string;
|
|
@@ -108,38 +171,54 @@ interface CopyFromContainerProps {
|
|
|
108
171
|
|
|
109
172
|
Cypress.Commands.add(
|
|
110
173
|
'copyFromContainer',
|
|
111
|
-
(
|
|
112
|
-
{
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
destination
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
return cy.exec(`docker cp ${name}:${source} "${destination}"`, options);
|
|
174
|
+
({ name = 'web', source, destination }: CopyFromContainerProps) => {
|
|
175
|
+
cy.log(`Copy content from ${name}:${source} to ${destination}`);
|
|
176
|
+
|
|
177
|
+
return cy.task('copyFromContainer', {
|
|
178
|
+
destination,
|
|
179
|
+
serviceName: name,
|
|
180
|
+
source
|
|
181
|
+
});
|
|
120
182
|
}
|
|
121
183
|
);
|
|
122
184
|
|
|
185
|
+
export enum CopyToContainerContentType {
|
|
186
|
+
Directory = 'directory',
|
|
187
|
+
File = 'file'
|
|
188
|
+
}
|
|
189
|
+
|
|
123
190
|
interface CopyToContainerProps {
|
|
124
191
|
destination: string;
|
|
125
192
|
name?: string;
|
|
126
193
|
source: string;
|
|
194
|
+
type: CopyToContainerContentType;
|
|
127
195
|
}
|
|
128
196
|
|
|
129
197
|
Cypress.Commands.add(
|
|
130
198
|
'copyToContainer',
|
|
131
|
-
(
|
|
132
|
-
{
|
|
133
|
-
|
|
199
|
+
({ name = 'web', source, destination, type }: CopyToContainerProps) => {
|
|
200
|
+
cy.log(`Copy content from ${source} to ${name}:${destination}`);
|
|
201
|
+
|
|
202
|
+
return cy.task('copyToContainer', {
|
|
203
|
+
destination,
|
|
204
|
+
serviceName: name,
|
|
134
205
|
source,
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
options?: Partial<Cypress.ExecOptions>
|
|
138
|
-
) => {
|
|
139
|
-
return cy.exec(`docker cp ${source} ${name}:${destination}`, options);
|
|
206
|
+
type
|
|
207
|
+
});
|
|
140
208
|
}
|
|
141
209
|
);
|
|
142
210
|
|
|
211
|
+
Cypress.Commands.add('loginAsAdminViaApiV2', (): Cypress.Chainable => {
|
|
212
|
+
return cy.request({
|
|
213
|
+
body: {
|
|
214
|
+
login: 'admin',
|
|
215
|
+
password: 'Centreon!2021'
|
|
216
|
+
},
|
|
217
|
+
method: 'POST',
|
|
218
|
+
url: apiLoginV2
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
143
222
|
interface LoginByTypeOfUserProps {
|
|
144
223
|
jsonName?: string;
|
|
145
224
|
loginViaApi?: boolean;
|
|
@@ -186,6 +265,33 @@ Cypress.Commands.add(
|
|
|
186
265
|
}
|
|
187
266
|
);
|
|
188
267
|
|
|
268
|
+
Cypress.Commands.add('logout', (): void => {
|
|
269
|
+
cy.getByLabel({ label: 'Profile' }).should('exist').click();
|
|
270
|
+
|
|
271
|
+
cy.intercept({
|
|
272
|
+
method: 'GET',
|
|
273
|
+
times: 1,
|
|
274
|
+
url: '/centreon/api/latest/authentication/logout'
|
|
275
|
+
}).as('logout');
|
|
276
|
+
|
|
277
|
+
cy.contains(/^Logout$/).click();
|
|
278
|
+
|
|
279
|
+
cy.wait('@logout').its('response.statusCode').should('eq', 302);
|
|
280
|
+
|
|
281
|
+
// https://github.com/cypress-io/cypress/issues/25841
|
|
282
|
+
cy.clearAllCookies();
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
Cypress.Commands.add('logoutViaAPI', (): Cypress.Chainable => {
|
|
286
|
+
return cy
|
|
287
|
+
.request({
|
|
288
|
+
method: 'GET',
|
|
289
|
+
url: '/centreon/authentication/logout'
|
|
290
|
+
})
|
|
291
|
+
.visit('/')
|
|
292
|
+
.getByLabel({ label: 'Alias', tag: 'input' });
|
|
293
|
+
});
|
|
294
|
+
|
|
189
295
|
Cypress.Commands.add(
|
|
190
296
|
'visitEmptyPage',
|
|
191
297
|
(): Cypress.Chainable =>
|
|
@@ -197,32 +303,91 @@ Cypress.Commands.add(
|
|
|
197
303
|
.visit('/waiting-page')
|
|
198
304
|
);
|
|
199
305
|
|
|
200
|
-
Cypress.Commands.add('waitForContainerAndSetToken', (): Cypress.Chainable => {
|
|
201
|
-
return cy.setUserTokenApiV1();
|
|
202
|
-
});
|
|
203
|
-
|
|
204
306
|
interface ExecInContainerProps {
|
|
205
|
-
command: string
|
|
307
|
+
command: string | Array<string>;
|
|
206
308
|
name: string;
|
|
207
309
|
}
|
|
208
310
|
|
|
311
|
+
interface ExecInContainerResult {
|
|
312
|
+
exitCode: number;
|
|
313
|
+
output: string;
|
|
314
|
+
}
|
|
315
|
+
|
|
209
316
|
Cypress.Commands.add(
|
|
210
317
|
'execInContainer',
|
|
211
318
|
({ command, name }: ExecInContainerProps): Cypress.Chainable => {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
319
|
+
const commands =
|
|
320
|
+
typeof command === 'string' || command instanceof String
|
|
321
|
+
? [command]
|
|
322
|
+
: command;
|
|
323
|
+
|
|
324
|
+
const results = commands.reduce(
|
|
325
|
+
(acc, runCommand) => {
|
|
326
|
+
cy.task<ExecInContainerResult>(
|
|
327
|
+
'execInContainer',
|
|
328
|
+
{ command: runCommand, name },
|
|
329
|
+
{ timeout: 600000 }
|
|
330
|
+
).then((result) => {
|
|
331
|
+
if (result.exitCode) {
|
|
332
|
+
cy.log(result.output);
|
|
333
|
+
|
|
334
|
+
// output will not be truncated
|
|
335
|
+
throw new Error(`
|
|
336
|
+
Execution of "${runCommand}" failed
|
|
337
|
+
Exit code: ${result.exitCode}
|
|
338
|
+
Output:\n${result.output}`);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
acc.output = `${acc.output}${result.output}`;
|
|
342
|
+
});
|
|
223
343
|
|
|
224
|
-
return
|
|
225
|
-
}
|
|
344
|
+
return acc;
|
|
345
|
+
},
|
|
346
|
+
{ exitCode: 0, output: '' }
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
return cy.wrap(results);
|
|
350
|
+
}
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
interface RequestOnDatabaseProps {
|
|
354
|
+
database: string;
|
|
355
|
+
query: string;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
Cypress.Commands.add(
|
|
359
|
+
'requestOnDatabase',
|
|
360
|
+
({ database, query }: RequestOnDatabaseProps): Cypress.Chainable => {
|
|
361
|
+
return cy.task('requestOnDatabase', { database, query });
|
|
362
|
+
}
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
interface SetUserTokenApiV1Props {
|
|
366
|
+
login?: string;
|
|
367
|
+
password?: string;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
Cypress.Commands.add(
|
|
371
|
+
'setUserTokenApiV1',
|
|
372
|
+
({
|
|
373
|
+
login = 'admin',
|
|
374
|
+
password = 'Centreon!2021'
|
|
375
|
+
}: SetUserTokenApiV1Props = {}): Cypress.Chainable => {
|
|
376
|
+
return cy
|
|
377
|
+
.request({
|
|
378
|
+
body: {
|
|
379
|
+
password,
|
|
380
|
+
username: login
|
|
381
|
+
},
|
|
382
|
+
headers: {
|
|
383
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
384
|
+
},
|
|
385
|
+
method: 'POST',
|
|
386
|
+
url: `${apiActionV1}?action=authenticate`
|
|
387
|
+
})
|
|
388
|
+
.then(({ body }) =>
|
|
389
|
+
window.localStorage.setItem('userTokenApiV1', body.authToken)
|
|
390
|
+
);
|
|
226
391
|
}
|
|
227
392
|
);
|
|
228
393
|
|
|
@@ -232,6 +397,7 @@ interface PortBinding {
|
|
|
232
397
|
}
|
|
233
398
|
|
|
234
399
|
interface StartContainerProps {
|
|
400
|
+
command?: string;
|
|
235
401
|
image: string;
|
|
236
402
|
name: string;
|
|
237
403
|
portBindings: Array<PortBinding>;
|
|
@@ -239,145 +405,88 @@ interface StartContainerProps {
|
|
|
239
405
|
|
|
240
406
|
Cypress.Commands.add(
|
|
241
407
|
'startContainer',
|
|
242
|
-
({
|
|
408
|
+
({
|
|
409
|
+
command,
|
|
410
|
+
name,
|
|
411
|
+
image,
|
|
412
|
+
portBindings
|
|
413
|
+
}: StartContainerProps): Cypress.Chainable => {
|
|
243
414
|
cy.log(`Starting container ${name} from image ${image}`);
|
|
244
415
|
|
|
245
416
|
return cy.task(
|
|
246
417
|
'startContainer',
|
|
247
|
-
{ image, name, portBindings },
|
|
418
|
+
{ command, image, name, portBindings },
|
|
248
419
|
{ timeout: 600000 } // 10 minutes because docker pull can be very slow
|
|
249
420
|
);
|
|
250
421
|
}
|
|
251
422
|
);
|
|
252
423
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
interface StartWebContainerProps {
|
|
261
|
-
name?: string;
|
|
262
|
-
os?: string;
|
|
424
|
+
interface StartContainersProps {
|
|
425
|
+
composeFile?: string;
|
|
426
|
+
databaseImage?: string;
|
|
427
|
+
moduleName?: string;
|
|
428
|
+
openidImage?: string;
|
|
429
|
+
profiles?: Array<string>;
|
|
430
|
+
samlImage?: string;
|
|
263
431
|
useSlim?: boolean;
|
|
264
|
-
|
|
432
|
+
webOs?: string;
|
|
433
|
+
webVersion?: string;
|
|
265
434
|
}
|
|
266
435
|
|
|
267
436
|
Cypress.Commands.add(
|
|
268
|
-
'
|
|
437
|
+
'startContainers',
|
|
269
438
|
({
|
|
270
|
-
|
|
271
|
-
|
|
439
|
+
composeFile,
|
|
440
|
+
databaseImage = Cypress.env('DATABASE_IMAGE'),
|
|
441
|
+
moduleName = 'centreon-web',
|
|
442
|
+
openidImage = `docker.centreon.com/centreon/keycloak:${Cypress.env(
|
|
443
|
+
'OPENID_IMAGE_VERSION'
|
|
444
|
+
)}`,
|
|
445
|
+
profiles = [],
|
|
446
|
+
samlImage = `docker.centreon.com/centreon/keycloak:${Cypress.env(
|
|
447
|
+
'SAML_IMAGE_VERSION'
|
|
448
|
+
)}`,
|
|
272
449
|
useSlim = true,
|
|
273
|
-
|
|
274
|
-
|
|
450
|
+
webOs = Cypress.env('WEB_IMAGE_OS'),
|
|
451
|
+
webVersion = Cypress.env('WEB_IMAGE_VERSION')
|
|
452
|
+
}: StartContainersProps = {}): Cypress.Chainable => {
|
|
453
|
+
cy.log('Starting containers ...');
|
|
454
|
+
|
|
455
|
+
let composeFilePath = composeFile;
|
|
456
|
+
if (!composeFile) {
|
|
457
|
+
const cypressDir = path.dirname(Cypress.config('configFile'));
|
|
458
|
+
composeFilePath = `${cypressDir}/../../../.github/docker/docker-compose.yml`;
|
|
459
|
+
}
|
|
460
|
+
|
|
275
461
|
const slimSuffix = useSlim ? '-slim' : '';
|
|
276
462
|
|
|
277
|
-
const
|
|
463
|
+
const webImage = `docker.centreon.com/centreon/${moduleName}${slimSuffix}-${webOs}:${webVersion}`;
|
|
278
464
|
|
|
279
465
|
return cy
|
|
280
|
-
.
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
466
|
+
.task(
|
|
467
|
+
'startContainers',
|
|
468
|
+
{
|
|
469
|
+
composeFile: composeFilePath,
|
|
470
|
+
databaseImage,
|
|
471
|
+
openidImage,
|
|
472
|
+
profiles,
|
|
473
|
+
samlImage,
|
|
474
|
+
webImage
|
|
475
|
+
},
|
|
476
|
+
{ timeout: 600000 } // 10 minutes because docker pull can be very slow
|
|
477
|
+
)
|
|
285
478
|
.then(() => {
|
|
286
479
|
const baseUrl = 'http://127.0.0.1:4000';
|
|
287
480
|
|
|
288
481
|
Cypress.config('baseUrl', baseUrl);
|
|
289
482
|
|
|
290
|
-
return cy.
|
|
291
|
-
'waitOn',
|
|
292
|
-
`${baseUrl}/centreon/api/latest/platform/installation/status`
|
|
293
|
-
);
|
|
483
|
+
return cy.wrap(null);
|
|
294
484
|
})
|
|
295
485
|
.visit('/') // this is necessary to refresh browser cause baseUrl has changed (flash appears in video)
|
|
296
486
|
.setUserTokenApiV1();
|
|
297
487
|
}
|
|
298
488
|
);
|
|
299
489
|
|
|
300
|
-
interface StopWebContainerProps {
|
|
301
|
-
name?: string;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
Cypress.Commands.add(
|
|
305
|
-
'stopWebContainer',
|
|
306
|
-
({
|
|
307
|
-
name = Cypress.env('dockerName')
|
|
308
|
-
}: StopWebContainerProps = {}): Cypress.Chainable => {
|
|
309
|
-
const logDirectory = `results/logs/${Cypress.spec.name.replace(
|
|
310
|
-
artifactIllegalCharactersMatcher,
|
|
311
|
-
'_'
|
|
312
|
-
)}/${Cypress.currentTest.title.replace(
|
|
313
|
-
artifactIllegalCharactersMatcher,
|
|
314
|
-
'_'
|
|
315
|
-
)}`;
|
|
316
|
-
|
|
317
|
-
return cy
|
|
318
|
-
.visitEmptyPage()
|
|
319
|
-
.createDirectory(logDirectory)
|
|
320
|
-
.copyFromContainer({
|
|
321
|
-
destination: `${logDirectory}/broker`,
|
|
322
|
-
name,
|
|
323
|
-
source: '/var/log/centreon-broker'
|
|
324
|
-
})
|
|
325
|
-
.copyFromContainer({
|
|
326
|
-
destination: `${logDirectory}/engine`,
|
|
327
|
-
name,
|
|
328
|
-
source: '/var/log/centreon-engine'
|
|
329
|
-
})
|
|
330
|
-
.copyFromContainer({
|
|
331
|
-
destination: `${logDirectory}/centreon`,
|
|
332
|
-
name,
|
|
333
|
-
source: '/var/log/centreon'
|
|
334
|
-
})
|
|
335
|
-
.copyFromContainer({
|
|
336
|
-
destination: `${logDirectory}/centreon-gorgone`,
|
|
337
|
-
name,
|
|
338
|
-
source: '/var/log/centreon-gorgone'
|
|
339
|
-
})
|
|
340
|
-
.then(() => {
|
|
341
|
-
if (Cypress.env('WEB_IMAGE_OS').includes('alma')) {
|
|
342
|
-
return cy.copyFromContainer({
|
|
343
|
-
destination: `${logDirectory}/php`,
|
|
344
|
-
name,
|
|
345
|
-
source: '/var/log/php-fpm'
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
return cy.copyFromContainer(
|
|
350
|
-
{
|
|
351
|
-
destination: `${logDirectory}/php8.1-fpm-centreon-error.log`,
|
|
352
|
-
name,
|
|
353
|
-
source: '/var/log/php8.1-fpm-centreon-error.log'
|
|
354
|
-
},
|
|
355
|
-
{ failOnNonZeroExit: false }
|
|
356
|
-
);
|
|
357
|
-
})
|
|
358
|
-
.then(() => {
|
|
359
|
-
if (Cypress.env('WEB_IMAGE_OS').includes('alma')) {
|
|
360
|
-
return cy.copyFromContainer({
|
|
361
|
-
destination: `${logDirectory}/httpd`,
|
|
362
|
-
name,
|
|
363
|
-
source: '/var/log/httpd'
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
return cy.copyFromContainer(
|
|
368
|
-
{
|
|
369
|
-
destination: `${logDirectory}/apache2`,
|
|
370
|
-
name,
|
|
371
|
-
source: '/var/log/apache2'
|
|
372
|
-
},
|
|
373
|
-
{ failOnNonZeroExit: false }
|
|
374
|
-
);
|
|
375
|
-
})
|
|
376
|
-
.exec(`chmod -R 755 "${logDirectory}"`)
|
|
377
|
-
.stopContainer({ name });
|
|
378
|
-
}
|
|
379
|
-
);
|
|
380
|
-
|
|
381
490
|
interface StopContainerProps {
|
|
382
491
|
name: string;
|
|
383
492
|
}
|
|
@@ -387,20 +496,109 @@ Cypress.Commands.add(
|
|
|
387
496
|
({ name }: StopContainerProps): Cypress.Chainable => {
|
|
388
497
|
cy.log(`Stopping container ${name}`);
|
|
389
498
|
|
|
390
|
-
cy.
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
499
|
+
return cy.task('stopContainer', { name });
|
|
500
|
+
}
|
|
501
|
+
);
|
|
502
|
+
|
|
503
|
+
Cypress.Commands.add('stopContainers', (): Cypress.Chainable => {
|
|
504
|
+
cy.log('Stopping containers ...');
|
|
505
|
+
|
|
506
|
+
const logDirectory = `results/logs/${Cypress.spec.name.replace(
|
|
507
|
+
artifactIllegalCharactersMatcher,
|
|
508
|
+
'_'
|
|
509
|
+
)}/${Cypress.currentTest.title.replace(
|
|
510
|
+
artifactIllegalCharactersMatcher,
|
|
511
|
+
'_'
|
|
512
|
+
)}`;
|
|
513
|
+
|
|
514
|
+
const name = 'web';
|
|
515
|
+
|
|
516
|
+
return cy
|
|
517
|
+
.visitEmptyPage()
|
|
518
|
+
.createDirectory(logDirectory)
|
|
519
|
+
.getContainersLogs()
|
|
520
|
+
.then((containersLogs: Array<Array<string>>) => {
|
|
521
|
+
Object.entries(containersLogs).forEach(([containerName, logs]) => {
|
|
522
|
+
cy.writeFile(
|
|
523
|
+
`results/logs/${Cypress.spec.name.replace(
|
|
524
|
+
artifactIllegalCharactersMatcher,
|
|
525
|
+
'_'
|
|
526
|
+
)}/${Cypress.currentTest.title.replace(
|
|
527
|
+
artifactIllegalCharactersMatcher,
|
|
528
|
+
'_'
|
|
529
|
+
)}/container-${containerName}.log`,
|
|
530
|
+
logs
|
|
531
|
+
);
|
|
532
|
+
});
|
|
533
|
+
})
|
|
534
|
+
.copyFromContainer({
|
|
535
|
+
destination: `${logDirectory}/broker`,
|
|
536
|
+
name,
|
|
537
|
+
source: '/var/log/centreon-broker'
|
|
538
|
+
})
|
|
539
|
+
.copyFromContainer({
|
|
540
|
+
destination: `${logDirectory}/engine`,
|
|
541
|
+
name,
|
|
542
|
+
source: '/var/log/centreon-engine'
|
|
543
|
+
})
|
|
544
|
+
.copyFromContainer({
|
|
545
|
+
destination: `${logDirectory}/centreon`,
|
|
546
|
+
name,
|
|
547
|
+
source: '/var/log/centreon'
|
|
548
|
+
})
|
|
549
|
+
.copyFromContainer({
|
|
550
|
+
destination: `${logDirectory}/centreon-gorgone`,
|
|
551
|
+
name,
|
|
552
|
+
source: '/var/log/centreon-gorgone'
|
|
553
|
+
})
|
|
554
|
+
.then(() => {
|
|
555
|
+
if (Cypress.env('WEB_IMAGE_OS').includes('alma')) {
|
|
556
|
+
return cy.copyFromContainer({
|
|
557
|
+
destination: `${logDirectory}/php`,
|
|
558
|
+
name,
|
|
559
|
+
source: '/var/log/php-fpm'
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
return cy.copyFromContainer(
|
|
564
|
+
{
|
|
565
|
+
destination: `${logDirectory}/php8.1-fpm-centreon-error.log`,
|
|
566
|
+
name,
|
|
567
|
+
source: '/var/log/php8.1-fpm-centreon-error.log'
|
|
568
|
+
},
|
|
569
|
+
{ failOnNonZeroExit: false }
|
|
570
|
+
);
|
|
571
|
+
})
|
|
572
|
+
.then(() => {
|
|
573
|
+
if (Cypress.env('WEB_IMAGE_OS').includes('alma')) {
|
|
574
|
+
return cy.copyFromContainer({
|
|
575
|
+
destination: `${logDirectory}/httpd`,
|
|
576
|
+
name,
|
|
577
|
+
source: '/var/log/httpd'
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
return cy.copyFromContainer(
|
|
582
|
+
{
|
|
583
|
+
destination: `${logDirectory}/apache2`,
|
|
584
|
+
name,
|
|
585
|
+
source: '/var/log/apache2'
|
|
586
|
+
},
|
|
587
|
+
{ failOnNonZeroExit: false }
|
|
400
588
|
);
|
|
401
|
-
})
|
|
589
|
+
})
|
|
590
|
+
.exec(`chmod -R 755 "${logDirectory}"`)
|
|
591
|
+
.task(
|
|
592
|
+
'stopContainers',
|
|
593
|
+
{},
|
|
594
|
+
{ timeout: 600000 } // 10 minutes because docker pull can be very slow
|
|
595
|
+
);
|
|
596
|
+
});
|
|
402
597
|
|
|
403
|
-
|
|
598
|
+
Cypress.Commands.add(
|
|
599
|
+
'createDirectory',
|
|
600
|
+
(directoryPath: string): Cypress.Chainable => {
|
|
601
|
+
return cy.task('createDirectory', directoryPath);
|
|
404
602
|
}
|
|
405
603
|
);
|
|
406
604
|
|
|
@@ -576,6 +774,19 @@ declare global {
|
|
|
576
774
|
command,
|
|
577
775
|
name
|
|
578
776
|
}: ExecInContainerProps) => Cypress.Chainable;
|
|
777
|
+
getByLabel: ({
|
|
778
|
+
patternType,
|
|
779
|
+
tag,
|
|
780
|
+
label
|
|
781
|
+
}: GetByLabelProps) => Cypress.Chainable;
|
|
782
|
+
getByTestId: ({
|
|
783
|
+
patternType,
|
|
784
|
+
tag,
|
|
785
|
+
testId
|
|
786
|
+
}: GetByTestIdProps) => Cypress.Chainable;
|
|
787
|
+
getContainerId: (containerName: string) => Cypress.Chainable;
|
|
788
|
+
getContainerIpAddress: (containerName: string) => Cypress.Chainable;
|
|
789
|
+
getContainersLogs: () => Cypress.Chainable;
|
|
579
790
|
getIframeBody: () => Cypress.Chainable;
|
|
580
791
|
getTimeFromHeader: () => Cypress.Chainable;
|
|
581
792
|
getWebVersion: () => Cypress.Chainable;
|
|
@@ -586,36 +797,51 @@ declare global {
|
|
|
586
797
|
dashboard: Dashboard,
|
|
587
798
|
patch: PatchDashboardBody
|
|
588
799
|
) => Cypress.Chainable;
|
|
589
|
-
|
|
800
|
+
loginAsAdminViaApiV2: () => Cypress.Chainable;
|
|
590
801
|
loginByTypeOfUser: ({
|
|
591
802
|
jsonName,
|
|
592
803
|
loginViaApi
|
|
593
804
|
}: LoginByTypeOfUserProps) => Cypress.Chainable;
|
|
805
|
+
logout: () => void;
|
|
806
|
+
logoutViaAPI: () => Cypress.Chainable;
|
|
594
807
|
moveSortableElement: (direction: string) => Cypress.Chainable;
|
|
595
808
|
navigateTo: ({
|
|
596
809
|
page,
|
|
597
810
|
rootItemNumber,
|
|
598
811
|
subMenu
|
|
599
812
|
}: NavigateToProps) => Cypress.Chainable;
|
|
813
|
+
requestOnDatabase: ({
|
|
814
|
+
database,
|
|
815
|
+
query
|
|
816
|
+
}: RequestOnDatabaseProps) => Cypress.Chainable;
|
|
817
|
+
setUserTokenApiV1: ({
|
|
818
|
+
login,
|
|
819
|
+
password
|
|
820
|
+
}?: SetUserTokenApiV1Props) => Cypress.Chainable;
|
|
600
821
|
shareDashboardToUser: ({
|
|
601
822
|
dashboardName,
|
|
602
823
|
userName,
|
|
603
824
|
role
|
|
604
825
|
}: ShareDashboardToUserProps) => Cypress.Chainable;
|
|
605
826
|
startContainer: ({
|
|
827
|
+
command,
|
|
606
828
|
name,
|
|
607
|
-
image
|
|
829
|
+
image,
|
|
830
|
+
portBindings
|
|
608
831
|
}: StartContainerProps) => Cypress.Chainable;
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
832
|
+
startContainers: ({
|
|
833
|
+
composeFile,
|
|
834
|
+
databaseImage,
|
|
835
|
+
moduleName,
|
|
836
|
+
openidImage,
|
|
837
|
+
profiles,
|
|
612
838
|
useSlim,
|
|
613
|
-
|
|
614
|
-
|
|
839
|
+
webOs,
|
|
840
|
+
webVersion
|
|
841
|
+
}?: StartContainersProps) => Cypress.Chainable;
|
|
615
842
|
stopContainer: ({ name }: StopContainerProps) => Cypress.Chainable;
|
|
616
|
-
|
|
843
|
+
stopContainers: () => Cypress.Chainable;
|
|
617
844
|
visitEmptyPage: () => Cypress.Chainable;
|
|
618
|
-
waitForContainerAndSetToken: () => Cypress.Chainable;
|
|
619
845
|
}
|
|
620
846
|
}
|
|
621
847
|
}
|
|
@@ -13,7 +13,6 @@ import tasks from './tasks';
|
|
|
13
13
|
|
|
14
14
|
interface ConfigurationOptions {
|
|
15
15
|
cypressFolder?: string;
|
|
16
|
-
dockerName?: string;
|
|
17
16
|
env?: Record<string, unknown>;
|
|
18
17
|
envFile?: string;
|
|
19
18
|
isDevelopment?: boolean;
|
|
@@ -24,7 +23,6 @@ export default ({
|
|
|
24
23
|
specPattern,
|
|
25
24
|
cypressFolder,
|
|
26
25
|
isDevelopment,
|
|
27
|
-
dockerName,
|
|
28
26
|
env,
|
|
29
27
|
envFile
|
|
30
28
|
}: ConfigurationOptions): Cypress.ConfigOptions => {
|
|
@@ -41,6 +39,7 @@ export default ({
|
|
|
41
39
|
return defineConfig({
|
|
42
40
|
chromeWebSecurity: false,
|
|
43
41
|
defaultCommandTimeout: 6000,
|
|
42
|
+
downloadsFolder: `${resultsFolder}/downloads`,
|
|
44
43
|
e2e: {
|
|
45
44
|
excludeSpecPattern: ['*.js', '*.ts', '*.md'],
|
|
46
45
|
fixturesFolder: 'fixtures',
|
|
@@ -60,16 +59,17 @@ export default ({
|
|
|
60
59
|
},
|
|
61
60
|
env: {
|
|
62
61
|
...env,
|
|
62
|
+
DATABASE_IMAGE: 'bitnami/mariadb:10.5',
|
|
63
63
|
OPENID_IMAGE_VERSION: process.env.MAJOR || '24.04',
|
|
64
|
+
SAML_IMAGE_VERSION: process.env.MAJOR || '24.04',
|
|
64
65
|
WEB_IMAGE_OS: 'alma9',
|
|
65
|
-
WEB_IMAGE_VERSION: webImageVersion
|
|
66
|
-
dockerName: dockerName || 'centreon-dev'
|
|
66
|
+
WEB_IMAGE_VERSION: webImageVersion
|
|
67
67
|
},
|
|
68
68
|
execTimeout: 60000,
|
|
69
69
|
requestTimeout: 10000,
|
|
70
70
|
retries: 0,
|
|
71
71
|
screenshotsFolder: `${resultsFolder}/screenshots`,
|
|
72
|
-
video:
|
|
72
|
+
video: isDevelopment,
|
|
73
73
|
videoCompression: 0,
|
|
74
74
|
videosFolder: `${resultsFolder}/videos`
|
|
75
75
|
});
|
package/cypress/e2e/plugins.ts
CHANGED
package/cypress/e2e/tasks.ts
CHANGED
|
@@ -1,10 +1,40 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
import { execSync } from 'child_process';
|
|
2
3
|
import { existsSync, mkdirSync } from 'fs';
|
|
4
|
+
import path from 'path';
|
|
3
5
|
|
|
4
|
-
import
|
|
6
|
+
import tar from 'tar-fs';
|
|
7
|
+
import {
|
|
8
|
+
DockerComposeEnvironment,
|
|
9
|
+
GenericContainer,
|
|
10
|
+
StartedDockerComposeEnvironment,
|
|
11
|
+
StartedTestContainer,
|
|
12
|
+
Wait,
|
|
13
|
+
getContainerRuntimeClient
|
|
14
|
+
} from 'testcontainers';
|
|
15
|
+
import { createConnection } from 'mysql2/promise';
|
|
16
|
+
|
|
17
|
+
interface Containers {
|
|
18
|
+
[key: string]: StartedTestContainer;
|
|
19
|
+
}
|
|
5
20
|
|
|
6
21
|
export default (on: Cypress.PluginEvents): void => {
|
|
7
|
-
|
|
22
|
+
let dockerEnvironment: StartedDockerComposeEnvironment | null = null;
|
|
23
|
+
const containers: Containers = {};
|
|
24
|
+
|
|
25
|
+
const getContainer = (containerName): StartedTestContainer => {
|
|
26
|
+
let container;
|
|
27
|
+
|
|
28
|
+
if (dockerEnvironment !== null) {
|
|
29
|
+
container = dockerEnvironment.getContainer(`${containerName}-1`);
|
|
30
|
+
} else if (containers[containerName]) {
|
|
31
|
+
container = containers[containerName];
|
|
32
|
+
} else {
|
|
33
|
+
throw new Error(`Cannot get container ${containerName}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return container;
|
|
37
|
+
};
|
|
8
38
|
|
|
9
39
|
interface PortBinding {
|
|
10
40
|
destination: number;
|
|
@@ -12,6 +42,7 @@ export default (on: Cypress.PluginEvents): void => {
|
|
|
12
42
|
}
|
|
13
43
|
|
|
14
44
|
interface StartContainerProps {
|
|
45
|
+
command?: string;
|
|
15
46
|
image: string;
|
|
16
47
|
name: string;
|
|
17
48
|
portBindings: Array<PortBinding>;
|
|
@@ -22,6 +53,48 @@ export default (on: Cypress.PluginEvents): void => {
|
|
|
22
53
|
}
|
|
23
54
|
|
|
24
55
|
on('task', {
|
|
56
|
+
copyFromContainer: async ({ destination, serviceName, source }) => {
|
|
57
|
+
try {
|
|
58
|
+
if (dockerEnvironment !== null) {
|
|
59
|
+
const container = dockerEnvironment.getContainer(`${serviceName}-1`);
|
|
60
|
+
|
|
61
|
+
await container
|
|
62
|
+
.copyArchiveFromContainer(source)
|
|
63
|
+
.then((archiveStream) => {
|
|
64
|
+
return new Promise<void>((resolve) => {
|
|
65
|
+
const dest = tar.extract(destination);
|
|
66
|
+
archiveStream.pipe(dest);
|
|
67
|
+
dest.on('finish', resolve);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error(error);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return null;
|
|
76
|
+
},
|
|
77
|
+
copyToContainer: async ({ destination, serviceName, source, type }) => {
|
|
78
|
+
const container = getContainer(serviceName);
|
|
79
|
+
|
|
80
|
+
if (type === 'directory') {
|
|
81
|
+
await container.copyDirectoriesToContainer([
|
|
82
|
+
{
|
|
83
|
+
source,
|
|
84
|
+
target: destination
|
|
85
|
+
}
|
|
86
|
+
]);
|
|
87
|
+
} else if (type === 'file') {
|
|
88
|
+
await container.copyFilesToContainer([
|
|
89
|
+
{
|
|
90
|
+
source,
|
|
91
|
+
target: destination
|
|
92
|
+
}
|
|
93
|
+
]);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return null;
|
|
97
|
+
},
|
|
25
98
|
createDirectory: async (directoryPath: string) => {
|
|
26
99
|
if (!existsSync(directoryPath)) {
|
|
27
100
|
mkdirSync(directoryPath, { recursive: true });
|
|
@@ -29,70 +102,150 @@ export default (on: Cypress.PluginEvents): void => {
|
|
|
29
102
|
|
|
30
103
|
return null;
|
|
31
104
|
},
|
|
105
|
+
execInContainer: async ({ command, name }) => {
|
|
106
|
+
const { exitCode, output } = await getContainer(name).exec([
|
|
107
|
+
'bash',
|
|
108
|
+
'-c',
|
|
109
|
+
command
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
return { exitCode, output };
|
|
113
|
+
},
|
|
114
|
+
getContainerId: (containerName: string) =>
|
|
115
|
+
getContainer(containerName).getId(),
|
|
116
|
+
getContainerIpAddress: (containerName: string) => {
|
|
117
|
+
const container = getContainer(containerName);
|
|
118
|
+
|
|
119
|
+
const networkNames = container.getNetworkNames();
|
|
120
|
+
|
|
121
|
+
return container.getIpAddress(networkNames[0]);
|
|
122
|
+
},
|
|
123
|
+
getContainersLogs: async () => {
|
|
124
|
+
try {
|
|
125
|
+
const { dockerode } = (await getContainerRuntimeClient()).container;
|
|
126
|
+
const loggedContainers = await dockerode.listContainers();
|
|
127
|
+
|
|
128
|
+
return loggedContainers.reduce((acc, container) => {
|
|
129
|
+
const containerName = container.Names[0].replace('/', '');
|
|
130
|
+
acc[containerName] = execSync(`docker logs -t ${container.Id}`, {
|
|
131
|
+
stdio: 'pipe'
|
|
132
|
+
}).toString('utf8');
|
|
133
|
+
|
|
134
|
+
return acc;
|
|
135
|
+
}, {});
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.warn('Cannot get containers logs');
|
|
138
|
+
console.warn(error);
|
|
139
|
+
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
requestOnDatabase: async ({ database, query }) => {
|
|
144
|
+
let container: StartedTestContainer | null = null;
|
|
145
|
+
|
|
146
|
+
if (dockerEnvironment !== null) {
|
|
147
|
+
container = dockerEnvironment.getContainer('db-1');
|
|
148
|
+
} else {
|
|
149
|
+
container = getContainer('web');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const client = await createConnection({
|
|
153
|
+
database,
|
|
154
|
+
host: container.getHost(),
|
|
155
|
+
password: 'centreon',
|
|
156
|
+
port: container.getMappedPort(3306),
|
|
157
|
+
user: 'centreon'
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const [rows, fields] = await client.execute(query);
|
|
161
|
+
|
|
162
|
+
await client.end();
|
|
163
|
+
|
|
164
|
+
return [rows, fields];
|
|
165
|
+
},
|
|
32
166
|
startContainer: async ({
|
|
167
|
+
command,
|
|
33
168
|
image,
|
|
34
169
|
name,
|
|
35
170
|
portBindings = []
|
|
36
171
|
}: StartContainerProps) => {
|
|
37
|
-
|
|
38
|
-
'docker image list --format "{{.Repository}}:{{.Tag}}"'
|
|
39
|
-
).toString('utf8');
|
|
40
|
-
|
|
41
|
-
if (
|
|
42
|
-
!imageList.match(
|
|
43
|
-
new RegExp(
|
|
44
|
-
`^${image.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')}`,
|
|
45
|
-
'm'
|
|
46
|
-
)
|
|
47
|
-
)
|
|
48
|
-
) {
|
|
49
|
-
execSync(`docker pull ${image}`);
|
|
50
|
-
}
|
|
172
|
+
let container = await new GenericContainer(image).withName(name);
|
|
51
173
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
174
|
+
portBindings.forEach(({ source, destination }) => {
|
|
175
|
+
container = container.withExposedPorts({
|
|
176
|
+
container: source,
|
|
177
|
+
host: destination
|
|
178
|
+
});
|
|
55
179
|
});
|
|
56
|
-
if (webContainers.length) {
|
|
57
|
-
return webContainers[0];
|
|
58
|
-
}
|
|
59
180
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
accumulator[`${currentValue.source}/tcp`] = {};
|
|
66
|
-
|
|
67
|
-
return accumulator;
|
|
68
|
-
}, {}),
|
|
69
|
-
HostConfig: {
|
|
70
|
-
PortBindings: portBindings.reduce((accumulator, currentValue) => {
|
|
71
|
-
accumulator[`${currentValue.source}/tcp`] = [
|
|
72
|
-
{
|
|
73
|
-
HostIP: '127.0.0.1',
|
|
74
|
-
HostPort: `${currentValue.destination}`
|
|
75
|
-
}
|
|
76
|
-
];
|
|
77
|
-
|
|
78
|
-
return accumulator;
|
|
79
|
-
}, {})
|
|
80
|
-
},
|
|
81
|
-
Image: image,
|
|
82
|
-
OpenStdin: false,
|
|
83
|
-
StdinOnce: false,
|
|
84
|
-
Tty: true,
|
|
85
|
-
name
|
|
86
|
-
});
|
|
181
|
+
if (command) {
|
|
182
|
+
container
|
|
183
|
+
.withCommand(['bash', '-c', command])
|
|
184
|
+
.withWaitStrategy(Wait.forSuccessfulCommand('ls'));
|
|
185
|
+
}
|
|
87
186
|
|
|
88
|
-
await container.start();
|
|
187
|
+
containers[name] = await container.start();
|
|
89
188
|
|
|
90
189
|
return container;
|
|
91
190
|
},
|
|
191
|
+
startContainers: async ({
|
|
192
|
+
composeFile,
|
|
193
|
+
databaseImage,
|
|
194
|
+
openidImage,
|
|
195
|
+
profiles,
|
|
196
|
+
samlImage,
|
|
197
|
+
webImage
|
|
198
|
+
}) => {
|
|
199
|
+
try {
|
|
200
|
+
const composeFileDir = path.dirname(composeFile);
|
|
201
|
+
const composeFileName = path.basename(composeFile);
|
|
202
|
+
|
|
203
|
+
dockerEnvironment = await new DockerComposeEnvironment(
|
|
204
|
+
composeFileDir,
|
|
205
|
+
composeFileName
|
|
206
|
+
)
|
|
207
|
+
.withEnvironment({
|
|
208
|
+
MYSQL_IMAGE: databaseImage,
|
|
209
|
+
OPENID_IMAGE: openidImage,
|
|
210
|
+
SAML_IMAGE: samlImage,
|
|
211
|
+
WEB_IMAGE: webImage
|
|
212
|
+
})
|
|
213
|
+
.withProfiles(...profiles)
|
|
214
|
+
.withWaitStrategy(
|
|
215
|
+
'web-1',
|
|
216
|
+
Wait.forAll([
|
|
217
|
+
Wait.forHealthCheck(),
|
|
218
|
+
Wait.forLogMessage('Centreon is ready')
|
|
219
|
+
])
|
|
220
|
+
)
|
|
221
|
+
.up();
|
|
222
|
+
|
|
223
|
+
return null;
|
|
224
|
+
} catch (error) {
|
|
225
|
+
if (error instanceof Error) {
|
|
226
|
+
console.error(error.message);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
throw error;
|
|
230
|
+
}
|
|
231
|
+
},
|
|
92
232
|
stopContainer: async ({ name }: StopContainerProps) => {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
233
|
+
if (containers[name]) {
|
|
234
|
+
const container = containers[name];
|
|
235
|
+
|
|
236
|
+
await container.stop();
|
|
237
|
+
|
|
238
|
+
delete containers[name];
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return null;
|
|
242
|
+
},
|
|
243
|
+
stopContainers: async () => {
|
|
244
|
+
if (dockerEnvironment !== null) {
|
|
245
|
+
await dockerEnvironment.down();
|
|
246
|
+
|
|
247
|
+
dockerEnvironment = null;
|
|
248
|
+
}
|
|
96
249
|
|
|
97
250
|
return null;
|
|
98
251
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@centreon/js-config",
|
|
3
3
|
"description": "Centreon Frontend shared build configuration",
|
|
4
|
-
"version": "24.4.
|
|
4
|
+
"version": "24.4.22",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/centreon/centreon-frontend.git"
|
|
@@ -24,23 +24,23 @@
|
|
|
24
24
|
"cypress"
|
|
25
25
|
],
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"
|
|
28
|
-
"
|
|
27
|
+
"eslint": "^8.53.0",
|
|
28
|
+
"prettier": "^3.0.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@badeball/cypress-cucumber-preprocessor": "^
|
|
31
|
+
"@badeball/cypress-cucumber-preprocessor": "^20.0.1",
|
|
32
32
|
"@bahmutov/cypress-esbuild-preprocessor": "^2.2.0",
|
|
33
33
|
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
|
|
34
34
|
"@esbuild-plugins/node-modules-polyfill": "^0.2.2",
|
|
35
35
|
"@tsconfig/node16": "^16.1.1",
|
|
36
36
|
"@tsconfig/node20": "^20.1.2",
|
|
37
37
|
"@types/cypress-cucumber-preprocessor": "^4.0.5",
|
|
38
|
-
"
|
|
38
|
+
"cypress": "^13.6.4",
|
|
39
39
|
"cypress-multi-reporters": "^1.6.4",
|
|
40
|
-
"cypress-terminal-report": "^
|
|
41
|
-
"
|
|
42
|
-
"dotenv": "^16.
|
|
43
|
-
"esbuild": "^0.
|
|
40
|
+
"cypress-terminal-report": "^6.0.0",
|
|
41
|
+
"cypress-wait-until": "^3.0.1",
|
|
42
|
+
"dotenv": "^16.4.1",
|
|
43
|
+
"esbuild": "^0.20.0",
|
|
44
44
|
"eslint": "^8.53.0",
|
|
45
45
|
"eslint-config-airbnb": "19.0.4",
|
|
46
46
|
"eslint-config-prettier": "^8.5.0",
|
|
@@ -58,6 +58,9 @@
|
|
|
58
58
|
"eslint-plugin-react-hooks": "^4.5.0",
|
|
59
59
|
"eslint-plugin-sort-keys-fix": "^1.1.2",
|
|
60
60
|
"eslint-plugin-typescript-sort-keys": "^2.1.0",
|
|
61
|
-
"mochawesome": "^7.1.3"
|
|
61
|
+
"mochawesome": "^7.1.3",
|
|
62
|
+
"mysql2": "^3.9.1",
|
|
63
|
+
"tar-fs": "^3.0.4",
|
|
64
|
+
"testcontainers": "^10.7.1"
|
|
62
65
|
}
|
|
63
66
|
}
|