@centreon/js-config 24.4.29 → 24.4.30

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.
@@ -18,6 +18,15 @@ interface MountProps {
18
18
  Component: React.ReactNode;
19
19
  options?: object;
20
20
  }
21
+ interface Resolution {
22
+ height: number;
23
+ width: number;
24
+ }
25
+
26
+ interface MakeSnapshotWithCustomResolution {
27
+ resolution: Resolution;
28
+ title: string;
29
+ }
21
30
 
22
31
  export enum Method {
23
32
  DELETE = 'DELETE',
@@ -53,6 +62,7 @@ interface Query {
53
62
 
54
63
  export interface InterceptAPIRequestProps<T> {
55
64
  alias: string;
65
+ delay?: number;
56
66
  method: Method;
57
67
  path: string;
58
68
  query?: Query;
@@ -68,7 +78,8 @@ Cypress.Commands.add(
68
78
  response,
69
79
  alias,
70
80
  query,
71
- statusCode = 200
81
+ statusCode = 200,
82
+ delay = 500
72
83
  }: InterceptAPIRequestProps<T>): void => {
73
84
  cy.interceptRequest(
74
85
  method,
@@ -77,14 +88,14 @@ Cypress.Commands.add(
77
88
  const getQuery = req?.url?.searchParams?.get(query?.name);
78
89
  if (query && equals(query.value, getQuery)) {
79
90
  return res(
80
- ctx.delay(500),
91
+ ctx.delay(delay),
81
92
  ctx.json(response),
82
93
  ctx.status(statusCode)
83
94
  );
84
95
  }
85
96
  if (!getQuery && isNil(query)) {
86
97
  return res(
87
- ctx.delay(500),
98
+ ctx.delay(delay),
88
99
  ctx.json(response),
89
100
  ctx.status(statusCode)
90
101
  );
@@ -97,20 +108,32 @@ Cypress.Commands.add(
97
108
  }
98
109
  );
99
110
 
100
- Cypress.Commands.add('moveSortableElement', ({ element, direction }): void => {
101
- const key = `{${direction}arrow}`;
111
+ interface MoveSortableElementProps {
112
+ direction: 'up' | 'down' | 'left' | 'right';
113
+ element: Cypress.Chainable<JQuery<HTMLElement>>;
114
+ times?: number;
115
+ }
102
116
 
103
- element.type(' ', {
104
- force: true,
105
- scrollBehavior: false
106
- });
107
- element.eq(-1).type(key, {
108
- scrollBehavior: false
109
- });
110
- element.eq(-1).type(' ', {
111
- scrollBehavior: false
112
- });
113
- });
117
+ Cypress.Commands.add(
118
+ 'moveSortableElement',
119
+ ({ element, direction, times = 1 }: MoveSortableElementProps): void => {
120
+ const key = `{${direction}arrow}`;
121
+
122
+ element.type(' ', {
123
+ force: true,
124
+ scrollBehavior: false
125
+ });
126
+
127
+ Array.from({ length: times }).forEach(() => {
128
+ element.eq(-1).type(key, {
129
+ scrollBehavior: false
130
+ });
131
+ });
132
+ element.eq(-1).type(' ', {
133
+ scrollBehavior: false
134
+ });
135
+ }
136
+ );
114
137
 
115
138
  Cypress.Commands.add(
116
139
  'moveSortableElementUsingAriaLabel',
@@ -137,6 +160,15 @@ Cypress.Commands.add('makeSnapshot', (title?: string) => {
137
160
  cy.matchImageSnapshot(title);
138
161
  });
139
162
 
163
+ Cypress.Commands.add(
164
+ 'makeSnapshotWithCustomResolution',
165
+ ({ title, resolution }: MakeSnapshotWithCustomResolution) => {
166
+ const { width, height } = resolution;
167
+ cy.viewport(width, height);
168
+ cy.matchImageSnapshot(title);
169
+ }
170
+ );
171
+
140
172
  Cypress.Commands.add('cssDisableMotion', (): void => {
141
173
  Cypress.on('window:before:load', (cyWindow) => {
142
174
  disableMotion(cyWindow);
@@ -148,13 +180,22 @@ declare global {
148
180
  interface Chainable {
149
181
  adjustViewport: () => Cypress.Chainable;
150
182
  cssDisableMotion: () => Cypress.Chainable;
183
+ getRequestCalls: (alias) => Cypress.Chainable;
151
184
  interceptAPIRequest: <T extends object>(
152
185
  props: InterceptAPIRequestProps<T>
153
186
  ) => Cypress.Chainable;
154
187
  interceptRequest: (method, path, mock, alias) => Cypress.Chainable;
155
188
  makeSnapshot: (title?: string) => void;
189
+ makeSnapshotWithCustomResolution: ({
190
+ title,
191
+ resolution
192
+ }: MakeSnapshotWithCustomResolution) => Cypress.Chainable;
156
193
  mount: ({ Component, options }: MountProps) => Cypress.Chainable;
157
- moveSortableElement: ({ element, direction }) => void;
194
+ moveSortableElement: ({
195
+ element,
196
+ direction,
197
+ times
198
+ }: MoveSortableElementProps) => void;
158
199
  moveSortableElementUsingAriaLabel: ({ ariaLabel, direction }) => void;
159
200
  waitForRequest: (alias) => Cypress.Chainable;
160
201
  }
@@ -3,6 +3,7 @@ const { defineConfig } = require('cypress');
3
3
  const {
4
4
  addMatchImageSnapshotPlugin
5
5
  } = require('@simonsmith/cypress-image-snapshot/plugin');
6
+ const cypressCodeCoverageTask = require('@cypress/code-coverage/task');
6
7
 
7
8
  module.exports = ({
8
9
  webpackConfig,
@@ -25,9 +26,12 @@ module.exports = ({
25
26
  setupNodeEvents: (on, config) => {
26
27
  addMatchImageSnapshotPlugin(on, config);
27
28
 
29
+ cypressCodeCoverageTask(on, config);
30
+
28
31
  on('before:browser:launch', (browser, launchOptions) => {
29
32
  if (browser.name === 'chrome' && browser.isHeadless) {
30
33
  launchOptions.args.push('--headless=new');
34
+ launchOptions.args.push('--force-color-profile=srgb');
31
35
  }
32
36
 
33
37
  return launchOptions;
@@ -37,8 +41,17 @@ module.exports = ({
37
41
  supportFile: `${mainCypressFolder}/support/component.tsx`
38
42
  },
39
43
  env: {
40
- ...env,
41
- baseUrl: 'http://localhost:9092'
44
+ baseUrl: 'http://localhost:9092',
45
+ codeCoverage: {
46
+ exclude: [
47
+ 'cypress/**/*.*',
48
+ 'packages/**',
49
+ 'node_modules',
50
+ '**/*.js',
51
+ '**/*.spec.tsx'
52
+ ]
53
+ },
54
+ ...env
42
55
  },
43
56
  reporter: 'mochawesome',
44
57
  reporterOptions: {
@@ -0,0 +1,36 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const filePath = process.argv[2];
5
+
6
+ const { error: logError } = console;
7
+
8
+ try {
9
+ const outFile = fs.readFileSync(path.resolve(filePath)).toString();
10
+ const outFileJson = JSON.parse(outFile);
11
+
12
+ const coveragesWithoutNodeModules = Object.entries(outFileJson)
13
+ .map(([key, value]) => {
14
+ if (key.includes('node_modules')) {
15
+ return undefined;
16
+ }
17
+
18
+ return [key, value];
19
+ })
20
+ .filter((v) => v);
21
+
22
+ const finalOutJson = coveragesWithoutNodeModules.reduce(
23
+ (acc, [key, value]) => ({
24
+ ...acc,
25
+ [key]: value
26
+ }),
27
+ {}
28
+ );
29
+
30
+ fs.writeFileSync(
31
+ path.resolve(filePath),
32
+ JSON.stringify(finalOutJson, null, 2)
33
+ );
34
+ } catch (error) {
35
+ logError(error.message);
36
+ }
@@ -1,5 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-namespace */
2
2
 
3
+ import { Action } from 'e2e/features/ACLs/commands';
4
+
3
5
  const apiBase = '/centreon/api';
4
6
  const apiActionV1 = `${apiBase}/index.php`;
5
7
 
@@ -138,6 +140,102 @@ Cypress.Commands.add(
138
140
  }
139
141
  );
140
142
 
143
+ interface Contact {
144
+ admin?: boolean;
145
+ alias?: string | null;
146
+ authenticationType?: 'local' | 'ldap';
147
+ email: string;
148
+ enableNotifications?: boolean;
149
+ GUIAccess?: boolean;
150
+ language?: string;
151
+ name: string;
152
+ password: string;
153
+ }
154
+
155
+ Cypress.Commands.add(
156
+ 'addContact',
157
+ ({
158
+ admin = true,
159
+ alias = null,
160
+ authenticationType = 'local',
161
+ email,
162
+ enableNotifications = true,
163
+ GUIAccess = true,
164
+ language = 'en_US',
165
+ name,
166
+ password
167
+ }: Contact): Cypress.Chainable => {
168
+ const contactAdmin = admin ? 1 : 0;
169
+ const contactAlias = alias === null ? name : alias;
170
+ const contactEnableNotifications = enableNotifications ? 1 : 0;
171
+ const contactGUIAccess = GUIAccess ? 1 : 0;
172
+
173
+ return cy
174
+ .executeActionViaClapi({
175
+ bodyContent: {
176
+ action: 'ADD',
177
+ object: 'CONTACT',
178
+ values: `${name};${contactAlias};${email};${password};${contactAdmin};${contactGUIAccess};${language};${authenticationType}`
179
+ }
180
+ })
181
+ .then(() => {
182
+ const contactParams = {
183
+ enable_notifications: contactEnableNotifications
184
+ };
185
+ Object.entries(contactParams).map(([paramName, paramValue]) => {
186
+ if (paramValue === null) {
187
+ return null;
188
+ }
189
+
190
+ return cy.executeActionViaClapi({
191
+ bodyContent: {
192
+ action: 'SETPARAM',
193
+ object: 'CONTACT',
194
+ values: `${name};${paramName};${paramValue}`
195
+ }
196
+ });
197
+ });
198
+
199
+ return cy.wrap(null);
200
+ });
201
+ }
202
+ );
203
+
204
+ interface ContactGroup {
205
+ alias?: string | null;
206
+ contacts: string[];
207
+ name: string;
208
+ }
209
+
210
+ Cypress.Commands.add(
211
+ 'addContactGroup',
212
+ ({ alias = null, contacts, name }: ContactGroup): Cypress.Chainable => {
213
+ const contactGroupAlias = alias === null ? name : alias;
214
+
215
+ return cy
216
+ .executeActionViaClapi({
217
+ bodyContent: {
218
+ action: 'ADD',
219
+ object: 'CG',
220
+ values: `${name};${contactGroupAlias}`
221
+ }
222
+ })
223
+ .then(() => {
224
+ contacts.map((contact) => {
225
+ return cy.executeActionViaClapi({
226
+ bodyContent: {
227
+ action: 'ADDCONTACT',
228
+ object: 'CG',
229
+ values: `${name};${contact}`
230
+ }
231
+ });
232
+ });
233
+
234
+ return cy.wrap(null);
235
+ });
236
+ }
237
+ );
238
+
141
239
  interface Host {
142
240
  activeCheckEnabled?: boolean;
143
241
  address?: string;
@@ -208,6 +306,26 @@ Cypress.Commands.add(
208
306
  }
209
307
  );
210
308
 
309
+ interface HostGroup {
310
+ alias?: string | null;
311
+ name: string;
312
+ }
313
+
314
+ Cypress.Commands.add(
315
+ 'addHostGroup',
316
+ ({ alias = null, name }: HostGroup): Cypress.Chainable => {
317
+ const hostGroupAlias = alias === null ? name : alias;
318
+
319
+ return cy.executeActionViaClapi({
320
+ bodyContent: {
321
+ action: 'ADD',
322
+ object: 'HG',
323
+ values: `${name};${hostGroupAlias}`
324
+ }
325
+ });
326
+ }
327
+ );
328
+
211
329
  interface ServiceTemplate {
212
330
  activeCheckEnabled?: boolean;
213
331
  checkCommand?: string | null;
@@ -329,6 +447,45 @@ Cypress.Commands.add(
329
447
  }
330
448
  );
331
449
 
450
+ interface ServiceGroup {
451
+ alias?: string | null;
452
+ hostsAndServices: string[][];
453
+ name: string;
454
+ }
455
+
456
+ Cypress.Commands.add(
457
+ 'addServiceGroup',
458
+ ({
459
+ alias = null,
460
+ hostsAndServices,
461
+ name
462
+ }: ServiceGroup): Cypress.Chainable => {
463
+ const serviceGroupAlias = alias === null ? name : alias;
464
+
465
+ return cy
466
+ .executeActionViaClapi({
467
+ bodyContent: {
468
+ action: 'ADD',
469
+ object: 'SG',
470
+ values: `${name};${serviceGroupAlias}`
471
+ }
472
+ })
473
+ .then(() => {
474
+ hostsAndServices.map((hostAndService) => {
475
+ return cy.executeActionViaClapi({
476
+ bodyContent: {
477
+ action: 'ADDSERVICE',
478
+ object: 'SG',
479
+ values: `${name};${hostAndService[0]},${hostAndService[1]}`
480
+ }
481
+ });
482
+ });
483
+
484
+ return cy.wrap(null);
485
+ });
486
+ }
487
+ );
488
+
332
489
  Cypress.Commands.add(
333
490
  'applyPollerConfiguration',
334
491
  (pollerName = 'Central'): Cypress.Chainable => {
@@ -341,12 +498,179 @@ Cypress.Commands.add(
341
498
  }
342
499
  );
343
500
 
501
+ interface ACLGroup {
502
+ alias?: string | null;
503
+ contacts?: string[];
504
+ contactGroups?: string[];
505
+ name: string;
506
+ }
507
+
508
+ Cypress.Commands.add(
509
+ 'addACLGroup',
510
+ ({
511
+ alias = null,
512
+ contacts = [],
513
+ contactGroups = [],
514
+ name
515
+ }: ACLGroup): Cypress.Chainable => {
516
+ const ACLGroupALias = alias === null ? name : alias;
517
+
518
+ return cy
519
+ .executeActionViaClapi({
520
+ bodyContent: {
521
+ action: 'ADD',
522
+ object: 'ACLGROUP',
523
+ values: `${name};${ACLGroupALias}`
524
+ }
525
+ })
526
+ .then(() => {
527
+ if (contacts) {
528
+ contacts.map((contact) => {
529
+ cy.executeActionViaClapi({
530
+ bodyContent: {
531
+ action: 'ADDCONTACT',
532
+ object: 'ACLGROUP',
533
+ values: `${name};${contact}`
534
+ }
535
+ });
536
+ });
537
+ }
538
+ if (contactGroups) {
539
+ contactGroups.map((contactGroup) => {
540
+ cy.executeActionViaClapi({
541
+ bodyContent: {
542
+ action: 'ADDCONTACTGROUP',
543
+ object: 'ACLGROUP',
544
+ values: `${name};${contactGroup}`
545
+ }
546
+ });
547
+ });
548
+ }
549
+ });
550
+ }
551
+ );
552
+
553
+ interface ACLMenu {
554
+ name: string;
555
+ rule?: string[];
556
+ alias?: string | null;
557
+ includeChildren?: boolean;
558
+ readOnly?: boolean;
559
+ }
560
+
561
+ Cypress.Commands.add(
562
+ 'addACLMenu',
563
+ ({
564
+ name,
565
+ rule = [],
566
+ alias = null,
567
+ includeChildren = true,
568
+ readOnly = false
569
+ }: ACLMenu): Cypress.Chainable => {
570
+ const ACLMenuAlias = alias === null ? name : alias;
571
+ const action = readOnly ? 'GRANTRO' : 'GRANTRW';
572
+ const children = includeChildren ? '1' : '0';
573
+
574
+ return cy
575
+ .executeActionViaClapi({
576
+ bodyContent: {
577
+ action: 'ADD',
578
+ object: 'ACLMENU',
579
+ values: `${name};${ACLMenuAlias}`
580
+ }
581
+ })
582
+ .then(() => {
583
+ if (rule.length == 0) {
584
+ return cy.wrap(null);
585
+ }
586
+
587
+ let ruleCommand = '';
588
+ rule.map((rulePage, index) => {
589
+ ruleCommand += rulePage + (index == rule.length - 1 ? '' : ';');
590
+ });
591
+ cy.executeActionViaClapi({
592
+ bodyContent: {
593
+ action: action,
594
+ object: 'ACLMENU',
595
+ values: `${name};${children};${ruleCommand}`
596
+ }
597
+ });
598
+ return cy.wrap(null);
599
+ });
600
+ }
601
+ );
602
+
603
+ interface ACLAction {
604
+ name: string;
605
+ description: string;
606
+ actions?: Action[];
607
+ }
608
+
609
+ Cypress.Commands.add(
610
+ 'addACLAction',
611
+ ({ name, description, actions = [] }: ACLAction): Cypress.Chainable => {
612
+ return cy
613
+ .executeActionViaClapi({
614
+ bodyContent: {
615
+ action: 'ADD',
616
+ object: 'ACLACTION',
617
+ values: `${name};${description}`
618
+ }
619
+ })
620
+ .then(() => {
621
+ if (actions.length == 0) {
622
+ return cy.wrap(null);
623
+ }
624
+
625
+ let actionCommand = '';
626
+ actions.map((action, index) => {
627
+ actionCommand += action + (index == actions.length - 1 ? '' : '|');
628
+ });
629
+ cy.executeActionViaClapi({
630
+ bodyContent: {
631
+ action: 'GRANT',
632
+ object: 'ACLACTION',
633
+ values: `${name};${actionCommand}`
634
+ }
635
+ });
636
+ return cy.wrap(null);
637
+ });
638
+ }
639
+ );
640
+
641
+ interface ACLResource {
642
+ name: string;
643
+ alias?: string | null;
644
+ }
645
+
646
+ Cypress.Commands.add(
647
+ 'addACLResource',
648
+ ({ name, alias = null }: ACLResource): Cypress.Chainable => {
649
+ const ACLResourcesAlias = alias === null ? name : alias;
650
+ return cy.executeActionViaClapi({
651
+ bodyContent: {
652
+ action: 'ADD',
653
+ object: 'ACLRESOURCE',
654
+ values: `${name};${ACLResourcesAlias}`
655
+ }
656
+ });
657
+ }
658
+ );
659
+
344
660
  declare global {
345
661
  namespace Cypress {
346
662
  interface Chainable {
663
+ addACLAction: (props: ACLAction) => Cypress.Chainable;
664
+ addACLGroup: (props: ACLGroup) => Cypress.Chainable;
665
+ addACLMenu: (props: ACLMenu) => Cypress.Chainable;
666
+ addACLResource: (props: ACLResource) => Cypress.Chainable;
347
667
  addCheckCommand: (props: CheckCommand) => Cypress.Chainable;
668
+ addContact: (props: Contact) => Cypress.Chainable;
669
+ addContactGroup: (props: ContactGroup) => Cypress.Chainable;
348
670
  addHost: (props: Host) => Cypress.Chainable;
671
+ addHostGroup: (props: HostGroup) => Cypress.Chainable;
349
672
  addService: (props: Service) => Cypress.Chainable;
673
+ addServiceGroup: (props: ServiceGroup) => Cypress.Chainable;
350
674
  addServiceTemplate: (props: ServiceTemplate) => Cypress.Chainable;
351
675
  addTimePeriod: (props: TimePeriod) => Cypress.Chainable;
352
676
  applyPollerConfiguration: (props?: string) => Cypress.Chainable;