Skip to content

Commit

Permalink
[ML] Add functional tests for Field statistics embeddable in Dashboar…
Browse files Browse the repository at this point in the history
…d, check for filters (#116774)

* [ML] Add functional tests for dashboard embeddable, filters

* [ML] Fix permissions

* [ML] Update tests to use bulk api

* [ML] Change to constants

* [ML] Fix savedSearchTitle

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
qn895 and kibanamachine authored Nov 5, 2021
1 parent 735a286 commit 6fe0052
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 50 deletions.
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

0 comments on commit 6fe0052

Please sign in to comment.