Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ test: test-frontend
test-frontend: lint-frontend
cd web && npm run test:unit

.PHONY: test-e2e
test-e2e:
cd web && npm install && npm run test:e2e

.PHONY: install-frontend
install-frontend:
cd web && npm install
Expand Down
116 changes: 116 additions & 0 deletions web/cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { defineConfig } from 'cypress';
import path from 'path';
import fs from 'fs';

// Plugins
import registerCodeCoverage from '@cypress/code-coverage/task';
import cypressGrepPlugin from '@cypress/grep/src/plugin';

const reportDir = process.env.ARTIFACT_DIR || '/tmp';

Comment thread
anpingli marked this conversation as resolved.
export default defineConfig({
// --- General Settings ---
fixturesFolder: 'fixtures',
defaultCommandTimeout: 30000,
viewportWidth: 1600,
viewportHeight: 1200,
retries: {
runMode: 0,
openMode: 0,
},

// --- Artifacts & Reporting ---
screenshotsFolder: path.join(reportDir, 'cypress', 'screenshots'),
screenshotOnRunFailure: true,
trashAssetsBeforeRuns: true,
videosFolder: path.join(reportDir, 'cypress', 'videos'),
video: true,
Comment thread
anpingli marked this conversation as resolved.
videoCompression: false,

reporter: './node_modules/cypress-multi-reporters',
reporterOptions: {
reporterEnabled: 'mocha-junit-reporter, mochawesome',
mochaJunitReporterReporterOptions: {
mochaFile: path.join(reportDir, 'junit_cypress-[hash].xml'),
toConsole: false,
},
mochawesomeReporterOptions: {
reportDir: reportDir,
reportFilename: 'cypress_report',
overwrite: false,
html: false,
json: true,
},
},

// --- Environment Variables ---
env: {
grepFilterSpecs: false,
KUBECONFIG_PATH: process.env.KUBECONFIG,
OPENSHIFT_VERSION: process.env.CYPRESS_OPENSHIFT_VERSION,
OPENSHIFT_LOGGING_ENABLED: process.env.CYPRESS_OPENSHIFT_LOGGING_ENABLED === 'true',
OPENSHIFT_TRACING_ENABLED: process.env.CYPRESS_OPENSHIFT_TRACING_ENABLED === 'false',
OPENSHIFT_NETOBS_ENABLED: process.env.CYPRESS_OPENSHIFT_NETOBS_ENABLED === 'false',
},

// --- E2E Specific Configuration ---
e2e: {
baseUrl: process.env.CYPRESS_BASE_URL || process.env.BASE_URL || 'http://localhost:9003',
pageLoadTimeout: 300000, // 5 minutes
supportFile: './cypress/support/e2e.ts',
specPattern: './cypress/e2e/*.cy.{js,jsx,ts,tsx}',
testIsolation: false,
numTestsKeptInMemory: 1,

// Experimental Features
experimentalModifyObstructiveThirdPartyCode: true,
experimentalOriginDependencies: true,
experimentalMemoryManagement: true,
experimentalCspAllowList: ['default-src', 'script-src'],

setupNodeEvents(on, config) {
// --- Register Plugins ---
registerCodeCoverage(on, config);
cypressGrepPlugin(config);

// --- Browser Launch ---
on('before:browser:launch', (browser, launchOptions) => {
if (browser.family === 'chromium' && browser.name !== 'electron') {
launchOptions.args.push('--enable-precise-memory-info');
}
return launchOptions;
});

// --- Custom Tasks ---
on('task', {
log: (msg) => { console.log(msg); return null; },
logError: (msg) => { console.error(msg); return null; },
logTable: (data) => { console.table(data); return null; },
readFileIfExists: (filename) => fs.existsSync(filename) ? fs.readFileSync(filename, 'utf8') : null,
});

// --- Screenshot Rename Logic ---
on('after:screenshot', async (details) => {
const pathObj = path.parse(details.path);
const timestamp = Date.now();
const newPath = path.join(pathObj.dir, `${timestamp}_${pathObj.base}`);
await fs.promises.rename(details.path, newPath);
return { path: newPath };
});

// --- Video Cleanup ---
on('after:spec', (spec, results) => {
if (results?.video) {
const hasFailures = results.tests?.some((test) =>
test.attempts.some((attempt) => attempt.state === 'failed')
);
if (!hasFailures && fs.existsSync(results.video)) {
fs.unlinkSync(results.video);
}
}
});

return config;
},
},
});
96 changes: 96 additions & 0 deletions web/cypress/e2e/acceptance.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import * as dt from '../fixtures/data-test'

describe('TroubleShoot Test', { tags: ['@admin'] }, () => {
before( function() {
cy.uiLoginAsClusterAdminForUser("first");
cy.openTroubleshootPanel();

});

after( function() {
cy.closeTroubleshootPanel();
cy.uiLogoutClusterAdminForUser("first");
});

it('Essential elements validation when focus on Alerting',{tags:['@smoke']}, () => {
cy.clickNavLink(['Observe', 'Alerting']);
cy.openTroubleshootPanel();

//Elements in Title
cy.get(dt.Classes.TroubleShootPanelPopoverTitleBar)
.should('exist')
.within(() => {
cy.contains('h1', 'Troubleshooting');
cy.get('h1').find('button').should('exist')
cy.get('button[aria-label="Close"]').should('exist');
cy.get(dt.Classes.TroubleShootPanelPopoverClose).should('exist');
})

//Elements in Toolbar
cy.get(dt.Classes.TroubleShootPanelToolBar)
.should('exist')
.within(() => {
cy.contains('button','Focus');
//timepicker button
cy.contains('button', 'Last 1 hours');
//Advanced button
cy.get('div[aria-label="Advanced search parameters"]').should('exist');
//The refresh button exists
cy.get('button[aria-label="Refresh"]').should('exist');
})

//focus on Observe->Alerting
cy.focusTroubleshootPanel();

//Elements under in Advance Container
cy.clickTroubleshootPanelAdvance();
cy.get(dt.Classes.TroubleShootPanelToolBarAdvanced)
.find('form')
.within(() => {
cy.contains('label', 'Start Query');
cy.contains('div', 'Select starting data');
cy.get('textarea[id="query-input"]')
.should('exist')
.should('have.value', 'alert:alert:{}');
cy.contains('label', 'Search Type');
cy.contains('div', 'Neighbours or Goal search');
cy.contains('button', 'Neighbours');
cy.get('button[aria-label="Minus"]').should('exist');
cy.get('input[value="3"]').should('exist');
cy.get('button[aria-label="Plus"]').should('exist');
cy.contains('div', 'hops');
cy.contains('button', 'Search');
cy.contains('button', 'Cancel');
});

//Elements under in topology-container
cy.get(dt.Classes.TroubleShootPanelTopologyContainer).should('exist');
cy.get('div[data-test-id="topology"]').should('exist');
cy.get('g[data-id="korrel8r_graph"]')
.within(() => {
cy.get('ellipse').should('exist'); // node
cy.get(dt.Classes.TroubleShootPanelTopologyNodeLabel).should('exist'); // text panels
cy.get(dt.Classes.TroubleShootPanelTopologyNodeBackGroud).should('exist'); //backgroup panels
cy.get('g[data-test-id="edge-handler"]').should('exist'); // lines
})
cy.get(dt.Classes.TroubleShootPanelTopologyGraphControlBar)
.within(() => {
cy.get('button[id="zoom-in"]').should('exist');
cy.get('button[id="zoom-out"]').should('exist');
cy.get('button[id="reset-view"]').should('exist');
})
//Two nodes in topology-container when focus on Observe->alerting
cy.get('g[data-id="korrel8r_graph"]') // get the parent <g>
.find('g[data-id="alert:alert"]') // find the child <g>
.should('exist')
.find('text')
.contains('Alert')
.should('exist')
cy.get('g[data-id="korrel8r_graph"]') // get the parent <g>
.find('g[data-id="metric:metric"]') // find the child <g>
.should('exist')
.find('text')
.contains('Metric')
.should('exist')
});
})
Loading