Skip to content

Commit 523ecd7

Browse files
[Uptime] Add a11y tests (#65514)
* Add test attributes and missing aria labels to uptime UI code. * Add uptime a11y tests and associated helper functions. * Append a11y test instructions to uptime README. * Update some copy on README page. Refresh outdated snapshot. * Add test for alert popover on overview page. Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent 8f05cf0 commit 523ecd7

File tree

10 files changed

+171
-0
lines changed

10 files changed

+171
-0
lines changed

x-pack/plugins/uptime/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,19 @@ We can run these tests like described above, but with some special config.
7575
`node scripts/functional_tests_server.js --config=test/functional_with_es_ssl/config.ts`
7676

7777
`node scripts/functional_test_runner.js --config=test/functional_with_es_ssl/config.ts`
78+
79+
#### Running accessibility tests
80+
81+
We maintain a suite of Accessibility tests (you may see them referred to elsewhere as `a11y` tests).
82+
83+
These tests render each of our pages and ensure that the inputs and other elements contain the
84+
attributes necessary to ensure all users are able to make use of Kibana (for example, users relying
85+
on screen readers).
86+
87+
The commands for running these tests are very similar to the other functional tests described above.
88+
89+
From the `~/x-pack` directory:
90+
91+
Start the server: `node scripts/functional_tests_server --config test/accessibility/config.ts`
92+
93+
Run the uptime `a11y` tests: `node scripts/functional_test_runner.js --config test/accessibility/config.ts --grep=uptime`

x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ export const MonitorListComponent: React.FC<Props> = ({
171171
return (
172172
<EuiButtonIcon
173173
aria-label={labels.getExpandDrawerLabel(id)}
174+
data-test-subj={`xpack.uptime.monitorList.${id}.expandMonitorDetail`}
174175
iconType={drawerIds.includes(id) ? 'arrowUp' : 'arrowDown'}
175176
onClick={() => {
176177
if (drawerIds.includes(id)) {

x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/actions_popover.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export const ActionsPopoverComponent = ({
4141
values: { monitorUrl },
4242
}
4343
)}
44+
data-test-subj={`xpack.uptime.monitorList.actionsPopover.${summary.monitor_id}`}
4445
onClick={() => togglePopoverIsVisible({ id: popoverId, open: true })}
4546
iconType="arrowDown"
4647
iconSide="right"

x-pack/plugins/uptime/public/components/settings/certificate_form.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../common/constants';
2121
import { DynamicSettings } from '../../../common/runtime_types';
2222
import { SettingsFormProps } from '../../pages/settings';
23+
import { certificateFormTranslations } from './translations';
2324

2425
export type OnFieldChangeType = (changedValues: Partial<DynamicSettings>) => void;
2526

@@ -80,6 +81,7 @@ export const CertificateExpirationForm: React.FC<SettingsFormProps> = ({
8081
<EuiFlexGroup>
8182
<EuiFlexItem grow={2}>
8283
<EuiFieldNumber
84+
aria-label={certificateFormTranslations.expirationInputAriaLabel}
8385
data-test-subj={`expiration-threshold-input-${loading ? 'loading' : 'loaded'}`}
8486
fullWidth
8587
disabled={isDisabled}
@@ -126,6 +128,7 @@ export const CertificateExpirationForm: React.FC<SettingsFormProps> = ({
126128
<EuiFlexGroup>
127129
<EuiFlexItem grow={2}>
128130
<EuiFieldNumber
131+
aria-label={certificateFormTranslations.ageInputAriaLabel}
129132
data-test-subj={`age-threshold-input-${loading ? 'loading' : 'loaded'}`}
130133
fullWidth
131134
disabled={isDisabled}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { i18n } from '@kbn/i18n';
8+
9+
export const certificateFormTranslations = {
10+
ageInputAriaLabel: i18n.translate(
11+
'xpack.uptime.sourceConfiguration.ageLimitThresholdInput.ariaLabel',
12+
{
13+
defaultMessage:
14+
'An input that controls the maximum number of days for which a TLS certificate may be valid before Kibana will show a warning.',
15+
}
16+
),
17+
expirationInputAriaLabel: i18n.translate(
18+
'xpack.uptime.sourceConfiguration.certificateExpirationThresholdInput.ariaLabel',
19+
{
20+
defaultMessage:
21+
'An input that controls the minimum number of days remaining for TLS certificate expiration before Kibana will show a warning.',
22+
}
23+
),
24+
};
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import moment from 'moment';
8+
import { FtrProviderContext } from '../ftr_provider_context';
9+
import { makeChecks } from '../../api_integration/apis/uptime/rest/helper/make_checks';
10+
11+
const A11Y_TEST_MONITOR_ID = 'a11yTestMonitor';
12+
13+
export default function({ getService, getPageObjects }: FtrProviderContext) {
14+
const { uptime } = getPageObjects(['common', 'uptime']);
15+
const a11y = getService('a11y');
16+
const uptimeService = getService('uptime');
17+
const esArchiver = getService('esArchiver');
18+
const es = getService('es');
19+
20+
describe('uptime', () => {
21+
before(async () => {
22+
await esArchiver.load('uptime/blank');
23+
await makeChecks(es, A11Y_TEST_MONITOR_ID, 150, 1, 1000, {
24+
tls: {
25+
certificate_not_valid_after: moment()
26+
.add(30, 'days')
27+
.toISOString(),
28+
certificate_not_valid_before: moment()
29+
.subtract(90, 'days')
30+
.toISOString(),
31+
server: {
32+
x509: {
33+
subject: {
34+
common_name: 'a11y_common_name',
35+
},
36+
issuer: {
37+
common_name: 'a11y_issuer_name',
38+
},
39+
},
40+
},
41+
},
42+
});
43+
});
44+
45+
beforeEach(async () => {
46+
await uptime.goToRoot();
47+
});
48+
49+
after(async () => {
50+
await esArchiver.unload('uptime/blank');
51+
});
52+
53+
it('overview page', async () => {
54+
await a11y.testAppSnapshot();
55+
});
56+
57+
it('overview page with expanded monitor detail', async () => {
58+
await uptimeService.overview.expandMonitorDetail(A11Y_TEST_MONITOR_ID);
59+
await uptimeService.overview.openIntegrationsPopoverForMonitor(A11Y_TEST_MONITOR_ID);
60+
await a11y.testAppSnapshot();
61+
});
62+
63+
it('overview alert popover controls', async () => {
64+
await uptimeService.overview.openAlertsPopover();
65+
await a11y.testAppSnapshot();
66+
await uptimeService.overview.navigateToNestedPopover();
67+
await a11y.testAppSnapshot();
68+
});
69+
70+
it('detail page', async () => {
71+
await uptimeService.navigation.goToMonitor(A11Y_TEST_MONITOR_ID);
72+
await uptimeService.monitor.locationMapIsRendered();
73+
await a11y.testAppSnapshot();
74+
});
75+
76+
it('settings page', async () => {
77+
await uptimeService.navigation.goToSettings();
78+
await a11y.testAppSnapshot();
79+
});
80+
81+
it('certificates page', async () => {
82+
await uptimeService.navigation.goToCertificates();
83+
await a11y.testAppSnapshot();
84+
});
85+
});
86+
}

x-pack/test/accessibility/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export default async function({ readConfigFile }: FtrConfigProviderContext) {
1919
require.resolve('./apps/home'),
2020
require.resolve('./apps/grok_debugger'),
2121
require.resolve('./apps/search_profiler'),
22+
require.resolve('./apps/uptime'),
2223
],
2324
pageObjects,
2425
services,
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { FtrProviderContext } from '../../ftr_provider_context';
8+
9+
export function UptimeOverviewProvider({ getService }: FtrProviderContext) {
10+
const testSubjects = getService('testSubjects');
11+
12+
return {
13+
async expandMonitorDetail(id: string): Promise<void> {
14+
return testSubjects.click(`xpack.uptime.monitorList.${id}.expandMonitorDetail`);
15+
},
16+
async openIntegrationsPopoverForMonitor(id: string): Promise<void> {
17+
return testSubjects.click(`xpack.uptime.monitorList.actionsPopover.${id}`);
18+
},
19+
async openAlertsPopover(): Promise<void> {
20+
return testSubjects.click('xpack.uptime.alertsPopover.toggleButton');
21+
},
22+
/**
23+
* If the popover is already open, click the nested button.
24+
* Otherwise, open the popover, then click the nested button.
25+
*/
26+
async navigateToNestedPopover(): Promise<void> {
27+
if (testSubjects.exists('xpack.uptime.openAlertContextPanel')) {
28+
return testSubjects.click('xpack.uptime.openAlertContextPanel');
29+
}
30+
await testSubjects.click('xpack.uptime.alertsPopover.toggleButton');
31+
return testSubjects.click('xpack.uptime.openAlertContextPanel');
32+
},
33+
};
34+
}

x-pack/test/functional/services/uptime/uptime.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { UptimeNavigationProvider } from './navigation';
1313
import { UptimeAlertsProvider } from './alerts';
1414
import { UptimeMLAnomalyProvider } from './ml_anomaly';
1515
import { UptimeCertProvider } from './certificates';
16+
import { UptimeOverviewProvider } from './overview';
1617

1718
export function UptimeProvider(context: FtrProviderContext) {
1819
const common = UptimeCommonProvider(context);
@@ -22,6 +23,7 @@ export function UptimeProvider(context: FtrProviderContext) {
2223
const alerts = UptimeAlertsProvider(context);
2324
const ml = UptimeMLAnomalyProvider(context);
2425
const cert = UptimeCertProvider(context);
26+
const overview = UptimeOverviewProvider(context);
2527

2628
return {
2729
common,
@@ -31,5 +33,6 @@ export function UptimeProvider(context: FtrProviderContext) {
3133
alerts,
3234
ml,
3335
cert,
36+
overview,
3437
};
3538
}

0 commit comments

Comments
 (0)