Skip to content

Commit

Permalink
Merge pull request #372 from cisagov/Playwright_Accessibility_Testing
Browse files Browse the repository at this point in the history
Update Playwright for Login.gov and Accessibility Testing
  • Loading branch information
JCantu248 authored Aug 20, 2024
2 parents 9c25ff5 + 667a56b commit 22c6de7
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 185 deletions.
6 changes: 1 addition & 5 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: Playwright Tests
name: UI Testing
on:
deployment_status:
push:
Expand All @@ -13,10 +13,6 @@ jobs:
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.41.2-jammy
# TODO: Refactor action to use updated logic for Login.gov
# when a service account to run tests is available for use.
# Issue: CRASH-337
if: true == false
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
Expand Down
27 changes: 27 additions & 0 deletions playwright/axe-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { test as base, defineConfig } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
import { describe } from 'node:test';
import { configure } from 'axe-core';

type AxeFixture = {
makeAxeBuilder: () => AxeBuilder;
};

// Extend base test by providing "makeAxeBuilder"
//
// This new "test" can be used in multiple test files, and each of them will get
// a consistently configured AxeBuilder instance.
export const test = base.extend<AxeFixture>({
makeAxeBuilder: async ({ page }, use, testInfo) => {
const makeAxeBuilder = () =>
new AxeBuilder({ page }).withTags([
'wcag2a',
'wcag2aa',
'wcag21a',
'wcag21aa'
]);
await use(makeAxeBuilder);
}
});
export { expect } from '@playwright/test';
export { Page } from '@playwright/test';
84 changes: 25 additions & 59 deletions playwright/e2e/global-admin/home.spec.ts
Original file line number Diff line number Diff line change
@@ -1,66 +1,32 @@
import { test, expect, Page } from '@playwright/test';
import exp from 'constants';
import { describe } from 'node:test';

test.describe.configure({ mode: 'serial' });
let page: Page;
const { test, expect, Page } = require('../../axe-test');

test.beforeAll(async ({ browser }) => {
page = await browser.newPage();
await page.goto('/');
});
test.describe.configure({ mode: 'parallel' });
let page: InstanceType<typeof Page>;

test.afterAll(async () => {
await page.close();
});
test('home', async () => {
// Expect home page to show Latest Vulnerabilities.
await expect(
page.getByRole('heading', { name: 'Latest Vulnerabilities' })
).toBeVisible();
await expect(
page.getByRole('heading', { name: 'Open Vulnerabilities by Domain' })
).toBeVisible();
await expect(
page.getByRole('heading', { name: 'Most Common Ports' })
).toBeVisible();
await expect(
page.getByRole('heading', { name: 'Most Common Vulnerabilities' })
).toBeVisible();
await expect(
page.getByRole('heading', { name: 'Severity Levels' })
).toBeVisible();
await expect(
page.getByPlaceholder('Search a domain, vuln, port, service, IP')
).toBeVisible();
await expect(page.getByRole('link', { name: 'Inventory' })).toBeVisible();
await page.screenshot({ path: 'test-results/img/global-admin/home.png' });
});
test.describe('home', () => {
test.beforeEach(async ({ browser }) => {
const context = await browser.newContext();
page = await context.newPage();
await page.goto('/');
});

test('Open Vulnerabilities by Domain', async () => {
await page.getByRole('button', { name: 'All' }).click();
await page.screenshot({
path: 'test-results/img/global-admin/open_vuln_all.png'
test.afterEach(async () => {
await page.close();
});
if (
(await page.getByRole('button', { name: 'Medium' }).isDisabled()) == false
) {
await page.getByRole('button', { name: 'Medium' }).click();
await page.screenshot({
path: 'test-results/img/global-admin/open_vuln_medium.png'
});
}
if (
(await page.getByRole('button', { name: 'High' }).isDisabled()) == false
) {
await page.getByRole('button', { name: 'High' }).click();
await page.screenshot({
path: 'test-results/img/global-admin/open_vuln_high.png'

test('Test homepage accessibility', async ({
page,
makeAxeBuilder
}, testInfo) => {
const accessibilityScanResults = await makeAxeBuilder().analyze();

await testInfo.attach('accessibility-scan-results', {
body: JSON.stringify(accessibilityScanResults, null, 2),
contentType: 'application/json'
});
}
if ((await page.getByLabel('Go to next page').isDisabled()) == false) {
await page.getByLabel('Go to next page').click();
}
if ((await page.getByLabel('Go to previous page').isDisabled()) == false) {
await page.getByLabel('Go to previous page').click();
}

expect(accessibilityScanResults.violations).toHaveLength(0);
});
});
136 changes: 74 additions & 62 deletions playwright/e2e/global-admin/inventory.spec.ts
Original file line number Diff line number Diff line change
@@ -1,72 +1,84 @@
import { test, expect, chromium, Page } from '@playwright/test';
import { describe } from 'node:test';

test.describe.configure({ mode: 'serial' });
let page: Page;
const { test, expect, Page } = require('../../axe-test');

test.beforeAll(async ({ browser }) => {
page = await browser.newPage();
await page.goto('/');
});
test.describe.configure({ mode: 'parallel' });
let page: InstanceType<typeof Page>;

test.afterAll(async () => {
await page.close();
});
test('Inventory', async () => {
await page.getByRole('link', { name: 'Inventory' }).click();
await expect(page).toHaveURL('/inventory');
await page.getByRole('button', { name: 'IP(s)' }).click();
await page.getByRole('button', { name: 'Severity' }).click();
await page.getByLabel('Sort by:').first().click();
await page.getByRole('option', { name: 'Domain Name' }).click();
await page.getByLabel('Sort by:').first().click();
await page.getByRole('option', { name: 'IP' }).click();
await page.getByLabel('Sort by:').first().click();
await page.getByRole('option', { name: 'Last Seen' }).click();
await page.getByLabel('Sort by:').first().click();
await page.getByRole('option', { name: 'First Seen' }).click();
await page.screenshot({
path: 'test-results/img/global-admin/inventory.png'
test.describe('Inventory', () => {
test.beforeEach(async ({ browser }) => {
const context = await browser.newContext();
page = await context.newPage();
await page.goto('/');
});
});

test('Domains', async () => {
await page.goto('/inventory');
await page.getByRole('link', { name: 'All Domains' }).click();
await expect(page).toHaveURL('/inventory/domains');
if ((await page.getByLabel('Go to next page').isDisabled()) == false) {
await page.getByLabel('Go to next page').click();
}
if ((await page.getByLabel('Go to previous page').isDisabled()) == false) {
await page.getByLabel('Go to previous page').click();
}
await page.screenshot({ path: 'test-results/img/global-admin/domains.png' });
});
test.afterEach(async () => {
await page.close();
});
test('Test inventory accessibility', async ({ makeAxeBuilder }, testInfo) => {
await page.getByRole('link', { name: 'Inventory' }).click();
await expect(page).toHaveURL('/inventory');

test('Domain details', async () => {
await page.goto('/inventory/domains');
await page.getByRole('row').nth(2).getByRole('link').click();
await expect(page).toHaveURL(new RegExp('/inventory/domain/'));
await expect(page.getByText('IP:')).toBeVisible();
await expect(page.getByText('First Seen:')).toBeVisible();
await expect(page.getByText('Last Seen:')).toBeVisible();
await expect(page.getByText('Organization:')).toBeVisible();
await page.screenshot({
path: 'test-results/img/global-admin/domain_details.png'
const accessibilityScanResults = await makeAxeBuilder().analyze();

await testInfo.attach('accessibility-scan-results', {
body: JSON.stringify(accessibilityScanResults, null, 2),
contentType: 'application/json'
});

expect(accessibilityScanResults.violations).toHaveLength(0);
});
});

test('Domains filter', async () => {
await page.goto('/inventory/domains');
await page.locator('#organizationName').click();
await page.locator('#organizationName').fill('Homeland');
await page.locator('#organizationName').press('Enter');
let rowCount = await page.getByRole('row').count();
for (let it = 2; it < rowCount; it++) {
await expect(
page.getByRole('row').nth(it).getByRole('cell').nth(1)
).toContainText('Homeland');
}
await page.screenshot({
path: 'test-results/img/global-admin/domain_filter.png'
test('Test domain accessibility', async ({ makeAxeBuilder }, testInfo) => {
await page.goto('/inventory');
await page.getByRole('link', { name: 'All Domains' }).click();
await expect(page).toHaveURL('/inventory/domains');

const accessibilityScanResults = await makeAxeBuilder().analyze();

await testInfo.attach('accessibility-scan-results', {
body: JSON.stringify(accessibilityScanResults, null, 2),
contentType: 'application/json'
});

expect(accessibilityScanResults.violations).toHaveLength(0);
});

test('Test domain details accessibility', async ({
makeAxeBuilder
}, testInfo) => {
await page.goto('/inventory/domains');
await page
.getByRole('row')
.nth(1)
.getByRole('cell')
.nth(8)
.getByRole('button')
.click();
await expect(page).toHaveURL(new RegExp('/inventory/domain/'));

const accessibilityScanResults = await makeAxeBuilder().analyze();

await testInfo.attach('accessibility-scan-results', {
body: JSON.stringify(accessibilityScanResults, null, 2),
contentType: 'application/json'
});

expect(accessibilityScanResults.violations).toHaveLength(0);
});

test('Test domain table filter', async () => {
await page.goto('/inventory/domains');
await page.getByLabel('Show filters').click();
await page.getByPlaceholder('Filter value').click();
await page.getByPlaceholder('Filter value').fill('Homeland');
await page.getByPlaceholder('Filter value').press('Enter');

let rowCount = await page.getByRole('row').count();
for (let it = 2; it < rowCount; it++) {
await expect(
page.getByRole('row').nth(it).getByRole('cell').nth(0)
).toContainText('Homeland');
}
});
});
Loading

0 comments on commit 22c6de7

Please sign in to comment.