Skip to content

Commit

Permalink
cypress a11y: expanded coverage, improved reporting
Browse files Browse the repository at this point in the history
  • Loading branch information
dtaylor113 committed Sep 22, 2020
1 parent b6ffd5a commit 4d3cafb
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 86 deletions.
39 changes: 0 additions & 39 deletions frontend/integration-tests/tests/crud.scenario.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,43 +237,4 @@ describe('Kubernetes resource CRUD operations', () => {
leakedResources.delete(JSON.stringify({ name, plural, namespace: testName }));
});
});

describe('Visiting other routes', () => {
const otherRoutes = [
'/',
'/k8s/cluster/clusterroles/view',
'/k8s/cluster/nodes',
'/k8s/all-namespaces/events',
'/k8s/all-namespaces/import',
'/api-explorer',
'/api-resource/ns/default/core~v1~Pod',
'/api-resource/ns/default/core~v1~Pod/schema',
'/api-resource/ns/default/core~v1~Pod/instances',
...(browser.params.openshift === 'true'
? [
'/api-resource/ns/default/core~v1~Pod/access',
'/k8s/cluster/user.openshift.io~v1~User',
'/k8s/ns/openshift-machine-api/machine.openshift.io~v1beta1~Machine',
'/k8s/ns/openshift-machine-api/machine.openshift.io~v1beta1~MachineSet',
'/k8s/ns/openshift-machine-api/autoscaling.openshift.io~v1beta1~MachineAutoscaler',
'/k8s/ns/openshift-machine-api/machine.openshift.io~v1beta1~MachineHealthCheck',
'/k8s/cluster/machineconfiguration.openshift.io~v1~MachineConfig',
'/k8s/cluster/machineconfiguration.openshift.io~v1~MachineConfigPool',
'/k8s/all-namespaces/monitoring.coreos.com~v1~Alertmanager',
'/k8s/ns/openshift-monitoring/monitoring.coreos.com~v1~Alertmanager/main',
'/settings/cluster',
'/monitoring/query-browser',
// Test loading search page for a kind with no static model.
'/search/all-namespaces?kind=config.openshift.io~v1~Console',
]
: []),
];
otherRoutes.forEach((route) => {
it(`successfully displays view for route: ${route}`, async () => {
await browser.get(`${appHost}${route}`);
await browser.sleep(5000);
expect(crudView.errorPage.isPresent()).toBe(false);
});
});
});
});
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"test-cypress-headless": "cd packages/integration-tests-cypress && node --max-old-space-size=4096 ../../node_modules/.bin/cypress run --env openshift=true --browser ${BRIDGE_E2E_BROWSER_NAME:=chrome} --headless",
"cypress-merge": "mochawesome-merge ./gui_test_screenshots/cypress_report*.json > ./gui_test_screenshots/cypress.json",
"cypress-generate": "marge -o ./gui_test_screenshots/ -f cypress-report -t 'OpenShift Console Cypress Test Results' -p 'OpenShift Cypress Test Results' --showPassed false --assetsDir ./gui_test_screenshots/cypress/assets ./gui_test_screenshots/cypress.json",
"cypress-postreport": "yarn run cypress-merge && yarn run cypress-generate && rm -f ./gui_test_screenshots/cypress*.json",
"cypress-a11y-report": "echo '\nA11y Test Results:' && mv packages/integration-tests-cypress/cypress-a11y-report.json ./gui_test_screenshots/ && node -e \"console.table(JSON.parse(require('fs').readFileSync(process.argv[1])));\" ./gui_test_screenshots/cypress-a11y-report.json",
"cypress-postreport": "yarn run cypress-merge && yarn run cypress-generate && yarn run cypress-a11y-report",
"debug-test-suite": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' node -r ts-node/register --inspect-brk ./node_modules/.bin/protractor integration-tests/protractor.conf.ts",
"analyze": "NODE_ENV=production NODE_OPTIONS=--max-old-space-size=4096 ts-node -O '{\"module\":\"commonjs\"}' ./node_modules/.bin/webpack --mode=production --profile --json | awk '{if(NR>2)print}' > public/dist/stats.json && ts-node -O '{\"module\":\"commonjs\"}' ./node_modules/.bin/webpack-bundle-analyzer --mode static -r public/dist/report.html public/dist/stats.json",
"prettier-all": "prettier --write '**/*.{js,jsx,ts,tsx,json}'",
Expand Down
7 changes: 7 additions & 0 deletions frontend/packages/integration-tests-cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
const wp = require('@cypress/webpack-preprocessor');
const fs = require('fs');

module.exports = (on, config) => {
const options = {
Expand Down Expand Up @@ -33,6 +34,12 @@ module.exports = (on, config) => {
console.table(data);
return null;
},
readFileIfExists(filename) {
if (fs.existsSync(filename)) {
return fs.readFileSync(filename, 'utf8');
}
return null;
},
});
on('file:preprocessor', wp(options));
/* In a Docker container, the default size of the /dev/shm shared memory space is 64MB. This is not typically enough
Expand Down
60 changes: 60 additions & 0 deletions frontend/packages/integration-tests-cypress/support/a11y.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import 'cypress-jest-adapter';
import 'cypress-axe';
import { Result } from 'axe-core';

declare global {
namespace Cypress {
interface Chainable<Subject> {
logA11yViolations(violations: Result[], target: string): Chainable<Element>;
testA11y(target: string): Chainable<Element>;
}
}
}

export const a11yTestResults: a11yTestResultsType = {
numberViolations: 0,
numberChecks: 0,
};

Cypress.Commands.add('logA11yViolations', (violations: Result[], target: string) => {
// pluck specific keys to keep the table readable
const violationData = violations.map(({ id, impact, description, nodes }) => ({
id,
impact,
description,
nodes: nodes.length,
}));
a11yTestResults.numberViolations += violations.length;
cy.task(
'log',
`${violations.length} accessibility violation${violations.length === 1 ? '' : 's'} ${
violations.length === 1 ? 'was' : 'were'
} detected ${target ? `for ${target}` : ''}`,
);
cy.task('logTable', violationData);
});

Cypress.Commands.add('testA11y', (target: string) => {
cy.injectAxe();
cy.configureAxe({
rules: [
{ id: 'color-contrast', enabled: false }, // seem to be somewhat inaccurate and has difficulty always picking up the correct colors, tons of open issues for it on axe-core
{ id: 'focusable-content', enabled: false }, // recently updated and need to give the PF team time to fix issues before enabling
{ id: 'scrollable-region-focusable', enabled: false }, // recently updated and need to give the PF team time to fix issues before enabling
],
});
a11yTestResults.numberChecks += 1;
cy.checkA11y(
null,
{
includedImpacts: ['serious', 'critical'],
},
(violations) => cy.logA11yViolations(violations, target),
true,
);
});

type a11yTestResultsType = {
numberViolations: number;
numberChecks: number;
};
63 changes: 20 additions & 43 deletions frontend/packages/integration-tests-cypress/support/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,34 @@ import './project';
import './selectors';
import './nav';
import './resources';
import 'cypress-jest-adapter';
import 'cypress-axe';
import { Result } from 'axe-core';

declare global {
namespace Cypress {
interface Chainable<Subject> {
logA11yViolations(violations: Result[], target: string): Chainable<Element>;
testA11y(target: string): Chainable<Element>;
}
}
}
import { a11yTestResults } from './a11y';

Cypress.Cookies.defaults({
preserve: ['openshift-session-token', 'csrf-token'],
});

Cypress.Commands.add('logA11yViolations', (violations: Result[], target: string) => {
// pluck specific keys to keep the table readable
const violationData = violations.map(({ id, impact, description, nodes }) => ({
id,
impact,
description,
nodes: nodes.length,
}));
cy.task(
'log',
`${violations.length} accessibility violation${violations.length === 1 ? '' : 's'} ${
violations.length === 1 ? 'was' : 'were'
} detected ${target ? `for ${target}` : ''}`,
);
cy.task('logTable', violationData);
before(() => {
cy.task('readFileIfExists', 'cypress-a11y-report.json').then((a11yReportOrNull) => {
if (a11yReportOrNull !== null) {
try {
const a11yReport = JSON.parse(a11yReportOrNull);
a11yTestResults.numberViolations = Number(a11yReport.numberViolations);
a11yTestResults.numberChecks = Number(a11yReport.numberChecks);
return;
} catch (e) {
cy.task('logError', `couldn't parse cypress-a11y-results.json. ${e}`);
}
}
a11yTestResults.numberViolations = 0;
a11yTestResults.numberChecks = 0;
});
});

Cypress.Commands.add('testA11y', (target: string) => {
cy.injectAxe();
cy.configureAxe({
rules: [
{ id: 'color-contrast', enabled: false }, // seem to be somewhat inaccurate and has difficulty always picking up the correct colors, tons of open issues for it on axe-core
{ id: 'focusable-content', enabled: false }, // recently updated and need to give the PF team time to fix issues before enabling
{ id: 'scrollable-region-focusable', enabled: false }, // recently updated and need to give the PF team time to fix issues before enabling
],
after(() => {
cy.writeFile('cypress-a11y-report.json', {
numberChecks: `${a11yTestResults.numberChecks}`,
numberViolations: `${a11yTestResults.numberViolations}`,
});
cy.checkA11y(
null,
{
includedImpacts: ['serious', 'critical'],
},
(violations) => cy.logA11yViolations(violations, target),
true,
);
});

export const checkErrors = () =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ describe('Namespace', () => {
listPage.rows.shouldNotExist(newName);
listPage.filter.byName(testName);
listPage.rows.shouldExist(testName); // created via cy.createProject(testName) above
cy.testA11y('Namespace List page');

cy.log('creates the Namespace');
listPage.clickCreateYAMLbutton();
modal.shouldBeOpened();
cy.byTestID('input-name').type(newName);
cy.testA11y('Create Namespace modal');
modal.submit();
modal.shouldBeClosed();
cy.url().should('include', `/k8s/cluster/namespaces/${newName}`);
Expand All @@ -41,6 +43,7 @@ describe('Namespace', () => {
listPage.rows.clickKebabAction(newName, 'Delete Namespace');
modal.shouldBeOpened();
cy.byTestID('project-name-input').type(newName);
cy.testA11y('Delete Namespace modal');
modal.submit();
modal.shouldBeClosed();
listPage.rows.shouldNotExist(newName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { checkErrors } from '../../support';

describe('Visiting other routes', () => {
before(() => {
cy.login();
});

afterEach(() => {
checkErrors();
});

after(() => {
cy.logout();
});

const otherRoutes = [
'/',
'/k8s/cluster/clusterroles/view',
'/k8s/cluster/nodes',
'/k8s/all-namespaces/events',
'/k8s/all-namespaces/import',
'/api-explorer',
'/api-resource/ns/default/core~v1~Pod',
'/api-resource/ns/default/core~v1~Pod/schema',
'/api-resource/ns/default/core~v1~Pod/instances',
...(Cypress.env('openshift') === true
? [
'/api-resource/ns/default/core~v1~Pod/access',
'/k8s/cluster/user.openshift.io~v1~User',
'/k8s/ns/openshift-machine-api/machine.openshift.io~v1beta1~Machine',
'/k8s/ns/openshift-machine-api/machine.openshift.io~v1beta1~MachineSet',
'/k8s/ns/openshift-machine-api/autoscaling.openshift.io~v1beta1~MachineAutoscaler',
'/k8s/ns/openshift-machine-api/machine.openshift.io~v1beta1~MachineHealthCheck',
'/k8s/cluster/machineconfiguration.openshift.io~v1~MachineConfig',
'/k8s/cluster/machineconfiguration.openshift.io~v1~MachineConfigPool',
'/k8s/all-namespaces/monitoring.coreos.com~v1~Alertmanager',
'/k8s/ns/openshift-monitoring/monitoring.coreos.com~v1~Alertmanager/main',
'/settings/cluster',
'/monitoring/query-browser',
// Test loading search page for a kind with no static model.
'/search/all-namespaces?kind=config.openshift.io~v1~Console',
]
: []),
];
otherRoutes.forEach((route) => {
it(`successfully displays view for route: ${route}`, () => {
cy.visit(`${route}`);
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(5000); // wait for page to load
cy.byLegacyTestID('error-page').should('not.be.visible');
cy.testA11y(`${route} page`);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ describe('Monitoring: Alerts', () => {
cy.byLegacyTestID('resource-title').should('have.text', 'Alerting');
listPage.projectDropdownShouldNotExist();
listPage.rows.shouldBeLoaded();
cy.testA11y('Monitor Alerting list page');

cy.log('filter Alerts');
listPage.filter.byName('Watchdog');
Expand All @@ -53,12 +54,14 @@ describe('Monitoring: Alerts', () => {
cy.log('drills down to Alert details page');
listPage.rows.shouldExist('Watchdog').click();
shouldBeWatchdogAlertDetailsPage();
cy.testA11y('Alerting details page');

cy.log('drill down to the Alerting Rule details page');
cy.byTestID('alert-rules-detail-resource-link')
.contains('Watchdog')
.click();
shouldBeWatchdogAlertRulesPage();
cy.testA11y('Alerting Rule details page');

cy.log('drill back up to the Alert details page');
// Active Alerts list should contain a link back to the Alert details page
Expand Down Expand Up @@ -88,7 +91,7 @@ describe('Monitoring: Alerts', () => {
// Change duration
cy.byLegacyTestID('dropdown-button')
.click()
.get(`[data-test-dropdown-menu="1h"]`)
.get('[data-test-dropdown-menu="1h"]')
.click();
cy.byTestID('until').should('have.value', '1h from now');
// Change to not start now
Expand Down Expand Up @@ -116,15 +119,16 @@ describe('Monitoring: Alerts', () => {
// Change duration back again
cy.byLegacyTestID('dropdown-button')
.click()
.get(`[data-test-dropdown-menu="2h"]`)
.get('[data-test-dropdown-menu="2h"]')
.click();
cy.byTestID('until').should('have.value', '2h from now');
// add comment and submit
cy.byTestID('silence-comment').type('test comment');
cy.testA11y('Silence Alert form');
cy.get(submitButton).click();
cy.get(errorMessage).should('not.exist');
shouldBeWatchdogSilencePage();

cy.testA11y('Silence details page');
cy.log('shows the silenced Alert in the Silenced Alerts list');
// Click the link to navigate back to the Alert details link
cy.byTestID('firing-alerts')
Expand All @@ -144,6 +148,7 @@ describe('Monitoring: Alerts', () => {
cy.log('expires the Silence');
detailsPage.clickPageActionFromDropdown('Expire Silence');
modal.shouldBeOpened();
cy.testA11y('Expire Silence modal');
modal.submit();
modal.shouldBeClosed();
cy.get(errorMessage).should('not.exist');
Expand Down

0 comments on commit 4d3cafb

Please sign in to comment.