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] Add functional tests for Field statistics embeddable in Dashboard, check for filters #116774

Merged
merged 8 commits into from
Nov 5, 2021
10 changes: 9 additions & 1 deletion test/functional/page_objects/discover_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class DiscoverPageObject extends FtrService {
await fieldSearch.clearValue();
}

public async saveSearch(searchName: string) {
public async saveSearch(searchName: string, saveAsNew?: boolean) {
await this.clickSaveSearchButton();
// preventing an occasional flakiness when the saved object wasn't set and the form can't be submitted
await this.retry.waitFor(
Expand All @@ -59,6 +59,14 @@ export class DiscoverPageObject extends FtrService {
return (await saveButton.getAttribute('disabled')) !== 'true';
}
);

if (saveAsNew !== undefined) {
await this.retry.waitFor(`save as new switch is set`, async () => {
await this.testSubjects.setEuiSwitch('saveAsNewCheckbox', saveAsNew ? 'check' : 'uncheck');
return (await this.testSubjects.isEuiSwitchChecked('saveAsNewCheckbox')) === saveAsNew;
});
}

await this.testSubjects.click('confirmSaveSavedObjectButton');
await this.header.waitUntilLoadingHasFinished();
// LeeDr - this additional checking for the saved search name was an attempt
Expand Down
1 change: 1 addition & 0 deletions x-pack/test/functional/apps/ml/data_visualizer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default function ({ loadTestFile }: FtrProviderContext) {

loadTestFile(require.resolve('./index_data_visualizer'));
loadTestFile(require.resolve('./index_data_visualizer_grid_in_discover'));
loadTestFile(require.resolve('./index_data_visualizer_grid_in_dashboard'));
loadTestFile(require.resolve('./index_data_visualizer_actions_panel'));
loadTestFile(require.resolve('./index_data_visualizer_index_pattern_management'));
loadTestFile(require.resolve('./file_data_visualizer'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
import { TestData, MetricFieldVisConfig } from './types';
import {
farequoteDataViewTestData,
farequoteKQLFiltersSearchTestData,
farequoteKQLSearchTestData,
farequoteLuceneSearchTestData,
sampleLogTestData,
Expand Down Expand Up @@ -76,6 +77,13 @@ export default function ({ getService }: FtrProviderContext) {
);
await ml.dataVisualizerIndexBased.assertTotalFieldsCount(testData.expected.totalFieldsCount);

if (testData.expected.filters) {
await ml.testExecution.logTestStep('displays filters in filter bar correctly');
for (const filter of testData.expected.filters!) {
await ml.dataVisualizerIndexBased.assertFilterBarFilterContent(filter);
}
}

await ml.testExecution.logTestStep(
'displays details for metric fields and non-metric fields correctly'
);
Expand All @@ -96,7 +104,9 @@ export default function ({ getService }: FtrProviderContext) {
fieldRow.fieldName!,
fieldRow.docCountFormatted,
fieldRow.exampleCount,
fieldRow.viewableInLens
fieldRow.viewableInLens,
false,
fieldRow.exampleContent
);
}

Expand Down Expand Up @@ -150,6 +160,7 @@ export default function ({ getService }: FtrProviderContext) {
await ml.testResources.createIndexPatternIfNeeded('ft_module_sample_logs', '@timestamp');
await ml.testResources.createSavedSearchFarequoteLuceneIfNeeded();
await ml.testResources.createSavedSearchFarequoteKueryIfNeeded();
await ml.testResources.createSavedSearchFarequoteFilterAndKueryIfNeeded();
await ml.testResources.setKibanaTimeZoneToUTC();

await ml.securityUI.loginAsMlPowerUser();
Expand Down Expand Up @@ -182,6 +193,14 @@ export default function ({ getService }: FtrProviderContext) {
});

runTests(farequoteLuceneSearchTestData);

it(`${farequoteKQLFiltersSearchTestData.suiteTitle} loads the data visualizer selector page`, async () => {
// Start navigation from the base of the ML app.
await ml.navigation.navigateToMl();
await ml.navigation.navigateToDataVisualizer();
});

runTests(farequoteKQLFiltersSearchTestData);
});

describe('with module_sample_logs ', function () {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* 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';
import { TestData, MetricFieldVisConfig } from './types';
import { farequoteLuceneFiltersSearchTestData } from './index_test_data';

const SHOW_FIELD_STATISTICS = 'discover:showFieldStatistics';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const PageObjects = getPageObjects(['common', 'discover', 'timePicker', 'settings', 'dashboard']);
const ml = getService('ml');
const retry = getService('retry');
const dashboardAddPanel = getService('dashboardAddPanel');

function runTests(testData: TestData) {
const savedSearchTitle = `Field stats for ${testData.suiteTitle} ${Date.now()}`;
const dashboardTitle = `Dashboard for ${testData.suiteTitle} ${Date.now()}`;
const startTime = 'Jan 1, 2016 @ 00:00:00.000';
const endTime = 'Nov 1, 2020 @ 00:00:00.000';

describe(`with ${testData.suiteTitle}`, function () {
after(async function () {
await ml.testResources.deleteSavedSearchByTitle(savedSearchTitle);
await ml.testResources.deleteDashboardByTitle(dashboardTitle);
});

it(`saves search with Field statistics table in Discover`, async function () {
await ml.testResources.setAdvancedSettingProperty(SHOW_FIELD_STATISTICS, true);

await PageObjects.common.navigateToApp('discover');
if (testData.isSavedSearch) {
await retry.tryForTime(2 * 1000, async () => {
await PageObjects.discover.loadSavedSearch(testData.sourceIndexOrSavedSearch);
});
} else {
await ml.dashboardEmbeddables.selectDiscoverIndexPattern(
testData.sourceIndexOrSavedSearch
);
}
await PageObjects.timePicker.setAbsoluteRange(startTime, endTime);

await PageObjects.discover.assertViewModeToggleExists();
await PageObjects.discover.clickViewModeFieldStatsButton();
await ml.testExecution.logTestStep('saves as new search');
await PageObjects.discover.saveSearch(savedSearchTitle, true);
});

it(`displays Field statistics table in Dashboard when enabled`, async function () {
await PageObjects.common.navigateToApp('dashboard');
await PageObjects.dashboard.gotoDashboardLandingPage();
await PageObjects.dashboard.clickNewDashboard();
await dashboardAddPanel.addSavedSearch(savedSearchTitle);
await PageObjects.dashboard.waitForRenderComplete();

await PageObjects.timePicker.setAbsoluteRange(startTime, endTime);
await PageObjects.dashboard.waitForRenderComplete();

for (const fieldRow of testData.expected.metricFields as Array<
Required<MetricFieldVisConfig>
>) {
await ml.dataVisualizerTable.assertNumberFieldContents(
fieldRow.fieldName,
fieldRow.docCountFormatted,
fieldRow.topValuesCount,
fieldRow.viewableInLens
);
}

for (const fieldRow of testData.expected.nonMetricFields!) {
await ml.dataVisualizerTable.assertNonMetricFieldContents(
fieldRow.type,
fieldRow.fieldName!,
fieldRow.docCountFormatted,
fieldRow.exampleCount,
fieldRow.viewableInLens,
false,
fieldRow.exampleContent
);
}

await PageObjects.dashboard.saveDashboard(dashboardTitle);
});

it(`doesn't display Field statistics table in Dashboard when disabled`, async function () {
await ml.testResources.setAdvancedSettingProperty(SHOW_FIELD_STATISTICS, false);

await PageObjects.common.navigateToApp('dashboard');
await PageObjects.dashboard.gotoDashboardEditMode(dashboardTitle);
await PageObjects.dashboard.waitForRenderComplete();

await dashboardAddPanel.addSavedSearch(savedSearchTitle);
await PageObjects.dashboard.waitForRenderComplete();

await PageObjects.timePicker.setAbsoluteRange(startTime, endTime);
await PageObjects.dashboard.waitForRenderComplete();

await PageObjects.discover.assertFieldStatsTableNotExists();
await PageObjects.dashboard.saveDashboard(dashboardTitle);
});
});
}

describe('field statistics in Dashboard', function () {
before(async function () {
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/farequote');
await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp');
await ml.testResources.createSavedSearchFarequoteFilterAndLuceneIfNeeded();
await ml.securityUI.loginAsMlPowerUser();
});

after(async function () {
await ml.testResources.clearAdvancedSettingProperty(SHOW_FIELD_STATISTICS);
});

runTests(farequoteLuceneFiltersSearchTestData);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* 2.0.
*/

import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { TestData, MetricFieldVisConfig } from './types';

Expand All @@ -22,39 +21,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const PageObjects = getPageObjects(['common', 'discover', 'timePicker', 'settings']);
const ml = getService('ml');
const testSubjects = getService('testSubjects');
const retry = getService('retry');
const toasts = getService('toasts');

const selectIndexPattern = async (indexPattern: string) => {
await retry.tryForTime(2 * 1000, async () => {
await PageObjects.discover.selectIndexPattern(indexPattern);
const indexPatternTitle = await testSubjects.getVisibleText('indexPattern-switch-link');
expect(indexPatternTitle).to.be(indexPattern);
});
};

const clearAdvancedSetting = async (propertyName: string) => {
await retry.tryForTime(2 * 1000, async () => {
await PageObjects.common.navigateToUrl('management', 'kibana/settings', {
shouldUseHashForSubUrl: false,
});
if ((await PageObjects.settings.getAdvancedSettingCheckbox(propertyName)) === 'true') {
await PageObjects.settings.clearAdvancedSettings(propertyName);
}
});
};

const setAdvancedSettingCheckbox = async (propertyName: string, checkedState: boolean) => {
await retry.tryForTime(2 * 1000, async () => {
await PageObjects.common.navigateToUrl('management', 'kibana/settings', {
shouldUseHashForSubUrl: false,
});
await testSubjects.click('settings');
await toasts.dismissAllToasts();
await PageObjects.settings.toggleAdvancedSettingCheckbox(propertyName, checkedState);
});
};
const startTime = 'Jan 1, 2016 @ 00:00:00.000';
const endTime = 'Nov 1, 2020 @ 00:00:00.000';

function runTestsWhenDisabled(testData: TestData) {
it('should not show view mode toggle or Field stats table', async function () {
Expand All @@ -64,13 +34,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.discover.loadSavedSearch(testData.sourceIndexOrSavedSearch);
});
} else {
await selectIndexPattern(testData.sourceIndexOrSavedSearch);
await ml.dashboardEmbeddables.selectDiscoverIndexPattern(testData.sourceIndexOrSavedSearch);
}

await PageObjects.timePicker.setAbsoluteRange(
'Jan 1, 2016 @ 00:00:00.000',
'Nov 1, 2020 @ 00:00:00.000'
);
await PageObjects.timePicker.setAbsoluteRange(startTime, endTime);

await PageObjects.discover.assertViewModeToggleNotExists();
await PageObjects.discover.assertFieldStatsTableNotExists();
Expand All @@ -86,12 +53,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.discover.loadSavedSearch(testData.sourceIndexOrSavedSearch);
});
} else {
await selectIndexPattern(testData.sourceIndexOrSavedSearch);
await ml.dashboardEmbeddables.selectDiscoverIndexPattern(
testData.sourceIndexOrSavedSearch
);
}
await PageObjects.timePicker.setAbsoluteRange(
'Jan 1, 2016 @ 00:00:00.000',
'Nov 1, 2020 @ 00:00:00.000'
);
await PageObjects.timePicker.setAbsoluteRange(startTime, endTime);

await PageObjects.discover.assertHitCount(testData.expected.totalDocCountFormatted);
await PageObjects.discover.assertViewModeToggleExists();
Expand Down Expand Up @@ -140,16 +106,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});

after(async function () {
await clearAdvancedSetting(SHOW_FIELD_STATISTICS);
await ml.testResources.clearAdvancedSettingProperty(SHOW_FIELD_STATISTICS);
});

describe('when enabled', function () {
before(async function () {
await setAdvancedSettingCheckbox(SHOW_FIELD_STATISTICS, true);
await ml.testResources.setAdvancedSettingProperty(SHOW_FIELD_STATISTICS, true);
});

after(async function () {
await clearAdvancedSetting(SHOW_FIELD_STATISTICS);
await ml.testResources.clearAdvancedSettingProperty(SHOW_FIELD_STATISTICS);
});

runTests(farequoteDataViewTestData);
Expand All @@ -163,7 +129,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
describe('when disabled', function () {
before(async function () {
// Ensure that the setting is set to default state which is false
await setAdvancedSettingCheckbox(SHOW_FIELD_STATISTICS, false);
await ml.testResources.setAdvancedSettingProperty(SHOW_FIELD_STATISTICS, false);
});

runTestsWhenDisabled(farequoteDataViewTestData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ export const farequoteKQLFiltersSearchTestData: TestData = {
{ size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } },
],
expected: {
filters: [{ key: 'airline', value: 'ASA' }],
totalDocCountFormatted: '5,674',
metricFields: [
{
Expand Down Expand Up @@ -408,6 +409,7 @@ export const farequoteLuceneFiltersSearchTestData: TestData = {
{ size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } },
],
expected: {
filters: [{ key: 'airline', value: 'ASA' }],
totalDocCountFormatted: '5,673',
metricFields: [
{
Expand Down
7 changes: 7 additions & 0 deletions x-pack/test/functional/apps/ml/data_visualizer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ export interface TestData {
expected: { field: string; docCountFormatted: string };
}>;
expected: {
filters?: Array<{
key: string;
value: string;
enabled?: boolean;
pinned?: boolean;
negated?: boolean;
}>;
totalDocCountFormatted: string;
metricFields?: MetricFieldVisConfig[];
nonMetricFields?: NonMetricFieldVisConfig[];
Expand Down
11 changes: 10 additions & 1 deletion x-pack/test/functional/services/ml/dashboard_embeddables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import { FtrProviderContext } from '../../ftr_provider_context';
import { MlDashboardJobSelectionTable } from './dashboard_job_selection_table';

export function MachineLearningDashboardEmbeddablesProvider(
{ getService }: FtrProviderContext,
{ getService, getPageObjects }: FtrProviderContext,
mlDashboardJobSelectionTable: MlDashboardJobSelectionTable
) {
const retry = getService('retry');
const testSubjects = getService('testSubjects');
const find = getService('find');
const dashboardAddPanel = getService('dashboardAddPanel');
const PageObjects = getPageObjects(['discover']);

return {
async assertAnomalyChartsEmbeddableInitializerExists() {
Expand Down Expand Up @@ -112,5 +113,13 @@ export function MachineLearningDashboardEmbeddablesProvider(
await mlDashboardJobSelectionTable.assertJobSelectionTableExists();
});
},

async selectDiscoverIndexPattern(indexPattern: string) {
await retry.tryForTime(2 * 1000, async () => {
await PageObjects.discover.selectIndexPattern(indexPattern);
const indexPatternTitle = await testSubjects.getVisibleText('indexPattern-switch-link');
expect(indexPatternTitle).to.be(indexPattern);
});
},
};
}
Loading