Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ML] Transforms: Adds a11y tests for Transform plugin #93197

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,12 @@
/x-pack/plugins/ml/ @elastic/ml-ui
/x-pack/test/functional/apps/ml/ @elastic/ml-ui
/x-pack/test/functional/services/ml/ @elastic/ml-ui
/x-pack/test/accessibility/apps/ml.ts @elastic/ml-ui
# ML team owns and maintains the transform plugin despite it living in the Elasticsearch management section.
/x-pack/plugins/transform/ @elastic/ml-ui
/x-pack/test/functional/apps/transform/ @elastic/ml-ui
/x-pack/test/functional/services/transform/ @elastic/ml-ui
/x-pack/test/accessibility/apps/transform.ts @elastic/ml-ui
/x-pack/test/api_integration_basic/apis/ml/ @elastic/ml-ui
/x-pack/test/functional_basic/apps/ml/ @elastic/ml-ui

Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/ml/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
9 changes: 9 additions & 0 deletions x-pack/plugins/transform/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
16 changes: 4 additions & 12 deletions x-pack/test/accessibility/apps/ml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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 () => {
Expand All @@ -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 () => {
Expand All @@ -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 () => {
Expand Down
262 changes: 262 additions & 0 deletions x-pack/test/accessibility/apps/transform.ts
Original file line number Diff line number Diff line change
@@ -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();
});
});
});
});
}
1 change: 1 addition & 0 deletions x-pack/test/accessibility/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand Down