mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Adding fleet cypress a11y tests (#138192)
* Updated test to use uiSettings. * Added initial files for adding Fleet A11y tests. * Added setup for a11y test. * Still working with combobox * Got combobox to work. * Added tests for Agents tag. * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * More tests. * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * Fixed typo. * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * Added more tests and stuff. * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * Added more tests and stuff. * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * Finished the fleet screens. * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * Added exception for cypres-real-events devDependency. * Skipped test with a11y violation. * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * Ignoring dev dependencies. * Look for input before trying to type into it. * Updated cypress readme about a11y checks. Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
d260286da6
commit
47bc3592c4
17 changed files with 227 additions and 11 deletions
|
@ -178,6 +178,7 @@ const DEV_PATTERNS = [
|
|||
'src/dev/**/*',
|
||||
'x-pack/{dev-tools,tasks,scripts,test,build_chromium}/**/*',
|
||||
'x-pack/plugins/*/server/scripts/**/*',
|
||||
'x-pack/plugins/fleet/cypress',
|
||||
];
|
||||
|
||||
/** Restricted imports with suggested alternatives */
|
||||
|
|
|
@ -160,6 +160,12 @@ taken into consideration until another solution is implemented:
|
|||
|
||||
Remember that minimizing the number of times the web page is loaded, we minimize as well the execution time.
|
||||
|
||||
### Accessibility
|
||||
|
||||
The `checkA11y({ skipFailures: false });` call uses [axe-core](https://github.com/dequelabs/axe-core) to perform a full page check for accessibility violations.
|
||||
|
||||
See [axe-core](https://github.com/dequelabs/axe-core)'s documentation for details on what is checked for.
|
||||
|
||||
## Linting
|
||||
|
||||
Optional linting rules for Cypress and linting setup can be found [here](https://github.com/cypress-io/eslint-plugin-cypress#usage)
|
||||
|
|
141
x-pack/plugins/fleet/cypress/integration/a11y/home_page.spec.ts
Normal file
141
x-pack/plugins/fleet/cypress/integration/a11y/home_page.spec.ts
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
/* eslint-disable-next-line import/no-extraneous-dependencies */
|
||||
import 'cypress-real-events/support';
|
||||
import { checkA11y } from '../../support/commands';
|
||||
import { FLEET, navigateTo } from '../../tasks/navigation';
|
||||
import {
|
||||
GENERATE_FLEET_SERVER_POLICY_BUTTON,
|
||||
AGENTS_QUICK_START_TAB_BUTTON,
|
||||
PLATFORM_TYPE_LINUX_BUTTON,
|
||||
AGENTS_ADVANCED_TAB_BUTTON,
|
||||
ADVANCED_FLEET_SERVER_ADD_HOST_BUTTON,
|
||||
ADVANCED_FLEET_SERVER_GENERATE_SERVICE_TOKEN_BUTTON,
|
||||
AGENT_POLICIES_TAB,
|
||||
AGENT_POLICIES_CREATE_AGENT_POLICY_BUTTON,
|
||||
AGENT_POLICIES_CREATE_AGENT_POLICY_FLYOUT_TITLE,
|
||||
AGENT_POLICY_CREATE_AGENT_POLICY_NAME_FIELD,
|
||||
AGENT_POLICIES_FLYOUT_ADVANCED_DEFAULT_NAMESPACE_HEADER,
|
||||
AGENT_POLICY_FLYOUT_CREATE_BUTTON,
|
||||
ENROLLMENT_TOKENS_TAB,
|
||||
ENROLLMENT_TOKENS_CREATE_TOKEN_BUTTON,
|
||||
ENROLLMENT_TOKENS_CREATE_TOKEN_NAME_FIELD,
|
||||
DATA_STREAMS_TAB,
|
||||
SETTINGS_TAB,
|
||||
SETTINGS_FLEET_SERVER_HOST_HEADING,
|
||||
} from '../../screens/fleet';
|
||||
import { AGENT_POLICY_NAME_LINK } from '../../screens/integrations';
|
||||
import { cleanupAgentPolicies, unenrollAgent } from '../../tasks/cleanup';
|
||||
describe('Home page', () => {
|
||||
before(() => {
|
||||
navigateTo(FLEET);
|
||||
cy.getBySel(AGENTS_QUICK_START_TAB_BUTTON, { timeout: 15000 }).should('be.visible');
|
||||
});
|
||||
|
||||
describe('Agents', () => {
|
||||
const fleetServerHost = 'https://localhost:8220';
|
||||
describe('Quick Start', () => {
|
||||
it('Get started with fleet', () => {
|
||||
checkA11y({ skipFailures: false });
|
||||
});
|
||||
it('Install Fleet Server', () => {
|
||||
cy.getBySel('fleetServerHostInput', { timeout: 15000 }).should('be.visible');
|
||||
cy.getBySel('fleetServerHostInput').getBySel('comboBoxSearchInput').type(fleetServerHost);
|
||||
cy.getBySel(GENERATE_FLEET_SERVER_POLICY_BUTTON).click();
|
||||
cy.getBySel(PLATFORM_TYPE_LINUX_BUTTON, { timeout: 15000 }).should('be.visible');
|
||||
checkA11y({ skipFailures: false });
|
||||
});
|
||||
});
|
||||
describe('Advanced', () => {
|
||||
before(() => {
|
||||
cy.getBySel(AGENTS_ADVANCED_TAB_BUTTON).click();
|
||||
});
|
||||
it('Select policy for fleet', () => {
|
||||
checkA11y({ skipFailures: false });
|
||||
});
|
||||
it('Add your fleet sever host', () => {
|
||||
cy.getBySel(ADVANCED_FLEET_SERVER_ADD_HOST_BUTTON).click();
|
||||
checkA11y({ skipFailures: false });
|
||||
});
|
||||
it('Generate service token', () => {
|
||||
cy.getBySel(ADVANCED_FLEET_SERVER_ADD_HOST_BUTTON, { timeout: 15000 }).should('be.visible');
|
||||
cy.getBySel(ADVANCED_FLEET_SERVER_GENERATE_SERVICE_TOKEN_BUTTON).click();
|
||||
cy.getBySel(PLATFORM_TYPE_LINUX_BUTTON, { timeout: 15000 }).should('be.visible');
|
||||
checkA11y({ skipFailures: false });
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('Agent Policies', () => {
|
||||
before(() => {
|
||||
cy.getBySel(AGENT_POLICIES_TAB).click();
|
||||
cy.getBySel(AGENT_POLICIES_CREATE_AGENT_POLICY_BUTTON, { timeout: 15000 }).should(
|
||||
'be.visible'
|
||||
);
|
||||
});
|
||||
it('Agent Table', () => {
|
||||
checkA11y({ skipFailures: false });
|
||||
});
|
||||
it('Create Policy Flyout', () => {
|
||||
cy.getBySel(AGENT_POLICIES_CREATE_AGENT_POLICY_BUTTON).click();
|
||||
cy.getBySel(AGENT_POLICIES_CREATE_AGENT_POLICY_FLYOUT_TITLE, { timeout: 15000 }).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.getBySel(AGENT_POLICY_CREATE_AGENT_POLICY_NAME_FIELD).type('testName');
|
||||
cy.get('.ingest-active-button').click();
|
||||
cy.getBySel(AGENT_POLICIES_FLYOUT_ADVANCED_DEFAULT_NAMESPACE_HEADER, {
|
||||
timeout: 15000,
|
||||
}).should('be.visible');
|
||||
checkA11y({ skipFailures: false });
|
||||
});
|
||||
it('Agent Table After Adding Another Agent', () => {
|
||||
cy.getBySel(AGENT_POLICY_FLYOUT_CREATE_BUTTON).click();
|
||||
cy.getBySel(AGENT_POLICY_NAME_LINK, { timeout: 15000 }).should('be.visible');
|
||||
checkA11y({ skipFailures: true });
|
||||
});
|
||||
});
|
||||
describe('Enrollment Tokens', () => {
|
||||
before(() => {
|
||||
cy.getBySel(ENROLLMENT_TOKENS_TAB).click();
|
||||
});
|
||||
it('Enrollment Tokens Table', () => {
|
||||
cy.getBySel('tableHeaderCell_name_0', { timeout: 15000 }).should('be.visible');
|
||||
checkA11y({ skipFailures: false });
|
||||
});
|
||||
it('Create Enrollment Token Modal', () => {
|
||||
cy.getBySel(ENROLLMENT_TOKENS_CREATE_TOKEN_BUTTON).click();
|
||||
cy.getBySel(ENROLLMENT_TOKENS_CREATE_TOKEN_NAME_FIELD, { timeout: 15000 }).should(
|
||||
'be.visible'
|
||||
);
|
||||
checkA11y({ skipFailures: false });
|
||||
});
|
||||
});
|
||||
describe('Data Streams', () => {
|
||||
before(() => {
|
||||
cy.getBySel('confirmModalCancelButton').click();
|
||||
cy.getBySel(DATA_STREAMS_TAB, { timeout: 15000 }).should('be.visible');
|
||||
cy.getBySel(DATA_STREAMS_TAB).click();
|
||||
});
|
||||
it('Datastreams Empty Table', () => {
|
||||
cy.getBySel('tableHeaderSortButton', { timeout: 15000 }).should('be.visible');
|
||||
checkA11y({ skipFailures: false });
|
||||
});
|
||||
});
|
||||
describe.skip('Settings', () => {
|
||||
// A11y Violation https://github.com/elastic/kibana/issues/138474
|
||||
before(() => {
|
||||
cy.getBySel(SETTINGS_TAB).click();
|
||||
});
|
||||
it('Settings Form', () => {
|
||||
cy.getBySel(SETTINGS_FLEET_SERVER_HOST_HEADING, { timeout: 15000 }).should('be.visible');
|
||||
checkA11y({ skipFailures: false });
|
||||
});
|
||||
});
|
||||
after(() => {
|
||||
unenrollAgent();
|
||||
cleanupAgentPolicies();
|
||||
});
|
||||
});
|
|
@ -14,6 +14,7 @@ export const AGENT_POLICY_CODE_BLOCK = 'agentPolicyCodeBlock';
|
|||
export const AGENTS_TAB = 'fleet-agents-tab';
|
||||
export const AGENT_POLICIES_TAB = 'fleet-agent-policies-tab';
|
||||
export const ENROLLMENT_TOKENS_TAB = 'fleet-enrollment-tokens-tab';
|
||||
export const DATA_STREAMS_TAB = 'fleet-datastreams-tab';
|
||||
export const SETTINGS_TAB = 'fleet-settings-tab';
|
||||
export const STANDALONE_TAB = 'standaloneTab';
|
||||
export const MISSING_PRIVILEGES_TITLE = 'missingPrivilegesPromptTitle';
|
||||
|
@ -23,6 +24,22 @@ export const FLEET_SERVER_MISSING_PRIVILEGES_TITLE = 'fleetServerMissingPrivileg
|
|||
export const AGENT_POLICY_SAVE_INTEGRATION = 'saveIntegration';
|
||||
export const PACKAGE_POLICY_TABLE_LINK = 'PackagePoliciesTableLink';
|
||||
export const ADD_PACKAGE_POLICY_BTN = 'addPackagePolicyButton';
|
||||
export const GENERATE_FLEET_SERVER_POLICY_BUTTON = 'generateFleetServerPolicyButton';
|
||||
export const ADD_FLEET_SERVER_HEADER = 'addFleetServerHeader';
|
||||
export const AGENTS_QUICK_START_TAB_BUTTON = 'fleetServerFlyoutTab-quickStart';
|
||||
export const AGENTS_ADVANCED_TAB_BUTTON = 'fleetServerFlyoutTab-advanced';
|
||||
export const PLATFORM_TYPE_LINUX_BUTTON = 'platformTypeLinux';
|
||||
export const ADVANCED_FLEET_SERVER_ADD_HOST_BUTTON = 'fleetServerAddHostBtn';
|
||||
export const ADVANCED_FLEET_SERVER_GENERATE_SERVICE_TOKEN_BUTTON =
|
||||
'fleetServerGenerateServiceTokenBtn';
|
||||
export const AGENT_POLICIES_CREATE_AGENT_POLICY_BUTTON = 'createAgentPolicyButton';
|
||||
export const AGENT_POLICIES_CREATE_AGENT_POLICY_FLYOUT_TITLE = 'createAgentPolicyFlyoutTitle';
|
||||
export const AGENT_POLICY_CREATE_AGENT_POLICY_NAME_FIELD = 'createAgentPolicyNameField';
|
||||
export const AGENT_POLICIES_FLYOUT_ADVANCED_DEFAULT_NAMESPACE_HEADER = 'defaultNamespaceHeader';
|
||||
export const AGENT_POLICY_FLYOUT_CREATE_BUTTON = 'createAgentPolicyFlyoutBtn';
|
||||
export const ENROLLMENT_TOKENS_CREATE_TOKEN_BUTTON = 'createEnrollmentTokenButton';
|
||||
export const ENROLLMENT_TOKENS_CREATE_TOKEN_NAME_FIELD = 'createEnrollmentTokenNameField';
|
||||
export const SETTINGS_FLEET_SERVER_HOST_HEADING = 'fleetServerHostHeader';
|
||||
|
||||
export const AGENT_BINARY_SOURCES_TABLE = 'AgentDownloadSourcesTable';
|
||||
export const AGENT_BINARY_SOURCES_TABLE_ACTIONS = {
|
||||
|
|
|
@ -15,3 +15,27 @@
|
|||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
/* eslint-disable-next-line import/no-extraneous-dependencies */
|
||||
import 'cypress-axe';
|
||||
/* eslint-disable-next-line import/no-extraneous-dependencies */
|
||||
import { AXE_CONFIG, AXE_OPTIONS } from '@kbn/axe-config';
|
||||
|
||||
const axeConfig = {
|
||||
...AXE_CONFIG,
|
||||
};
|
||||
const axeOptions = {
|
||||
...AXE_OPTIONS,
|
||||
runOnly: [...AXE_OPTIONS.runOnly, 'best-practice'],
|
||||
};
|
||||
|
||||
export const checkA11y = ({ skipFailures }: { skipFailures: boolean }) => {
|
||||
// https://github.com/component-driven/cypress-axe#cychecka11y
|
||||
cy.injectAxe();
|
||||
cy.configureAxe(axeConfig);
|
||||
const context = '.kbnAppWrapper'; // Scopes a11y checks to only our app
|
||||
/**
|
||||
* We can get rid of the last two params when we don't need to add skipFailures
|
||||
* params = (context, options, violationCallback, skipFailures)
|
||||
*/
|
||||
cy.checkA11y(context, axeOptions, undefined, skipFailures);
|
||||
};
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
"outDir": "target/types",
|
||||
"types": [
|
||||
"cypress",
|
||||
"node"
|
||||
"node",
|
||||
"cypress-real-events"
|
||||
],
|
||||
"resolveJsonModule": true,
|
||||
"target": "ES2019",
|
||||
|
|
|
@ -69,7 +69,7 @@ const Header: React.FunctionComponent<{
|
|||
return (
|
||||
<>
|
||||
<EuiTitle size="m">
|
||||
<h2>
|
||||
<h2 data-test-subj="addFleetServerHeader">
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.fleetServerFlyout.title"
|
||||
defaultMessage="Add a Fleet Server"
|
||||
|
|
|
@ -116,7 +116,7 @@ const ServiceTokenStepContent: React.FunctionComponent<{
|
|||
<EuiSpacer size="m" />
|
||||
<EuiFlexGroup direction="column" gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<strong>
|
||||
<strong data-test-subject="serviceTokenSaveReminderHeader">
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.fleetServerSetup.serviceTokenLabel"
|
||||
defaultMessage="Service token"
|
||||
|
|
|
@ -109,7 +109,7 @@ export const AgentPolicyAdvancedOptionsContent: React.FunctionComponent<Props> =
|
|||
</EuiDescribedFormGroup>
|
||||
<EuiDescribedFormGroup
|
||||
title={
|
||||
<h4>
|
||||
<h4 data-test-subj="defaultNamespaceHeader">
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.agentPolicyForm.namespaceFieldLabel"
|
||||
defaultMessage="Default namespace"
|
||||
|
|
|
@ -174,7 +174,8 @@ export const AgentPolicyCreateInlineForm: React.FunctionComponent<Props> = ({
|
|||
<>
|
||||
<EuiSpacer size="s" />
|
||||
<StyledEuiAccordion
|
||||
id="advancedOptions"
|
||||
id="advancedOptionsJustChanged"
|
||||
data-test-subj="advancedOptionsButton"
|
||||
buttonContent={
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.agentPolicyForm.advancedOptionsToggleLabel"
|
||||
|
|
|
@ -43,6 +43,7 @@ export const AgentPolicyGeneralFields: React.FunctionComponent<Props> = ({
|
|||
isInvalid={Boolean(touchedFields.name && validation.name)}
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="createAgentPolicyNameField"
|
||||
disabled={agentPolicy.is_managed === true}
|
||||
fullWidth
|
||||
value={agentPolicy.name}
|
||||
|
|
|
@ -95,7 +95,6 @@ export const AgentPolicyIntegrationForm: React.FunctionComponent<Props> = ({
|
|||
/>
|
||||
}
|
||||
buttonClassName="ingest-active-button"
|
||||
data-test-subj="advancedOptionsBtn"
|
||||
>
|
||||
<EuiSpacer size="l" />
|
||||
<AgentPolicyAdvancedOptionsContent
|
||||
|
|
|
@ -68,7 +68,7 @@ export const CreateAgentPolicyFlyout: React.FunctionComponent<Props> = ({
|
|||
const header = (
|
||||
<EuiFlyoutHeader hasBorder aria-labelledby="CreateAgentPolicyFlyoutTitle">
|
||||
<EuiTitle size="m">
|
||||
<h2 id="CreateAgentPolicyFlyoutTitle">
|
||||
<h2 id="CreateAgentPolicyFlyoutTitle" data-test-subj="createAgentPolicyFlyoutTitle">
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.createAgentPolicy.flyoutTitle"
|
||||
defaultMessage="Create agent policy"
|
||||
|
|
|
@ -181,6 +181,25 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => {
|
|||
iconType="plusInCircle"
|
||||
isDisabled={!hasFleetAllPrivileges}
|
||||
onClick={() => setIsCreateAgentPolicyFlyoutOpen(true)}
|
||||
data-test-subj="createAgentPolicyButton"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.agentPolicyList.addButton"
|
||||
defaultMessage="Create agent policy"
|
||||
/>
|
||||
</EuiButton>
|
||||
),
|
||||
[hasFleetAllPrivileges, setIsCreateAgentPolicyFlyoutOpen]
|
||||
);
|
||||
|
||||
const emptyStateCreateAgentPolicyButton = useMemo(
|
||||
() => (
|
||||
<EuiButton
|
||||
fill
|
||||
iconType="plusInCircle"
|
||||
isDisabled={!hasFleetAllPrivileges}
|
||||
onClick={() => setIsCreateAgentPolicyFlyoutOpen(true)}
|
||||
data-test-subj="emptyPromptCreateAgentPolicyButton"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.agentPolicyList.addButton"
|
||||
|
@ -202,10 +221,10 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => {
|
|||
/>
|
||||
</h2>
|
||||
}
|
||||
actions={createAgentPolicyButton}
|
||||
actions={emptyStateCreateAgentPolicyButton}
|
||||
/>
|
||||
),
|
||||
[createAgentPolicyButton]
|
||||
[emptyStateCreateAgentPolicyButton]
|
||||
);
|
||||
|
||||
const onTableChange = (criteria: CriteriaWithPagination<AgentPolicy>) => {
|
||||
|
|
|
@ -305,7 +305,12 @@ export const EnrollmentTokenListPage: React.FunctionComponent<{}> = () => {
|
|||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton fill iconType="plusInCircle" onClick={() => setModalOpen(true)}>
|
||||
<EuiButton
|
||||
data-test-subj="createEnrollmentTokenButton"
|
||||
fill
|
||||
iconType="plusInCircle"
|
||||
onClick={() => setModalOpen(true)}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.enrollmentTokensList.newKeyButton"
|
||||
defaultMessage="Create enrollment token"
|
||||
|
|
|
@ -64,7 +64,7 @@ export const SettingsSection: React.FunctionComponent<SettingsSectionProps> = ({
|
|||
return (
|
||||
<>
|
||||
<EuiTitle size="s">
|
||||
<h4>
|
||||
<h4 data-test-subj="fleetServerHostHeader">
|
||||
<FormattedMessage
|
||||
id="xpack.fleet.settings.fleetServerHostSectionTitle"
|
||||
defaultMessage="Fleet server hosts"
|
||||
|
|
|
@ -115,6 +115,7 @@ export const NewEnrollmentTokenModal: React.FunctionComponent<Props> = ({
|
|||
})}
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="createEnrollmentTokenNameField"
|
||||
name="name"
|
||||
autoComplete="off"
|
||||
placeholder={i18n.translate('xpack.fleet.newEnrollmentKey.placeholder', {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue