@centreon/js-config 24.10.2 → 24.10.4
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 +6 -6
- package/cypress/e2e/commands.ts +272 -142
- package/cypress/e2e/configuration.ts +13 -2
- package/cypress/e2e/plugins.ts +7 -16
- package/cypress/e2e/tasks.ts +28 -14
- package/package.json +1 -1
- package/rspack/base/globalConfig.js +6 -2
- package/rspack/patch/devServer.js +3 -1
package/biome/base.json
CHANGED
|
@@ -21,12 +21,10 @@
|
|
|
21
21
|
"correctness": {
|
|
22
22
|
"noUnusedImports": "error",
|
|
23
23
|
"noUnusedVariables": "error",
|
|
24
|
-
"useExhaustiveDependencies": "off"
|
|
25
|
-
"noUnknownUnit": "error",
|
|
26
|
-
"noUnknownProperty": "error",
|
|
27
|
-
"noUnknownFunction": "error"
|
|
24
|
+
"useExhaustiveDependencies": "off"
|
|
28
25
|
},
|
|
29
26
|
"nursery": {
|
|
27
|
+
"noConsole": "error",
|
|
30
28
|
"noRestrictedImports": {
|
|
31
29
|
"level": "error",
|
|
32
30
|
"options": {
|
|
@@ -35,10 +33,12 @@
|
|
|
35
33
|
"moment": "Using moment is not encouraged."
|
|
36
34
|
}
|
|
37
35
|
}
|
|
38
|
-
}
|
|
36
|
+
},
|
|
37
|
+
"noUnknownFunction": "error",
|
|
38
|
+
"noUnknownProperty": "error",
|
|
39
|
+
"noUnknownUnit": "error"
|
|
39
40
|
},
|
|
40
41
|
"suspicious": {
|
|
41
|
-
"noConsole": "error",
|
|
42
42
|
"useAwait": "error"
|
|
43
43
|
},
|
|
44
44
|
"performance": {
|
package/cypress/e2e/commands.ts
CHANGED
|
@@ -166,6 +166,12 @@ Cypress.Commands.add('getContainersLogs', () => {
|
|
|
166
166
|
return cy.task('getContainersLogs');
|
|
167
167
|
});
|
|
168
168
|
|
|
169
|
+
Cypress.Commands.add('getContainerMappedPort', (containerName: string, containerPort: number) => {
|
|
170
|
+
cy.log(`Getting mapped port ${containerPort} of container ${containerName}`);
|
|
171
|
+
|
|
172
|
+
return cy.task('getContainerMappedPort', { containerName, containerPort });
|
|
173
|
+
});
|
|
174
|
+
|
|
169
175
|
interface CopyFromContainerProps {
|
|
170
176
|
destination: string;
|
|
171
177
|
name?: string;
|
|
@@ -290,7 +296,15 @@ Cypress.Commands.add('logoutViaAPI', (): Cypress.Chainable => {
|
|
|
290
296
|
return cy
|
|
291
297
|
.request({
|
|
292
298
|
method: 'GET',
|
|
293
|
-
url: '/centreon/authentication/logout'
|
|
299
|
+
url: '/centreon/authentication/logout',
|
|
300
|
+
failOnStatusCode: false,
|
|
301
|
+
})
|
|
302
|
+
.then((response) => {
|
|
303
|
+
if (response.status !== 200 && response.status !== 302) {
|
|
304
|
+
cy.log(`Logout failed with status: ${response.status}`);
|
|
305
|
+
throw new Error(`Logout API returned unexpected status: ${response.status}`);
|
|
306
|
+
}
|
|
307
|
+
cy.log(`Logout successful with status: ${response.status}`);
|
|
294
308
|
})
|
|
295
309
|
.visit('/')
|
|
296
310
|
.getByLabel({ label: 'Alias', tag: 'input' });
|
|
@@ -511,103 +525,111 @@ Cypress.Commands.add(
|
|
|
511
525
|
}
|
|
512
526
|
);
|
|
513
527
|
|
|
514
|
-
Cypress.Commands.add(
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
528
|
+
Cypress.Commands.add(
|
|
529
|
+
'getLogDirectory',
|
|
530
|
+
(): Cypress.Chainable => {
|
|
531
|
+
const logDirectory = `results/logs/${Cypress.spec.name.replace(
|
|
532
|
+
artifactIllegalCharactersMatcher,
|
|
533
|
+
'_'
|
|
534
|
+
)}/${Cypress.currentTest.title.replace(
|
|
535
|
+
artifactIllegalCharactersMatcher,
|
|
536
|
+
'_'
|
|
537
|
+
)}`;
|
|
524
538
|
|
|
525
|
-
|
|
539
|
+
return cy
|
|
540
|
+
.createDirectory(logDirectory)
|
|
541
|
+
.exec(`chmod -R 755 "${logDirectory}"`)
|
|
542
|
+
.wrap(logDirectory);
|
|
543
|
+
}
|
|
544
|
+
);
|
|
526
545
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
.getContainersLogs()
|
|
531
|
-
.then((containersLogs: Array<Array<string>>) => {
|
|
532
|
-
if (!containersLogs) {
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
546
|
+
interface CopyWebContainerLogsProps {
|
|
547
|
+
name: string;
|
|
548
|
+
}
|
|
535
549
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
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(() => {
|
|
550
|
+
Cypress.Commands.add(
|
|
551
|
+
'copyWebContainerLogs',
|
|
552
|
+
({ name }: CopyWebContainerLogsProps): Cypress.Chainable => {
|
|
553
|
+
cy.log(`Getting logs from container ${name} ...`);
|
|
554
|
+
|
|
555
|
+
return cy.getLogDirectory().then((logDirectory) => {
|
|
556
|
+
let sourcePhpLogs = '/var/log/php8.2-fpm-centreon-error.log';
|
|
557
|
+
let targetPhpLogs = `${logDirectory}/php8.2-fpm-centreon-error.log`;
|
|
558
|
+
let sourceApacheLogs = '/var/log/apache2';
|
|
559
|
+
let targetApacheLogs = `${logDirectory}/apache2`;
|
|
570
560
|
if (Cypress.env('WEB_IMAGE_OS').includes('alma')) {
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
});
|
|
561
|
+
sourcePhpLogs = '/var/log/php-fpm';
|
|
562
|
+
targetPhpLogs = `${logDirectory}/php`;
|
|
563
|
+
sourceApacheLogs = '/var/log/httpd';
|
|
564
|
+
targetApacheLogs = `${logDirectory}/httpd`;
|
|
576
565
|
}
|
|
577
566
|
|
|
578
|
-
return cy
|
|
579
|
-
{
|
|
580
|
-
destination: `${logDirectory}/
|
|
567
|
+
return cy
|
|
568
|
+
.copyFromContainer({
|
|
569
|
+
destination: `${logDirectory}/broker`,
|
|
581
570
|
name,
|
|
582
|
-
source: '/var/log/
|
|
583
|
-
}
|
|
584
|
-
{
|
|
585
|
-
|
|
586
|
-
})
|
|
587
|
-
.then(() => {
|
|
588
|
-
if (Cypress.env('WEB_IMAGE_OS').includes('alma')) {
|
|
589
|
-
return cy.copyFromContainer({
|
|
590
|
-
destination: `${logDirectory}/httpd`,
|
|
571
|
+
source: '/var/log/centreon-broker'
|
|
572
|
+
})
|
|
573
|
+
.copyFromContainer({
|
|
574
|
+
destination: `${logDirectory}/engine`,
|
|
591
575
|
name,
|
|
592
|
-
source: '/var/log/
|
|
593
|
-
})
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
return cy.copyFromContainer(
|
|
597
|
-
{
|
|
598
|
-
destination: `${logDirectory}/apache2`,
|
|
576
|
+
source: '/var/log/centreon-engine'
|
|
577
|
+
})
|
|
578
|
+
.copyFromContainer({
|
|
579
|
+
destination: `${logDirectory}/centreon`,
|
|
599
580
|
name,
|
|
600
|
-
source: '/var/log/
|
|
601
|
-
}
|
|
602
|
-
{
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
581
|
+
source: '/var/log/centreon'
|
|
582
|
+
})
|
|
583
|
+
.copyFromContainer({
|
|
584
|
+
destination: `${logDirectory}/centreon-gorgone`,
|
|
585
|
+
name,
|
|
586
|
+
source: '/var/log/centreon-gorgone'
|
|
587
|
+
})
|
|
588
|
+
.copyFromContainer({
|
|
589
|
+
destination: targetPhpLogs,
|
|
590
|
+
name,
|
|
591
|
+
source: sourcePhpLogs,
|
|
592
|
+
})
|
|
593
|
+
.copyFromContainer({
|
|
594
|
+
destination: targetApacheLogs,
|
|
595
|
+
name,
|
|
596
|
+
source: sourceApacheLogs,
|
|
597
|
+
})
|
|
598
|
+
.exec(`chmod -R 755 "${logDirectory}"`);
|
|
599
|
+
});
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
Cypress.Commands.add('stopContainers', (): Cypress.Chainable => {
|
|
603
|
+
cy.log('Stopping containers ...');
|
|
604
|
+
|
|
605
|
+
const name = 'web';
|
|
606
|
+
|
|
607
|
+
return cy
|
|
608
|
+
.visitEmptyPage()
|
|
609
|
+
.getLogDirectory()
|
|
610
|
+
.then((logDirectory) => {
|
|
611
|
+
return cy
|
|
612
|
+
.getContainersLogs()
|
|
613
|
+
.then((containersLogs: Array<Array<string>>) => {
|
|
614
|
+
if (!containersLogs) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
Object.entries(containersLogs).forEach(([containerName, logs]) => {
|
|
619
|
+
cy.writeFile(
|
|
620
|
+
`${logDirectory}/container-${containerName}.log`,
|
|
621
|
+
logs
|
|
622
|
+
);
|
|
623
|
+
});
|
|
624
|
+
})
|
|
625
|
+
.copyWebContainerLogs({ name })
|
|
626
|
+
.exec(`chmod -R 755 "${logDirectory}"`)
|
|
627
|
+
.task(
|
|
628
|
+
'stopContainers',
|
|
629
|
+
{},
|
|
630
|
+
{ timeout: 600000 } // 10 minutes because docker pull can be very slow
|
|
631
|
+
);
|
|
632
|
+
});
|
|
611
633
|
});
|
|
612
634
|
|
|
613
635
|
Cypress.Commands.add(
|
|
@@ -650,40 +672,52 @@ Cypress.Commands.add(
|
|
|
650
672
|
}
|
|
651
673
|
);
|
|
652
674
|
|
|
653
|
-
Cypress.Commands.add(
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
675
|
+
Cypress.Commands.add('insertDashboardWithWidget', (dashboardBody, patchBody, widgetName, widgetType) => {
|
|
676
|
+
cy.request({
|
|
677
|
+
body: { ...dashboardBody },
|
|
678
|
+
method: 'POST',
|
|
679
|
+
url: '/centreon/api/latest/configuration/dashboards'
|
|
680
|
+
}).then((response) => {
|
|
681
|
+
const dashboardId = response.body.id;
|
|
682
|
+
|
|
683
|
+
cy.waitUntil(
|
|
684
|
+
() => {
|
|
685
|
+
return cy.request({
|
|
686
|
+
method: 'GET',
|
|
687
|
+
url: `/centreon/api/latest/configuration/dashboards/${dashboardId}`
|
|
688
|
+
}).then((getResponse) => {
|
|
689
|
+
return getResponse.body && getResponse.body.id === dashboardId;
|
|
690
|
+
});
|
|
659
691
|
},
|
|
692
|
+
{ timeout: 10000 }
|
|
693
|
+
);
|
|
694
|
+
|
|
695
|
+
const formData = new FormData();
|
|
696
|
+
|
|
697
|
+
formData.append('panels[0][name]', widgetName);
|
|
698
|
+
formData.append('panels[0][widget_type]', widgetType);
|
|
699
|
+
|
|
700
|
+
formData.append('panels[0][layout][x]', '0');
|
|
701
|
+
formData.append('panels[0][layout][y]', '0');
|
|
702
|
+
formData.append('panels[0][layout][width]', '12');
|
|
703
|
+
formData.append('panels[0][layout][height]', '3');
|
|
704
|
+
formData.append('panels[0][layout][min_width]', '2');
|
|
705
|
+
formData.append('panels[0][layout][min_height]', '2');
|
|
706
|
+
|
|
707
|
+
formData.append('panels[0][widget_settings]', JSON.stringify(patchBody));
|
|
708
|
+
|
|
709
|
+
cy.request({
|
|
660
710
|
method: 'POST',
|
|
661
|
-
url:
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
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
|
-
});
|
|
711
|
+
url: `/centreon/api/latest/configuration/dashboards/${dashboardId}`,
|
|
712
|
+
body: formData,
|
|
713
|
+
headers: {
|
|
714
|
+
'Content-Type': 'multipart/form-data',
|
|
715
|
+
},
|
|
716
|
+
}).then((patchResponse) => {
|
|
717
|
+
console.log('Widget added successfully:', patchResponse);
|
|
684
718
|
});
|
|
685
|
-
}
|
|
686
|
-
);
|
|
719
|
+
});
|
|
720
|
+
});
|
|
687
721
|
|
|
688
722
|
interface ShareDashboardToUserProps {
|
|
689
723
|
dashboardName: string;
|
|
@@ -699,29 +733,48 @@ interface ListingRequestResult {
|
|
|
699
733
|
};
|
|
700
734
|
}
|
|
701
735
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
736
|
+
type PatchDashboardBody = {
|
|
737
|
+
widget_settings: {
|
|
738
|
+
data: {
|
|
739
|
+
resources: Array<{
|
|
740
|
+
resourceType: string;
|
|
741
|
+
resources: Array<{
|
|
742
|
+
id: number;
|
|
743
|
+
name: string;
|
|
744
|
+
}>;
|
|
745
|
+
}>;
|
|
746
|
+
metrics: Array<{
|
|
747
|
+
criticalHighThreshold: number;
|
|
748
|
+
criticalLowThreshold: number;
|
|
749
|
+
id: number;
|
|
750
|
+
name: string;
|
|
751
|
+
unit: string;
|
|
752
|
+
warningHighThreshold: number;
|
|
753
|
+
warningLowThreshold: number;
|
|
754
|
+
}>;
|
|
755
|
+
};
|
|
714
756
|
options: {
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
757
|
+
timeperiod: {
|
|
758
|
+
start: any;
|
|
759
|
+
end: any;
|
|
760
|
+
timePeriodType: number;
|
|
761
|
+
};
|
|
762
|
+
threshold: {
|
|
763
|
+
enabled: boolean;
|
|
764
|
+
customCritical: any;
|
|
765
|
+
criticalType: string;
|
|
766
|
+
customWarning: any;
|
|
767
|
+
warningType: string;
|
|
768
|
+
};
|
|
769
|
+
refreshInterval: string;
|
|
770
|
+
curveType: string;
|
|
771
|
+
description: {
|
|
772
|
+
content: string;
|
|
773
|
+
enabled: boolean;
|
|
774
|
+
};
|
|
720
775
|
};
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
}>;
|
|
724
|
-
}
|
|
776
|
+
};
|
|
777
|
+
};
|
|
725
778
|
|
|
726
779
|
Cypress.Commands.add(
|
|
727
780
|
'shareDashboardToUser',
|
|
@@ -772,6 +825,71 @@ Cypress.Commands.add('getTimeFromHeader', (): Cypress.Chainable => {
|
|
|
772
825
|
});
|
|
773
826
|
});
|
|
774
827
|
|
|
828
|
+
Cypress.Commands.add('insertDashboardWithDoubleWidget', (dashboardBody, patchBody1, patchBody2, widgetName, widgetType) => {
|
|
829
|
+
cy.request({
|
|
830
|
+
body: { ...dashboardBody },
|
|
831
|
+
method: 'POST',
|
|
832
|
+
url: '/centreon/api/latest/configuration/dashboards'
|
|
833
|
+
}).then((response) => {
|
|
834
|
+
const dashboardId = response.body.id;
|
|
835
|
+
|
|
836
|
+
cy.waitUntil(
|
|
837
|
+
() => {
|
|
838
|
+
return cy.request({
|
|
839
|
+
method: 'GET',
|
|
840
|
+
url: `/centreon/api/latest/configuration/dashboards/${dashboardId}`
|
|
841
|
+
}).then((getResponse) => {
|
|
842
|
+
return getResponse.body && getResponse.body.id === dashboardId;
|
|
843
|
+
});
|
|
844
|
+
},
|
|
845
|
+
{ timeout: 10000 }
|
|
846
|
+
);
|
|
847
|
+
|
|
848
|
+
const formData = new FormData();
|
|
849
|
+
|
|
850
|
+
// Panel 1
|
|
851
|
+
formData.append('panels[0][name]', widgetName);
|
|
852
|
+
formData.append('panels[0][widget_type]', widgetType);
|
|
853
|
+
formData.append('panels[0][layout][x]', '0');
|
|
854
|
+
formData.append('panels[0][layout][y]', '0');
|
|
855
|
+
formData.append('panels[0][layout][width]', '12');
|
|
856
|
+
formData.append('panels[0][layout][height]', '3');
|
|
857
|
+
formData.append('panels[0][layout][min_width]', '2');
|
|
858
|
+
formData.append('panels[0][layout][min_height]', '2');
|
|
859
|
+
formData.append('panels[0][widget_settings]', JSON.stringify(patchBody1));
|
|
860
|
+
|
|
861
|
+
// Panel 2
|
|
862
|
+
formData.append('panels[1][name]', widgetName);
|
|
863
|
+
formData.append('panels[1][widget_type]', widgetType);
|
|
864
|
+
formData.append('panels[1][layout][x]', '0');
|
|
865
|
+
formData.append('panels[1][layout][y]', '3');
|
|
866
|
+
formData.append('panels[1][layout][width]', '12');
|
|
867
|
+
formData.append('panels[1][layout][height]', '3');
|
|
868
|
+
formData.append('panels[1][layout][min_width]', '2');
|
|
869
|
+
formData.append('panels[1][layout][min_height]', '2');
|
|
870
|
+
formData.append('panels[1][widget_settings]', JSON.stringify(patchBody2));
|
|
871
|
+
|
|
872
|
+
// Log form data
|
|
873
|
+
const dataToLog = {};
|
|
874
|
+
formData.forEach((value, key) => {
|
|
875
|
+
dataToLog[key] = value;
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
console.log('FormData before POST:', JSON.stringify(dataToLog, null, 2));
|
|
879
|
+
|
|
880
|
+
cy.request({
|
|
881
|
+
method: 'POST',
|
|
882
|
+
url: `/centreon/api/latest/configuration/dashboards/${dashboardId}`,
|
|
883
|
+
body: formData,
|
|
884
|
+
headers: {
|
|
885
|
+
'Content-Type': 'multipart/form-data',
|
|
886
|
+
},
|
|
887
|
+
}).then((patchResponse) => {
|
|
888
|
+
console.log('Widget added successfully:', patchResponse);
|
|
889
|
+
});
|
|
890
|
+
});
|
|
891
|
+
});
|
|
892
|
+
|
|
775
893
|
declare global {
|
|
776
894
|
namespace Cypress {
|
|
777
895
|
interface Chainable {
|
|
@@ -784,6 +902,7 @@ declare global {
|
|
|
784
902
|
props: CopyToContainerProps,
|
|
785
903
|
options?: Partial<Cypress.ExecOptions>
|
|
786
904
|
) => Cypress.Chainable;
|
|
905
|
+
copyWebContainerLogs: (props: CopyWebContainerLogsProps) => Cypress.Chainable;
|
|
787
906
|
createDirectory: (directoryPath: string) => Cypress.Chainable;
|
|
788
907
|
execInContainer: (
|
|
789
908
|
props: ExecInContainerProps,
|
|
@@ -802,7 +921,9 @@ declare global {
|
|
|
802
921
|
getContainerId: (containerName: string) => Cypress.Chainable;
|
|
803
922
|
getContainerIpAddress: (containerName: string) => Cypress.Chainable;
|
|
804
923
|
getContainersLogs: () => Cypress.Chainable;
|
|
924
|
+
getContainerMappedPort: (containerName: string, containerPort: number) => Cypress.Chainable;
|
|
805
925
|
getIframeBody: () => Cypress.Chainable;
|
|
926
|
+
getLogDirectory: () => Cypress.Chainable;
|
|
806
927
|
getTimeFromHeader: () => Cypress.Chainable;
|
|
807
928
|
getWebVersion: () => Cypress.Chainable;
|
|
808
929
|
hoverRootMenuItem: (rootItemNumber: number) => Cypress.Chainable;
|
|
@@ -810,7 +931,16 @@ declare global {
|
|
|
810
931
|
insertDashboardList: (fixtureFile: string) => Cypress.Chainable;
|
|
811
932
|
insertDashboardWithWidget: (
|
|
812
933
|
dashboard: Dashboard,
|
|
813
|
-
|
|
934
|
+
patchBody: Record<string, any>,
|
|
935
|
+
widgetName:string,
|
|
936
|
+
widgetType:string
|
|
937
|
+
) => Cypress.Chainable;
|
|
938
|
+
insertDashboardWithDoubleWidget: (
|
|
939
|
+
dashboard: Dashboard,
|
|
940
|
+
patchBody1: Record<string, any>,
|
|
941
|
+
patchBody2: Record<string, any>,
|
|
942
|
+
widgetName: string,
|
|
943
|
+
widgetType: string
|
|
814
944
|
) => Cypress.Chainable;
|
|
815
945
|
loginAsAdminViaApiV2: () => Cypress.Chainable;
|
|
816
946
|
loginByTypeOfUser: ({
|
|
@@ -50,14 +50,24 @@ export default ({
|
|
|
50
50
|
},
|
|
51
51
|
setupNodeEvents: async (cypressOn, config) => {
|
|
52
52
|
const on = require('cypress-on-fix')(cypressOn)
|
|
53
|
-
installLogsPrinter(on
|
|
53
|
+
installLogsPrinter(on, {
|
|
54
|
+
commandTrimLength: 5000,
|
|
55
|
+
defaultTrimLength: 5000,
|
|
56
|
+
});
|
|
57
|
+
on('task', {
|
|
58
|
+
logVersion(message) {
|
|
59
|
+
console.log(`[LOG]: ${message}`);
|
|
60
|
+
return null;
|
|
61
|
+
},
|
|
62
|
+
});
|
|
54
63
|
await esbuildPreprocessor(on, config);
|
|
55
64
|
tasks(on);
|
|
56
65
|
|
|
57
66
|
return plugins(on, config);
|
|
58
67
|
},
|
|
59
68
|
specPattern,
|
|
60
|
-
supportFile: 'support/e2e.{js,jsx,ts,tsx}'
|
|
69
|
+
supportFile: 'support/e2e.{js,jsx,ts,tsx}',
|
|
70
|
+
testIsolation: true,
|
|
61
71
|
},
|
|
62
72
|
env: {
|
|
63
73
|
...env,
|
|
@@ -65,6 +75,7 @@ export default ({
|
|
|
65
75
|
OPENID_IMAGE_VERSION: process.env.MAJOR || '24.04',
|
|
66
76
|
SAML_IMAGE_VERSION: process.env.MAJOR || '24.04',
|
|
67
77
|
STABILITY: 'unstable',
|
|
78
|
+
TARGET_STABILITY: 'unstable',
|
|
68
79
|
WEB_IMAGE_OS: 'alma9',
|
|
69
80
|
WEB_IMAGE_VERSION: webImageVersion
|
|
70
81
|
},
|
package/cypress/e2e/plugins.ts
CHANGED
|
@@ -36,36 +36,27 @@ export default (
|
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
on('after:run', (results) => {
|
|
39
|
-
const testRetries: { [key: string]:
|
|
39
|
+
const testRetries: { [key: string]: Number } = {};
|
|
40
40
|
if ('runs' in results) {
|
|
41
41
|
results.runs.forEach((run) => {
|
|
42
42
|
run.tests.forEach((test) => {
|
|
43
|
-
|
|
43
|
+
console.log(test)
|
|
44
|
+
if (test.attempts && test.attempts.length > 1 && test.state === 'passed') {
|
|
44
45
|
const testTitle = test.title.join(' > '); // Convert the array to a string
|
|
45
|
-
testRetries[testTitle] =
|
|
46
|
+
testRetries[testTitle] = test.attempts.length - 1;
|
|
46
47
|
}
|
|
47
48
|
});
|
|
48
49
|
});
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
console.log('After run results:', results);
|
|
52
|
-
console.log('Test retries:', testRetries);
|
|
53
|
-
|
|
54
52
|
// Save the testRetries object to a file in the e2e/results directory
|
|
55
53
|
const resultFilePath = path.join(
|
|
56
54
|
__dirname,
|
|
57
55
|
'../../../../tests/e2e/results',
|
|
58
|
-
'
|
|
56
|
+
'retries.json'
|
|
59
57
|
);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
} else if (Object.keys(testRetries).length > 0) {
|
|
63
|
-
// If tests succeeded but there were retries, write the retries to the file
|
|
64
|
-
fs.writeFileSync(resultFilePath, JSON.stringify(testRetries, null, 2));
|
|
65
|
-
} else {
|
|
66
|
-
// If no retries, empty the file
|
|
67
|
-
fs.writeFileSync(resultFilePath, '{}');
|
|
68
|
-
}
|
|
58
|
+
|
|
59
|
+
fs.writeFileSync(resultFilePath, JSON.stringify(testRetries, null, 2));
|
|
69
60
|
});
|
|
70
61
|
|
|
71
62
|
return config;
|
package/cypress/e2e/tasks.ts
CHANGED
|
@@ -18,6 +18,13 @@ interface Containers {
|
|
|
18
18
|
[key: string]: StartedTestContainer;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
class NotFoundContainerError extends Error {
|
|
22
|
+
constructor(message) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = 'NotFoundContainerError';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
21
28
|
export default (on: Cypress.PluginEvents): void => {
|
|
22
29
|
let dockerEnvironment: StartedDockerComposeEnvironment | null = null;
|
|
23
30
|
const containers: Containers = {};
|
|
@@ -30,7 +37,7 @@ export default (on: Cypress.PluginEvents): void => {
|
|
|
30
37
|
} else if (containers[containerName]) {
|
|
31
38
|
container = containers[containerName];
|
|
32
39
|
} else {
|
|
33
|
-
throw new
|
|
40
|
+
throw new NotFoundContainerError(`Cannot get container ${containerName}`);
|
|
34
41
|
}
|
|
35
42
|
|
|
36
43
|
return container;
|
|
@@ -55,21 +62,23 @@ export default (on: Cypress.PluginEvents): void => {
|
|
|
55
62
|
on('task', {
|
|
56
63
|
copyFromContainer: async ({ destination, serviceName, source }) => {
|
|
57
64
|
try {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
dest.on('finish', resolve);
|
|
68
|
-
});
|
|
65
|
+
const container = getContainer(serviceName);
|
|
66
|
+
|
|
67
|
+
await container
|
|
68
|
+
.copyArchiveFromContainer(source)
|
|
69
|
+
.then((archiveStream) => {
|
|
70
|
+
return new Promise<void>((resolve) => {
|
|
71
|
+
const dest = tar.extract(destination);
|
|
72
|
+
archiveStream.pipe(dest);
|
|
73
|
+
dest.on('finish', resolve);
|
|
69
74
|
});
|
|
70
|
-
|
|
75
|
+
});
|
|
71
76
|
} catch (error) {
|
|
72
|
-
|
|
77
|
+
if (error instanceof NotFoundContainerError) {
|
|
78
|
+
console.log(`Cannot get ${source} from container ${serviceName} because it doesn't exist.`);
|
|
79
|
+
} else {
|
|
80
|
+
console.error(error);
|
|
81
|
+
}
|
|
73
82
|
}
|
|
74
83
|
|
|
75
84
|
return null;
|
|
@@ -140,6 +149,11 @@ export default (on: Cypress.PluginEvents): void => {
|
|
|
140
149
|
return null;
|
|
141
150
|
}
|
|
142
151
|
},
|
|
152
|
+
getContainerMappedPort: async ({ containerName, containerPort }) => {
|
|
153
|
+
const container = getContainer(containerName);
|
|
154
|
+
|
|
155
|
+
return container.getMappedPort(containerPort);
|
|
156
|
+
},
|
|
143
157
|
requestOnDatabase: async ({ database, query }) => {
|
|
144
158
|
let container: StartedTestContainer | null = null;
|
|
145
159
|
|
package/package.json
CHANGED
|
@@ -63,8 +63,12 @@ module.exports = {
|
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
output: {
|
|
66
|
-
chunkFilename:
|
|
67
|
-
|
|
66
|
+
chunkFilename: isDev
|
|
67
|
+
? '[name].[chunkhash:8].chunk.js'
|
|
68
|
+
: '[name].[contenthash].[chunkhash].[hash].js',
|
|
69
|
+
filename: isDev
|
|
70
|
+
? '[name].[chunkhash:8].js'
|
|
71
|
+
: '[name].[contenthash].[hash].js',
|
|
68
72
|
libraryTarget: 'umd',
|
|
69
73
|
umdNamedDefine: true
|
|
70
74
|
}
|
|
@@ -13,7 +13,9 @@ const externalInterface = Object.keys(interfaces).find(
|
|
|
13
13
|
!process.env.IS_STATIC_PORT_FORWARDED
|
|
14
14
|
);
|
|
15
15
|
|
|
16
|
-
const devServerAddress =
|
|
16
|
+
const devServerAddress = externalInterface
|
|
17
|
+
? interfaces[externalInterface][0].address
|
|
18
|
+
: 'localhost';
|
|
17
19
|
|
|
18
20
|
const publicPath = `http://${devServerAddress}:${devServerPort}/static/`;
|
|
19
21
|
|