From a63ddd9b24a93e4f811a39daa557b8f50c0a5f9e Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Wed, 3 Mar 2021 15:40:31 +0000 Subject: [PATCH] [ML] Transforms: Adds a11y tests for Transform plugin (#93197) (#93419) # Conflicts: # .github/CODEOWNERS --- x-pack/plugins/ml/readme.md | 2 +- x-pack/plugins/transform/readme.md | 9 + x-pack/test/accessibility/apps/ml.ts | 16 +- x-pack/test/accessibility/apps/transform.ts | 262 ++++++++++++++++++++ x-pack/test/accessibility/config.ts | 1 + 5 files changed, 277 insertions(+), 13 deletions(-) create mode 100644 x-pack/test/accessibility/apps/transform.ts diff --git a/x-pack/plugins/ml/readme.md b/x-pack/plugins/ml/readme.md index e6238a8339ff8..8425054d3f648 100644 --- a/x-pack/plugins/ml/readme.md +++ b/x-pack/plugins/ml/readme.md @@ -139,7 +139,7 @@ and Kibana instance that the tests will be run against. node scripts/functional_tests_server --config test/accessibility/config.ts node scripts/functional_test_runner.js --config test/accessibility/config.ts --grep=ml - ML accessibility tests are located in `x-pack/test/accessibility/app`. + ML accessibility tests are located in `x-pack/test/accessibility/apps`. ## Shared functions diff --git a/x-pack/plugins/transform/readme.md b/x-pack/plugins/transform/readme.md index a1005c43687e2..51a89f224fb29 100644 --- a/x-pack/plugins/transform/readme.md +++ b/x-pack/plugins/transform/readme.md @@ -131,3 +131,12 @@ and Kibana instance that the tests will be run against. node scripts/functional_test_runner.js --config test/api_integration_basic/config.ts --include-tag transform Transform API integration `Basic` license tests are located in `x-pack/test/api_integration_basic/apis/ml`. + +1. Accessibility tests: + + We maintain a suite of accessibility tests (you may see them referred to elsewhere as `a11y` tests). These tests render each of our pages and ensure that the inputs and other elements contain the attributes necessary to ensure all users are able to make use of Transforms (for example, users relying on screen readers). + + node scripts/functional_tests_server --config test/accessibility/config.ts + node scripts/functional_test_runner.js --config test/accessibility/config.ts --grep=transform + + Transform accessibility tests are located in `x-pack/test/accessibility/apps`. diff --git a/x-pack/test/accessibility/apps/ml.ts b/x-pack/test/accessibility/apps/ml.ts index 323fe5d783c70..bc7069c40db48 100644 --- a/x-pack/test/accessibility/apps/ml.ts +++ b/x-pack/test/accessibility/apps/ml.ts @@ -217,9 +217,7 @@ export default function ({ getService }: FtrProviderContext) { await a11y.testAppSnapshot(); }); - it.skip('anomaly detection Anomaly Explorer page', async () => { - // Skip test until the dots used in the Elastic chart legend no longer have duplicate ids - // see https://github.com/elastic/elastic-charts/issues/970 + it('anomaly detection Anomaly Explorer page', async () => { await ml.singleMetricViewer.openAnomalyExplorer(); await ml.commonUI.waitForMlLoadingIndicatorToDisappear(); await a11y.testAppSnapshot(); @@ -235,9 +233,7 @@ export default function ({ getService }: FtrProviderContext) { await ml.dataFrameAnalyticsResults.assertOutlierTablePanelExists(); await ml.dataFrameAnalyticsResults.assertResultsTableExists(); await ml.dataFrameAnalyticsResults.assertResultsTableNotEmpty(); - // EuiDataGrid does not have row roles - // https://github.com/elastic/eui/issues/4471 - // await a11y.testAppSnapshot(); + await a11y.testAppSnapshot(); }); it('data frame analytics create job select index pattern modal', async () => { @@ -253,9 +249,7 @@ export default function ({ getService }: FtrProviderContext) { ); await ml.jobSourceSelection.selectSourceForAnalyticsJob(ihpIndexPattern); await ml.dataFrameAnalyticsCreation.assertConfigurationStepActive(); - // EuiDataGrid does not have row roles - // https://github.com/elastic/eui/issues/4471 - // await a11y.testAppSnapshot(); + await a11y.testAppSnapshot(); }); it('data frame analytics create job configuration step for outlier job', async () => { @@ -268,9 +262,7 @@ export default function ({ getService }: FtrProviderContext) { await ml.dataFrameAnalyticsCreation.enableSourceDataPreviewHistogramCharts(true); await ml.testExecution.logTestStep('displays the include fields selection'); await ml.dataFrameAnalyticsCreation.assertIncludeFieldsSelectionExists(); - // EuiDataGrid does not have row roles - // https://github.com/elastic/eui/issues/4471 - // await a11y.testAppSnapshot(); + await a11y.testAppSnapshot(); }); it('data frame analytics create job additional options step for outlier job', async () => { diff --git a/x-pack/test/accessibility/apps/transform.ts b/x-pack/test/accessibility/apps/transform.ts new file mode 100644 index 0000000000000..4c0cae4174d36 --- /dev/null +++ b/x-pack/test/accessibility/apps/transform.ts @@ -0,0 +1,262 @@ +/* + * 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. + */ + +import { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const a11y = getService('a11y'); + const transform = getService('transform'); + + describe('transform', () => { + const esArchiver = getService('esArchiver'); + + before(async () => { + await transform.securityCommon.createTransformRoles(); + await transform.securityCommon.createTransformUsers(); + }); + + after(async () => { + await transform.securityCommon.cleanTransformUsers(); + await transform.securityCommon.cleanTransformRoles(); + }); + + describe('for user with full Transform access', function () { + before(async () => { + await transform.securityUI.loginAsTransformPowerUser(); + }); + + after(async () => { + await transform.securityUI.logout(); + }); + + describe('with no transforms created', function () { + it('Transform management page', async () => { + await transform.navigation.navigateTo(); + await a11y.testAppSnapshot(); + }); + }); + + describe('with data loaded', function () { + const ecIndexPattern = 'ft_ecommerce'; + + const pivotGroupByEntries = [ + { + identifier: 'terms(category.keyword)', + label: 'category.keyword', + }, + { + identifier: 'date_histogram(order_date)', + label: 'order_date', + intervalLabel: '1m', + }, + ]; + const pivotAggregationEntries = [ + { + identifier: 'avg(products.base_price)', + label: 'products.base_price.avg', + }, + { + identifier: 'avg(taxful_total_price)', + label: 'taxful_total_price.avg', + }, + ]; + const pivotTransformId = `ec_pivot_${Date.now()}`; + const pivotTransformDescription = 'ecommerce batch pivot transform'; + const pivotTransformDestinationIndex = `user-${pivotTransformId}`; + + const latestTransformUniqueKeys = [ + { + identifier: 'geoip.country_iso_code', + label: 'geoip.country_iso_code', + }, + ]; + const latestTransformSortField = { + identifier: 'order_date', + label: 'order_date', + }; + const latestTransformId = `ec_latest_${Date.now()}`; + const latestTransformDescription = 'ecommerce batch latest transform'; + const latestTransformDestinationIndex = `user-${latestTransformId}`; + + before(async () => { + await esArchiver.loadIfNeeded('ml/ecommerce'); + await transform.testResources.createIndexPatternIfNeeded(ecIndexPattern, 'order_date'); + await transform.testResources.setKibanaTimeZoneToUTC(); + }); + + after(async () => { + await transform.api.cleanTransformIndices(); + await transform.api.deleteIndices(pivotTransformDestinationIndex); + await transform.api.deleteIndices(latestTransformDestinationIndex); + await transform.testResources.deleteIndexPatternByTitle(pivotTransformDestinationIndex); + await transform.testResources.deleteIndexPatternByTitle(latestTransformDestinationIndex); + await transform.testResources.deleteIndexPatternByTitle(ecIndexPattern); + await esArchiver.unload('ml/ecommerce'); + await transform.testResources.resetKibanaTimeZone(); + }); + + it('create transform select index pattern modal', async () => { + await transform.navigation.navigateTo(); + await transform.management.startTransformCreation(); + await a11y.testAppSnapshot(); + }); + + it('create transform configuration step source preview', async () => { + await transform.testExecution.logTestStep( + 'transform creation selects the source data and loads the Transform wizard page' + ); + await transform.sourceSelection.selectSource(ecIndexPattern); + + await transform.testExecution.logTestStep('loads the index preview'); + await transform.wizard.assertIndexPreviewLoaded(); + await transform.testExecution.logTestStep('displays an empty transform preview'); + await transform.wizard.assertTransformPreviewEmpty(); + await a11y.testAppSnapshot(); + }); + + it('create pivot transform configuration step transform preview', async () => { + await transform.testExecution.logTestStep('adding pivot transform group by entries'); + for (const [index, entry] of pivotGroupByEntries.entries()) { + await transform.wizard.addGroupByEntry( + index, + entry.identifier, + entry.label, + entry.intervalLabel + ); + } + + await transform.testExecution.logTestStep('adds pivot transform aggregation entries'); + await transform.wizard.addAggregationEntries(pivotAggregationEntries); + await transform.wizard.assertPivotPreviewLoaded(); + await a11y.testAppSnapshot(); + }); + + it('create pivot transform configuration step JSON editor', async () => { + await transform.testExecution.logTestStep('displays the JSON pivot configuration'); + await transform.wizard.assertAdvancedPivotEditorSwitchExists(); + await transform.wizard.enableAdvancedPivotEditor(); + await a11y.testAppSnapshot(); + }); + + it('create pivot transform details step', async () => { + await transform.wizard.advanceToDetailsStep(); + await transform.testExecution.logTestStep('inputs the transform id'); + await transform.wizard.assertTransformIdInputExists(); + await transform.wizard.setTransformId(pivotTransformId); + + await transform.testExecution.logTestStep('inputs the transform description'); + await transform.wizard.assertTransformDescriptionInputExists(); + await transform.wizard.setTransformDescription(pivotTransformDescription); + + await transform.testExecution.logTestStep('inputs the destination index'); + await transform.wizard.assertDestinationIndexInputExists(); + await transform.wizard.setDestinationIndex(pivotTransformDestinationIndex); + + await a11y.testAppSnapshot(); + }); + + it('create pivot transform create step', async () => { + await transform.wizard.advanceToCreateStep(); + await transform.testExecution.logTestStep('displays the create and start button'); + await transform.wizard.assertCreateAndStartButtonExists(); + await a11y.testAppSnapshot(); + }); + + it('runs the pivot transform and displays management page', async () => { + await transform.testExecution.logTestStep('creates the transform'); + await transform.wizard.createTransform(); + + await transform.testExecution.logTestStep('starts the transform and finishes processing'); + await transform.wizard.startTransform(); + await transform.wizard.waitForProgressBarComplete(); + + await transform.testExecution.logTestStep('returns to the management page'); + await transform.wizard.returnToManagement(); + + await transform.testExecution.logTestStep('displays the transforms table'); + await transform.management.assertTransformsTableExists(); + + await a11y.testAppSnapshot(); + }); + + it('create latest transform configuration step source preview', async () => { + await transform.navigation.navigateTo(); + await transform.management.startTransformCreation(); + await transform.testExecution.logTestStep( + 'selects the source data and loads the Transform wizard page' + ); + await transform.sourceSelection.selectSource(ecIndexPattern); + await transform.wizard.assertIndexPreviewLoaded(); + await transform.wizard.assertTransformPreviewEmpty(); + + await transform.testExecution.logTestStep('sets latest transform method'); + await transform.wizard.selectTransformFunction('latest'); + await a11y.testAppSnapshot(); + }); + + it('create latest transform configuration step transform preview', async () => { + await transform.testExecution.logTestStep('adding latest transform unique keys'); + for (const { identifier, label } of latestTransformUniqueKeys) { + await transform.wizard.assertUniqueKeysInputExists(); + await transform.wizard.assertUniqueKeysInputValue([]); + await transform.wizard.addUniqueKeyEntry(identifier, label); + } + + await transform.testExecution.logTestStep('adds latest transform sort field'); + await transform.wizard.assertSortFieldInputExists(); + await transform.wizard.setSortFieldValue( + latestTransformSortField.identifier, + latestTransformSortField.label + ); + await transform.wizard.assertPivotPreviewLoaded(); + await a11y.testAppSnapshot(); + }); + + it('create latest transform details step', async () => { + await transform.wizard.advanceToDetailsStep(); + await transform.testExecution.logTestStep('inputs the transform id'); + await transform.wizard.assertTransformIdInputExists(); + await transform.wizard.setTransformId(latestTransformId); + + await transform.testExecution.logTestStep('inputs the transform description'); + await transform.wizard.assertTransformDescriptionInputExists(); + await transform.wizard.setTransformDescription(latestTransformDescription); + + await transform.testExecution.logTestStep('inputs the destination index'); + await transform.wizard.assertDestinationIndexInputExists(); + await transform.wizard.setDestinationIndex(latestTransformDestinationIndex); + + await a11y.testAppSnapshot(); + }); + + it('create latest transform create step', async () => { + await transform.wizard.advanceToCreateStep(); + await transform.testExecution.logTestStep('displays the create and start button'); + await transform.wizard.assertCreateAndStartButtonExists(); + await a11y.testAppSnapshot(); + }); + + it('runs the latest transform and displays management page', async () => { + await transform.testExecution.logTestStep('creates the transform'); + await transform.wizard.createTransform(); + + await transform.testExecution.logTestStep('starts the transform and finishes processing'); + await transform.wizard.startTransform(); + await transform.wizard.waitForProgressBarComplete(); + + await transform.testExecution.logTestStep('returns to the management page'); + await transform.wizard.returnToManagement(); + + await transform.testExecution.logTestStep('displays the transforms table'); + await transform.management.assertTransformsTableExists(); + + await a11y.testAppSnapshot(); + }); + }); + }); + }); +} diff --git a/x-pack/test/accessibility/config.ts b/x-pack/test/accessibility/config.ts index b014f672ed5a6..c6d85c8755a6b 100644 --- a/x-pack/test/accessibility/config.ts +++ b/x-pack/test/accessibility/config.ts @@ -30,6 +30,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('./apps/ingest_node_pipelines'), require.resolve('./apps/index_lifecycle_management'), require.resolve('./apps/ml'), + require.resolve('./apps/transform'), require.resolve('./apps/lens'), require.resolve('./apps/upgrade_assistant'), require.resolve('./apps/canvas'),