diff --git a/web/cypress.config.ts b/web/cypress.config.ts
index fcedccf8c..3b6935a03 100644
--- a/web/cypress.config.ts
+++ b/web/cypress.config.ts
@@ -1,13 +1,131 @@
import { defineConfig } from 'cypress';
+const fs = require('fs');
+const path = require('path');
+const report_dir = process.env.ARTIFACT_DIR || '/tmp';
export default defineConfig({
+ screenshotsFolder: path.join(report_dir, 'cypress', 'screenshots'),
+ screenshotOnRunFailure: true,
+ trashAssetsBeforeRuns: true,
+ videosFolder: path.join(report_dir, 'cypress', 'videos'),
+ video: true,
+ videoCompression: false,
+ reporter: './node_modules/cypress-multi-reporters',
+ reporterOptions: {
+ reporterEnabled: 'mocha-junit-reporter, mochawesome',
+ mochaJunitReporterReporterOptions: {
+ mochaFile: path.join(report_dir, 'junit_cypress-[hash].xml'),
+ toConsole: false
+ },
+ mochawesomeReporterOptions: {
+ reportDir: report_dir,
+ reportFilename: 'cypress_report',
+ overwrite: false,
+ html: false,
+ json: true
+ }
+ },
+ env: {
+ grepFilterSpecs: false,
+ 'KUBECONFIG_PATH': process.env.KUBECONFIG,
+ 'NOO_CS_IMAGE': process.env.MULTISTAGE_PARAM_OVERRIDE_CYPRESS_NOO_CS_IMAGE,
+ 'OPENSHIFT_VERSION': process.env.CYPRESS_OPENSHIFT_VERSION,
+ },
+ fixturesFolder: 'fixtures',
+ defaultCommandTimeout: 30000,
+ retries: {
+ runMode: 0,
+ openMode: 0,
+ },
+ viewportWidth: 1600,
+ viewportHeight: 1200,
e2e: {
- baseUrl: 'http://localhost:9003',
+ baseUrl: process.env.CYPRESS_BASE_URL || process.env.BASE_URL || 'http://localhost:9003',
setupNodeEvents(on, config) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('@cypress/code-coverage/task')(on, config);
+ on('before:browser:launch', (browser = {
+ name: "",
+ family: "chromium",
+ channel: "",
+ displayName: "",
+ version: "",
+ majorVersion: "",
+ path: "",
+ isHeaded: false,
+ isHeadless: false
+ }, launchOptions) => {
+ if (browser.family === 'chromium' && browser.name !== 'electron') {
+ // auto open devtools
+ launchOptions.args.push('--enable-precise-memory-info')
+ }
+
+ return launchOptions
+
+ });
+ // `on` is used to hook into various events Cypress emits
+ on('task', {
+ log(message) {
+ console.log(message);
+ return null;
+ },
+ logError(message) {
+ console.error(message);
+ return null;
+ },
+ logTable(data) {
+ console.table(data);
+ return null;
+ },
+ readFileIfExists(filename) {
+ if (fs.existsSync(filename)) {
+ return fs.readFileSync(filename, 'utf8');
+ }
+ return null;
+ },
+ });
+ on('after:screenshot', (details) => {
+ // Prepend "1_", "2_", etc. to screenshot filenames because they are sorted alphanumerically in CI's artifacts dir
+ const pathObj = path.parse(details.path);
+ fs.readdir(pathObj.dir, (error, files) => {
+ const newPath = `${pathObj.dir}${path.sep}${files.length}_${pathObj.base}`;
+ return new Promise((resolve, reject) => {
+ // eslint-disable-next-line consistent-return
+ fs.rename(details.path, newPath, (err) => {
+ if (err) return reject(err);
+ // because we renamed and moved the image, resolve with the new path
+ // so it is accurate in the test results
+ resolve({ path: newPath });
+ });
+ });
+ });
+ });
+ on(
+ 'after:spec',
+ (spec: Cypress.Spec, results: CypressCommandLine.RunResult) => {
+ if (results && results.video) {
+ // Do we have failures for any retry attempts?
+ const failures = results.tests.some((test) =>
+ test.attempts.some((attempt) => attempt.state === 'failed')
+ )
+ if (!failures && fs.existsSync(results.video)) {
+ // delete the video if the spec passed and no tests retried
+ fs.unlinkSync(results.video)
+ }
+ }
+ }
+ );
+ require('@cypress/grep/src/plugin')(config);
return config;
},
+ supportFile: './cypress/support/e2e.ts',
+ specPattern: './cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
+ numTestsKeptInMemory: 1,
+ testIsolation: false,
+ experimentalModifyObstructiveThirdPartyCode: true,
+ experimentalOriginDependencies: true,
+ experimentalMemoryManagement: true,
+ experimentalCspAllowList: ['default-src', 'script-src']
},
numTestsKeptInMemory: 2,
video: false,
diff --git a/web/cypress/README.md b/web/cypress/README.md
new file mode 100644
index 000000000..c42763d4b
--- /dev/null
+++ b/web/cypress/README.md
@@ -0,0 +1,8 @@
+#The following file are copyed from https://github.com/openshift/monitoring-plugin/tree/main/web. This will be synced manually.
+web/cypress/support/commands/auth-commands.ts
+web/cypress/support/commands/selector-commands.ts
+web/cypress/support/commands/utility-commands.ts
+web/cypress/views/nav.ts
+web/cypress/views/tour.ts
+web/cypress/views/utils.ts
+web/src/components/data-test.ts
diff --git a/web/cypress/e2e/logging/adminConsoleAggregatedLogs.cy.ts b/web/cypress/e2e/logging/adminConsoleAggregatedLogs.cy.ts
new file mode 100644
index 000000000..853e6fb37
--- /dev/null
+++ b/web/cypress/e2e/logging/adminConsoleAggregatedLogs.cy.ts
@@ -0,0 +1,81 @@
+import { TestIds } from '../../../src/test-ids';
+import { aggrLogTest, observeLogTest, commonTest } from './testUtils.cy.ts';
+import { APP_NAMESPACE1,APP_NAMESPACE2,APP_MESSAGE } from './testUtils.cy.ts';
+
+describe('AdminConsole: Admin in AggregatedLogs', { tags: ['@admin'] }, () => {
+ before( function() {
+ cy.uiLoginAsClusterAdmin("first_user");
+ });
+
+ beforeEach( function() {
+ cy.showAdminConsolePodAggrLog(APP_NAMESPACE1);
+ });
+
+ after( function() {
+ cy.uiLogoutClusterAdmin("first_user");
+ });
+
+ aggrLogTest();
+ commonTest();
+ it('admin can display infra container logs',{tags:['@aggr']}, () => {
+ cy.showAdminConsolePodAggrLog('openshift-monitoring','alertmanager-main-0');
+ const indexFields : IndexField = [
+ { name: '_timestamp', value: "" },
+ { name: 'k8s_container_name', value: "" },
+ { name: 'k8s_namespace_name', value: "openshift-monitoring" },
+ { name: 'k8s_node_name', value: "" },
+ { name: 'k8s_pod_name', value: "alertmanager-main-0" },
+ { name: 'openshift_log_type', value: "infrastructure" },
+ { name: 'log_source', value: "container" },
+ { name: 'hostname', value: "" },
+ { name: 'openshift_cluster_id', value: "" },
+ { name: 'openshift_sequence', value: "" },
+ ];
+ cy.assertFieldsInLogDetail(indexFields)
+ });
+})
+
+describe('AdminConsole: Impersonate User in AggregatedLogs',{ tags: ['@admin'] }, () => {
+ before( function() {
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ cy.cliLogin("second_user")
+ cy.uiLoginAsClusterAdmin("first_user");
+ cy.uiImpersonateUser("second_user");
+ cy.switchToAdmConsole();
+ });
+
+ beforeEach( function() {
+ cy.showAdminConsolePodAggrLog(APP_NAMESPACE1);
+ });
+
+ after( function() {
+ cy.uiLogoutUser("second_user");
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ });
+
+ aggrLogTest();
+ commonTest();
+})
+
+describe('AdminConsole: User in Aggregated Logs', { tags: ['@user'] }, () => {
+ before( function() {
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ cy.uiLoginUser("second_user");
+ });
+
+ beforeEach( function() {
+ cy.showAdminConsolePodAggrLog(APP_NAMESPACE1);
+ });
+
+ after( function() {
+ cy.uiLogoutUser("second_user");
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ });
+
+ aggrLogTest();
+ commonTest();
+})
diff --git a/web/cypress/e2e/logging/adminConsoleObserveLogs.cy.ts b/web/cypress/e2e/logging/adminConsoleObserveLogs.cy.ts
new file mode 100644
index 000000000..4956476c8
--- /dev/null
+++ b/web/cypress/e2e/logging/adminConsoleObserveLogs.cy.ts
@@ -0,0 +1,215 @@
+import { TestIds } from '../../../src/test-ids';
+import { aggrLogTest, observeLogTest, commonTest, getRunningPodName } from './testUtils.cy.ts';
+import { APP_NAMESPACE1,APP_NAMESPACE2,APP_MESSAGE } from './testUtils.cy.ts';
+
+
+function admConsoleUserObsTest() {
+ it('user can not display audit logs',{tags:['@observ']}, () => {
+ cy.byTestID(TestIds.TenantToggle)
+ .click()
+ .get('#logging-view-tenant-dropdown')
+ .contains('button', 'audit')
+ .click()
+ cy.byTestID(TestIds.LogsTable)
+ .should('exist')
+ .within(() => {
+ cy.get('div.lv-plugin__table__row-error', { timeout: 600 }).should('contain', 'Forbidden');
+ })
+ });
+}
+
+function admConsoleObserveTest(){
+ it('validate elements in core observeLogs',{tags:['@observ']}, () => {
+ const commonElements = [
+ TestIds.ToggleHistogramButton,
+ TestIds.TimeRangeDropdown,
+ TestIds.RefreshIntervalDropdown,
+ TestIds.SyncButton,
+ TestIds.AvailableAttributes,
+ TestIds.SeverityDropdown,
+ TestIds.ShowStatsToggle,
+ TestIds.ExecuteVolumeButton,
+ TestIds.ExecuteQueryButton,
+ TestIds.ShowQueryToggle,
+ TestIds.LogsTable,
+ ];
+ commonElements.forEach(id => {
+ cy.byTestID(id).should('exist');
+ });
+
+ cy.byTestID(TestIds.TenantToggle).should('exist');
+ cy.byTestID(TestIds.AttributeFilters).within(() => {
+ cy.byTestID(TestIds.AvailableAttributes).click();
+ cy.contains('li', 'Content');
+ cy.contains('li', 'Pod');
+ cy.contains('li', 'Containers');
+ cy.contains('li', 'Namespaces');
+ })
+ if (Cypress.env('CLUSTERLOGGING_DATAMODE') === "select" ) {
+ cy.byTestID(TestIds.SchemaToggle).should('exist');
+ }
+ })
+
+ it('selected containers',{tags:['@observ']}, () => {
+ getRunningPodName(APP_NAMESPACE1).as('pod1Name');
+ getRunningPodName(APP_NAMESPACE2).as('pod2Name');
+
+ cy.get('@pod1Name').then((pod1Name) => {
+ cy.get('@pod2Name').then((pod2Name) => {
+ const containers = [`${pod1Name} / centos-logtest`,`${pod2Name} / centos-logtest`]
+ cy.log(`container1=${pod1Name} / centos-logtest, container2=${pod2Name} / centos-logtest`);
+ cy.checkLogContainers(containers)
+
+ cy.showQueryInput();
+ let pattern = /{ kubernetes_container_name="centos-logtest", kubernetes_pod_name=~"centos-logtest-\w+|centos-logtest-\w+" } | json/;
+ if (String(Cypress.env('CLUSTERLOGGING_DATAMODE')) === "otel") {
+ pattern = /{ k8s_container_name="centos-logtest", k8s_pod_name=~"centos-logtest-\w+|centos-logtest-\w+" } /;
+ }
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .should('match', pattern);
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ const indexFields : IndexField = [
+ { name: 'k8s_namespace_name', value: `${APP_NAMESPACE1}|${APP_NAMESPACE2}` },
+ { name: 'k8s_pod_name', value: `${pod1Name}|${pod2Name}` },
+ { name: 'k8s_container_name', value: 'centos-logtest' },
+ ]
+ cy.assertFieldsInLogDetail(indexFields)
+ });
+ });
+ })
+}
+
+describe('AdminConsole:: Admin in ObserveLogs', { tags: ['@admin'] }, () => {
+ before( function() {
+ cy.uiLoginAsClusterAdmin("first_user");
+ });
+
+ beforeEach( function() {
+ // Load the other page to ensure Observe-Logs in clean status
+ cy.clickNavLink(['Home', 'Search'])
+ cy.clickNavLink(['Observe', 'Logs'])
+ });
+
+ after( function() {
+ cy.uiLogoutClusterAdmin("first_user");
+ });
+ admConsoleObserveTest();
+ observeLogTest();
+ commonTest();
+ it('admin can display infra logs',{tags:['@observ']}, () => {
+ cy.selectLogTenant('infrastructure')
+ let query = '{ log_type="infrastructure" } | json'
+ if (String(Cypress.env('CLUSTERLOGGING_DATAMODE')) === "otel") {
+ query = '{ log_type="infrastructure" }'
+ }
+ cy.showQueryInput();
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .should('eq', query)
+ cy.assertInfraLogsInLogsTable();
+ });
+
+ it('admin can display infra container logs',{tags:['@observ']}, () => {
+ cy.selectLogTenant('infrastructure')
+ cy.runLogQuery('{{}log_type="infrastructure"{}}|json|log_source="container"');
+
+ const indexFields : IndexField = [
+ { name: '_timestamp', value: "" },
+ { name: 'k8s_container_name', value: "" },
+ { name: 'k8s_namespace_name', value: "" },
+ { name: 'k8s_node_name', value: "" },
+ { name: 'k8s_pod_name', value: "" },
+ { name: 'openshift_log_type', value: "infrastructure" },
+ { name: 'log_source', value: "container" },
+ { name: 'hostname', value: "" },
+ { name: 'openshift_cluster_id', value: "" },
+ { name: 'openshift_sequence', value: "" },
+ ];
+ cy.assertFieldsInLogDetail(indexFields)
+ });
+
+ it('admin can display infra node logs',{tags:['@smoke','@observ']}, () => {
+ cy.selectLogTenant('infrastructure')
+ cy.runLogQuery('{{}log_type="infrastructure"{}}|json|log_source="node"')
+ const indexFields : IndexField = [
+ { name: '_timestamp', value: "" },
+ { name: 'log_type', value: "infrastructure" },
+ { name: 'openshift_log_type', value: "infrastructure" },
+ { name: 'log_source', value: "node" },
+ { name: 'hostname', value: "" },
+ { name: 'openshift_cluster_id', value: "" },
+ { name: 'openshift_sequence', value: "" },
+ ];
+ cy.assertFieldsInLogDetail(indexFields);
+ });
+
+ it('admin can display audit logs',{tags:['@observ']}, () => {
+ cy.selectLogTenant('audit')
+ let query = '{ log_type="audit" } | json'
+ if (String(Cypress.env('CLUSTERLOGGING_DATAMODE')) === "otel") {
+ query = '{ log_type="audit" }'
+ }
+ cy.showQueryInput();
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .should('eq', query)
+ cy.assertAuditLogsInLogsTable();
+ });
+})
+
+describe.skip('AdminConsole: Impersonate User in ObserveLogs', { tags: ['@admin'] }, () => {
+ before( function() {
+ cy.cliLogin("second_user");
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ cy.uiLoginAsClusterAdmin("first_user");
+ cy.uiImpersonateUser("second_user");
+ cy.switchToAdmConsole();
+ });
+
+ beforeEach( function() {
+ // Load the other page to ensure Observe-Logs in clean status
+ cy.clickNavLink(['Home', 'Search'])
+ cy.clickNavLink(['Observe', 'Logs'])
+ });
+
+ after( function() {
+ cy.uiLogoutUser("second_user");
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ });
+
+ admConsoleObserveTest();
+ admConsoleUserObsTest();
+ observeLogTest();
+ commonTest();
+})
+
+describe.skip('AdminConsole: User in ObserveLogs', { tags: ['@user'] }, () => {
+ before( function() {
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE1}`)
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE2}`)
+ cy.uiLoginUser("second_user");
+ });
+
+ beforeEach( function() {
+ // Load the other page to ensure Observe-Logs in clean status
+ cy.clickNavLink(['Home', 'Search'])
+ cy.clickNavLink(['Observe', 'Logs'])
+ });
+
+ after( function() {
+ cy.uiLogoutUser("second_user");
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ });
+
+ admConsoleObserveTest();
+ admConsoleUserObsTest();
+ observeLogTest();
+ commonTest();
+})
diff --git a/web/cypress/e2e/logging/devConsoleAggregatedLogs.cy.ts b/web/cypress/e2e/logging/devConsoleAggregatedLogs.cy.ts
new file mode 100644
index 000000000..1c7df745b
--- /dev/null
+++ b/web/cypress/e2e/logging/devConsoleAggregatedLogs.cy.ts
@@ -0,0 +1,113 @@
+import { TestIds } from '../../../src/test-ids';
+import { isDevConsoleReady, aggrLogTest, commonTest } from './testUtils.cy.ts';
+import { APP_NAMESPACE1,APP_NAMESPACE2,APP_MESSAGE } from './testUtils.cy.ts';
+
+let SKIPALL= false
+
+function devConsoleUserAggrTest(){
+ it('user can not display infra logs',{tags:['@aggr']}, () => {
+ cy.runLogQuery('{{} k8s_namespace_name="openshift-monitoring" {}}');
+ cy.getByTestId(TestIds.LogsTable)
+ .should('contain.text', 'Warning alert:No datapoints found');
+ });
+}
+
+describe('DevConsole: Admin in AggregatedLogs ', { tags: ['@admin'] }, () => {
+ before( function() {
+ //Check if DevConsole is ready
+ isDevConsoleReady().then((ready) => {
+ if (!ready) {
+ SKIPALL= true
+ cy.task('log','DeveloperConsole is not ready — skipping suite');
+ this.skip()
+ }
+ });
+ cy.uiLoginAsClusterAdmin("first_user");
+ cy.switchToDevConsole();
+ });
+
+ beforeEach( function() {
+ cy.showDevConsolePodAggrLog(APP_NAMESPACE1)
+ });
+
+ after( function() {
+ if (!SKIPALL) {
+ cy.uiLogoutClusterAdmin("first_user");
+ }
+ });
+ aggrLogTest();
+ commonTest();
+
+ it('admin can display infra container logs', {tags: ['@aggr'] }, () => {
+ //load Aggregated Logs for pod in openshift-monitoring
+ cy.showDevConsolePodAggrLog('openshift-monitoring')
+ cy.assertInfraLogsInLogsTable();
+ });
+})
+
+describe('DevConsole: Impersonate User in AggregatedLogs', { tags: ['@admin'] },() => {
+ before( function() {
+ //Check if DevConsole is ready
+ isDevConsoleReady().then((ready) => {
+ if (!ready) {
+ cy.task('log','DeveloperConsole is not ready — skipping suite');
+ SKIPALL= true
+ this.skip()
+ }
+ });
+ cy.cliLogin("second_user");
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ cy.uiLoginAsClusterAdmin("first_user");
+ cy.uiImpersonateUser("second_user");
+ cy.switchToDevConsole();
+ });
+
+ beforeEach( function() {
+ cy.showDevConsolePodAggrLog(APP_NAMESPACE1)
+ });
+
+ after( function() {
+ if (!SKIPALL) {
+ cy.uiLogoutUser("second_user");
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ }
+ });
+ devConsoleUserAggrTest();
+ aggrLogTest();
+ commonTest()
+})
+
+describe('DevConsole: User in AggregatedLogs', { tags: ['@admin'] }, () => {
+ before( function() {
+ //Check if DevConsole is ready
+ isDevConsoleReady().then((ready) => {
+ if (!ready) {
+ cy.task('log','DeveloperConsole is not ready — skipping suite');
+ SKIPALL= true
+ this.skip()
+ }
+ });
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ cy.uiLoginUser("second_user");
+ cy.switchToDevConsole();
+ });
+
+ beforeEach( function() {
+ //hover on project page
+ cy.showDevConsolePodAggrLog(APP_NAMESPACE1)
+ });
+
+ after( function() {
+ if (!SKIPALL) {
+ cy.uiLogoutUser("second_user");
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ }
+ });
+ devConsoleUserAggrTest();
+ aggrLogTest();
+ commonTest();
+});
diff --git a/web/cypress/e2e/logging/devConsoleObserveLogs.cy.ts b/web/cypress/e2e/logging/devConsoleObserveLogs.cy.ts
new file mode 100644
index 000000000..f2f837802
--- /dev/null
+++ b/web/cypress/e2e/logging/devConsoleObserveLogs.cy.ts
@@ -0,0 +1,216 @@
+import { TestIds } from '../../../src/test-ids';
+import { isDevConsoleReady, observeLogTest, commonTest, getRunningPodName } from './testUtils.cy.ts';
+import { APP_NAMESPACE1,APP_NAMESPACE2,APP_MESSAGE } from './testUtils.cy.ts';
+
+let SKIPALL= false
+
+function devConsoleObsTest(){
+ it('validate elements in dev observeLogs',{tags:['@devobserv']}, () => {
+ const commonElements = [
+ TestIds.ToggleHistogramButton,
+ TestIds.TimeRangeDropdown,
+ TestIds.RefreshIntervalDropdown,
+ TestIds.SyncButton,
+ TestIds.AvailableAttributes,
+ TestIds.SeverityDropdown,
+ TestIds.ShowStatsToggle,
+ TestIds.ExecuteVolumeButton,
+ TestIds.ExecuteQueryButton,
+ TestIds.ShowQueryToggle,
+ TestIds.LogsTable,
+ ];
+ commonElements.forEach(id => {
+ cy.byTestID(id).should('exist');
+ });
+
+ cy.byTestID(TestIds.TenantToggle).should('not.exist'); //Specical feature
+ cy.byTestID(TestIds.AttributeFilters).within(() => {
+ cy.byTestID(TestIds.AvailableAttributes).click();
+ cy.contains('li', 'Content');
+ cy.contains('li', 'Pod');
+ cy.contains('li', 'Containers');
+ cy.contains('li', 'Namespaces');
+ })
+ if (Cypress.env('CLUSTERLOGGING_DATAMODE') === "select" ) {
+ cy.byTestID(TestIds.SchemaToggle).should('exist');
+ }
+ })
+
+ it('selected containers',{tags:['@devobserv']}, () => {
+ getRunningPodName(APP_NAMESPACE1).as('pod1Name');
+ getRunningPodName(APP_NAMESPACE2).as('pod2Name');
+
+ cy.get('@pod1Name').then((pod1Name) => {
+ cy.get('@pod2Name').then((pod2Name) => {
+ //const containers = [`${pod1Name} / centos-logtest`,`${pod2Name} / centos-logtest`]
+ //cy.log(`container1=${pod1Name} / centos-logtest, container2=${pod2Name} / centos-logtest`);
+ const containers = ['centos-logtest']
+ cy.log('containers = centos-logtest')
+ cy.checkLogContainers(containers);
+
+ cy.showQueryInput();
+ let pattern = /{ kubernetes_container_name="centos-logtest", kubernetes_pod_name=~"centos-logtest-\w+|centos-logtest-\w+" } | json/;
+ if (String(Cypress.env('CLUSTERLOGGING_DATAMODE')) === "otel") {
+ pattern = /{ k8s_container_name="centos-logtest", k8s_pod_name=~"centos-logtest-\w+|centos-logtest-\w+" } /;
+ }
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .should('match', pattern);
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ const indexFields : IndexField = [
+ { name: 'k8s_namespace_name', value: `${APP_NAMESPACE1}|${APP_NAMESPACE2}` },
+ { name: 'k8s_pod_name', value: `${pod1Name}|${pod2Name}` },
+ { name: 'k8s_container_name', value: 'centos-logtest' },
+ ]
+ cy.assertFieldsInLogDetail(indexFields)
+ });
+ });
+ })
+
+}
+
+function devConsoleUserObsTest(){
+ it('user can not display infra logs',{tags:['@smoke','@devobserv']}, () => {
+ cy.runLogQuery('{{} k8s_namespace_name="openshift-monitoring" {}}')
+ cy.getByTestId(TestIds.LogsTable)
+ .should('contain.text', 'No datapoints found');
+ });
+}
+
+describe('DevConsole: Admin in ObserveLogs', { tags: ['@admin'] }, () => {
+ before( function() {
+ //Check if DevConsole is ready
+ isDevConsoleReady().then((ready) => {
+ if (!ready) {
+ cy.task('log','DeveloperConsole is not ready — skipping suite');
+ SKIPALL= true
+ this.skip()
+ return; // stop execution in this callback
+ }
+ });
+ cy.uiLoginAsClusterAdmin("first_user");
+ cy.switchToDevConsole();
+ });
+
+ beforeEach( function() {
+ // reload observe->logs for current pod in APP_NAMESPACE1
+ cy.clickNavLink(['Observe'])
+ cy.changeNamespace(APP_NAMESPACE1)
+ cy.byLegacyTestID('horizontal-link-Logs').click();
+ cy.assertLogsInLogsTable();
+ });
+
+ after( function() {
+ if (!SKIPALL) {
+ cy.uiLogoutClusterAdmin("first_user");
+ }
+ });
+
+ devConsoleObsTest();
+ observeLogTest();
+ commonTest();
+
+ it('admin can display infra logs',{tags:['@smoke','@devobserv']}, () => {
+ // reload observe->logs
+ cy.changeNamespace('openshift-monitoring');
+
+ let query = '{ kubernetes_namespace_name="openshift-monitoring" } | json'
+ if (String(Cypress.env('CLUSTERLOGGING_DATAMODE')) === "otel") {
+ query = '{ k8s_namespace_name="openshift-monitoring" }'
+ }
+ cy.showQueryInput();
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .should('eq', query)
+ cy.assertInfraLogsInLogsTable();
+ });
+
+ it('admin can not query without namespace',{tags:['@smoke','@devobserv']}, () => {
+ let queryText = `{{}log_type="infrastructure" {}}`
+ cy.showQueryInput();
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .clear()
+ .type(queryText, { delay: 0 })
+ cy.byTestID(TestIds.ExecuteQueryButton).should('be.disabled');
+ cy.byTestID(TestIds.LogsQueryInput)
+ .should('contain.text', 'Please select a namespace');
+ });
+})
+
+describe('DevConsole: Impersonate User in ObserveLogs',{ tags: ['@admin'] }, () => {
+ before( function() {
+ //Check if DevConsole is ready
+ isDevConsoleReady().then((ready) => {
+ if (!ready) {
+ cy.task('log','DeveloperConsole is not ready — skipping suite');
+ SKIPALL= true
+ this.skip();
+ return; // stop execution in this callback
+ }
+ });
+ cy.cliLogin("second_user");
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ cy.uiLoginAsClusterAdmin("first_user");
+ cy.uiImpersonateUser("second_user");
+ cy.switchToDevConsole();
+ });
+
+ beforeEach( function() {
+ // reload observe->logs for current pod in APP_NAMESPACE1
+ cy.clickNavLink(['Observe'])
+ cy.changeNamespace(APP_NAMESPACE1)
+ cy.byLegacyTestID('horizontal-link-Logs').click();
+ });
+
+ after( function() {
+ if (!SKIPALL) {
+ cy.uiLogoutUser("second_user");
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ }
+ });
+ devConsoleObsTest();
+ devConsoleUserObsTest();
+ observeLogTest();
+ commonTest();
+})
+
+describe('DevConsole: User in ObserveLogs', { tags: ['@user'] }, () => {
+ before( function() {
+ //Check if DevConsole is ready
+ isDevConsoleReady().then((ready) => {
+ if (!ready) {
+ cy.task('log','DeveloperConsole is not ready — skipping suite');
+ SKIPALL= true
+ this.skip()
+ return; // stop execution in this callback
+ }
+ });
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.grantLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ cy.uiLoginUser("second_user");
+ cy.switchToDevConsole();
+ });
+
+ beforeEach( function() {
+ cy.clickNavLink(['Observe'])
+ cy.changeNamespace(APP_NAMESPACE1)
+ cy.byLegacyTestID('horizontal-link-Logs').click();
+ });
+
+ after( function() {
+ if (!SKIPALL) {
+ cy.uiLogoutUser("second_user");
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE1}`);
+ cy.removeLogViewRoles("second_user", `${APP_NAMESPACE2}`);
+ }
+ });
+ devConsoleObsTest();
+ devConsoleUserObsTest();
+ observeLogTest();
+ commonTest();
+})
diff --git a/web/cypress/e2e/logging/testUtils.cy.ts b/web/cypress/e2e/logging/testUtils.cy.ts
new file mode 100644
index 000000000..52afe0d05
--- /dev/null
+++ b/web/cypress/e2e/logging/testUtils.cy.ts
@@ -0,0 +1,531 @@
+//Common logging UI Cases
+//Note: the default namespace is APP_NAMESPACE1 for all test in this file
+import { TestIds } from '../../../src/test-ids';
+export const APP_NAMESPACE1 = "log-test-app1";
+export const APP_NAMESPACE2 = "log-test-app2";
+export const APP_MESSAGE = "SVTLogger";
+
+export function isDevConsoleReady(): boolean {
+ //Check if DevConsole is enabled in 4.19+
+ cy.task('log','Check if devConsole is enabled');
+ const rawversion = Cypress.env('OPENSHIFT_VERSION');
+ if (!rawversion) {
+ throw new Error('OPENSHIFT_VERSION is not defined');
+ }
+ const version = String(rawversion)
+ const [major, minor] = version.split('.').map(Number);
+ if (major > 4 || (major === 4 && minor > 18)) {
+ return cy.exec("oc get console.operator cluster -o jsonpath='{.spec.customization.perspectives}'", { failOnNonZeroExit: false })
+ .then((result) => {
+ const devReady = result.stdout === '[{"id":"dev","visibility":{"state":"Enabled"}}]';
+ return devReady;
+ });
+ }
+ return cy.wrap(true);
+}
+
+export function getRunningPodName(namespace: string, labelSelector?: string) {
+ // Build the oc command
+ let cmd = `oc get pods -n ${namespace} --field-selector=status.phase=Running -o jsonpath="{.items[0].metadata.name}"`
+ if (labelSelector) {
+ cmd += ` -l ${labelSelector}`
+ }
+ return cy.exec(cmd).then((res) => res.stdout.trim())
+}
+
+export function aggrLogTest() {
+ it('validate elements in Aggregated Logs',{tags:['@aggr']}, () => {
+ const commonElements = [
+ TestIds.ToggleHistogramButton,
+ TestIds.TimeRangeDropdown,
+ TestIds.RefreshIntervalDropdown,
+ TestIds.SyncButton,
+ TestIds.AvailableAttributes,
+ TestIds.SeverityDropdown,
+ TestIds.ShowStatsToggle,
+ TestIds.ExecuteVolumeButton,
+ TestIds.ExecuteQueryButton,
+ TestIds.ShowQueryToggle,
+ TestIds.LogsTable,
+ ];
+ commonElements.forEach(id => {
+ cy.byTestID(id).should('exist');
+ });
+
+ cy.byTestID(TestIds.TenantToggle).should('not.exist'); //Specical feature
+ cy.byTestID(TestIds.AttributeFilters).within(() => {
+ cy.byTestID(TestIds.AvailableAttributes).click();
+ cy.contains('li', 'Content');
+ cy.contains('li', 'Pod');
+ cy.contains('li', 'Containers');
+ cy.contains('li', 'Namespaces').should('not.exist'); //Specical feature
+ })
+ if (Cypress.env('CLUSTERLOGGING_DATAMODE') === "select" ) {
+ cy.byTestID(TestIds.SchemaToggle).should('exist');
+ }
+ })
+
+ it('Show Resources',{tags:['@common']}, () => {
+ cy.get('button').contains('Show Resources').click();
+ getRunningPodName(APP_NAMESPACE1).then((pod1Name) => {
+ const pods = [pod1Name]
+ cy.checkLogPods(pods);
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ cy.byTestID(TestIds.LogsTable).within(() => {
+ cy.get('td[data-label="message"]')
+ .first()
+ .within(()=> {
+ cy.get(`a[href="/k8s/cluster/namespaces/${APP_NAMESPACE1}"]`).should('exist');
+ cy.get(`a[href="/k8s/ns/${APP_NAMESPACE1}/pods/${pod1Name}"]`).should('exist');
+ cy.get(`a[href="/k8s/ns/${APP_NAMESPACE1}/pods/${pod1Name}/containers/centos-logtest"]`).should('exist')
+ });
+ });
+ });
+ });
+
+ //verify we can select both running and deleted pods
+ it('select both running and deleted pods',{tags:['@aggr']}, () => {
+ getRunningPodName(APP_NAMESPACE1).as('pod1Name');
+ cy.get('@pod1Name').then((podName) => {
+ cy.exec(`oc -n ${APP_NAMESPACE1} delete pods ${podName} --wait=true`);
+ });
+ getRunningPodName(APP_NAMESPACE1).as('pod1NewName');
+ cy.get('@pod1NewName').then((pod1NewName) => {
+ cy.exec(`oc -n ${APP_NAMESPACE1} wait pods/${pod1NewName} --for=condition=Ready`);
+ });
+
+ cy.get('@pod1Name').then((pod1Name) => {
+ cy.get('@pod1NewName').then((pod1NewName) => {
+ const pods = [pod1Name, pod1NewName]
+ cy.log(`pod1Name=${pod1Name},pod1NewName=${pod1NewName}`);
+ //cy.task('log', `pod1Name=${pod1Name} pod1NewName=${pod1NewName}`);
+ cy.checkLogPods(pods);
+ cy.showQueryInput();
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .then((val) => {
+ //{ kubernetes_pod_name=~"centos-logtest-xx|centos-logtest-yyy"
+ expect(val).to.include(pod1Name)
+ expect(val).to.include(pod1NewName)
+ });
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ const indexFields : IndexField = [
+ { name: 'openshift_log_type', value: "application" },
+ { name: 'k8s_namespace_name', value: APP_NAMESPACE1 },
+ { name: 'k8s_pod_name', value: `${pod1Name}|${pod1NewName}` },
+ ]
+ cy.assertFieldsInLogDetail(indexFields);
+ });
+ });
+ });
+
+ it('selected containers',{tags:['@aggr']}, () => {
+ const containers = ['centos-logtest']
+ cy.log(`container=centos-logtest`);
+ cy.checkLogContainers(containers);
+
+ cy.showQueryInput();
+ let pattern = /{ kubernetes_container_name="centos-logtest", kubernetes_pod_name=~"centos-logtest-\w+|centos-logtest-\w+" } | json/;
+ if (String(Cypress.env('CLUSTERLOGGING_DATAMODE')) === "otel") {
+ pattern = /{ k8s_container_name="centos-logtest", k8s_pod_name=~"centos-logtest-\w+|centos-logtest-\w+" } /;
+ }
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .should('match', pattern);
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ const indexFields : IndexField = [
+ { name: 'k8s_namespace_name', value: `${APP_NAMESPACE1}` },
+ { name: 'k8s_container_name', value: 'centos-logtest' },
+ ]
+ cy.assertFieldsInLogDetail(indexFields)
+ });
+}
+
+export function observeLogTest() {
+
+ it('Show Resources',{tags:['@common']}, () => {
+ cy.get('button').contains('Show Resources').click();
+ getRunningPodName(APP_NAMESPACE1).then((pod1Name) => {
+ const namespaces = [APP_NAMESPACE1]
+ const pods = [pod1Name]
+ cy.checkLogNamespaces(namespaces);
+ cy.checkLogPods(pods);
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ cy.byTestID(TestIds.LogsTable).within(() => {
+ cy.get('td[data-label="message"]')
+ .first()
+ .within(()=> {
+ cy.get(`a[href="/k8s/cluster/namespaces/${APP_NAMESPACE1}"]`).should('exist');
+ cy.get(`a[href="/k8s/ns/${APP_NAMESPACE1}/pods/${pod1Name}"]`).should('exist');
+ cy.get(`a[href="/k8s/ns/${APP_NAMESPACE1}/pods/${pod1Name}/containers/centos-logtest"]`).should('exist')
+ });
+ });
+ });
+ });
+
+ it('selected namespaces',{tags:['@observ']}, () => {
+ const namespaces=[APP_NAMESPACE1, APP_NAMESPACE2]
+ cy.checkLogNamespaces(namespaces);
+ cy.showQueryInput();
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .then((val) => {
+ expect(val).to.include(APP_NAMESPACE1);
+ expect(val).to.include(APP_NAMESPACE2);
+ });
+
+ const indexFields : IndexField = [
+ { name: 'openshift_log_type', value: "application" },
+ { name: 'k8s_namespace_name', value: `${APP_NAMESPACE1}|${APP_NAMESPACE2}` },
+ ]
+ cy.assertFieldsInLogDetail(indexFields)
+ });
+
+ //verify we can select both running and deleted pods
+ it('select both running and deleted pods',{tags:['@observ']}, () => {
+ getRunningPodName(APP_NAMESPACE1).as('pod1Name');
+ cy.get('@pod1Name').then((podName) => {
+ cy.exec(`oc -n ${APP_NAMESPACE1} delete pods ${podName} --wait=true`);
+ });
+ getRunningPodName(APP_NAMESPACE1).as('pod1NewName');
+ cy.get('@pod1NewName').then((pod1NewName) => {
+ cy.exec(`oc -n ${APP_NAMESPACE1} wait pods/${pod1NewName} --for=condition=Ready`);
+ });
+ getRunningPodName(APP_NAMESPACE2).as('pod2Name');
+
+ cy.get('@pod1Name').then((pod1Name) => {
+ cy.get('@pod1NewName').then((pod1NewName) => {
+ cy.get('@pod2Name').then((pod2Name) => {
+ const pods = [pod1Name, pod1NewName, pod2Name]
+ cy.log(`pod1Name=${pod1Name},pod1NewName=${pod1NewName}, pod2Name=${pod2Name}`);
+ cy.checkLogPods(pods);
+ //cy.task('log', `pod1Name=${pod1Name} pod1NewName=${pod1NewName}, pod2Name=${pod2Name} `);
+ cy.showQueryInput();
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .then((val) => {
+ //{ kubernetes_pod_name=~"centos-logtest-xx|centos-logtest-yyy|centos-logtest-zzz"
+ expect(val).to.include(pod1Name);
+ expect(val).to.include(pod1NewName);
+ expect(val).to.include(pod2Name);
+ });
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ const indexFields : IndexField = [
+ { name: 'openshift_log_type', value: "application" },
+ { name: 'k8s_namespace_name', value: `${APP_NAMESPACE1}|${APP_NAMESPACE2}` },
+ { name: 'k8s_pod_name', value: `${pod1Name}|${pod1NewName}|${pod2Name}` },
+ ]
+ cy.assertFieldsInLogDetail(indexFields);
+ });
+ });
+ });
+ });
+}
+
+export function commonTest() {
+ it('display applicatioins logs',{tags:['@common']}, () => {
+ cy.runLogQuery(`{{}kubernetes_namespace_name="${APP_NAMESPACE1}" {}}`)
+ cy.assertAppLogsInLogsTable();
+ });
+
+ // search APP_NAMESPACE1, this ensure the case succeed in Observe/Logs when there multiple namespace
+ it('Search by content ',{tags:['@common']}, () => {
+ cy.selectLogAttribute('Content');
+ cy.byTestID(TestIds.AttributeFilters).within(() => {
+ cy.get('input[aria-label="Search by Content"]')
+ .clear()
+ .type('SVTLogger', {delay: 0})
+ });
+ cy.showQueryInput();
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .should('include', 'SVTLogger')
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ cy.assertAppLogsInLogsTable();
+ })
+
+ it('filter logs by last duration ',{tags:['@common']}, () => {
+ cy.byTestID(TestIds.TimeRangeDropdown)
+ .click()
+ .within(() => {
+ cy.contains('Last 5 minutes').click();
+ });
+ cy.url().should('match', /start=now-5m&end=now/);
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ cy.assertLogsInLogsTable()
+
+ cy.byTestID(TestIds.TimeRangeDropdown)
+ .click()
+ .within(() => {
+ cy.contains('Last 2 hours').click();
+ });
+ cy.url().should('match', /start=now-2h&end=now/);
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ cy.assertLogsInLogsTable()
+
+ cy.byTestID(TestIds.TimeRangeDropdown)
+ .click()
+ .within(() => {
+ cy.contains('Last 1 day').click();
+ });
+ cy.url().should('match', /start=now-1d&end=now/);
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ cy.assertLogsInLogsTable()
+
+ cy.byTestID(TestIds.TimeRangeDropdown)
+ .click()
+ .within(() => {
+ cy.contains('Last 2 weeks').click();
+ });
+ cy.url().should('match', /start=now-2w&end=now/);
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ cy.assertLogsInLogsTable()
+ // recover to 1 hour
+ cy.byTestID(TestIds.TimeRangeDropdown)
+ .click()
+ .within(() => {
+ cy.contains('Last 1 hour').click();
+ });
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ cy.assertLogsInLogsTable()
+ });
+
+ it('filter logs by custom range',{tags:['@common']}, () => {
+ const pad = (num) => num.toString().padStart(2, '0');
+ const now = new Date();
+ // startDate = now-3day
+ const startDate = new Date(now.getTime() - 3 * 24 * 60 * 60 * 1000)
+ const startDay = `${startDate.getFullYear()}-${pad(startDate.getMonth() + 1)}-${pad(startDate.getDate())}`;
+ // endDate = now-2day
+ const endDate = new Date(now.getTime() - 2* 24 * 60 * 60 * 1000)
+ // Format as 'YYYY-MM-DD'
+ const endDay = `${endDate.getFullYear()}-${pad(endDate.getMonth() + 1)}-${pad(endDate.getDate())}`;
+ // Format as 'hh:mm'
+ const startTime = `${pad(startDate.getHours())}:${pad(startDate.getMinutes())}`;
+ const endTime = `${pad(startDate.getHours())}:${pad(startDate.getMinutes())}`;
+
+ cy.byTestID(TestIds.TimeRangeDropdown)
+ .click()
+ .within(() => {
+ cy.contains('Custom time range').click();
+ });
+ cy.byTestID(TestIds.TimeRangeSelectModal).within(() => {
+ cy.get('input[aria-label="Date picker"]').first().clear().type(`${startDay}`).blur();
+ cy.get('input[aria-label="Precision time picker"]').first().clear().type(`${startTime}{enter}`);
+
+ cy.get('input[aria-label="Date picker"]').last().clear().type(`${endDay}`).blur();
+ cy.get('input[aria-label="Precision time picker"]').last().clear().type(`${endTime}{enter}`);
+ });
+ cy.byTestID(TestIds.TimeRangeDropdownSaveButton).click();
+ cy.byTestID(TestIds.TimeRangeDropdown)
+ .within(() => {
+ cy.contains(`${startDay} ${startTime} - ${endDay} ${endTime}`);
+ });
+
+ //Remove milleseconds as we won't provide it in console
+ const start = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate(), startDate.getHours(), startDate.getMinutes())
+ const end = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate(), endDate.getHours(), endDate.getMinutes())
+ cy.url().should('match', new RegExp(`start=${start.getTime()}&end=${end.getTime()}`));
+ // recover to 1 hour
+
+ cy.byTestID(TestIds.TimeRangeDropdown)
+ .click()
+ .within(() => {
+ cy.contains('Last 1 hour').click();
+ });
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ cy.assertLogsInLogsTable()
+ });
+
+ //Check the fileds in Log detail for viaq
+ it('validate Viaq log format for container',{tags:['@common']}, function () {
+ if (String(Cypress.env('CLUSTERLOGGING_DATAMODE')) !== "viaq") {
+ this.skip();
+ }
+ const isoTimestampRegex = '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z$'
+ const timestampPattern = /^[A-Z][a-z]{2} \d{1,2}, \d{4}, \d{2}:\d{2}:\d{2}\.\d{3}$/;
+ const viaqlogFormat = '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3} - SVTLogger - INFO - .*$'
+
+ const viaqUniqueFields : IndexField = [
+ { name: '_timestamp', value: isoTimestampRegex },
+ { name: 'hostname', value: "" },
+ { name: 'message', value: "" },
+ { name: 'kubernetes_container_id', value: "" },
+ { name: 'kubernetes_container_image', value: "" },
+ { name: 'kubernetes_container_iostream', value: "" },
+ { name: 'kubernetes_pod_ip', value: "" },
+ { name: 'kubernetes_pod_id', value: "" },
+ { name: 'kubernetes_pod_owner', value: "" },
+ { name: 'kubernetes_namespace_id',value: "" },
+ { name: 'openshift_cluster_id', value: "" },
+ { name: 'openshift_sequence', value: "" },
+ { name: 'level', value: "" },
+ { name: 'log_source', value: "container" },
+ ];
+ const otelFields : IndexField = [
+ { name: 'k8s_container_name', value: "" },
+ { name: 'k8s_namespace_name', value: "" },
+ { name: 'k8s_node_name', value: "" },
+ { name: 'k8s_pod_name', value: "" },
+ { name: 'kubernetes_container_name',value: "" },
+ { name: 'kubernetes_host', value: "" },
+ { name: 'kubernetes_namespace_name', value: "" },
+ { name: 'kubernetes_pod_name', value: "" },
+ { name: 'log_type', value: "application" },
+ { name: 'openshift_log_type', value: "application" },
+ ];
+ const mergedFields = [...viaqUniqueFields, ...otelFields];
+
+ cy.showQueryInput();
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .should('include', '| json');
+
+ cy.byTestID(TestIds.LogsTable)
+ .should('exist')
+ .within(() => {
+ cy.get('td[data-label="date"]')
+ .first()
+ .invoke('text')
+ .should('match', timestampPattern);
+ cy.get('td[data-label="message"]')
+ .first()
+ .invoke('text')
+ .should('match', viaqlogFormat);
+ });
+ cy.assertFieldsInLogDetail(mergedFields)
+ });
+
+ it('validate Otel log format for container',{tags:['@common']}, function(){
+ if (String(Cypress.env('CLUSTERLOGGING_DATAMODE')) != "otel" ) {
+ this.skip();
+ }
+ const viaqUniqueFields : IndexField = [
+ { name: '_timestamp', value: isoTimestampRegex },
+ { name: 'hostname', value: "" },
+ { name: 'message', value: "" },
+ { name: 'kubernetes_container_id', value: "" },
+ { name: 'kubernetes_container_image', value: "" },
+ { name: 'kubernetes_container_iostream', value: "" },
+ { name: 'kubernetes_pod_ip', value: "" },
+ { name: 'kubernetes_pod_id', value: "" },
+ { name: 'kubernetes_pod_owner', value: "" },
+ { name: 'kubernetes_namespace_id',value: "" },
+ { name: 'openshift_cluster_id', value: "" },
+ { name: 'openshift_sequence', value: "" },
+ { name: 'level', value: "" },
+ { name: 'log_source', value: "container" },
+ ];
+ const otelFields : IndexField = [
+ { name: 'k8s_container_name', value: "" },
+ { name: 'k8s_namespace_name', value: "" },
+ { name: 'k8s_node_name', value: "" },
+ { name: 'k8s_pod_name', value: "" },
+ { name: 'kubernetes_container_name',value: "" },
+ { name: 'kubernetes_host', value: "" },
+ { name: 'kubernetes_namespace_name', value: "" },
+ { name: 'kubernetes_pod_name', value: "" },
+ { name: 'log_type', value: "application" },
+ { name: 'openshift_log_type', value: "application" },
+ ];
+
+ const timestampPattern = /^[A-Z][a-z]{2} \d{1,2}, \d{4}, \d{2}:\d{2}:\d{2}\.\d{3}$/;
+ const otellogFormat = /^\{.*"@timestamp":".+?",.*"hostname":".+?",.*"kubernetes":\{.*\},.*"level":"\w+",.*"log_source":"container",.*"log_type":"application",.*"message":".+?",.*"openshift":\{.*\}.*\}$/
+
+ cy.showQueryInput();
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .should('not.include', '| json');
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+
+ cy.byTestID(TestIds.LogsTable)
+ .should('exist')
+ .within(() => {
+ cy.get('td[data-label="date"]')
+ .first()
+ .invoke('text')
+ .should('match', timestampPattern);
+
+ cy.get('td[data-label="message"]')
+ .first()
+ .invoke('text')
+ .should('match', otellogFormat);
+
+ });
+ cy.assertFieldsInLogDetail(otelFields)
+ });
+
+ it('switch the dataFormat',{tags:['@common']}, function () {
+ if (String(Cypress.env('CLUSTERLOGGING_DATAMODE')) != "select" ) {
+ this.skip();
+ }
+ const viaqlogFormat = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3} - SVTLogger - INFO - .*$/
+ const otellogFormat = /^\{.*"@timestamp":".+?",.*"hostname":".+?",.*"kubernetes":\{.*\},.*"level":"\w+",.*"log_source":"container",.*"log_type":"application",.*"message":".+?",.*"openshift":\{.*\}.*\}$/
+
+ //default viaq
+ cy.byTestID(TestIds.SchemaToggle)
+ .invoke('text')
+ .should('eq', 'viaq');
+ cy.showQueryInput();
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .should('include', '| json');
+ cy.byTestID(TestIds.LogsTable)
+ .within(() => {
+ // Check first message matches viaqlogFormat
+ cy.get('td[data-label="message"]')
+ .first()
+ .invoke('text')
+ .should('match', viaqlogFormat);
+ });
+
+ //switch to Otel
+ cy.byTestID(TestIds.SchemaToggle).click({force: true});
+ cy.get('li')
+ .contains('button', 'otel')
+ .click();
+ cy.showQueryInput();
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .should('not.include', '| json');
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ cy.byTestID(TestIds.LogsTable)
+ .should('exist')
+ .within(() => {
+ // Check first message matches otellogFormat
+ cy.get('td[data-label="message"]')
+ .first()
+ .invoke('text')
+ .should('match', otellogFormat);
+ });
+
+ //switch back to Viaq
+ cy.byTestID(TestIds.SchemaToggle).click({force: true});
+ cy.get('li')
+ .contains('button', 'viaq')
+ .click();
+ cy.showQueryInput();
+ cy.byTestID(TestIds.LogsQueryInput)
+ .find('textarea')
+ .invoke('val')
+ .should('include', '| json');
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ cy.byTestID(TestIds.LogsTable)
+ .should('exist')
+ .within(() => {
+ cy.get('td[data-label="message"]')
+ .first()
+ .invoke('text')
+ .should('match', viaqlogFormat);
+ });
+ });
+}
diff --git a/web/cypress/fixtures/data-test.ts b/web/cypress/fixtures/data-test.ts
new file mode 100644
index 000000000..5d3479045
--- /dev/null
+++ b/web/cypress/fixtures/data-test.ts
@@ -0,0 +1,232 @@
+export const DataTestIDs = {
+ AlertCluster: 'alert-cluster',
+ AlertResourceIcon: 'alert-resource-icon',
+ AlertResourceLink: 'alert-resource-link',
+ AlertNamespace: 'alert-namespace',
+ AlertState: 'alert-state',
+ AlertSource: 'alert-source',
+ AlertingRuleArrow: 'alerting-rule-arrow',
+ AlertingRuleResourceIcon: 'alerting-rule-resource-icon',
+ AlertingRuleResourceLink: 'alerting-rule-resource-link',
+ AlertingRuleSeverityBadge: 'alerting-rule-severity-badge',
+ AlertingRuleStateBadge: 'alerting-rule-state-badge',
+ AlertingRuleTotalAlertsBadge: 'alerting-rule-total-alerts-badge',
+ LabelSuggestion: 'suggestion-line',
+ CancelButton: 'cancel-button',
+ Breadcrumb: 'breadcrumb',
+ DownloadCSVButton: 'download-csv-button',
+ EmptyBoxBody: 'empty-box-body',
+ ExpireSilenceButton: 'expire-silence-button',
+ ExpireXSilencesButton: 'expire-x-silences-button',
+ Expression: 'expression',
+ KebabDropdownButton: 'kebab-dropdown-button',
+ MastHeadHelpIcon: 'help-dropdown-toggle',
+ MastHeadApplicationItem: 'application-launcher-item',
+ MetricGraph: 'metric-graph',
+ MetricGraphNoDatapointsFound: 'datapoints-msg',
+ MetricGraphTimespanDropdown: 'graph-timespan-dropdown',
+ MetricGraphTimespanInput: 'graph-timespan-input',
+ MetricDisconnectedCheckbox: 'disconnected-checkbox',
+ MetricDropdownPollInterval: 'dropdown-poll-interval',
+ MetricGraphUnitsDropDown: 'graph-units-dropdown',
+ MetricHideShowGraphButton: 'hide-show-graph-button',
+ MetricResetZoomButton: 'reset-zoom-button',
+ MetricStackedCheckbox: 'stacked-checkbox',
+ MetricsPageActionsDropdownButton: 'actions-dropdown-button',
+ MetricsPageAddQueryButton: 'add-query-button',
+ MetricsPageAddQueryDropdownItem: 'add-query-dropdown-item',
+ MetricsPageDeleteAllQueriesDropdownItem: 'delete-all-queries-dropdown-item',
+ MetricsPageDeleteQueryDropdownItem: 'delete-query-dropdown-item',
+ MetricsPageDisableEnableQuerySwitch: 'disable-enable-query-switch',
+ MetricsPageDuplicateQueryDropdownItem: 'duplicate-query-dropdown-item',
+ MetricsPageDisableEnableQueryDropdownItem: 'disable-enable-query-dropdown-item',
+ MetricsPageExpandCollapseRowButton: 'expand-collapse-row-button', //div
+ MetricsPageExpandCollapseAllDropdownItem: 'expand-collapse-all-dropdown-item',
+ MetricsPageExportCsvDropdownItem: 'export-csv-dropdown-item',
+ MetricsPageHideShowAllSeriesDropdownItem: 'hide-show-all-series-dropdown-item',
+ MetricsPageInsertExampleQueryButton: 'insert-example-query-button',
+ MetricsPageNoQueryEnteredTitle: 'no-query-entered-title',
+ MetricsPageNoQueryEntered: 'no-query-entered',
+ MetricsPageQueryTable: 'query-table',
+ MetricsPageRunQueriesButton: 'run-queries-button',
+ MetricsPageSelectAllUnselectAllButton: 'select-all-unselect-all-button',
+ MetricsPageSeriesButton: 'series-button',
+ MetricsPageYellowNoDatapointsFound: 'yellow-no-datapoints-found',
+ NameInput: 'name-filter-input',
+ NameLabelDropdown: 'console-select-menu-toggle',
+ NamespaceDropdownMenuLink: 'dropdown-menu-item-link',
+ NameLabelDropdownOptions: 'console-select-item',
+ NamespaceDropdownShowSwitch: 'showSystemSwitch',
+ NamespaceDropdownTextFilter: 'dropdown-text-filter',
+ PersesDashboardDropdown: 'dashboard-dropdown',
+ SeverityBadgeHeader: 'severity-badge-header',
+ SeverityBadge: 'severity-badge',
+ SilenceAlertDropdownItem: 'silence-alert-dropdown-item',
+ SilenceButton: 'silence-button',
+ SilenceEditDropdownItem: 'silence-edit-dropdown-item',
+ SilenceExpireDropdownItem: 'silence-expire-dropdown-item',
+ SilenceRecreateDropdownItem: 'silence-recreate-dropdown-item',
+ SilenceResourceIcon: 'silence-resource-icon',
+ SilenceResourceLink: 'silence-resource-link',
+ SilencesPageFormTestIDs: {
+ AddLabel: 'add-label',
+ AlertLabelsDescription: 'alert-labels-description',
+ Comment: 'comment',
+ Creator: 'creator',
+ Description: 'description-header',
+ LabelName: 'label-name',
+ LabelValue: 'label-value',
+ NegativeMatcherCheckbox: 'negative-matcher-checkbox',
+ Regex: 'regex-checkbox',
+ RemoveLabel: 'remove-label',
+ SilenceFrom: 'silence-from',
+ SilenceFor: 'silence-for',
+ SilenceForToggle: 'silence-for-toggle',
+ SilenceUntil: 'silence-until',
+ StartImmediately: 'start-immediately',
+ },
+ TypeaheadSelectInput: 'query-select-typeahead-input',
+ Table: 'OUIA-Generated-Table', //table ouiaid - ID to be used with byOUIAID(DataTestIDs.Table)
+ MetricsGraphAlertDanger: 'OUIA-Generated-Alert-danger', //ID to be used with byOUIAID(DataTestIDs.MetricsGraphAlertDanger)
+
+ // Incidents Page Test IDs
+ IncidentsPage: {
+ Toolbar: 'incidents-toolbar',
+ DaysSelect: 'incidents-days-select',
+ DaysSelectToggle: 'incidents-days-select-toggle',
+ DaysSelectList: 'incidents-days-select-list',
+ DaysSelectOption: 'incidents-days-select-option',
+ FiltersSelect: 'incidents-filters-select',
+ FiltersSelectToggle: 'incidents-filters-select-toggle',
+ FiltersSelectList: 'incidents-filters-select-list',
+ FiltersSelectOption: 'incidents-filters-select-option',
+ FilterChip: 'incidents-filter-chip',
+ FilterChipRemove: 'incidents-filter-chip-remove',
+ ClearAllFiltersButton: 'incidents-clear-all-filters',
+ ToggleChartsButton: 'incidents-toggle-charts',
+ LoadingSpinner: 'incidents-loading-spinner',
+ },
+
+ // Incidents Chart Test IDs
+ IncidentsChart: {
+ Card: 'incidents-chart-card',
+ Title: 'incidents-chart-title',
+ ChartContainer: 'incidents-chart-container',
+ LoadingSpinner: 'incidents-chart-loading-spinner',
+ ChartBars: 'incidents-chart-bars',
+ ChartBar: 'incidents-chart-bar',
+ },
+
+ // Alerts Chart Test IDs
+ AlertsChart: {
+ Card: 'alerts-chart-card',
+ Title: 'alerts-chart-title',
+ EmptyState: 'alerts-chart-empty-state',
+ ChartContainer: 'alerts-chart-container',
+ ChartBar: 'alerts-chart-bar',
+ },
+
+ // Incidents Table Test IDs
+ IncidentsTable: {
+ Table: 'incidents-alerts-table',
+ ExpandButton: 'incidents-table-expand-button',
+ Row: 'incidents-table-row',
+ ComponentCell: 'incidents-table-component-cell',
+ SeverityCell: 'incidents-table-severity-cell',
+ StateCell: 'incidents-table-state-cell',
+ },
+
+ // Incidents Details Row Table Test IDs
+ IncidentsDetailsTable: {
+ Table: 'incidents-details-table',
+ LoadingSpinner: 'incidents-details-loading-spinner',
+ Row: 'incidents-details-row',
+ AlertRuleCell: 'incidents-details-alert-rule-cell',
+ NamespaceCell: 'incidents-details-namespace-cell',
+ SeverityCell: 'incidents-details-severity-cell',
+ StateCell: 'incidents-details-state-cell',
+ StartCell: 'incidents-details-start-cell',
+ EndCell: 'incidents-details-end-cell',
+ AlertRuleLink: 'incidents-details-alert-rule-link',
+ },
+};
+
+export const LegacyDashboardPageTestIDs = {
+ TimeRangeDropdown: 'time-range-dropdown', //div
+ TimeRangeDropdownOptions: 'time-range-dropdown-options',
+ PollIntervalDropdown: 'poll-interval-dropdown', //div
+ PollIntervalDropdownOptions: 'poll-interval-dropdown-options',
+ Inspect: 'inspect',
+ ExportAsCsv: 'export-as-csv',
+ DashboardDropdown: 'dashboard-dropdown', //div
+ DashboardTimeRangeDropdownMenu: 'monitoring-time-range-dropdown', //div using get('#'+LegacyDashboardPageTestIDs.DashboardTimeRangeDropdownMenu)
+ DashboardRefreshIntervalDropdownMenu: 'refresh-interval-dropdown', //div using get('#'+LegacyDashboardPageTestIDs.DashboardRefreshIntervalDropdownMenu)
+ Graph: 'graph',
+};
+
+export const LegacyTestIDs = {
+ ItemFilter: 'item-filter',
+ SelectAllSilencesCheckbox: 'select-all-silences-checkbox',
+ PersesDashboardSection: 'dashboard',
+ NamespaceBarDropdown: 'namespace-bar-dropdown',
+};
+
+export const IDs = {
+ ChartAxis0ChartLabel: 'chart-axis-0-ChartLabel', //id^=IDs.ChartAxis0ChartLabel AxisX
+ ChartAxis1ChartLabel: 'chart-axis-1-ChartLabel', //id^=IDs.ChartAxis1ChartLabel AxisY
+};
+
+export const Classes = {
+ ExpandedRow: 'button[class="pf-v6-c-button pf-m-plain pf-m-expanded"]',
+ ToExpandRow: 'button[class="pf-v6-c-button pf-m-plain"]',
+ FilterDropdown: '.pf-v6-c-menu-toggle, .pf-v5-c-menu-toggle',
+ FilterDropdownExpanded: '.pf-v6-c-menu-toggle.pf-m-expanded, .pf-v5-c-menu-toggle.pf-m-expanded',
+ FilterDropdownOption: '.pf-v6-c-menu__item, .pf-c-select__menu-item',
+ GraphCardInlineInfo:
+ '.pf-v6-c-alert.pf-m-inline.pf-m-plain.pf-m-info, .pf-v5-c-alert.pf-m-inline.pf-m-plain.pf-m-info.query-browser__reduced-resolution',
+ HorizontalNav: '.pf-v6-c-tabs__item, .co-m-horizontal-nav__menu-item',
+ IndividualTag: '.pf-v6-c-label__text, .pf-v5-c-chip__text',
+ LabelTag: '.pf-v6-c-label__text, .pf-v5-c-label__text',
+ MainTag: '.pf-v6-c-label-group__label, .pf-v5-c-chip-group__label',
+ MenuItem: '.pf-v6-c-menu__item, .pf-c-dropdown__menu-item',
+ MenuItemDisabled: '.pf-v6-c-menu__list-item.pf-m-aria-disabled',
+ MenuToggle: '.pf-v6-c-menu-toggle, .pf-c-dropdown__toggle',
+ MetricsPagePredefinedQueriesMenuItem: '.pf-v6-c-menu__item, .pf-v5-c-select__menu-item',
+ MetricsPageRows: '.pf-v6-c-data-list.pf-m-grid-md',
+ MetricsPageExpandedRowIcon: '.pf-v6-c-data-list__item.pf-m-expanded', //li
+ MetricsPageCollapsedRowIcon: '.pf-v6-c-data-list__item', //li
+ MetricsPageQueryInput: '.cm-content.cm-lineWrapping',
+ MetricsPageUngraphableResults: '.pf-v6-c-title.pf-m-md',
+ MetricsPageUngraphableResultsDescription: '.pf-v6-c-empty-state__body',
+ MetricsPageQueryAutocomplete: '.cm-tooltip-autocomplete.cm-tooltip.cm-tooltip-below',
+ MoreLessTag: '.pf-v6-c-label-group__label, .pf-v5-c-chip-group__label',
+ NamespaceDropdown: '.pf-v6-c-menu-toggle.co-namespace-dropdown__menu-toggle',
+ SectionHeader: '.pf-v6-c-title.pf-m-h2, .co-section-heading',
+ TableHeaderColumn: '.pf-v6-c-table__button, .pf-c-table__button',
+ SilenceAlertTitle: '.pf-v6-c-alert__title, .pf-v5-c-alert__title',
+ SilenceAlertDescription: '.pf-v6-c-alert__description, .pf-v5-c-alert__description',
+ SilenceCommentWithoutError: '.pf-v6-c-form-control.pf-m-textarea.pf-m-resize-both',
+ SilenceCommentWithError: '.pf-v6-c-form-control.pf-m-textarea.pf-m-resize-both.pf-m-error',
+ SilenceCreatorWithError: '.pf-v6-c-form-control.pf-m-error',
+ SilenceHelpText: '.pf-v6-c-helper-text__item-text, .pf-v5-c-helper-text__item-text',
+ SilenceKebabDropdown: '.pf-v6-c-menu-toggle.pf-m-plain, .pf-v5-c-dropdown__toggle.pf-m-plain',
+ SilenceLabelRow: '.pf-v6-l-grid.pf-m-all-12-col-on-sm.pf-m-all-4-col-on-md.pf-m-gutter, .row',
+ SilenceState: '.pf-v6-l-stack__item, .co-break-word',
+ LogDetail: 'pf-v5-c-table__td lv-plugin__table__details',
+ LogToolbar: 'pf-v5-c-toolbar__content-section',
+};
+
+export const persesAriaLabels = {
+ TimeRangeDropdown: 'Select time range. Currently set to [object Object]',
+ RefreshButton: 'Refresh',
+ RefreshIntervalDropdown: 'Select refresh interval. Currently set to 0s',
+ ZoomInButton: 'Zoom in',
+ ZoomOutButton: 'Zoom out',
+};
+
+export const persesDataTestIDs = {
+ variableDropdown: 'variable',
+ panelGroupHeader: 'panel-group-header',
+ panelHeader: 'panel',
+};
+
diff --git a/web/cypress/support/commands.ts b/web/cypress/support/commands.ts
deleted file mode 100644
index 123a73aa7..000000000
--- a/web/cypress/support/commands.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-/* eslint-disable @typescript-eslint/no-namespace */
-///
-import { TestIds } from '../../src/test-ids';
-
-declare global {
- namespace Cypress {
- interface Chainable {
- getByTestId(testId: TestIds): Chainable>;
- }
- }
-}
-
-Cypress.Commands.add('getByTestId', (testId: TestIds) => cy.get(`[data-test="${testId}"]`));
diff --git a/web/cypress/support/commands/auth-commands.ts b/web/cypress/support/commands/auth-commands.ts
new file mode 100644
index 000000000..2988f68c0
--- /dev/null
+++ b/web/cypress/support/commands/auth-commands.ts
@@ -0,0 +1,215 @@
+import { nav } from '../../views/nav';
+import { guidedTour } from '../../views/tour';
+
+
+
+export {};
+declare global {
+ namespace Cypress {
+ interface Chainable {
+ switchPerspective(perspective: string);
+ uiLogin(provider: string, username: string, password: string, oauthurl?: string);
+ uiLogout();
+ cliLogin(username?, password?, hostapi?);
+ cliLogout();
+ login(provider?: string, username?: string, password?: string, oauthurl?: string): Chainable;
+ loginNoSession(provider: string, username: string, password: string, oauthurl: string): Chainable;
+ adminCLI(command: string, options?);
+ executeAndDelete(command: string);
+ validateLogin(): Chainable;
+ }
+ }
+}
+
+
+ // Core login function (used by both session and non-session versions)
+ function performLogin(
+ provider: string,
+ username: string,
+ password: string,
+ oauthurl: string
+ ): void {
+ cy.visit(Cypress.config('baseUrl'));
+ cy.log('Session - after visiting');
+ cy.window().then(
+ (
+ win: any, // eslint-disable-line @typescript-eslint/no-explicit-any
+ ) => {
+ // Check if auth is disabled (for a local development environment)
+ if (win.SERVER_FLAGS?.authDisabled) {
+ cy.task('log', ' skipping login, console is running with auth disabled');
+ return;
+ }
+ cy.exec(
+ `oc get node --selector=hypershift.openshift.io/managed --kubeconfig ${Cypress.env('KUBECONFIG_PATH')}`,
+ ).then((result) => {
+ cy.log(result.stdout);
+ cy.task('log', result.stdout);
+ if (result.stdout.includes('Ready')) {
+ cy.log(`Attempting login via cy.origin to: ${oauthurl}`);
+ cy.task('log', `Attempting login via cy.origin to: ${oauthurl}`);
+ cy.origin(
+ oauthurl,
+ { args: { username, password } },
+ ({ username, password }) => {
+ cy.get('#inputUsername').type(username);
+ cy.get('#inputPassword').type(password);
+ cy.get('button[type=submit]').click();
+ },
+ );
+ } else {
+ cy.task('log', ` Logging in as ${username} using fallback on ${oauthurl}`);
+ cy.origin(
+ oauthurl,
+ { args: { provider, username, password } },
+ ({ provider, username, password }) => {
+ cy.get('[data-test-id="login"]').should('be.visible');
+ cy.get('body').then(($body) => {
+ if ($body.text().includes(provider)) {
+ cy.contains(provider).should('be.visible').click();
+ }
+ });
+ cy.get('#inputUsername').type(username);
+ cy.get('#inputPassword').type(password);
+ cy.get('button[type=submit]').click();
+ }
+ );
+ }
+ });
+ },
+ );
+ }
+
+ Cypress.Commands.add('validateLogin', () => {
+ cy.visit('/');
+ cy.wait(2000);
+ cy.byTestID("username", {timeout: 120000}).should('be.visible');
+ guidedTour.close();
+ });
+
+ // Session-wrapped login
+ Cypress.Commands.add(
+ 'login',
+ (
+ provider: string = Cypress.env('LOGIN_IDP'),
+ username: string = Cypress.env('LOGIN_USERNAME'),
+ password: string = Cypress.env('LOGIN_PASSWORD'),
+ oauthurl: string,
+ ) => {
+ cy.session(
+ [provider, username],
+ () => {
+ performLogin(provider, username, password, oauthurl);
+ },
+ {
+ cacheAcrossSpecs: true,
+ validate() {
+ cy.validateLogin();
+ },
+ },
+ );
+ },
+ );
+
+ // Non-session login (for use within sessions)
+ Cypress.Commands.add('loginNoSession', (provider: string, username: string, password: string, oauthurl: string) => {
+ performLogin(provider, username, password, oauthurl);
+ cy.validateLogin();
+ });
+
+ Cypress.Commands.add('switchPerspective', (perspective: string) => {
+ /* If side bar is collapsed then expand it
+ before switching perspecting */
+ cy.wait(2000);
+ cy.get('body').then((body) => {
+ if (body.find('.pf-m-collapsed').length > 0) {
+ cy.get('#nav-toggle').click();
+ }
+ });
+ nav.sidenav.switcher.changePerspectiveTo(perspective);
+ });
+
+ // To avoid influence from upstream login change
+ Cypress.Commands.add('uiLogin', (provider: string, username: string, password: string) => {
+ cy.log('Commands uiLogin');
+ cy.clearCookie('openshift-session-token');
+ cy.visit('/');
+ cy.window().then(
+ (
+ win: any, // eslint-disable-line @typescript-eslint/no-explicit-any
+ ) => {
+ if (win.SERVER_FLAGS?.authDisabled) {
+ cy.task('log', 'Skipping login, console is running with auth disabled');
+ return;
+ }
+ cy.get('[data-test-id="login"]').should('be.visible');
+ cy.get('body').then(($body) => {
+ if ($body.text().includes(provider)) {
+ cy.contains(provider).should('be.visible').click();
+ } else if ($body.find('li.idp').length > 0) {
+ //Using the last idp if doesn't provider idp name
+ cy.get('li.idp').last().click();
+ }
+ });
+ cy.get('#inputUsername').type(username);
+ cy.get('#inputPassword').type(password);
+ cy.get('button[type=submit]').click();
+ cy.byTestID('username', { timeout: 120000 }).should('be.visible');
+ },
+ );
+ cy.switchPerspective('Administrator');
+ });
+
+ Cypress.Commands.add('uiLogout', () => {
+ cy.window().then(
+ (
+ win: any, // eslint-disable-line @typescript-eslint/no-explicit-any
+ ) => {
+ if (win.SERVER_FLAGS?.authDisabled) {
+ cy.log('Skipping logout, console is running with auth disabled');
+ return;
+ }
+ cy.log('Log out UI');
+ cy.byTestID('username').click();
+ cy.byTestID('log-out').should('be.visible');
+ cy.byTestID('log-out').click({ force: true });
+ },
+ );
+ });
+
+ Cypress.Commands.add('cliLogin', (username?, password?, hostapi?) => {
+ const loginUsername = username || Cypress.env('LOGIN_USERNAME');
+ const loginPassword = password || Cypress.env('LOGIN_PASSWORD');
+ const hostapiurl = hostapi || Cypress.env('HOST_API');
+ cy.exec(
+ `oc login -u ${loginUsername} -p ${loginPassword} ${hostapiurl} --insecure-skip-tls-verify=true`,
+ { failOnNonZeroExit: false },
+ ).then((result) => {
+ cy.log(result.stderr);
+ cy.log(result.stdout);
+ });
+ });
+
+ Cypress.Commands.add('cliLogout', () => {
+ cy.exec(`oc logout`, { failOnNonZeroExit: false }).then((result) => {
+ cy.log(result.stderr);
+ cy.log(result.stdout);
+ });
+ });
+
+ Cypress.Commands.add('adminCLI', (command: string) => {
+ const kubeconfig = Cypress.env('KUBECONFIG_PATH');
+ cy.log(`Run admin command: ${command}`);
+ cy.exec(`${command} --kubeconfig ${kubeconfig}`);
+ });
+
+ Cypress.Commands.add('executeAndDelete', (command: string) => {
+ cy.exec(command, { failOnNonZeroExit: false })
+ .then(result => {
+ if (result.code !== 0) {
+ cy.task('logError', `Command "${command}" failed: ${result.stderr || result.stdout}`);
+ } else {
+ cy.task('log', `Command "${command}" executed successfully`);
+ }
+ });
+ });
diff --git a/web/cypress/support/commands/log-commands.ts b/web/cypress/support/commands/log-commands.ts
new file mode 100644
index 000000000..66260f039
--- /dev/null
+++ b/web/cypress/support/commands/log-commands.ts
@@ -0,0 +1,453 @@
+/* eslint-disable @typescript-eslint/no-namespace */
+///
+import 'cypress-wait-until';
+import { guidedTour } from '../../views/tour';
+import { TestIds } from '../../../src/test-ids';
+import { Classes } from '../../fixtures/data-test';
+import * as helperfuncs from '../views/utils';
+
+declare global {
+ namespace Cypress {
+ interface IndexField {
+ name: string;
+ value?: string;
+ }
+ interface Chainable {
+ cliLoginUser(rank: string);
+ uiLoginUser(rank: string);
+ uiLogoutAsUser(rank: string);
+ uiLoginAsClusterAdmin(rank: string);
+ uiLogoutClusterAdmin(rank: string);
+ switchToDevConsole();
+ switchToAdmConsole();
+ uiImpersonate(rank: string);
+ grantViewLogRoles(rank: string, project: string);
+ removeLogViewRoles(rank: string, project: string);
+ showQueryInput();
+ closeQueryInput();
+ runLogQuery(logQL: string);
+ assertLogsInLogsTable();
+ assertFieldsInLogDetail(indexFields: IndexField[]): Chainable;
+ assertAppLogsInLogsTable();
+ assertInfraLogsInLogsTable();
+ assertAuditLogsInLogsTable();
+ selectLogTenant(tenant: string);
+ selectLogAttribute(attribute: string);
+ checkLogNamespaces(namespaces: string[]);
+ checkLogPods(pods: string[]);
+ checkLogContainers(containers: string[]);
+ showAdminConsolePodAggrLog(projectName: string , podName?: string);
+ showDevConsolePodAggrLog(projectName: string , podName?: string);
+ waitUntilLogsInLokiStack(query?: string);
+ }
+ }
+}
+
+const admin_kubeconfig = Cypress.env('KUBECONFIG_PATH');
+const normal_kubeconfig = "/tmp/logging_ui_kubeconfig"
+const oauth_url = Cypress.config('baseUrl').replace("console-openshift-console", "oauth-openshift")
+const rank_2_num = {
+ "first_user": 0,
+ "second_user": 1,
+ "third_user": 2,
+ "fourth_user": 3,
+ "fifth_user": 4,
+};
+
+Cypress.Commands.add('getByTestId', (testId: TestIds) => cy.get(`[data-test="${testId}"]`));
+
+Cypress.Commands.add("getLogToolbar", () => {
+ cy.byClass(Classes.LogToolbar);
+})
+
+Cypress.Commands.add("showQueryInput", () => {
+ cy.byTestID(TestIds.ShowQueryToggle).then(($btn) => {
+ if ($btn.text().includes('Show Query')) {
+ cy.wrap($btn).click({ force: true });
+ }
+ });
+})
+
+Cypress.Commands.add("closeQueryInput", () => {
+ cy.byTestID(TestIds.ShowQueryToggle).then(($btn) => {
+ if ($btn.text().includes('Hide Query')) {
+ cy.wrap($btn).click({ force: true });
+ }
+ });
+})
+
+Cypress.Commands.add("runLogQuery", (logQL: string) => {
+ cy.showQueryInput();
+ cy.getByTestId(TestIds.LogsQueryInput)
+ .find('textarea')
+ .type(`{selectall}${logQL}`, { delay: 0 })
+ .then(() => {
+ cy.byTestID(TestIds.ExecuteQueryButton).click();
+ });
+})
+
+Cypress.Commands.add("switchToDevConsole",() => {
+ cy.switchPerspective('Developer');
+ guidedTour.close();
+})
+
+Cypress.Commands.add("switchToAdmConsole",() => {
+ cy.exec(`oc get console.operator cluster -o jsonpath='{.spec.customization.perspectives}'`).then((result) => {
+ if (!result.stdout.includes('{"state":"Enabled"}')){
+ cy.log('no customization.perspectives is enabled');
+ }else{
+ switch (String(Cypress.env('OPENSHIFT_VERSION'))) {
+ case '4.12':
+ case '4.13':
+ case '4.14':
+ case '4.15':
+ case '4.16':
+ case '4.17':
+ case '4.18':
+ case '4.19':
+ case '4.20':
+ cy.switchPerspective('Administrator');
+ break
+ default:
+ cy.switchPerspective('Core platform');
+ }
+ }
+ })
+ guidedTour.close();
+})
+
+//login user using cli.
+Cypress.Commands.add('cliLoginUser', (rank: string) => {
+ cy.log(`login ${rank}`);
+ let username="";
+ let userpassword="";
+ cy.readFile(admin_kubeconfig)
+ .then(content => cy.writeFile(normal_kubeconfig, content));
+
+ if (Cypress.env('LOGIN_USERS')){
+ username=Cypress.env('LOGIN_USERS').split(',')[rank_2_num[rank]].split(':')[0];
+ userpassword=Cypress.env('LOGIN_USERS').split(',')[rank_2_num[rank]].split(':')[1];
+ }
+ if( username != "" && userpassword != "" ){
+ cy.exec(`oc login -u ${username} -p ${userpassword} --kubeconfig=${normal_kubeconfig}`);
+ }else{
+ cy.log('no user can be found.');
+ cy.exit();
+ }
+})
+
+//Login user as the cluster-admin
+//Rank: first_user, second_user ... five_user
+Cypress.Commands.add('uiLoginAsClusterAdmin', (rank: string) => {
+ let username="";
+ let userpassword="";
+ if (Cypress.env('LOGIN_USERS')){
+ username=Cypress.env('LOGIN_USERS').split(',')[rank_2_num[rank]].split(':')[0];
+ userpassword=Cypress.env('LOGIN_USERS').split(',')[rank_2_num[rank]].split(':')[1];
+ }
+ if( username != "" && userpassword != "" && Cypress.env('LOGIN_IDP') != "" ){
+ cy.adminCLI(`oc adm policy add-cluster-role-to-user cluster-admin ${username}`);
+ cy.login(Cypress.env('LOGIN_IDP'), username, userpassword, oauth_url);
+ guidedTour.close()
+ }else{
+ cy.log('no user can be found.');
+ cy.exit();
+ }
+})
+
+//Login a user from LOGIN_USERS=test1:passwd,user2,passwd,user2:pasword,...
+Cypress.Commands.add('uiLoginUser', (rank: string) => {
+ let username="";
+ let userpassword="";
+ if (Cypress.env('LOGIN_USERS')){
+ username=Cypress.env('LOGIN_USERS').split(',')[rank_2_num[rank]].split(':')[0];
+ userpassword=Cypress.env('LOGIN_USERS').split(',')[rank_2_num[rank]].split(':')[1];
+ }
+ if( username != "" && userpassword != "" && Cypress.env('LOGIN_IDP') != "" ){
+ cy.login(Cypress.env('LOGIN_IDP'), username, userpassword, oauth_url);
+ guidedTour.close()
+ }else{
+ cy.log('no user can be found.');
+ cy.exit();
+ }
+})
+
+//Allow user to view observe/logs,alerts
+Cypress.Commands.add('grantLogViewRoles', (rank: string, project: string) => {
+ let username="";
+ if (Cypress.env('LOGIN_USERS')){
+ username=Cypress.env('LOGIN_USERS').split(',')[rank_2_num[rank]].split(':')[0];
+ if( username != "" ){
+ cy.exec(`oc -n ${project} policy add-role-to-user view ${username}`);
+ cy.exec(`oc -n ${project} policy add-role-to-user cluster-logging-application-view ${username}`);
+ cy.exec(`oc -n ${project} policy add-role-to-user monitoring-rules-edit ${username}`);
+ cy.exec(`oc -n ${project} policy add-role-to-user cluster-monitoring-view ${username}`);
+ }else{
+ cy.log(`can not find the ${rank}.`);
+ cy.exit();
+ }
+ }
+})
+
+//Remove observe/logs,alerts roles from the user
+Cypress.Commands.add('removeLogViewRoles', (rank: string, project: string) => {
+ let username="";
+ if (Cypress.env('LOGIN_USERS')){
+ username=Cypress.env('LOGIN_USERS').split(',')[rank_2_num[rank]].split(':')[0];
+ if( username != "" ){
+ cy.exec(`oc -n ${project} policy remove-role-from-user view ${username}`);
+ cy.exec(`oc -n ${project} policy remove-role-from-user cluster-logging-application-view ${username}`);
+ cy.exec(`oc -n ${project} policy remove-role-from-user monitoring-rules-edit ${username}`);
+ cy.exec(`oc -n ${project} policy remove-role-from-user cluster-monitoring-view ${username}`);
+ }else{
+ cy.log(`can not find the ${rank}.`);
+ cy.exit();
+ }
+ }
+})
+
+Cypress.Commands.add('uiLogoutUser', (rank: string) => {
+ cy.log('Logout user');
+ let username = "";
+ if (Cypress.env('LOGIN_USERS')){
+ username=Cypress.env('LOGIN_USERS').split(',')[rank_2_num[rank]].split(':')[0];
+ }
+ cy.uiLogout();
+})
+
+Cypress.Commands.add('uiLogoutClusterAdmin', (rank: string) => {
+ cy.log('Remove the cluster Admin role and Logout');
+ let username = "";
+ if (Cypress.env('LOGIN_USERS')){
+ username=Cypress.env('LOGIN_USERS').split(',')[rank_2_num[rank]].split(':')[0];
+ }
+ if( username != "" ){
+ cy.adminCLI(`oc adm policy remove-cluster-role-from-user cluster-admin ${username}`);
+ }
+ cy.uiLogout();
+})
+
+Cypress.Commands.add('uiImpersonateUser', (rank: string) => {
+ let username = "";
+ if (Cypress.env('LOGIN_USERS')){
+ username=Cypress.env('LOGIN_USERS').split(',')[rank_2_num[rank]].split(':')[0];
+ }
+ if( username == "" ){
+ cy.log(`can not find the ${rank}.`);
+ this.skip();
+ }
+ let fullusername=Cypress.env('LOGIN_IDP') + ":" + username
+
+ cy.switchToAdmConsole();
+ //cy.visit("/k8s/cluster/user.openshift.io~v1~User", { timeout: 120000 } );
+ cy.clickNavLink(['User Management', 'Users']);
+ //We can check if User Table exist or not in 4.22+
+ //cy.get(`table[aria-label="Users table"]`, { timeout: 120000 } ).should('exist');
+ cy.contains('td', fullusername, { timeout: 120000 } )
+ .closest('tr')
+ .find('button[data-test-id="kebab-button"]')
+ .click();
+ cy.contains('button', 'Impersonate User').click();
+ //find the username to see if Impersonate User succeed or not
+ cy.contains('[data-test="username"]', `${username}`).should('exist')
+
+ //Close guide tour bar
+ guidedTour.close()
+})
+
+Cypress.Commands.add('assertLogsInLogsTable', () => {
+ // Ensure the table has loaded rows
+ cy.getByTestId(TestIds.LogsTable).within(() => {
+ cy.get('tr[data-test-rows="resource-row" ]').first().within(() => {
+ cy.get('td[data-label="date"]').should('exist');
+ cy.get('td[data-label="message"]').should('exist');
+ });
+ //there are more than one row
+ cy.get('tr[data-test-rows="resource-row" ]')
+ .its('length')
+ .should('be.gt', 1);
+ });
+})
+
+//Expand the the first row and check the expected fields in the log detail
+//the filed value can be value, empty or pattern
+Cypress.Commands.add('assertFieldsInLogDetail', (indexFields: IndexField[]) => {
+
+ cy.getByTestId(TestIds.LogsTable).within(() => {
+ //there are more than one row in tables
+ cy.get('tr[data-test-rows="resource-row"]')
+ .its('length')
+ .should('be.gt', 1);
+
+ //show the detail table
+ cy.get('tr[data-test-rows="resource-row"]')
+ .first()
+ .find('td')
+ .first()
+ .find('button')
+ .then(($btn) => {
+ if ($btn.attr('aria-expanded') !== 'true') {
+ cy.wrap($btn).click({force: true});
+ }
+ })
+
+ // check the fields in detail
+ cy.byClass(Classes.LogDetail)
+ .within(() => {
+ indexFields.forEach(field => {
+ if (!Cypress._.isEmpty(field.value)) { // skip if value is empty, null, or undefined
+ let pattern = new RegExp(field.value);
+ cy.contains('dt', field.name)
+ .parent()
+ .within(() => {
+ cy.get('dd')
+ .invoke('text')
+ .should('match',pattern)
+ });
+ }
+ else{
+ cy.contains('dt', field.name)
+ }
+ });
+ });
+ });
+})
+
+Cypress.Commands.add('assertAppLogsInLogsTable', () => {
+ //only check some of these index fileds
+ const indexFields : IndexField = [
+ { name: 'openshift_log_type', value: 'application' },
+ { name: 'k8s_pod_name', value: '' },
+ { name: 'k8s_namespace_name', value: '' },
+ { name: 'k8s_node_name', value: '' },
+ ]
+ cy.assertFieldsInLogDetail(indexFields);
+})
+
+Cypress.Commands.add('assertInfraLogsInLogsTable', () => {
+ //only check some of these index fileds
+ const indexFields : IndexField = [
+ { name: 'openshift_log_type', value: 'infrastructure' },
+ ]
+ cy.assertFieldsInLogDetail(indexFields);
+})
+
+Cypress.Commands.add('assertAuditLogsInLogsTable', () => {
+ //only check some of these index fileds
+ const indexFields : IndexField = [
+ { name: 'openshift_log_type', value: 'audit' }
+ ]
+ cy.assertFieldsInLogDetail(indexFields);
+})
+
+//select a tenant for logs
+Cypress.Commands.add('selectLogTenant', (tenant: string) => {
+ cy.byTestID(TestIds.TenantToggle).click();
+ cy.get('#logging-view-tenant-dropdown')
+ .contains('button', tenant)
+ .click();
+ //close the dropdown list
+ cy.get('body').click(0, 0);
+})
+
+//select one Attribute in AttributeFilters
+Cypress.Commands.add('selectLogAttribute', (attribute: string) => {
+ cy.byTestID(TestIds.AvailableAttributes).click();
+ cy.byTestID(TestIds.AttributeFilters)
+ .contains('button', attribute)
+ .click();
+ //close the dropdown list
+ cy.get('body').click(0, 0);
+})
+
+//select options from AttributeOptions dropbox
+Cypress.Commands.add('checkLogDropboxOptions', (opts: string[]) => {
+ opts.forEach((opt) => {
+ cy.byTestID(TestIds.AttributeOptions)
+ .find('input[type="text"]') // input the expected options
+ .click()
+ .clear()
+ .type(opt);
+ cy.byTestID(TestIds.AttributeFilters, { timeout: 20000 }).within(() => {
+ cy.contains('[role="listbox"] li', opt, { timeout: 20000 , includeShadowDom: true })
+ .scrollIntoView() // in case it's offscreen
+ .find('input[type="checkbox"]')
+ .check({ force: true }) // safe: never unchecks if already checked
+ .should('be.checked')
+ });
+ });
+ //close the dropdown panel
+ cy.get('body').click(0, 0);
+})
+
+//select namespaces from AttributeOptions
+Cypress.Commands.add('checkLogNamespaces', (namespaces: string[]) => {
+ cy.selectLogAttribute('Namespaces');
+ cy.checkLogDropboxOptions(namespaces);
+})
+
+//select pods from AttributeOptions
+Cypress.Commands.add('checkLogPods', (pods: string[]) => {
+ cy.selectLogAttribute('Pods');
+ cy.checkLogDropboxOptions(pods);
+})
+
+//select Containers from AttributeOptions
+Cypress.Commands.add('checkLogContainers', (containers: string[]) => {
+ cy.selectLogAttribute('Containers');
+ cy.checkLogDropboxOptions(containers);
+})
+
+//if no podName, will click the first pod
+Cypress.Commands.add('clickPodLink', (podName?: string) => {
+ const name = podName ?? '.*'
+ const pattern = new RegExp(`/k8s/ns/.*/pods/${name}`)
+ cy.get('td a')
+ .filter((_, a) => a.href.match(pattern))
+ .first() // pick the first match only
+ .click();
+})
+
+//Show the AdminConsole pod logs in one project
+Cypress.Commands.add('showAdminConsolePodAggrLog', (projectName: string , podName?: string) => {
+ //navigate to Workloads->Pods
+ cy.clickNavLink(['Workloads','Pods']);
+ //select namespace
+ cy.changeNamespace(projectName);
+ //select the first pod matching the podName
+ if (!podName) {
+ cy.clickPodLink();
+ }else {
+ cy.clickPodLink(name);
+ }
+ cy.byLegacyTestID('horizontal-link-Aggregated Logs').click();
+})
+
+//Show the devConsole pod logs in one project
+Cypress.Commands.add('showDevConsolePodAggrLog', (projectName: string , podName?: string) => {
+ //navigate to Project page
+ cy.clickNavLink(['Project']);
+ //select namespace
+ cy.changeNamespace(projectName);
+ //navigate pods page in the project
+ cy.get(`a[data-test="resource-inventory-item"][href="/k8s/ns/${projectName}/pods"]`)
+ .scrollIntoView()
+ .click({ force: true });
+ //select the first pod matching the podName
+ if (!podName) {
+ cy.clickPodLink();
+ }else {
+ cy.clickPodLink(name);
+ }
+ cy.byLegacyTestID('horizontal-link-Aggregated Logs').click();
+})
+
+//ensure the logs in lokistack before use it in UI
+Cypress.Commands.add('waitUntilLogsInLokiStack', (query?: string) => {
+ cy.exec(`./cypress/support/scripts/findLogsInLokistack.sh '${query}'`, { failOnNonZeroExit: false })
+ .then(({ code, stdout }) => {
+ cy.log(stdout)
+ expect(code === 0).to.be.true
+ });
+})
+
diff --git a/web/cypress/support/commands/selector-commands.ts b/web/cypress/support/commands/selector-commands.ts
new file mode 100644
index 000000000..f397b8c79
--- /dev/null
+++ b/web/cypress/support/commands/selector-commands.ts
@@ -0,0 +1,116 @@
+import Loggable = Cypress.Loggable;
+import Timeoutable = Cypress.Timeoutable;
+import Withinable = Cypress.Withinable;
+import Shadow = Cypress.Shadow;
+
+export {};
+
+declare global {
+ namespace Cypress {
+ interface Chainable {
+ byTestID(
+ selector: string,
+ options?: Partial,
+ ): Chainable;
+ byTestActionID(selector: string): Chainable>;
+ byLegacyTestID(
+ selector: string,
+ options?: Partial,
+ ): Chainable>;
+ byButtonText(selector: string): Chainable>;
+ byDataID(selector: string): Chainable>;
+ byTestSelector(
+ selector: string,
+ options?: Partial,
+ ): Chainable>;
+ byTestDropDownMenu(selector: string): Chainable>;
+ byTestOperatorRow(
+ selector: string,
+ options?: Partial,
+ ): Chainable>;
+ byTestSectionHeading(selector: string): Chainable>;
+ byTestOperandLink(selector: string): Chainable>;
+ byOUIAID(selector: string): Chainable;
+ byClass(selector: string): Chainable;
+ bySemanticElement(element: string, text?: string): Chainable>;
+ byAriaLabel(label: string, options?: Partial): Chainable>;
+ byPFRole(role: string, options?: Partial): Chainable>;
+ }
+ }
+}
+
+
+Cypress.Commands.add(
+ 'byTestID',
+ (selector: string, options?: Partial) => {
+ cy.get(`[data-test="${selector}"]`, options);
+ },
+ );
+
+ Cypress.Commands.add('byTestActionID', (selector: string) =>
+ cy.get(`[data-test-action="${selector}"]:not([disabled])`),
+ );
+
+ // Deprecated! new IDs should use 'data-test', ie. `cy.byTestID(...)`
+ Cypress.Commands.add(
+ 'byLegacyTestID',
+ (selector: string, options?: Partial) => {
+ cy.get(`[data-test-id="${selector}"]`, options);
+ },
+ );
+
+ Cypress.Commands.add('byButtonText', (selector: string) => {
+ cy.get('button[type="button"]').contains(`${selector}`);
+ });
+
+ Cypress.Commands.add('byDataID', (selector: string) => {
+ cy.get(`[data-id="${selector}"]`);
+ });
+
+ Cypress.Commands.add(
+ 'byTestSelector',
+ (selector: string, options?: Partial) => {
+ cy.get(`[data-test-selector="${selector}"]`, options);
+ },
+ );
+
+ Cypress.Commands.add('byTestDropDownMenu', (selector: string) => {
+ cy.get(`[data-test-dropdown-menu="${selector}"]`);
+ });
+
+ Cypress.Commands.add('byTestOperatorRow', (selector: string, options?: object) => {
+ cy.get(`[data-test-operator-row="${selector}"]`, options);
+ });
+
+ Cypress.Commands.add('byTestSectionHeading', (selector: string) => {
+ cy.get(`[data-test-section-heading="${selector}"]`);
+ });
+
+ Cypress.Commands.add('byTestOperandLink', (selector: string) => {
+ cy.get(`[data-test-operand-link="${selector}"]`);
+ });
+
+ Cypress.Commands.add('byOUIAID', (selector: string) => cy.get(`[data-ouia-component-id^="${selector}"]`));
+
+ Cypress.Commands.add('byClass', (selector: string) => cy.get(`[class="${selector}"]`));
+
+ Cypress.Commands.add('bySemanticElement', (element: string, text?: string) => {
+ if (text) {
+ return cy.get(element).contains(text);
+ }
+ return cy.get(element);
+ });
+
+ Cypress.Commands.add(
+ 'byAriaLabel',
+ (label: string, options?: Partial) => {
+ return cy.get(`[aria-label="${label}"]`, options);
+ }
+ );
+
+ Cypress.Commands.add(
+ 'byPFRole',
+ (role: string, options?: Partial) => {
+ return cy.get(`[role="${role}"]`, options);
+ }
+ );
diff --git a/web/cypress/support/commands/utility-commands.ts b/web/cypress/support/commands/utility-commands.ts
new file mode 100644
index 000000000..40f8f8329
--- /dev/null
+++ b/web/cypress/support/commands/utility-commands.ts
@@ -0,0 +1,142 @@
+import { Classes, DataTestIDs, LegacyTestIDs } from "../../fixtures/data-test";
+export {};
+
+declare global {
+ namespace Cypress {
+ interface Chainable {
+ waitUntilWithCustomTimeout(
+ fn: () => any,
+ options: { interval: number; timeout: number; timeoutMessage: string }
+ ): Cypress.Chainable;
+ clickNavLink(path: string[]): Chainable;
+ changeNamespace(namespace: string): Chainable;
+ aboutModal(): Chainable;
+ podImage(pod: string, namespace: string): Chainable;
+ }
+ }
+ }
+
+// Custom waitUntil with timeout message
+Cypress.Commands.add('waitUntilWithCustomTimeout', (
+ fn: () => any,
+ options: { interval: number; timeout: number; timeoutMessage: string }
+ ) => {
+ const { timeoutMessage, ...waitOptions } = options;
+
+ // Set up custom error handling before the waitUntil call
+ cy.on('fail', (err) => {
+ if (err.message.includes('Timed out retrying')) {
+ // Create a new error with the custom message
+ const customError = new Error(timeoutMessage);
+ customError.stack = err.stack;
+ throw customError;
+ }
+ // For any other errors, re-throw them unchanged
+ throw err;
+ });
+
+ // Execute the waitUntil with the original options (without timeoutMessage)
+ return cy.waitUntil(fn, waitOptions);
+
+ });
+
+
+ Cypress.Commands.add('clickNavLink', (path: string[]) => {
+ cy.get('#page-sidebar')
+ .contains(path[0])
+ .then(($navItem) => {
+ if ($navItem.attr('aria-expanded') !== 'true') {
+ cy.wrap($navItem).click({force: true});
+ }
+ });
+ if (path.length === 2) {
+ cy.get('#page-sidebar')
+ .contains(path[1])
+ .click({force: true});
+ }
+ });
+
+ Cypress.Commands.add('changeNamespace', (namespace: string) => {
+ cy.log('Changing Namespace to: ' + namespace);
+ cy.wait(2000);
+ cy.get('body').then(($body) => {
+ const hasNamespaceBarDropdown = $body.find('[data-test-id="'+LegacyTestIDs.NamespaceBarDropdown+'"]').length > 0;
+ if (hasNamespaceBarDropdown) {
+ cy.byLegacyTestID(LegacyTestIDs.NamespaceBarDropdown).find('button').scrollIntoView().should('be.visible');
+ cy.byLegacyTestID(LegacyTestIDs.NamespaceBarDropdown).find('button').scrollIntoView().should('be.visible').click({force: true});
+ } else {
+ cy.get(Classes.NamespaceDropdown).scrollIntoView().should('be.visible');
+ cy.get(Classes.NamespaceDropdown).scrollIntoView().should('be.visible').click({force: true});
+ }
+ });
+ cy.get('body').then(($body) => {
+ const hasShowSystemSwitch = $body.find('[data-test="'+DataTestIDs.NamespaceDropdownShowSwitch+'"]').length > 0;
+ if (hasShowSystemSwitch) {
+ cy.get('[data-test="'+DataTestIDs.NamespaceDropdownShowSwitch+'"]').then(($element)=> {
+ if ($element.attr('data-checked-state') !== 'true') {
+ cy.byTestID(DataTestIDs.NamespaceDropdownShowSwitch).siblings('span').eq(0).should('be.visible');
+ cy.byTestID(DataTestIDs.NamespaceDropdownShowSwitch).siblings('span').eq(0).should('be.visible').click({force: true});
+ }
+ });
+ }
+ });
+ cy.byTestID(DataTestIDs.NamespaceDropdownTextFilter).type(namespace, {delay: 100});
+ cy.byTestID(DataTestIDs.NamespaceDropdownMenuLink).contains(namespace).should('be.visible');
+ cy.byTestID(DataTestIDs.NamespaceDropdownMenuLink).contains(namespace).should('be.visible').click({force: true});
+ cy.log('Namespace changed to: ' + namespace);
+ });
+
+ Cypress.Commands.add('aboutModal', () => {
+ cy.log('Getting OCP version');
+ if (Cypress.env('LOGIN_USERNAME') === 'kubeadmin') {
+ cy.byTestID(DataTestIDs.MastHeadHelpIcon).should('be.visible');
+ cy.byTestID(DataTestIDs.MastHeadHelpIcon).should('be.visible').click({force: true});
+ cy.byTestID(DataTestIDs.MastHeadApplicationItem).contains('About').should('be.visible').click();
+ cy.byAriaLabel('About modal').find('div[class*="co-select-to-copy"]').eq(0).should('be.visible').then(($ocpversion) => {
+ cy.log('OCP version: ' + $ocpversion.text());
+ });
+ cy.byAriaLabel('Close Dialog').should('be.visible').click();
+ }
+
+ });
+
+ Cypress.Commands.overwrite('log', (log, ...args) => {
+ if (Cypress.browser.isHeadless && Cypress.env('DEBUG')) {
+ // Log to the terminal using the custom task
+ return cy.task('log', args, { log: false }).then(() => {
+ // The original cy.log is still executed but its output is hidden from the
+ // command log in headless mode
+ return log(...args);
+ });
+ } else {
+ // In headed mode, use the original cy.log behavior
+ return log(...args);
+ }
+ });
+
+ Cypress.Commands.add('podImage', (pod: string, namespace: string) => {
+ cy.log('Get pod image');
+ cy.clickNavLink(['Workloads', 'Pods']);
+ cy.changeNamespace(namespace);
+ cy.byTestID('page-heading').contains('Pods').should('be.visible');
+ cy.wait(5000);
+ // Check for DataViewFilters component using Cypress's built-in retry-ability
+ cy.get('body').then(($body) => {
+ const hasDataViewFilters = $body.find('[data-ouia-component-id="DataViewFilters"]').length > 0;
+ if (hasDataViewFilters) {
+ cy.byOUIAID('DataViewFilters').find('button').contains('Status').scrollIntoView().should('be.visible').click();
+ cy.byOUIAID('OUIA-Generated-Menu').find('button').contains('Name').scrollIntoView().should('be.visible').click();
+ cy.byAriaLabel('Name filter').scrollIntoView().should('be.visible').type(pod);
+ } else {
+ cy.byTestID('name-filter-input').should('be.visible').type(pod);
+ }
+ });
+ cy.get(`a[data-test^="${pod}"]`).eq(0).as('podLink').click();
+ cy.get('@podLink').should('be.visible').click();
+ cy.byPFRole('rowgroup').find('td').eq(1).scrollIntoView().should('be.visible').then(($td) => {
+ cy.log('Pod image: ' + $td.text());
+ });
+ cy.log('Get pod image completed');
+ });
+
+
diff --git a/web/cypress/support/e2e.ts b/web/cypress/support/e2e.ts
index b755c86f6..264d1085d 100644
--- a/web/cypress/support/e2e.ts
+++ b/web/cypress/support/e2e.ts
@@ -1,2 +1,38 @@
-/* eslint-disable @typescript-eslint/no-var-requires */
-import './commands';
+import '@cypress/grep';
+
+import './commands/selector-commands';
+import './commands/auth-commands';
+import './commands/utility-commands';
+import './commands/log-commands';
+
+export const checkErrors = () =>
+ cy.window().then((win) => {
+ assert.isTrue(!win.windowError, win.windowError);
+ });
+
+ // Ignore benign ResizeObserver errors globally so they don't fail tests
+// See: https://docs.cypress.io/api/cypress-api/catalog-of-events#Uncaught-Exceptions
+Cypress.on('uncaught:exception', (err) => {
+ const message = err?.message || String(err || '');
+ if (
+ message.includes('ResizeObserver loop limit exceeded') ||
+ message.includes('ResizeObserver loop completed with undelivered notifications') ||
+ message.includes('ResizeObserver') ||
+ message.includes('Cannot read properties of undefined') ||
+ message.includes('Unauthorized') ||
+ message.includes('Bad Gateway') ||
+ message.includes(`Cannot read properties of null (reading 'default')`) ||
+ message.includes(`(intermediate value) is not a function`)
+ ) {
+ console.warn('Ignored frontend exception:', err.message);
+ return false;
+ }
+ // allow other errors to fail the test
+});
+
+
+
+Cypress.on('uncaught:exception', (err) => {
+ console.error("Uncaught error:", err.message);
+ return false;
+});
diff --git a/web/cypress/support/index.ts b/web/cypress/support/index.ts
new file mode 100644
index 000000000..2a9dd2dbf
--- /dev/null
+++ b/web/cypress/support/index.ts
@@ -0,0 +1,35 @@
+import '@cypress/grep';
+
+import './selectors';
+import './commands/selector-commands';
+import './commands/auth-commands';
+import './commands/operator-commands';
+import './commands/incident-commands';
+import './commands/utility-commands';
+import './incidents_prometheus_query_mocks';
+import './commands/virtualization-commands';
+
+export const checkErrors = () =>
+ cy.window().then((win) => {
+ assert.isTrue(!win.windowError, win.windowError);
+ });
+
+ // Ignore benign ResizeObserver errors globally so they don't fail tests
+// See: https://docs.cypress.io/api/cypress-api/catalog-of-events#Uncaught-Exceptions
+Cypress.on('uncaught:exception', (err) => {
+ const message = err?.message || String(err || '');
+ if (
+ message.includes('ResizeObserver loop limit exceeded') ||
+ message.includes('ResizeObserver loop completed with undelivered notifications') ||
+ message.includes('ResizeObserver') ||
+ message.includes('Cannot read properties of undefined') ||
+ message.includes('Unauthorized') ||
+ message.includes('Bad Gateway') ||
+ message.includes(`Cannot read properties of null (reading 'default')`) ||
+ message.includes(`(intermediate value) is not a function`)
+ ) {
+ console.warn('Ignored frontend exception:', err.message);
+ return false;
+ }
+ // allow other errors to fail the test
+});
diff --git a/web/cypress/support/scripts/findLogsInLokistack.sh b/web/cypress/support/scripts/findLogsInLokistack.sh
new file mode 100644
index 000000000..b9a63c4a5
--- /dev/null
+++ b/web/cypress/support/scripts/findLogsInLokistack.sh
@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+#Author: anli@redhat.com
+#Description: Validate logs appears until timeout. the script will search tenant applicaiton, infrastructure and audit if tenanet is not specified.
+#
+set -x
+QUERY=${1:-'{log_type="application"}'}
+QUERY=${QUERY//[[:space:]]/} #remove all spaces
+TIMEOUT=${2:-120} # seconds
+
+URL=$(oc get route logging-loki -n openshift-logging -o jsonpath='{.spec.host}')
+TOKEN=$(oc whoami -t)
+WINDOW="300" # seconds
+STEP="30s"
+INTERVAL="10"
+
+start_time=$(date +%s)
+echo "Waiting until logs appear..."
+
+function queryLogsInTenant()
+{
+ tenant=${1:-application}
+ result=$(curl -s -G -k -H "Authorization: Bearer ${TOKEN}" -H "X-Scope-OrgID:${tenant}" https://${URL}/api/logs/v1/${tenant}/loki/api/v1/query_range \
+ --data-urlencode "query=count_over_time(${QUERY} [${WINDOW}s])" | jq '.data.result|length')
+
+ if [ "$result" -gt 0 ]; then
+ echo "Logs appeared ($result)"
+ exit 0
+ fi
+}
+############## Main #################
+start_time=$(date +%s)
+while true; do
+ now=$(date +%s)
+ ##exit 0, if one return true
+ tenant=""
+
+ if [[ $QUERY =~ log_type=\"application\" ]]; then
+ echo "query tenant application"
+ tenant="application"
+ queryLogsInTenant ${tenant}
+ fi
+
+ if [[ $QUERY =~ log_type=\"infrastructure\" ]] || [[ $QUERY =~ namespace=\"default\" ]] || [[ $QUERY =~ namespace=\"openshift\" ]] || [[ $QUERY =~ namespace=\"kube- ]] || [[ $QUERY =~ namespaceu=\"openshift- ]] ; then
+ echo "query tenant infrastructure"
+ tenant="infrastructure"
+ queryLogsInTenant ${tenant}
+ fi
+
+ if [[ $QUERY =~ log_type=\"audit\" ]]; then
+ echo "query tenant audit"
+ tenant="audit"
+ queryLogsInTenant ${tenant}
+ fi
+
+ if [[ $tenant == "" ]]; then
+ echo "query all tenants"
+ queryLogsInTenant "application"
+ queryLogsInTenant "infrastructure"
+ queryLogsInTenant "audit"
+ fi
+
+ if [ $((now-start_time)) -ge "$TIMEOUT" ]; then
+ echo "Timeout waiting for logs"
+ exit 1
+ fi
+
+ sleep "$INTERVAL"
+done
diff --git a/web/cypress/views/nav.ts b/web/cypress/views/nav.ts
new file mode 100644
index 000000000..01c0f74d5
--- /dev/null
+++ b/web/cypress/views/nav.ts
@@ -0,0 +1,31 @@
+import { Classes } from '../fixtures/data-test';
+export const nav = {
+ sidenav: {
+ clickNavLink: (path: string[]) => {
+ cy.log('Click navLink - ' + `${path}`);
+ cy.clickNavLink(path);
+ },
+ switcher: {
+ changePerspectiveTo: (perspective: string) => {
+ cy.log('Switch perspective - ' + `${perspective}`);
+ cy.byLegacyTestID('perspective-switcher-toggle').scrollIntoView().should('be.visible');
+ cy.byLegacyTestID('perspective-switcher-toggle').scrollIntoView().should('be.visible').click({force: true});
+ cy.byLegacyTestID('perspective-switcher-menu-option').contains(perspective).should('be.visible');
+ cy.byLegacyTestID('perspective-switcher-menu-option').contains(perspective).should('be.visible').click({force: true});
+ },
+ shouldHaveText: (perspective: string) => {
+ cy.log('Should have text - ' + `${perspective}`);
+ cy.byLegacyTestID('perspective-switcher-toggle').contains(perspective).should('be.visible');
+ }
+ }
+ },
+ tabs: {
+ /**
+ * Switch to a tab by name
+ * @param tabname - The name of the tab to switch to
+ */
+ switchTab: (tabname: string) => {
+ cy.get(Classes.HorizontalNav).contains(tabname).should('be.visible').click();
+ }
+}
+};
diff --git a/web/cypress/views/tour.ts b/web/cypress/views/tour.ts
new file mode 100644
index 000000000..9884cede1
--- /dev/null
+++ b/web/cypress/views/tour.ts
@@ -0,0 +1,17 @@
+export const guidedTour = {
+ close: () => {
+ cy.get('body').then(($body) => {
+ if ($body.find(`[data-test="guided-tour-modal"]`).length > 0) {
+ cy.byTestID('tour-step-footer-secondary').contains('Skip tour').click();
+ }
+ });
+ },
+
+ closeKubevirtTour: () => {
+ cy.get('body').then(($body) => {
+ if ($body.find(`[aria-label="Welcome modal"]`).length > 0) {
+ cy.get('[aria-label="Close"]').should('be.visible').click();
+ }
+ });
+ },
+ };
\ No newline at end of file
diff --git a/web/cypress/views/utils.ts b/web/cypress/views/utils.ts
new file mode 100644
index 000000000..50164850b
--- /dev/null
+++ b/web/cypress/views/utils.ts
@@ -0,0 +1,43 @@
+export function clickIfExist(element) {
+ cy.get('body').then((body) => {
+ if (body.find(element).length > 0) {
+ cy.get(element).click();
+ }
+ });
+}
+
+export function getValFromElement(selector: string) {
+ cy.log('Get Val from Element');
+ cy.get(selector).should('be.visible');
+ const elementText = cy.get(selector).invoke('val');
+ return elementText;
+};
+
+export function getTextFromElement(selector: string) {
+ cy.log('Get Text from Element');
+ cy.get(selector).should('be.visible');
+ const elementText = cy.get(selector).invoke('text');
+ return elementText;
+};
+
+// PatternFly version detection and abstraction
+export function getPFVersion() {
+ // Detect PatternFly version from document classes or CSS variables
+ const htmlElement = Cypress.$('html')[0];
+ if (htmlElement) {
+ const classes = htmlElement.className;
+ const versionMatch = classes.match(/pf-(v\d+)/);
+ if (versionMatch) {
+ return versionMatch[1];
+ }
+ }
+ // Fallback to checking for CSS variables
+ const style = getComputedStyle(document.documentElement);
+ if (style.getPropertyValue('--pf-v6-global--FontSize--md')) {
+ return 'v6';
+ } else if (style.getPropertyValue('--pf-v5-global--FontSize--md')) {
+ return 'v5';
+ }
+ // Default to current version
+ return 'v6';
+};
\ No newline at end of file
diff --git a/web/package-lock.json b/web/package-lock.json
index bf94bb89b..5843729db 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -16,11 +16,13 @@
"@patternfly/react-table": "^5.4.15",
"@patternfly/react-virtualized-extension": "^5.1.0",
"i18next": "^22.4.12",
+ "mocha-junit-reporter": "^2.2.1",
"react-i18next": "^11.18.6",
"react-router-dom-v5-compat": "^6.30.0"
},
"devDependencies": {
"@cypress/code-coverage": "^3.10.0",
+ "@cypress/grep": "^3.1.3",
"@jsdevtools/coverage-istanbul-loader": "^3.0.5",
"@openshift-console/dynamic-plugin-sdk": "^4.19.0-prerelease.1",
"@openshift-console/dynamic-plugin-sdk-webpack": "4.19",
@@ -39,7 +41,9 @@
"copy-webpack-plugin": "^13.0.1",
"css-loader": "^6.7.1",
"cypress": "^14.5.3",
+ "cypress-multi-reporters": "^1.4.0",
"cypress-terminal-report": "^3.5.2",
+ "cypress-wait-until": "^3.0.2",
"eslint": "^8.44.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
@@ -49,6 +53,8 @@
"i18next-http-backend": "^2.2.0",
"i18next-parser": "^9.3.0",
"jest": "^30.1.3",
+ "junit-report-merger": "^3.0.6",
+ "mochawesome": "^6.1.1",
"nyc": "^15.1.0",
"prettier": "^2.6.0",
"react": "17.0.2",
@@ -2041,6 +2047,21 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/@cypress/grep": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/@cypress/grep/-/grep-3.1.5.tgz",
+ "integrity": "sha512-dbLKP9wGLId+TwTRFDcWVcr9AvJ06W3K7dVeJzLONiPbI5/XJh2mDZvnoyJlAz+VZxdwe0+nejk/CPmuphuzkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4",
+ "find-test-names": "^1.19.0",
+ "globby": "^11.0.4"
+ },
+ "peerDependencies": {
+ "cypress": ">=10"
+ }
+ },
"node_modules/@cypress/request": {
"version": "3.0.9",
"resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.9.tgz",
@@ -2765,7 +2786,6 @@
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
- "dev": true,
"license": "ISC",
"dependencies": {
"string-width": "^5.1.2",
@@ -2783,7 +2803,6 @@
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
"integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
@@ -2796,7 +2815,6 @@
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
"integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
@@ -2809,14 +2827,12 @@
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true,
"license": "MIT"
},
"node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"eastasianwidth": "^0.2.0",
@@ -2834,7 +2850,6 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
"integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
@@ -2850,7 +2865,6 @@
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^6.1.0",
@@ -4095,6 +4109,58 @@
"node": ">= 8"
}
},
+ "node_modules/@oozcitak/dom": {
+ "version": "1.15.10",
+ "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.10.tgz",
+ "integrity": "sha512-0JT29/LaxVgRcGKvHmSrUTEvZ8BXvZhGl2LASRUgHqDTC1M5g1pLmVv56IYNyt3bG2CUjDkc67wnyZC14pbQrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oozcitak/infra": "1.0.8",
+ "@oozcitak/url": "1.0.4",
+ "@oozcitak/util": "8.3.8"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/@oozcitak/infra": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.8.tgz",
+ "integrity": "sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oozcitak/util": "8.3.8"
+ },
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/@oozcitak/url": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.4.tgz",
+ "integrity": "sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oozcitak/infra": "1.0.8",
+ "@oozcitak/util": "8.3.8"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/@oozcitak/util": {
+ "version": "8.3.8",
+ "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.8.tgz",
+ "integrity": "sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
"node_modules/@openshift-console/dynamic-plugin-sdk": {
"version": "4.19.0-prerelease.1",
"resolved": "https://registry.npmjs.org/@openshift-console/dynamic-plugin-sdk/-/dynamic-plugin-sdk-4.19.0-prerelease.1.tgz",
@@ -4412,7 +4478,6 @@
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
- "dev": true,
"license": "MIT",
"optional": true,
"engines": {
@@ -6024,7 +6089,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -6034,7 +6098,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
@@ -6536,7 +6599,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true,
"license": "MIT"
},
"node_modules/bare-events": {
@@ -6968,6 +7030,13 @@
"node": "10.* || >= 12.*"
}
},
+ "node_modules/browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "license": "ISC",
+ "peer": true
+ },
"node_modules/browserslist": {
"version": "4.28.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
@@ -7231,7 +7300,6 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
@@ -7269,6 +7337,15 @@
"node": ">=10"
}
},
+ "node_modules/charenc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
+ "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/check-more-types": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz",
@@ -7720,7 +7797,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
@@ -7733,7 +7809,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
"license": "MIT"
},
"node_modules/colorette": {
@@ -8152,7 +8227,6 @@
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
@@ -8167,12 +8241,20 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
+ "node_modules/crypt": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
+ "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/css-loader": {
"version": "6.7.1",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz",
@@ -8324,6 +8406,23 @@
"node": "^18.0.0 || ^20.0.0 || >=22.0.0"
}
},
+ "node_modules/cypress-multi-reporters": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/cypress-multi-reporters/-/cypress-multi-reporters-1.6.4.tgz",
+ "integrity": "sha512-3xU2t6pZjZy/ORHaCvci5OT1DAboS4UuMMM8NBAizeb2C9qmHt+cgAjXgurazkwkPRdO7ccK39M5ZaPCju0r6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4",
+ "lodash": "^4.17.21"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "peerDependencies": {
+ "mocha": ">=3.1.2"
+ }
+ },
"node_modules/cypress-terminal-report": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/cypress-terminal-report/-/cypress-terminal-report-3.5.2.tgz",
@@ -8368,6 +8467,13 @@
"node": ">=10"
}
},
+ "node_modules/cypress-wait-until": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/cypress-wait-until/-/cypress-wait-until-3.0.2.tgz",
+ "integrity": "sha512-iemies796dD5CgjG5kV0MnpEmKSH+s7O83ZoJLVzuVbZmm4lheMsZqAVT73hlMx4QlkwhxbyUzhOBUOZwoOe0w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/cypress/node_modules/ci-info": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz",
@@ -8658,6 +8764,16 @@
"url": "https://opencollective.com/date-fns"
}
},
+ "node_modules/dateformat": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz",
+ "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
@@ -8669,7 +8785,6 @@
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
@@ -9051,8 +9166,7 @@
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "dev": true
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
"node_modules/ecc-jsbn": {
"version": "0.1.2",
@@ -9095,7 +9209,6 @@
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true,
"license": "MIT"
},
"node_modules/emojis-list": {
@@ -9459,7 +9572,6 @@
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "dev": true,
"engines": {
"node": ">=6"
}
@@ -10459,6 +10571,26 @@
"url": "https://github.com/avajs/find-cache-dir?sponsor=1"
}
},
+ "node_modules/find-test-names": {
+ "version": "1.29.19",
+ "resolved": "https://registry.npmjs.org/find-test-names/-/find-test-names-1.29.19.tgz",
+ "integrity": "sha512-fSO2GXgOU6dH+FdffmRXYN/kLdnd8zkBGIZrKsmAdfLSFUUDLpDFF7+F/h+wjmjDWQmMgD8hPfJZR+igiEUQHQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.27.2",
+ "@babel/plugin-syntax-jsx": "^7.27.1",
+ "acorn-walk": "^8.2.0",
+ "debug": "^4.3.3",
+ "simple-bin-help": "^1.8.0",
+ "tinyglobby": "^0.2.13"
+ },
+ "bin": {
+ "find-test-names": "bin/find-test-names.js",
+ "print-tests": "bin/print-tests.js",
+ "update-test-count": "bin/update-test-count.js"
+ }
+ },
"node_modules/find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
@@ -10477,7 +10609,6 @@
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
"integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
- "dev": true,
"license": "BSD-3-Clause",
"bin": {
"flat": "cli.js"
@@ -10732,6 +10863,13 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
+ "node_modules/fsu": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz",
+ "integrity": "sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
@@ -10793,7 +10931,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true,
"license": "ISC",
"engines": {
"node": "6.* || 8.* || >= 10.*"
@@ -11163,7 +11300,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -11279,7 +11415,6 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
- "dev": true,
"license": "MIT",
"bin": {
"he": "bin/he"
@@ -12040,6 +12175,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "license": "MIT"
+ },
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
@@ -12150,7 +12291,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -12328,7 +12468,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -12494,7 +12633,6 @@
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
@@ -12592,7 +12730,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
- "dev": true,
"license": "ISC"
},
"node_modules/isobject": {
@@ -12735,7 +12872,6 @@
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
- "dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
@@ -14973,6 +15109,54 @@
"node": ">=4.0"
}
},
+ "node_modules/junit-report-merger": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/junit-report-merger/-/junit-report-merger-3.0.6.tgz",
+ "integrity": "sha512-6oziSTxC7MjO3yhkkokbO6EXTDwAtmgjozZgk8EaLu54re3xoeLyc2/DUyEamcF4Pl+nPXnnaVpqo4s+W64h0Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-glob": "3.2.11",
+ "xmlbuilder2": "3.0.2"
+ },
+ "bin": {
+ "jrm": "cli.js",
+ "junit-report-merger": "cli.js"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/junit-report-merger/node_modules/fast-glob": {
+ "version": "3.2.11",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
+ "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/junit-report-merger/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -15170,6 +15354,34 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/lodash.isempty": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
+ "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.isfunction": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
+ "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.isobject": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz",
+ "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -15195,7 +15407,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
"integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"chalk": "^4.1.0",
@@ -15351,6 +15562,17 @@
"node": ">= 0.4"
}
},
+ "node_modules/md5": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
+ "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "charenc": "0.0.2",
+ "crypt": "0.0.2",
+ "is-buffer": "~1.1.6"
+ }
+ },
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -15514,12 +15736,26 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "dev": true,
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
+ "node_modules/mkdirp": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
+ "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "dist/cjs/src/bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/mktemp": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/mktemp/-/mktemp-0.4.0.tgz",
@@ -15529,13 +15765,686 @@
"node": ">0.9"
}
},
- "node_modules/ms": {
+ "node_modules/mocha": {
+ "version": "11.7.5",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz",
+ "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "browser-stdout": "^1.3.1",
+ "chokidar": "^4.0.1",
+ "debug": "^4.3.5",
+ "diff": "^7.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-up": "^5.0.0",
+ "glob": "^10.4.5",
+ "he": "^1.2.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "log-symbols": "^4.1.0",
+ "minimatch": "^9.0.5",
+ "ms": "^2.1.3",
+ "picocolors": "^1.1.1",
+ "serialize-javascript": "^6.0.2",
+ "strip-json-comments": "^3.1.1",
+ "supports-color": "^8.1.1",
+ "workerpool": "^9.2.0",
+ "yargs": "^17.7.2",
+ "yargs-parser": "^21.1.1",
+ "yargs-unparser": "^2.0.0"
+ },
+ "bin": {
+ "_mocha": "bin/_mocha",
+ "mocha": "bin/mocha.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/mocha-junit-reporter": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.2.1.tgz",
+ "integrity": "sha512-iDn2tlKHn8Vh8o4nCzcUVW4q7iXp7cC4EB78N0cDHIobLymyHNwe0XG8HEHHjc3hJlXm0Vy6zcrxaIhnI2fWmw==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4",
+ "md5": "^2.3.0",
+ "mkdirp": "^3.0.0",
+ "strip-ansi": "^6.0.1",
+ "xml": "^1.0.1"
+ },
+ "peerDependencies": {
+ "mocha": ">=2.2.5"
+ }
+ },
+ "node_modules/mocha/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "license": "Python-2.0",
+ "peer": true
+ },
+ "node_modules/mocha/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/mocha/node_modules/chokidar": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "readdirp": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/mocha/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/mocha/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/mocha/node_modules/diff": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz",
+ "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==",
+ "license": "BSD-3-Clause",
+ "peer": true,
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/mocha/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/mocha/node_modules/glob": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/mocha/node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/mocha/node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/mocha/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/mocha/node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/readdirp": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
+ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 14.18.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/mocha/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/mocha/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/mocha/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mocha/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/mochawesome": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-6.3.1.tgz",
+ "integrity": "sha512-G2J7Le8ap+0222otJQEUVFs7RYzphiIk21NzaBZE2dbyHJ2+9aai+V2cV7lreEKigDpwQ+SXeiiBH9KQlrkaAQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "diff": "^5.0.0",
+ "json-stringify-safe": "^5.0.1",
+ "lodash.isempty": "^4.4.0",
+ "lodash.isfunction": "^3.0.9",
+ "lodash.isobject": "^3.0.2",
+ "lodash.isstring": "^4.0.1",
+ "mochawesome-report-generator": "^5.2.0",
+ "strip-ansi": "^6.0.0",
+ "uuid": "^8.3.2"
+ },
+ "peerDependencies": {
+ "mocha": ">=7"
+ }
+ },
+ "node_modules/mochawesome-report-generator": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-5.2.0.tgz",
+ "integrity": "sha512-DDY/3jSkM/VrWy0vJtdYOf6qBLdaPaLcI7rQmBVbnclIX7AKniE1Rhz3T/cMT/7u54W5EHNo1z84z7efotq/Eg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^2.4.2",
+ "dateformat": "^3.0.2",
+ "escape-html": "^1.0.3",
+ "fs-extra": "^7.0.0",
+ "fsu": "^1.0.2",
+ "lodash.isfunction": "^3.0.8",
+ "opener": "^1.5.2",
+ "prop-types": "^15.7.2",
+ "tcomb": "^3.2.17",
+ "tcomb-validation": "^3.3.0",
+ "validator": "^10.11.0",
+ "yargs": "^13.2.2"
+ },
+ "bin": {
+ "marge": "bin/cli.js"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/ansi-regex": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+ "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/mochawesome-report-generator/node_modules/emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true,
"license": "MIT"
},
+ "node_modules/mochawesome-report-generator/node_modules/find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+ "dev": true,
+ "license": "MIT",
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/yargs": {
+ "version": "13.3.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
+ "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^5.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.1.2"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/yargs-parser": {
+ "version": "13.1.2",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
+ "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ },
+ "node_modules/mochawesome/node_modules/diff": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
+ "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
"node_modules/multicast-dns": {
"version": "7.2.5",
"resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz",
@@ -15986,6 +16895,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/opener": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
+ "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
+ "dev": true,
+ "license": "(WTFPL OR MIT)",
+ "bin": {
+ "opener": "bin/opener-bin.js"
+ }
+ },
"node_modules/optionator": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
@@ -16118,7 +17037,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
- "dev": true,
"license": "BlueOak-1.0.0"
},
"node_modules/param-case": {
@@ -16252,7 +17170,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -16292,7 +17209,6 @@
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
- "dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^10.2.0",
@@ -16309,7 +17225,6 @@
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
- "dev": true,
"license": "ISC"
},
"node_modules/path-to-regexp": {
@@ -16347,7 +17262,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "dev": true,
"license": "ISC"
},
"node_modules/picomatch": {
@@ -16808,7 +17722,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"safe-buffer": "^5.1.0"
@@ -17404,7 +18317,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -17640,7 +18552,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true,
"license": "MIT"
},
"node_modules/safe-push-apply": {
@@ -17812,7 +18723,6 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
- "dev": true,
"dependencies": {
"randombytes": "^2.1.0"
}
@@ -18092,7 +19002,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
@@ -18105,7 +19014,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -18203,6 +19111,16 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/simple-bin-help": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/simple-bin-help/-/simple-bin-help-1.8.0.tgz",
+ "integrity": "sha512-0LxHn+P1lF5r2WwVB/za3hLRIsYoLaNq1CXqjbrs3ZvLuvlWnRKrUjEWzV7umZL7hpQ7xULiQMV+0iXdRa5iFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ }
+ },
"node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
@@ -18517,7 +19435,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
@@ -18533,7 +19450,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
@@ -18646,7 +19562,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
@@ -18660,7 +19575,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
@@ -18693,7 +19607,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -18723,7 +19636,6 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
@@ -18786,6 +19698,23 @@
"node": ">=6"
}
},
+ "node_modules/tcomb": {
+ "version": "3.2.29",
+ "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz",
+ "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tcomb-validation": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz",
+ "integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tcomb": "^3.0.0"
+ }
+ },
"node_modules/teex": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz",
@@ -19806,6 +20735,16 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "node_modules/validator": {
+ "version": "10.11.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
+ "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/value-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
@@ -20806,7 +21745,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
@@ -20993,11 +21931,17 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/workerpool": {
+ "version": "9.3.4",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz",
+ "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==",
+ "license": "Apache-2.0",
+ "peer": true
+ },
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
@@ -21016,7 +21960,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
@@ -21103,6 +22046,43 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/xml": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
+ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==",
+ "license": "MIT"
+ },
+ "node_modules/xmlbuilder2": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-3.0.2.tgz",
+ "integrity": "sha512-h4MUawGY21CTdhV4xm3DG9dgsqyhDkZvVJBx88beqX8wJs3VgyGQgAn5VreHuae6unTQxh115aMK5InCVmOIKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oozcitak/dom": "1.15.10",
+ "@oozcitak/infra": "1.0.8",
+ "@oozcitak/util": "8.3.8",
+ "@types/node": "*",
+ "js-yaml": "3.14.0"
+ },
+ "engines": {
+ "node": ">=12.0"
+ }
+ },
+ "node_modules/xmlbuilder2/node_modules/js-yaml": {
+ "version": "3.14.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
+ "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@@ -21153,11 +22133,62 @@
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true,
"engines": {
"node": ">=12"
}
},
+ "node_modules/yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-unparser/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yargs-unparser/node_modules/decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yargs-unparser/node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/yargs/node_modules/yargs-parser": {
"version": "18.1.3",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
@@ -21197,7 +22228,6 @@
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
- "dev": true,
"engines": {
"node": ">=10"
},
@@ -22521,6 +23551,17 @@
}
}
},
+ "@cypress/grep": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/@cypress/grep/-/grep-3.1.5.tgz",
+ "integrity": "sha512-dbLKP9wGLId+TwTRFDcWVcr9AvJ06W3K7dVeJzLONiPbI5/XJh2mDZvnoyJlAz+VZxdwe0+nejk/CPmuphuzkQ==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.3.4",
+ "find-test-names": "^1.19.0",
+ "globby": "^11.0.4"
+ }
+ },
"@cypress/request": {
"version": "3.0.9",
"resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.9.tgz",
@@ -22921,7 +23962,6 @@
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
- "dev": true,
"requires": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
@@ -22934,26 +23974,22 @@
"ansi-regex": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
- "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
- "dev": true
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="
},
"ansi-styles": {
"version": "6.2.3",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
- "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
- "dev": true
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="
},
"emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
},
"string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
- "dev": true,
"requires": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
@@ -22964,7 +24000,6 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
"integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
- "dev": true,
"requires": {
"ansi-regex": "^6.0.1"
}
@@ -22973,7 +24008,6 @@
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
- "dev": true,
"requires": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
@@ -23848,6 +24882,42 @@
"fastq": "^1.6.0"
}
},
+ "@oozcitak/dom": {
+ "version": "1.15.10",
+ "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.10.tgz",
+ "integrity": "sha512-0JT29/LaxVgRcGKvHmSrUTEvZ8BXvZhGl2LASRUgHqDTC1M5g1pLmVv56IYNyt3bG2CUjDkc67wnyZC14pbQrQ==",
+ "dev": true,
+ "requires": {
+ "@oozcitak/infra": "1.0.8",
+ "@oozcitak/url": "1.0.4",
+ "@oozcitak/util": "8.3.8"
+ }
+ },
+ "@oozcitak/infra": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.8.tgz",
+ "integrity": "sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==",
+ "dev": true,
+ "requires": {
+ "@oozcitak/util": "8.3.8"
+ }
+ },
+ "@oozcitak/url": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.4.tgz",
+ "integrity": "sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==",
+ "dev": true,
+ "requires": {
+ "@oozcitak/infra": "1.0.8",
+ "@oozcitak/util": "8.3.8"
+ }
+ },
+ "@oozcitak/util": {
+ "version": "8.3.8",
+ "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.8.tgz",
+ "integrity": "sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ==",
+ "dev": true
+ },
"@openshift-console/dynamic-plugin-sdk": {
"version": "4.19.0-prerelease.1",
"resolved": "https://registry.npmjs.org/@openshift-console/dynamic-plugin-sdk/-/dynamic-plugin-sdk-4.19.0-prerelease.1.tgz",
@@ -24090,7 +25160,6 @@
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
- "dev": true,
"optional": true
},
"@pkgr/core": {
@@ -25275,14 +26344,12 @@
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
"requires": {
"color-convert": "^2.0.1"
}
@@ -25621,8 +26688,7 @@
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"bare-events": {
"version": "2.4.2",
@@ -25934,6 +27000,12 @@
"symlink-or-copy": "^1.3.1"
}
},
+ "browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "peer": true
+ },
"browserslist": {
"version": "4.28.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
@@ -26090,7 +27162,6 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -26111,6 +27182,11 @@
"integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
"dev": true
},
+ "charenc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
+ "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA=="
+ },
"check-more-types": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz",
@@ -26433,7 +27509,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
"requires": {
"color-name": "~1.1.4"
}
@@ -26441,8 +27516,7 @@
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"colorette": {
"version": "2.0.19",
@@ -26751,7 +27825,6 @@
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
- "dev": true,
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
@@ -26761,11 +27834,15 @@
"path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
}
}
},
+ "crypt": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
+ "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow=="
+ },
"css-loader": {
"version": "6.7.1",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz",
@@ -26927,6 +28004,16 @@
}
}
},
+ "cypress-multi-reporters": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/cypress-multi-reporters/-/cypress-multi-reporters-1.6.4.tgz",
+ "integrity": "sha512-3xU2t6pZjZy/ORHaCvci5OT1DAboS4UuMMM8NBAizeb2C9qmHt+cgAjXgurazkwkPRdO7ccK39M5ZaPCju0r6A==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.3.4",
+ "lodash": "^4.17.21"
+ }
+ },
"cypress-terminal-report": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/cypress-terminal-report/-/cypress-terminal-report-3.5.2.tgz",
@@ -26961,6 +28048,12 @@
}
}
},
+ "cypress-wait-until": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/cypress-wait-until/-/cypress-wait-until-3.0.2.tgz",
+ "integrity": "sha512-iemies796dD5CgjG5kV0MnpEmKSH+s7O83ZoJLVzuVbZmm4lheMsZqAVT73hlMx4QlkwhxbyUzhOBUOZwoOe0w==",
+ "dev": true
+ },
"d3-array": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
@@ -27086,6 +28179,12 @@
"integrity": "sha512-dlLD5rKaKxpFdnjrs+5azHDFOPEu4ANy/LTh04A1DTzMM7qoajmKCBc8pkKRFT41CNzw+4gQh79X5C+Jq27HAw==",
"dev": true
},
+ "dateformat": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz",
+ "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==",
+ "dev": true
+ },
"dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
@@ -27096,7 +28195,6 @@
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
- "dev": true,
"requires": {
"ms": "^2.1.3"
}
@@ -27346,8 +28444,7 @@
"eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "dev": true
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
"ecc-jsbn": {
"version": "0.1.2",
@@ -27380,8 +28477,7 @@
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"emojis-list": {
"version": "3.0.0",
@@ -27665,8 +28761,7 @@
"escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "dev": true
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="
},
"escape-html": {
"version": "1.0.3",
@@ -28382,6 +29477,20 @@
"pkg-dir": "^4.1.0"
}
},
+ "find-test-names": {
+ "version": "1.29.19",
+ "resolved": "https://registry.npmjs.org/find-test-names/-/find-test-names-1.29.19.tgz",
+ "integrity": "sha512-fSO2GXgOU6dH+FdffmRXYN/kLdnd8zkBGIZrKsmAdfLSFUUDLpDFF7+F/h+wjmjDWQmMgD8hPfJZR+igiEUQHQ==",
+ "dev": true,
+ "requires": {
+ "@babel/parser": "^7.27.2",
+ "@babel/plugin-syntax-jsx": "^7.27.1",
+ "acorn-walk": "^8.2.0",
+ "debug": "^4.3.3",
+ "simple-bin-help": "^1.8.0",
+ "tinyglobby": "^0.2.13"
+ }
+ },
"find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
@@ -28395,8 +29504,7 @@
"flat": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
- "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
- "dev": true
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ=="
},
"flat-cache": {
"version": "3.0.4",
@@ -28565,6 +29673,12 @@
"dev": true,
"optional": true
},
+ "fsu": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz",
+ "integrity": "sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==",
+ "dev": true
+ },
"function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
@@ -28606,8 +29720,7 @@
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"get-intrinsic": {
"version": "1.3.0",
@@ -28871,8 +29984,7 @@
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"has-own-prop": {
"version": "2.0.0",
@@ -28943,8 +30055,7 @@
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
- "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
- "dev": true
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
"heimdalljs": {
"version": "0.2.6",
@@ -29473,6 +30584,11 @@
"has-tostringtag": "^1.0.2"
}
},
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
"is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
@@ -29533,8 +30649,7 @@
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"is-generator-fn": {
"version": "2.1.0",
@@ -29633,8 +30748,7 @@
"is-path-inside": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
- "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
- "dev": true
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="
},
"is-plain-obj": {
"version": "3.0.0",
@@ -29729,8 +30843,7 @@
"is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
- "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
- "dev": true
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="
},
"is-valid-glob": {
"version": "1.0.0",
@@ -29787,8 +30900,7 @@
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
- "dev": true
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
"isobject": {
"version": "3.0.1",
@@ -29893,7 +31005,6 @@
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
- "dev": true,
"requires": {
"@isaacs/cliui": "^8.0.2",
"@pkgjs/parseargs": "^0.11.0"
@@ -31471,6 +32582,40 @@
"object.values": "^1.1.6"
}
},
+ "junit-report-merger": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/junit-report-merger/-/junit-report-merger-3.0.6.tgz",
+ "integrity": "sha512-6oziSTxC7MjO3yhkkokbO6EXTDwAtmgjozZgk8EaLu54re3xoeLyc2/DUyEamcF4Pl+nPXnnaVpqo4s+W64h0Q==",
+ "dev": true,
+ "requires": {
+ "fast-glob": "3.2.11",
+ "xmlbuilder2": "3.0.2"
+ },
+ "dependencies": {
+ "fast-glob": {
+ "version": "3.2.11",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
+ "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
+ }
+ },
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -31609,6 +32754,30 @@
"integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==",
"dev": true
},
+ "lodash.isempty": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
+ "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==",
+ "dev": true
+ },
+ "lodash.isfunction": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
+ "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==",
+ "dev": true
+ },
+ "lodash.isobject": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz",
+ "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==",
+ "dev": true
+ },
+ "lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "dev": true
+ },
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -31631,7 +32800,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
"integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
- "dev": true,
"requires": {
"chalk": "^4.1.0",
"is-unicode-supported": "^0.1.0"
@@ -31739,6 +32907,16 @@
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"dev": true
},
+ "md5": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
+ "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
+ "requires": {
+ "charenc": "0.0.2",
+ "crypt": "0.0.2",
+ "is-buffer": "~1.1.6"
+ }
+ },
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -31853,8 +33031,12 @@
"minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
- "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "dev": true
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="
+ },
+ "mkdirp": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
+ "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="
},
"mktemp": {
"version": "0.4.0",
@@ -31862,11 +33044,482 @@
"integrity": "sha512-IXnMcJ6ZyTuhRmJSjzvHSRhlVPiN9Jwc6e59V0bEJ0ba6OBeX2L0E+mRN1QseeOF4mM+F1Rit6Nh7o+rl2Yn/A==",
"dev": true
},
+ "mocha": {
+ "version": "11.7.5",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz",
+ "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==",
+ "peer": true,
+ "requires": {
+ "browser-stdout": "^1.3.1",
+ "chokidar": "^4.0.1",
+ "debug": "^4.3.5",
+ "diff": "^7.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-up": "^5.0.0",
+ "glob": "^10.4.5",
+ "he": "^1.2.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "log-symbols": "^4.1.0",
+ "minimatch": "^9.0.5",
+ "ms": "^2.1.3",
+ "picocolors": "^1.1.1",
+ "serialize-javascript": "^6.0.2",
+ "strip-json-comments": "^3.1.1",
+ "supports-color": "^8.1.1",
+ "workerpool": "^9.2.0",
+ "yargs": "^17.7.2",
+ "yargs-parser": "^21.1.1",
+ "yargs-unparser": "^2.0.0"
+ },
+ "dependencies": {
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "peer": true
+ },
+ "brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "peer": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "chokidar": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "peer": true,
+ "requires": {
+ "readdirp": "^4.0.1"
+ }
+ },
+ "cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "peer": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "peer": true,
+ "requires": {
+ "ms": "^2.1.3"
+ }
+ },
+ "diff": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz",
+ "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==",
+ "peer": true
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "peer": true
+ },
+ "find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "peer": true,
+ "requires": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "peer": true,
+ "requires": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ }
+ },
+ "glob": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
+ "peer": true,
+ "requires": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ }
+ },
+ "js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "peer": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "peer": true,
+ "requires": {
+ "p-locate": "^5.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "peer": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "peer": true
+ },
+ "p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "peer": true,
+ "requires": {
+ "yocto-queue": "^0.1.0"
+ }
+ },
+ "p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "peer": true,
+ "requires": {
+ "p-limit": "^3.0.2"
+ }
+ },
+ "readdirp": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
+ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+ "peer": true
+ },
+ "signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "peer": true
+ },
+ "supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "peer": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "peer": true
+ },
+ "yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "peer": true,
+ "requires": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ }
+ }
+ }
+ },
+ "mocha-junit-reporter": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.2.1.tgz",
+ "integrity": "sha512-iDn2tlKHn8Vh8o4nCzcUVW4q7iXp7cC4EB78N0cDHIobLymyHNwe0XG8HEHHjc3hJlXm0Vy6zcrxaIhnI2fWmw==",
+ "requires": {
+ "debug": "^4.3.4",
+ "md5": "^2.3.0",
+ "mkdirp": "^3.0.0",
+ "strip-ansi": "^6.0.1",
+ "xml": "^1.0.1"
+ }
+ },
+ "mochawesome": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-6.3.1.tgz",
+ "integrity": "sha512-G2J7Le8ap+0222otJQEUVFs7RYzphiIk21NzaBZE2dbyHJ2+9aai+V2cV7lreEKigDpwQ+SXeiiBH9KQlrkaAQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.1.0",
+ "diff": "^5.0.0",
+ "json-stringify-safe": "^5.0.1",
+ "lodash.isempty": "^4.4.0",
+ "lodash.isfunction": "^3.0.9",
+ "lodash.isobject": "^3.0.2",
+ "lodash.isstring": "^4.0.1",
+ "mochawesome-report-generator": "^5.2.0",
+ "strip-ansi": "^6.0.0",
+ "uuid": "^8.3.2"
+ },
+ "dependencies": {
+ "diff": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
+ "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
+ "dev": true
+ }
+ }
+ },
+ "mochawesome-report-generator": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-5.2.0.tgz",
+ "integrity": "sha512-DDY/3jSkM/VrWy0vJtdYOf6qBLdaPaLcI7rQmBVbnclIX7AKniE1Rhz3T/cMT/7u54W5EHNo1z84z7efotq/Eg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "dateformat": "^3.0.2",
+ "escape-html": "^1.0.3",
+ "fs-extra": "^7.0.0",
+ "fsu": "^1.0.2",
+ "lodash.isfunction": "^3.0.8",
+ "opener": "^1.5.2",
+ "prop-types": "^15.7.2",
+ "tcomb": "^3.2.17",
+ "tcomb-validation": "^3.3.0",
+ "validator": "^10.11.0",
+ "yargs": "^13.2.2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+ "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ }
+ },
+ "yargs": {
+ "version": "13.3.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
+ "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+ "dev": true,
+ "requires": {
+ "cliui": "^5.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.1.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "13.1.2",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
+ "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"multicast-dns": {
"version": "7.2.5",
@@ -32174,6 +33827,12 @@
"wsl-utils": "^0.1.0"
}
},
+ "opener": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
+ "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
+ "dev": true
+ },
"optionator": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
@@ -32264,8 +33923,7 @@
"package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
- "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
- "dev": true
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="
},
"param-case": {
"version": "3.0.4",
@@ -32364,8 +34022,7 @@
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
},
"path-is-absolute": {
"version": "1.0.1",
@@ -32395,7 +34052,6 @@
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
- "dev": true,
"requires": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
@@ -32404,8 +34060,7 @@
"lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
- "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
- "dev": true
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
}
}
},
@@ -32436,8 +34091,7 @@
"picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "dev": true
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
},
"picomatch": {
"version": "2.3.1",
@@ -32734,7 +34388,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
- "dev": true,
"requires": {
"safe-buffer": "^5.1.0"
}
@@ -33172,8 +34825,7 @@
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
},
"require-from-string": {
"version": "2.0.2",
@@ -33322,8 +34974,7 @@
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safe-push-apply": {
"version": "1.0.0",
@@ -33456,7 +35107,6 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
- "dev": true,
"requires": {
"randombytes": "^2.1.0"
}
@@ -33680,7 +35330,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
"requires": {
"shebang-regex": "^3.0.0"
}
@@ -33688,8 +35337,7 @@
"shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
},
"shell-quote": {
"version": "1.8.1",
@@ -33751,6 +35399,12 @@
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"dev": true
},
+ "simple-bin-help": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/simple-bin-help/-/simple-bin-help-1.8.0.tgz",
+ "integrity": "sha512-0LxHn+P1lF5r2WwVB/za3hLRIsYoLaNq1CXqjbrs3ZvLuvlWnRKrUjEWzV7umZL7hpQ7xULiQMV+0iXdRa5iFg==",
+ "dev": true
+ },
"slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
@@ -33997,7 +35651,6 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -34008,7 +35661,6 @@
"version": "npm:string-width@4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -34088,7 +35740,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"requires": {
"ansi-regex": "^5.0.1"
}
@@ -34097,7 +35748,6 @@
"version": "npm:strip-ansi@6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"requires": {
"ansi-regex": "^5.0.1"
}
@@ -34117,8 +35767,7 @@
"strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="
},
"style-loader": {
"version": "3.3.1",
@@ -34131,7 +35780,6 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
"requires": {
"has-flag": "^4.0.0"
}
@@ -34169,6 +35817,21 @@
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
"dev": true
},
+ "tcomb": {
+ "version": "3.2.29",
+ "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz",
+ "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==",
+ "dev": true
+ },
+ "tcomb-validation": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz",
+ "integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==",
+ "dev": true,
+ "requires": {
+ "tcomb": "^3.0.0"
+ }
+ },
"teex": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz",
@@ -34836,6 +36499,12 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "validator": {
+ "version": "10.11.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
+ "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==",
+ "dev": true
+ },
"value-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
@@ -35515,7 +37184,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
"requires": {
"isexe": "^2.0.0"
}
@@ -35642,11 +37310,16 @@
"integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
"dev": true
},
+ "workerpool": {
+ "version": "9.3.4",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz",
+ "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==",
+ "peer": true
+ },
"wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -35657,7 +37330,6 @@
"version": "npm:wrap-ansi@7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -35709,6 +37381,36 @@
}
}
},
+ "xml": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
+ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw=="
+ },
+ "xmlbuilder2": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-3.0.2.tgz",
+ "integrity": "sha512-h4MUawGY21CTdhV4xm3DG9dgsqyhDkZvVJBx88beqX8wJs3VgyGQgAn5VreHuae6unTQxh115aMK5InCVmOIKw==",
+ "dev": true,
+ "requires": {
+ "@oozcitak/dom": "1.15.10",
+ "@oozcitak/infra": "1.0.8",
+ "@oozcitak/util": "8.3.8",
+ "@types/node": "*",
+ "js-yaml": "3.14.0"
+ },
+ "dependencies": {
+ "js-yaml": {
+ "version": "3.14.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
+ "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ }
+ }
+ },
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@@ -35761,8 +37463,39 @@
"yargs-parser": {
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="
+ },
+ "yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "peer": true,
+ "requires": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "peer": true
+ },
+ "decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+ "peer": true
+ },
+ "is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "peer": true
+ }
+ }
},
"yauzl": {
"version": "2.10.0",
@@ -35783,8 +37516,7 @@
"yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
- "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
- "dev": true
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
},
"yup": {
"version": "0.32.11",
diff --git a/web/package.json b/web/package.json
index 307a1012c..e20f3aea3 100644
--- a/web/package.json
+++ b/web/package.json
@@ -21,7 +21,7 @@
"lint:tsc": "tsc --noEmit",
"cypress:open": "cypress open",
"cypress:run": "cypress run",
- "cypress:run:ci": "NO_COLOR=1 npx cypress run --browser electron",
+ "cypress:run:ci": "NO_COLOR=1 npx cypress run --spec cypress/e2e/integration/*.cy.ts --browser electron",
"test": "concurrently -n \"unit,e2e\" --kill-others-on-fail \"npm run test:unit\" \"npm run test:e2e\"",
"test:unit": "TZ=UTC jest --config jest.config.js",
"test:e2e": "./scripts/run-cypress.sh",
@@ -32,6 +32,7 @@
},
"devDependencies": {
"@cypress/code-coverage": "^3.10.0",
+ "@cypress/grep": "^3.1.3",
"@jsdevtools/coverage-istanbul-loader": "^3.0.5",
"@openshift-console/dynamic-plugin-sdk": "^4.19.0-prerelease.1",
"@openshift-console/dynamic-plugin-sdk-webpack": "4.19",
@@ -50,7 +51,9 @@
"copy-webpack-plugin": "^13.0.1",
"css-loader": "^6.7.1",
"cypress": "^14.5.3",
+ "cypress-multi-reporters": "^1.4.0",
"cypress-terminal-report": "^3.5.2",
+ "cypress-wait-until": "^3.0.2",
"eslint": "^8.44.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
@@ -60,6 +63,8 @@
"i18next-http-backend": "^2.2.0",
"i18next-parser": "^9.3.0",
"jest": "^30.1.3",
+ "junit-report-merger": "^3.0.6",
+ "mochawesome": "^6.1.1",
"nyc": "^15.1.0",
"prettier": "^2.6.0",
"react": "17.0.2",
@@ -101,6 +106,7 @@
"@patternfly/react-table": "^5.4.15",
"@patternfly/react-virtualized-extension": "^5.1.0",
"i18next": "^22.4.12",
+ "mocha-junit-reporter": "^2.2.1",
"react-i18next": "^11.18.6",
"react-router-dom-v5-compat": "^6.30.0"
},
diff --git a/web/scripts/run-cypress-logging.sh b/web/scripts/run-cypress-logging.sh
new file mode 100755
index 000000000..27313fdb7
--- /dev/null
+++ b/web/scripts/run-cypress-logging.sh
@@ -0,0 +1,231 @@
+#!/usr/bin/env bash
+set +x
+# Author: anli@redhat.com
+# Description: Run Logging UI test using the given users.
+# prerequisite:
+# clusterlogging are deployed, appplication, infrastructure and audit logs are sent to lokistack.
+# The pod produce logs in namespaces log-test-app1,log-test-app2 unceasingly.
+# (Note: In prow, the step openshift-observability-enable-cluster-logging can prepare test data)
+# The test need at least two users in the given IDP.
+# The function enable_idp_htpasswd can create htpasswd IPD with five users
+# You can also provide IDP using Environment CYPRESS_LOGIN_IDP,CYPRESS_LOGIN_USERS.
+# The Environment KUBECONFIG must be exported.
+# The CYPRESS_SPEC can be used to specify spec. The default value is cypress/e2e/logging/*.ts
+# The CYPRESS_TAG can be used to filter cases by tag
+#
+
+## Add htpasswd IDP and Users
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+UI_USERS=""
+
+function enable_idp_htpasswd()
+{
+ echo "## Create htpasswd IDP users"
+ htpass_file="/tmp/uihtpasswd"
+ uiusers_file="/tmp/uihtpusers"
+
+ idp_list=$(oc get oauth cluster -o jsonpath='{.spec.identityProviders}')
+ if [[ $idp_list =~ "uiauto-htpasswd-idp" ]];then
+ # using existing idp if the user can login
+ echo "The idp uiauto-htpasswd-idp had been created"
+ if [[ -f $uiusers_file ]];then
+ echo "Verify if user can login uiauto-htpasswd-idp"
+ UI_USERS=$(cat $uiusers_file)
+ echo "get users from ${uiusers_file}"
+ first_record=${UI_USERS%%,*}
+ first_passwd=${first_record##*:}
+ cp $KUBECONFIG /tmp/normal_kubeconfig || exit 1
+ oc login --username=uiauto-test-1 --password=${first_passwd} --kubeconfig=/tmp/normal_kubeconfig >/dev/null 2>&1
+ if [[ $? == 0 ]];then
+ echo "Login the idp succesed, the users are in $uiusers_file"
+ echo "Enable IDP uiauto-htpasswd-idp succesfully"
+ return 0
+ else
+ echo "Can not login the idp, please remove uiauto-htpasswd-idp from oauth/cluster and re-run this script"
+ exit 1
+ fi
+ else
+ echo "Can not find users, please remove uiauto-htpasswd-idp from oauth/cluster and re-run this script"
+ exit 1
+ fi
+ fi
+
+ echo "Create new users and add uiauto-htpasswd-idpuiauto-htpasswd-idp"
+ #Create users with random password and save users
+ for i in $(seq 1 5); do
+ username="uiauto-test-${i}"
+ password=$(tr $uiusers_file
+ echo "Users are store in ${UI_USERS}"
+
+ # record current generation number
+ gen_number=$(oc -n openshift-authentication get deployment oauth-openshift -o jsonpath='{.metadata.generation}')
+
+ # add users to cluster
+ oc -n openshift-config create secret generic uiauto-htpass-secret || true
+ oc -n openshift-config set data secret/uiauto-htpass-secret --from-file=htpasswd=${htpass_file} -n openshift-config || exit 1
+
+ idp_list=$(oc get oauth cluster -o jsonpath='{.spec.identityProviders}')
+ if [[ $idp_list == "" || $idp_list == "{}" ]];then
+ oc patch oauth cluster --type='json' -p='[{"op": "add", "path": "/spec/identityProviders", "value": [{"type": "HTPasswd", "name": "uiauto-htpasswd-idp", "mappingMethod": "claim", "htpasswd":{"fileData":{"name": "uiauto-htpass-secret"}}}]}]' || exit 1
+ else
+ oc patch oauth cluster --type='json' -p='[{"op": "add", "path": "/spec/identityProviders/-", "value": {"type": "HTPasswd", "name": "uiauto-htpasswd-idp", "mappingMethod": "claim", "htpasswd":{"fileData":{"name": "uiauto-htpass-secret"}}}}]' || exit 1
+ fi
+
+ echo "Wait up to 5 minutes for new idp take effect"
+ expected_replicas=$(oc -n openshift-authentication get deployment oauth-openshift -o jsonpath='{.spec.replicas}')
+ count=1
+ while [[ $count -le 6 ]]; do
+ echo "try the ${count} time "
+ available_replicas=$(oc -n openshift-authentication get deployment oauth-openshift -o jsonpath='{.status.availableReplicas}')
+ new_gen_number=$(oc get -n openshift-authentication deployment oauth-openshift -o jsonpath='{.metadata.generation}')
+ if [[ $expected_replicas == "$available_replicas" && $((new_gen_number)) -gt $((gen_number)) ]]; then
+ break
+ else
+ sleep 30s
+ fi
+ (( count=count+1 ))
+ done
+
+ echo "Verify if uiauto-htpasswd-idp works"
+ echo "Login as the new user"
+ cp $KUBECONFIG /tmp/normal_kubeconfig || exit 1
+ first_record=${UI_USERS%%,*}
+ first_passwd=${first_record##*:}
+
+ echo "oc login -u uiauto-test-1 -p --config=/tmp/normal_kubeconfig"
+ oc login --username=uiauto-test-1 --password=${first_passwd} --kubeconfig=/tmp/normal_kubeconfig >/dev/null 2>&1 || exit 1
+ echo "Enable IDP uiauto-htpasswd-idp succesfully"
+}
+
+function check_clusterlogging(){
+ echo "## Verify test data are ready for Logging UI Test"
+
+ echo "Check if the clusterlogging are are ready"
+ lokistack_name=$(oc get lokistack -n openshift-logging -o jsonpath={.items[0].metadata.name})
+ if [[ $lokistack_name == "" ]]; then
+ echo "No lokistack can be found in openshift-logging namespace"
+ exit 1
+ fi
+ echo "Warnig, lokistack ${lokistack_name} is selected, please confirm if that is the one you are using in openshift-logging"
+ oc -n openshift-logging wait pod --for=condition=ready -l app.kubernetes.io/instance=${lokistack_name} || exit 1
+ oc -n openshift-logging wait pod --for=condition=ready -l app.kubernetes.io/component=collector || exit 1
+
+
+ echo "Check if there are running test pods in log-test-app1 and log-test-app2"
+ oc -n log-test-app1 wait pod --for=condition=ready -l test=centos-logtest || exit 1
+ oc -n log-test-app2 wait pod --for=condition=ready -l test=centos-logtest || exit 1
+
+ echo "Check if logs can be found in lokistack"
+ lokistack_route=$(oc -n openshift-logging get route ${lokistack_name} -n openshift-logging -o json |jq '.spec.host' -r)
+ oc -n openshift-logging create sa lokistack-query >/dev/null 2>&1
+ oc -n openshift-logging adm policy add-cluster-role-to-user cluster-admin -z lokistack-query
+ oc -n openshift-logging adm policy add-cluster-role-to-user cluster-logging-application-view -z lokistack-query
+ oc -n openshift-logging adm policy add-cluster-role-to-user cluster-logging-audit-view -z lokistack-query
+ oc -n openshift-logging adm policy add-cluster-role-to-user cluster-logging-infrastructure-view -z lokistack-query
+
+ bearer_token=$(oc -n openshift-logging create token lokistack-query)
+
+ echo "Verify infrastructure logs in lokistack"
+ rm /tmp/loki_query.txt
+ curl -s -G -k -H "Authorization: Bearer ${bearer_token}" https://${lokistack_route}/api/logs/v1/infrastructure/loki/api/v1/query_range --data-urlencode 'query={log_type="infrastructure"}' --data-urlencode 'limit=1' -o /tmp/loki_query.txt
+ if [[ $(cat /tmp/loki_query.txt |jq '.data.result|length') == 1 ]]; then
+ echo "Found infrastructure logs"
+ else
+ echo "Exit, can not find infrastructure logs"
+ cat /tmp/loki_query.txt
+ exit 1
+ fi
+
+ echo "Verify application logs in lokistack"
+ rm /tmp/loki_query.txt
+ curl -s -G -k -H "Authorization: Bearer ${bearer_token}" https://${lokistack_route}/api/logs/v1/application/loki/api/v1/query_range --data-urlencode 'query={log_type="application"}' --data-urlencode 'limit=1' -o /tmp/loki_query.txt
+ if [[ $(cat /tmp/loki_query.txt |jq '.data.result|length') == 1 ]]; then
+ echo "Found application logs"
+ else
+ echo "Exit, can not find application logs"
+ cat /tmp/loki_query.txt
+ fi
+
+ echo "Verify audit logs in lokistack"
+ rm /tmp/loki_query.txt
+ curl -s -G -k -H "Authorization: Bearer ${bearer_token}" https://${lokistack_route}/api/logs/v1/audit/loki/api/v1/query_range --data-urlencode 'query={log_type="audit"}' --data-urlencode 'limit=1' -o /tmp/loki_query.txt
+ if [[ $(cat /tmp/loki_query.txt |jq '.data.result|length') == 1 ]]; then
+ echo "Found audit logs"
+ else
+ echo "Exit, can not find audit logs"
+ cat /tmp/loki_query.txt
+ exit 1
+ fi
+}
+
+########Main###################
+if [[ $KUBECONFIG == "" ]]; then
+ echo "Exit, you must expose the Environment KUBECONFIG"
+ exit 1
+fi
+
+export CYPRESS_BASE_URL="https://$(oc get route console -n openshift-console -o jsonpath={.spec.host})"
+export CYPRESS_OPENSHIFT_VERSION=$(oc version -o json |jq -r '.openshiftVersion'|cut -f 1,2 -d.)
+clusterlogging_csv=$(oc -n openshift-logging get csv -l "operators.coreos.com/cluster-logging.openshift-logging" -o jsonpath='{.items[0].metadata.name}')
+if [[ $clusterlogging_csv == "" ]];then
+ echo "can not find the cluster-logging csv"
+ exit 1
+fi
+clusterlogging_csv_version=${clusterlogging_csv#cluster-logging.v}
+export CYPRESS_CLUSTERLOGGING_VERSION=$(echo $clusterlogging_csv_version|cut -d. -f1,2)
+
+coo_csv=$(oc get csv -l olm.copiedFrom"="openshift-cluster-observability-operator -o jsonpath='{.items[0].metadata.name}')
+export CYPRESS_COO_VERSION=${coo_csv//cluster-observability-operator.v}
+
+data_mode=$(oc get uiplugin logging -o jsonpath='{.spec.logging.schema}')
+if [[ "$data_mode" == "" ]];then
+ data_mode="viaq"
+fi
+export CYPRESS_CLUSTERLOGGING_DATAMODE=${data_mode}
+
+check_clusterlogging
+
+if [[ "$CYPRESS_LOGIN_IDP" == "" || "$CYPRESS_LOGIN_USERS" == "" ]];then
+ enable_idp_htpasswd
+ export CYPRESS_LOGIN_IDP=uiauto-htpasswd-idp
+ export CYPRESS_LOGIN_USERS=$UI_USERS
+fi
+if [[ $CYPRESS_LOGIN_USERS == "" ]];then
+ echo "Please set correct Env CYPRESS_LOGIN_USERS and CYPRESS_LOGIN_IDP or leave these two Env unset"
+ exit 1
+fi
+
+echo "export KUBECONFIG=${KUBECONFIG}"
+echo "export CYPRESS_BASE_URL=$CYPRESS_BASE_URL"
+echo "export CYPRESS_LOGIN_IDP=$CYPRESS_LOGIN_IDP"
+echo "export CYPRESS_LOGIN_USERS=$CYPRESS_LOGIN_USERS"
+echo "export CYPRESS_OPENSHIFT_VERSION=$CYPRESS_OPENSHIFT_VERSION"
+echo "export CYPRESS_CLUSTERLOGGING_VERSION=$CYPRESS_CLUSTERLOGGING_VERSION"
+echo "export CYPRESS_CLUSTERLOGGING_DATAMODE=$CYPRESS_CLUSTERLOGGING_DATAMODE"
+echo "export CYPRESS_COO_VERSION=${CYPRESS_COO_VERSION}"
+
+echo "## Execute Cypress cases"
+script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+cd $script_dir/../
+
+cypress_args=""
+if [[ "$CYPRESS_SPEC" == "" ]];then
+ cypress_args=" --spec $(ls ${SCRIPT_DIR}/../cypress/e2e/logging/*.ts|paste -sd ',' -)"
+else
+ cypress_args=" --spec ${CYPRESS_SPEC}"
+fi
+if [[ "$CYPRESS_TAG" != "" ]]; then
+ cypress_args="$cypress_args --env grep=${CYPRESS_TAG// /}"
+fi
+echo "npx cypress run --e2e ${cypress_args}"
+npx cypress run --e2e ${cypress_args}