Skip to content

Commit 6fe0052

Browse files
qn895kibanamachine
andauthored
[ML] Add functional tests for Field statistics embeddable in Dashboard, 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 <42973632+kibanamachine@users.noreply.github.com>
1 parent 735a286 commit 6fe0052

File tree

11 files changed

+222
-50
lines changed

11 files changed

+222
-50
lines changed

test/functional/page_objects/discover_page.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export class DiscoverPageObject extends FtrService {
4848
await fieldSearch.clearValue();
4949
}
5050

51-
public async saveSearch(searchName: string) {
51+
public async saveSearch(searchName: string, saveAsNew?: boolean) {
5252
await this.clickSaveSearchButton();
5353
// preventing an occasional flakiness when the saved object wasn't set and the form can't be submitted
5454
await this.retry.waitFor(
@@ -59,6 +59,14 @@ export class DiscoverPageObject extends FtrService {
5959
return (await saveButton.getAttribute('disabled')) !== 'true';
6060
}
6161
);
62+
63+
if (saveAsNew !== undefined) {
64+
await this.retry.waitFor(`save as new switch is set`, async () => {
65+
await this.testSubjects.setEuiSwitch('saveAsNewCheckbox', saveAsNew ? 'check' : 'uncheck');
66+
return (await this.testSubjects.isEuiSwitchChecked('saveAsNewCheckbox')) === saveAsNew;
67+
});
68+
}
69+
6270
await this.testSubjects.click('confirmSaveSavedObjectButton');
6371
await this.header.waitUntilLoadingHasFinished();
6472
// LeeDr - this additional checking for the saved search name was an attempt

x-pack/test/functional/apps/ml/data_visualizer/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export default function ({ loadTestFile }: FtrProviderContext) {
1313

1414
loadTestFile(require.resolve('./index_data_visualizer'));
1515
loadTestFile(require.resolve('./index_data_visualizer_grid_in_discover'));
16+
loadTestFile(require.resolve('./index_data_visualizer_grid_in_dashboard'));
1617
loadTestFile(require.resolve('./index_data_visualizer_actions_panel'));
1718
loadTestFile(require.resolve('./index_data_visualizer_index_pattern_management'));
1819
loadTestFile(require.resolve('./file_data_visualizer'));

x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
99
import { TestData, MetricFieldVisConfig } from './types';
1010
import {
1111
farequoteDataViewTestData,
12+
farequoteKQLFiltersSearchTestData,
1213
farequoteKQLSearchTestData,
1314
farequoteLuceneSearchTestData,
1415
sampleLogTestData,
@@ -76,6 +77,13 @@ export default function ({ getService }: FtrProviderContext) {
7677
);
7778
await ml.dataVisualizerIndexBased.assertTotalFieldsCount(testData.expected.totalFieldsCount);
7879

80+
if (testData.expected.filters) {
81+
await ml.testExecution.logTestStep('displays filters in filter bar correctly');
82+
for (const filter of testData.expected.filters!) {
83+
await ml.dataVisualizerIndexBased.assertFilterBarFilterContent(filter);
84+
}
85+
}
86+
7987
await ml.testExecution.logTestStep(
8088
'displays details for metric fields and non-metric fields correctly'
8189
);
@@ -96,7 +104,9 @@ export default function ({ getService }: FtrProviderContext) {
96104
fieldRow.fieldName!,
97105
fieldRow.docCountFormatted,
98106
fieldRow.exampleCount,
99-
fieldRow.viewableInLens
107+
fieldRow.viewableInLens,
108+
false,
109+
fieldRow.exampleContent
100110
);
101111
}
102112

@@ -150,6 +160,7 @@ export default function ({ getService }: FtrProviderContext) {
150160
await ml.testResources.createIndexPatternIfNeeded('ft_module_sample_logs', '@timestamp');
151161
await ml.testResources.createSavedSearchFarequoteLuceneIfNeeded();
152162
await ml.testResources.createSavedSearchFarequoteKueryIfNeeded();
163+
await ml.testResources.createSavedSearchFarequoteFilterAndKueryIfNeeded();
153164
await ml.testResources.setKibanaTimeZoneToUTC();
154165

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

184195
runTests(farequoteLuceneSearchTestData);
196+
197+
it(`${farequoteKQLFiltersSearchTestData.suiteTitle} loads the data visualizer selector page`, async () => {
198+
// Start navigation from the base of the ML app.
199+
await ml.navigation.navigateToMl();
200+
await ml.navigation.navigateToDataVisualizer();
201+
});
202+
203+
runTests(farequoteKQLFiltersSearchTestData);
185204
});
186205

187206
describe('with module_sample_logs ', function () {
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { FtrProviderContext } from '../../../ftr_provider_context';
9+
import { TestData, MetricFieldVisConfig } from './types';
10+
import { farequoteLuceneFiltersSearchTestData } from './index_test_data';
11+
12+
const SHOW_FIELD_STATISTICS = 'discover:showFieldStatistics';
13+
export default function ({ getService, getPageObjects }: FtrProviderContext) {
14+
const esArchiver = getService('esArchiver');
15+
const PageObjects = getPageObjects(['common', 'discover', 'timePicker', 'settings', 'dashboard']);
16+
const ml = getService('ml');
17+
const retry = getService('retry');
18+
const dashboardAddPanel = getService('dashboardAddPanel');
19+
20+
function runTests(testData: TestData) {
21+
const savedSearchTitle = `Field stats for ${testData.suiteTitle} ${Date.now()}`;
22+
const dashboardTitle = `Dashboard for ${testData.suiteTitle} ${Date.now()}`;
23+
const startTime = 'Jan 1, 2016 @ 00:00:00.000';
24+
const endTime = 'Nov 1, 2020 @ 00:00:00.000';
25+
26+
describe(`with ${testData.suiteTitle}`, function () {
27+
after(async function () {
28+
await ml.testResources.deleteSavedSearchByTitle(savedSearchTitle);
29+
await ml.testResources.deleteDashboardByTitle(dashboardTitle);
30+
});
31+
32+
it(`saves search with Field statistics table in Discover`, async function () {
33+
await ml.testResources.setAdvancedSettingProperty(SHOW_FIELD_STATISTICS, true);
34+
35+
await PageObjects.common.navigateToApp('discover');
36+
if (testData.isSavedSearch) {
37+
await retry.tryForTime(2 * 1000, async () => {
38+
await PageObjects.discover.loadSavedSearch(testData.sourceIndexOrSavedSearch);
39+
});
40+
} else {
41+
await ml.dashboardEmbeddables.selectDiscoverIndexPattern(
42+
testData.sourceIndexOrSavedSearch
43+
);
44+
}
45+
await PageObjects.timePicker.setAbsoluteRange(startTime, endTime);
46+
47+
await PageObjects.discover.assertViewModeToggleExists();
48+
await PageObjects.discover.clickViewModeFieldStatsButton();
49+
await ml.testExecution.logTestStep('saves as new search');
50+
await PageObjects.discover.saveSearch(savedSearchTitle, true);
51+
});
52+
53+
it(`displays Field statistics table in Dashboard when enabled`, async function () {
54+
await PageObjects.common.navigateToApp('dashboard');
55+
await PageObjects.dashboard.gotoDashboardLandingPage();
56+
await PageObjects.dashboard.clickNewDashboard();
57+
await dashboardAddPanel.addSavedSearch(savedSearchTitle);
58+
await PageObjects.dashboard.waitForRenderComplete();
59+
60+
await PageObjects.timePicker.setAbsoluteRange(startTime, endTime);
61+
await PageObjects.dashboard.waitForRenderComplete();
62+
63+
for (const fieldRow of testData.expected.metricFields as Array<
64+
Required<MetricFieldVisConfig>
65+
>) {
66+
await ml.dataVisualizerTable.assertNumberFieldContents(
67+
fieldRow.fieldName,
68+
fieldRow.docCountFormatted,
69+
fieldRow.topValuesCount,
70+
fieldRow.viewableInLens
71+
);
72+
}
73+
74+
for (const fieldRow of testData.expected.nonMetricFields!) {
75+
await ml.dataVisualizerTable.assertNonMetricFieldContents(
76+
fieldRow.type,
77+
fieldRow.fieldName!,
78+
fieldRow.docCountFormatted,
79+
fieldRow.exampleCount,
80+
fieldRow.viewableInLens,
81+
false,
82+
fieldRow.exampleContent
83+
);
84+
}
85+
86+
await PageObjects.dashboard.saveDashboard(dashboardTitle);
87+
});
88+
89+
it(`doesn't display Field statistics table in Dashboard when disabled`, async function () {
90+
await ml.testResources.setAdvancedSettingProperty(SHOW_FIELD_STATISTICS, false);
91+
92+
await PageObjects.common.navigateToApp('dashboard');
93+
await PageObjects.dashboard.gotoDashboardEditMode(dashboardTitle);
94+
await PageObjects.dashboard.waitForRenderComplete();
95+
96+
await dashboardAddPanel.addSavedSearch(savedSearchTitle);
97+
await PageObjects.dashboard.waitForRenderComplete();
98+
99+
await PageObjects.timePicker.setAbsoluteRange(startTime, endTime);
100+
await PageObjects.dashboard.waitForRenderComplete();
101+
102+
await PageObjects.discover.assertFieldStatsTableNotExists();
103+
await PageObjects.dashboard.saveDashboard(dashboardTitle);
104+
});
105+
});
106+
}
107+
108+
describe('field statistics in Dashboard', function () {
109+
before(async function () {
110+
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/farequote');
111+
await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp');
112+
await ml.testResources.createSavedSearchFarequoteFilterAndLuceneIfNeeded();
113+
await ml.securityUI.loginAsMlPowerUser();
114+
});
115+
116+
after(async function () {
117+
await ml.testResources.clearAdvancedSettingProperty(SHOW_FIELD_STATISTICS);
118+
});
119+
120+
runTests(farequoteLuceneFiltersSearchTestData);
121+
});
122+
}

x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_grid_in_discover.ts

Lines changed: 12 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
* 2.0.
66
*/
77

8-
import expect from '@kbn/expect';
98
import { FtrProviderContext } from '../../../ftr_provider_context';
109
import { TestData, MetricFieldVisConfig } from './types';
1110

@@ -22,39 +21,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
2221
const esArchiver = getService('esArchiver');
2322
const PageObjects = getPageObjects(['common', 'discover', 'timePicker', 'settings']);
2423
const ml = getService('ml');
25-
const testSubjects = getService('testSubjects');
2624
const retry = getService('retry');
27-
const toasts = getService('toasts');
2825

29-
const selectIndexPattern = async (indexPattern: string) => {
30-
await retry.tryForTime(2 * 1000, async () => {
31-
await PageObjects.discover.selectIndexPattern(indexPattern);
32-
const indexPatternTitle = await testSubjects.getVisibleText('indexPattern-switch-link');
33-
expect(indexPatternTitle).to.be(indexPattern);
34-
});
35-
};
36-
37-
const clearAdvancedSetting = async (propertyName: string) => {
38-
await retry.tryForTime(2 * 1000, async () => {
39-
await PageObjects.common.navigateToUrl('management', 'kibana/settings', {
40-
shouldUseHashForSubUrl: false,
41-
});
42-
if ((await PageObjects.settings.getAdvancedSettingCheckbox(propertyName)) === 'true') {
43-
await PageObjects.settings.clearAdvancedSettings(propertyName);
44-
}
45-
});
46-
};
47-
48-
const setAdvancedSettingCheckbox = async (propertyName: string, checkedState: boolean) => {
49-
await retry.tryForTime(2 * 1000, async () => {
50-
await PageObjects.common.navigateToUrl('management', 'kibana/settings', {
51-
shouldUseHashForSubUrl: false,
52-
});
53-
await testSubjects.click('settings');
54-
await toasts.dismissAllToasts();
55-
await PageObjects.settings.toggleAdvancedSettingCheckbox(propertyName, checkedState);
56-
});
57-
};
26+
const startTime = 'Jan 1, 2016 @ 00:00:00.000';
27+
const endTime = 'Nov 1, 2020 @ 00:00:00.000';
5828

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

70-
await PageObjects.timePicker.setAbsoluteRange(
71-
'Jan 1, 2016 @ 00:00:00.000',
72-
'Nov 1, 2020 @ 00:00:00.000'
73-
);
40+
await PageObjects.timePicker.setAbsoluteRange(startTime, endTime);
7441

7542
await PageObjects.discover.assertViewModeToggleNotExists();
7643
await PageObjects.discover.assertFieldStatsTableNotExists();
@@ -86,12 +53,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
8653
await PageObjects.discover.loadSavedSearch(testData.sourceIndexOrSavedSearch);
8754
});
8855
} else {
89-
await selectIndexPattern(testData.sourceIndexOrSavedSearch);
56+
await ml.dashboardEmbeddables.selectDiscoverIndexPattern(
57+
testData.sourceIndexOrSavedSearch
58+
);
9059
}
91-
await PageObjects.timePicker.setAbsoluteRange(
92-
'Jan 1, 2016 @ 00:00:00.000',
93-
'Nov 1, 2020 @ 00:00:00.000'
94-
);
60+
await PageObjects.timePicker.setAbsoluteRange(startTime, endTime);
9561

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

142108
after(async function () {
143-
await clearAdvancedSetting(SHOW_FIELD_STATISTICS);
109+
await ml.testResources.clearAdvancedSettingProperty(SHOW_FIELD_STATISTICS);
144110
});
145111

146112
describe('when enabled', function () {
147113
before(async function () {
148-
await setAdvancedSettingCheckbox(SHOW_FIELD_STATISTICS, true);
114+
await ml.testResources.setAdvancedSettingProperty(SHOW_FIELD_STATISTICS, true);
149115
});
150116

151117
after(async function () {
152-
await clearAdvancedSetting(SHOW_FIELD_STATISTICS);
118+
await ml.testResources.clearAdvancedSettingProperty(SHOW_FIELD_STATISTICS);
153119
});
154120

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

169135
runTestsWhenDisabled(farequoteDataViewTestData);

x-pack/test/functional/apps/ml/data_visualizer/index_test_data.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ export const farequoteKQLFiltersSearchTestData: TestData = {
213213
{ size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } },
214214
],
215215
expected: {
216+
filters: [{ key: 'airline', value: 'ASA' }],
216217
totalDocCountFormatted: '5,674',
217218
metricFields: [
218219
{
@@ -408,6 +409,7 @@ export const farequoteLuceneFiltersSearchTestData: TestData = {
408409
{ size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } },
409410
],
410411
expected: {
412+
filters: [{ key: 'airline', value: 'ASA' }],
411413
totalDocCountFormatted: '5,673',
412414
metricFields: [
413415
{

x-pack/test/functional/apps/ml/data_visualizer/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ export interface TestData {
3333
expected: { field: string; docCountFormatted: string };
3434
}>;
3535
expected: {
36+
filters?: Array<{
37+
key: string;
38+
value: string;
39+
enabled?: boolean;
40+
pinned?: boolean;
41+
negated?: boolean;
42+
}>;
3643
totalDocCountFormatted: string;
3744
metricFields?: MetricFieldVisConfig[];
3845
nonMetricFields?: NonMetricFieldVisConfig[];

x-pack/test/functional/services/ml/dashboard_embeddables.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import { FtrProviderContext } from '../../ftr_provider_context';
1010
import { MlDashboardJobSelectionTable } from './dashboard_job_selection_table';
1111

1212
export function MachineLearningDashboardEmbeddablesProvider(
13-
{ getService }: FtrProviderContext,
13+
{ getService, getPageObjects }: FtrProviderContext,
1414
mlDashboardJobSelectionTable: MlDashboardJobSelectionTable
1515
) {
1616
const retry = getService('retry');
1717
const testSubjects = getService('testSubjects');
1818
const find = getService('find');
1919
const dashboardAddPanel = getService('dashboardAddPanel');
20+
const PageObjects = getPageObjects(['discover']);
2021

2122
return {
2223
async assertAnomalyChartsEmbeddableInitializerExists() {
@@ -112,5 +113,13 @@ export function MachineLearningDashboardEmbeddablesProvider(
112113
await mlDashboardJobSelectionTable.assertJobSelectionTableExists();
113114
});
114115
},
116+
117+
async selectDiscoverIndexPattern(indexPattern: string) {
118+
await retry.tryForTime(2 * 1000, async () => {
119+
await PageObjects.discover.selectIndexPattern(indexPattern);
120+
const indexPatternTitle = await testSubjects.getVisibleText('indexPattern-switch-link');
121+
expect(indexPatternTitle).to.be(indexPattern);
122+
});
123+
},
115124
};
116125
}

0 commit comments

Comments
 (0)