From 3c041f3375aa550c0c05512f95de9db8e94bf62c Mon Sep 17 00:00:00 2001 From: Robert Oskamp Date: Mon, 2 Nov 2020 17:29:31 +0100 Subject: [PATCH] [ML] Functional tests - add basic license tests (#82147) This PR adds initial functional tests and api integration tests running on a basic license for the ML and Transform apps. --- .../components/navigation_menu/main_tabs.tsx | 7 +- .../datavisualizer_selector.tsx | 2 + .../ml/public/application/routing/router.tsx | 2 +- x-pack/scripts/functional_tests.js | 2 + .../api_integration/apis/transform/index.ts | 2 +- .../test/api_integration_basic/apis/index.ts | 16 ++ .../apis/ml/data_visualizer/index.ts | 14 ++ .../api_integration_basic/apis/ml/index.ts | 39 +++++ .../apis/transform/index.ts | 16 ++ x-pack/test/api_integration_basic/config.ts | 32 ++++ .../ftr_provider_context.d.ts | 11 ++ .../apps/ml/data_visualizer/index.ts | 1 + .../data_visualizer/index_data_visualizer.ts | 39 ----- .../index_data_visualizer_actions_panel.ts | 62 +++++++ .../apps/ml/permissions/full_ml_access.ts | 27 ++- .../apps/ml/permissions/no_ml_access.ts | 4 +- .../apps/ml/permissions/read_ml_access.ts | 26 ++- .../functional/services/ml/data_visualizer.ts | 14 ++ .../test/functional/services/ml/navigation.ts | 32 +++- x-pack/test/functional_basic/apps/index.ts | 16 ++ .../apps/ml/data_visualizer/index.ts | 22 +++ x-pack/test/functional_basic/apps/ml/index.ts | 40 +++++ .../apps/ml/permissions/full_ml_access.ts | 163 ++++++++++++++++++ .../apps/ml/permissions/index.ts | 14 ++ .../apps/ml/permissions/no_ml_access.ts | 63 +++++++ .../apps/ml/permissions/read_ml_access.ts | 163 ++++++++++++++++++ .../functional_basic/apps/transform/index.ts | 15 ++ x-pack/test/functional_basic/config.ts | 30 ++++ .../ftr_provider_context.d.ts | 12 ++ 29 files changed, 838 insertions(+), 48 deletions(-) create mode 100644 x-pack/test/api_integration_basic/apis/index.ts create mode 100644 x-pack/test/api_integration_basic/apis/ml/data_visualizer/index.ts create mode 100644 x-pack/test/api_integration_basic/apis/ml/index.ts create mode 100644 x-pack/test/api_integration_basic/apis/transform/index.ts create mode 100644 x-pack/test/api_integration_basic/config.ts create mode 100644 x-pack/test/api_integration_basic/ftr_provider_context.d.ts create mode 100644 x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_actions_panel.ts create mode 100644 x-pack/test/functional_basic/apps/index.ts create mode 100644 x-pack/test/functional_basic/apps/ml/data_visualizer/index.ts create mode 100644 x-pack/test/functional_basic/apps/ml/index.ts create mode 100644 x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts create mode 100644 x-pack/test/functional_basic/apps/ml/permissions/index.ts create mode 100644 x-pack/test/functional_basic/apps/ml/permissions/no_ml_access.ts create mode 100644 x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts create mode 100644 x-pack/test/functional_basic/apps/transform/index.ts create mode 100644 x-pack/test/functional_basic/config.ts create mode 100644 x-pack/test/functional_basic/ftr_provider_context.d.ts diff --git a/x-pack/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx b/x-pack/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx index 671f0b196ce35..79b333fd3a51e 100644 --- a/x-pack/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx +++ b/x-pack/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx @@ -160,7 +160,12 @@ export const MainTabs: FC = ({ tabId, disableLinks }) => { const defaultPathId = (TAB_DATA[id].pathId || id) as MlUrlGeneratorState['page']; return disabled ? ( - + {tab.name} ) : ( diff --git a/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx b/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx index 7c30dc0cac690..9ef74854b92d6 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx @@ -189,6 +189,7 @@ export const DatavisualizerSelector: FC = () => { { /> } + data-test-subj="mlDataVisualizerCardStartTrial" /> diff --git a/x-pack/plugins/ml/public/application/routing/router.tsx b/x-pack/plugins/ml/public/application/routing/router.tsx index 7cb3a2f07c2ee..40a8239d36fc8 100644 --- a/x-pack/plugins/ml/public/application/routing/router.tsx +++ b/x-pack/plugins/ml/public/application/routing/router.tsx @@ -117,7 +117,7 @@ export const MlRouter: FC<{ -
+
diff --git a/x-pack/scripts/functional_tests.js b/x-pack/scripts/functional_tests.js index 8486c52145e6f..a10875de1bb55 100644 --- a/x-pack/scripts/functional_tests.js +++ b/x-pack/scripts/functional_tests.js @@ -8,6 +8,7 @@ require('../../src/setup_node_env'); require('@kbn/test').runTestsCli([ require.resolve('../test/functional/config.js'), + require.resolve('../test/functional_basic/config.ts'), require.resolve('../test/security_solution_endpoint/config.ts'), require.resolve('../test/plugin_functional/config.ts'), require.resolve('../test/functional_with_es_ssl/config.ts'), @@ -18,6 +19,7 @@ require('@kbn/test').runTestsCli([ require.resolve('../test/api_integration/config_security_basic.ts'), require.resolve('../test/api_integration/config_security_trial.ts'), require.resolve('../test/api_integration/config.ts'), + require.resolve('../test/api_integration_basic/config.ts'), require.resolve('../test/alerting_api_integration/basic/config.ts'), require.resolve('../test/alerting_api_integration/spaces_only/config.ts'), require.resolve('../test/alerting_api_integration/security_and_spaces/config.ts'), diff --git a/x-pack/test/api_integration/apis/transform/index.ts b/x-pack/test/api_integration/apis/transform/index.ts index ef08883534d10..c1dea4dc4a1b1 100644 --- a/x-pack/test/api_integration/apis/transform/index.ts +++ b/x-pack/test/api_integration/apis/transform/index.ts @@ -10,7 +10,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const transform = getService('transform'); - describe('Machine Learning', function () { + describe('transform', function () { this.tags(['transform']); before(async () => { diff --git a/x-pack/test/api_integration_basic/apis/index.ts b/x-pack/test/api_integration_basic/apis/index.ts new file mode 100644 index 0000000000000..66b3a45c12df3 --- /dev/null +++ b/x-pack/test/api_integration_basic/apis/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('apis', function () { + this.tags('ciGroup2'); + + loadTestFile(require.resolve('./ml')); + loadTestFile(require.resolve('./transform')); + }); +} diff --git a/x-pack/test/api_integration_basic/apis/ml/data_visualizer/index.ts b/x-pack/test/api_integration_basic/apis/ml/data_visualizer/index.ts new file mode 100644 index 0000000000000..ade7c6e1dc560 --- /dev/null +++ b/x-pack/test/api_integration_basic/apis/ml/data_visualizer/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('data visualizer', function () { + // The data visualizer APIs should work the same as with a trial license + loadTestFile(require.resolve('../../../../api_integration/apis/ml/data_visualizer')); + }); +} diff --git a/x-pack/test/api_integration_basic/apis/ml/index.ts b/x-pack/test/api_integration_basic/apis/ml/index.ts new file mode 100644 index 0000000000000..ba81b8c690e98 --- /dev/null +++ b/x-pack/test/api_integration_basic/apis/ml/index.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const ml = getService('ml'); + + describe('machine learning basic license', function () { + this.tags(['mlqa']); + + before(async () => { + await ml.securityCommon.createMlRoles(); + await ml.securityCommon.createMlUsers(); + }); + + after(async () => { + await ml.securityCommon.cleanMlUsers(); + await ml.securityCommon.cleanMlRoles(); + + await ml.testResources.deleteIndexPatternByTitle('ft_farequote'); + + await esArchiver.unload('ml/farequote'); + + await ml.testResources.resetKibanaTimeZone(); + }); + + loadTestFile(require.resolve('./data_visualizer')); + }); +} diff --git a/x-pack/test/api_integration_basic/apis/transform/index.ts b/x-pack/test/api_integration_basic/apis/transform/index.ts new file mode 100644 index 0000000000000..c2cab17abcb16 --- /dev/null +++ b/x-pack/test/api_integration_basic/apis/transform/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('transform basic license', function () { + this.tags(['transform']); + + // The transform UI should work the same as with a trial license + loadTestFile(require.resolve('../../../api_integration/apis/transform')); + }); +} diff --git a/x-pack/test/api_integration_basic/config.ts b/x-pack/test/api_integration_basic/config.ts new file mode 100644 index 0000000000000..131f29e7d58b4 --- /dev/null +++ b/x-pack/test/api_integration_basic/config.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const xpackApiIntegrationConfig = await readConfigFile( + require.resolve('../api_integration/config.ts') + ); + + return { + // default to the xpack api integration config + ...xpackApiIntegrationConfig.getAll(), + esTestCluster: { + ...xpackApiIntegrationConfig.get('esTestCluster'), + license: 'basic', + serverArgs: [ + 'xpack.license.self_generated.type=basic', + 'xpack.security.enabled=true', + 'xpack.security.authc.api_key.enabled=true', + ], + }, + testFiles: [require.resolve('./apis')], + junit: { + ...xpackApiIntegrationConfig.get('junit'), + reportName: 'Chrome X-Pack UI Functional Tests Basic License', + }, + }; +} diff --git a/x-pack/test/api_integration_basic/ftr_provider_context.d.ts b/x-pack/test/api_integration_basic/ftr_provider_context.d.ts new file mode 100644 index 0000000000000..2751dbcdc6539 --- /dev/null +++ b/x-pack/test/api_integration_basic/ftr_provider_context.d.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { GenericFtrProviderContext } from '@kbn/test/types/ftr'; + +import { services } from '../api_integration/services'; + +export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test/functional/apps/ml/data_visualizer/index.ts b/x-pack/test/functional/apps/ml/data_visualizer/index.ts index 77426afa92721..0e8aa1d8f567e 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/index.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/index.ts @@ -10,6 +10,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { this.tags(['skipFirefox']); loadTestFile(require.resolve('./index_data_visualizer')); + loadTestFile(require.resolve('./index_data_visualizer_actions_panel')); loadTestFile(require.resolve('./file_data_visualizer')); }); } diff --git a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts index 2dc1d9ec00eca..1c1afd86fb7d7 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts @@ -11,7 +11,6 @@ import { FieldVisConfig } from '../../../../../plugins/ml/public/application/dat interface TestData { suiteTitle: string; sourceIndexOrSavedSearch: string; - advancedJobWizardDatafeedQuery: string; metricFieldsFilter: string; nonMetricFieldsFilter: string; nonMetricFieldsTypeFilter: string; @@ -45,15 +44,6 @@ export default function ({ getService }: FtrProviderContext) { const farequoteIndexPatternTestData: TestData = { suiteTitle: 'index pattern', sourceIndexOrSavedSearch: 'ft_farequote', - advancedJobWizardDatafeedQuery: `{ - "bool": { - "must": [ - { - "match_all": {} - } - ] - } -}`, metricFieldsFilter: 'document', nonMetricFieldsFilter: 'airline', nonMetricFieldsTypeFilter: 'keyword', @@ -128,15 +118,6 @@ export default function ({ getService }: FtrProviderContext) { const farequoteKQLSearchTestData: TestData = { suiteTitle: 'KQL saved search', sourceIndexOrSavedSearch: 'ft_farequote_kuery', - advancedJobWizardDatafeedQuery: `{ - "bool": { - "must": [ - { - "match_all": {} - } - ] - } -}`, // Note query is not currently passed to the wizard metricFieldsFilter: 'responsetime', nonMetricFieldsFilter: 'airline', nonMetricFieldsTypeFilter: 'keyword', @@ -211,15 +192,6 @@ export default function ({ getService }: FtrProviderContext) { const farequoteLuceneSearchTestData: TestData = { suiteTitle: 'lucene saved search', sourceIndexOrSavedSearch: 'ft_farequote_lucene', - advancedJobWizardDatafeedQuery: `{ - "bool": { - "must": [ - { - "match_all": {} - } - ] - } -}`, // Note query is not currently passed to the wizard metricFieldsFilter: 'responsetime', nonMetricFieldsFilter: 'version', nonMetricFieldsTypeFilter: 'keyword', @@ -425,17 +397,6 @@ export default function ({ getService }: FtrProviderContext) { }); runTests(farequoteLuceneSearchTestData); - - // Test the Create advanced job button. - // Note the search is not currently passed to the wizard, just the index. - it(`${farequoteLuceneSearchTestData.suiteTitle} opens the advanced job wizard`, async () => { - await ml.dataVisualizerIndexBased.clickCreateAdvancedJobButton(); - await ml.jobTypeSelection.assertAdvancedJobWizardOpen(); - await ml.jobWizardAdvanced.assertDatafeedQueryEditorExists(); - await ml.jobWizardAdvanced.assertDatafeedQueryEditorValue( - farequoteLuceneSearchTestData.advancedJobWizardDatafeedQuery - ); - }); }); }); } diff --git a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_actions_panel.ts b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_actions_panel.ts new file mode 100644 index 0000000000000..ca7383ee823e7 --- /dev/null +++ b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_actions_panel.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const ml = getService('ml'); + + describe('index based actions panel', function () { + this.tags(['mlqa']); + + const indexPatternName = 'ft_farequote'; + const advancedJobWizardDatafeedQuery = `{ + "bool": { + "must": [ + { + "match_all": {} + } + ] + } +}`; // Note query is not currently passed to the wizard + + before(async () => { + await esArchiver.loadIfNeeded('ml/farequote'); + await ml.testResources.createIndexPatternIfNeeded(indexPatternName, '@timestamp'); + await ml.testResources.setKibanaTimeZoneToUTC(); + + await ml.securityUI.loginAsMlPowerUser(); + }); + + describe('create advanced job action', function () { + it('loads the source data in the data visualizer', async () => { + await ml.testExecution.logTestStep('loads the data visualizer selector page'); + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToDataVisualizer(); + + await ml.testExecution.logTestStep('loads the saved search selection page'); + await ml.dataVisualizer.navigateToIndexPatternSelection(); + + await ml.testExecution.logTestStep('loads the index data visualizer page'); + await ml.jobSourceSelection.selectSourceForIndexBasedDataVisualizer(indexPatternName); + }); + + it('opens the advanced job wizard', async () => { + await ml.testExecution.logTestStep('displays the actions panel with advanced job card'); + await ml.dataVisualizerIndexBased.assertActionsPanelExists(); + await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardExists(); + + // Note the search is not currently passed to the wizard, just the index. + await ml.testExecution.logTestStep('displays the actions panel with advanced job card'); + await ml.dataVisualizerIndexBased.clickCreateAdvancedJobButton(); + await ml.jobTypeSelection.assertAdvancedJobWizardOpen(); + await ml.jobWizardAdvanced.assertDatafeedQueryEditorExists(); + await ml.jobWizardAdvanced.assertDatafeedQueryEditorValue(advancedJobWizardDatafeedQuery); + }); + }); + }); +} diff --git a/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts b/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts index c3dde872fa4a6..4ce600084e43e 100644 --- a/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts +++ b/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts @@ -47,9 +47,32 @@ export default function ({ getService }: FtrProviderContext) { await ml.navigation.assertKibanaNavMLEntryExists(); }); + it('should display tabs in the ML app correctly', async () => { + await ml.testExecution.logTestStep('should load the ML app'); + await ml.navigation.navigateToMl(); + + await ml.testExecution.logTestStep('should display the enabled "Overview" tab'); + await ml.navigation.assertOverviewTabEnabled(true); + + await ml.testExecution.logTestStep( + 'should display the enabled "Anomaly Detection" tab' + ); + await ml.navigation.assertAnomalyDetectionTabEnabled(true); + + await ml.testExecution.logTestStep( + 'should display the enabled "Data Frame Analytics" tab' + ); + await ml.navigation.assertDataFrameAnalyticsTabEnabled(true); + + await ml.testExecution.logTestStep('should display the enabled "Data Visualizer" tab'); + await ml.navigation.assertDataVisualizerTabEnabled(true); + + await ml.testExecution.logTestStep('should display the enabled "Settings" tab'); + await ml.navigation.assertSettingsTabEnabled(true); + }); + it('should display elements on ML Overview page correctly', async () => { await ml.testExecution.logTestStep('should load the ML overview page'); - await ml.navigation.navigateToMl(); await ml.navigation.navigateToOverview(); await ml.testExecution.logTestStep('should display enabled AD create job button'); @@ -353,7 +376,7 @@ export default function ({ getService }: FtrProviderContext) { await ml.dataVisualizerFileBased.selectFile(uploadFilePath); await ml.testExecution.logTestStep( - 'should displays components of the file details page' + 'should display components of the file details page' ); await ml.dataVisualizerFileBased.assertFileTitle(expectedUploadFileTitle); await ml.dataVisualizerFileBased.assertFileContentPanelExists(); diff --git a/x-pack/test/functional/apps/ml/permissions/no_ml_access.ts b/x-pack/test/functional/apps/ml/permissions/no_ml_access.ts index 42b993c51b065..02a4ed3d4c2aa 100644 --- a/x-pack/test/functional/apps/ml/permissions/no_ml_access.ts +++ b/x-pack/test/functional/apps/ml/permissions/no_ml_access.ts @@ -27,7 +27,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await ml.securityUI.logout(); }); - it('should not allow to access the ML app', async () => { + it('should not allow access to the ML app', async () => { await ml.testExecution.logTestStep('should not load the ML overview page'); await PageObjects.common.navigateToUrl('ml', '', { shouldLoginIfPrompted: false, @@ -53,7 +53,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await ml.navigation.assertKibanaNavMLEntryNotExists(); }); - it('should not allow to access the Stack Management ML page', async () => { + it('should not allow access to the Stack Management ML page', async () => { await ml.testExecution.logTestStep( 'should load the stack management with the ML menu item being absent' ); diff --git a/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts b/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts index cb964995511ef..efeea203f5700 100644 --- a/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts +++ b/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts @@ -47,6 +47,30 @@ export default function ({ getService }: FtrProviderContext) { await ml.navigation.assertKibanaNavMLEntryExists(); }); + it('should display tabs in the ML app correctly', async () => { + await ml.testExecution.logTestStep('should load the ML app'); + await ml.navigation.navigateToMl(); + + await ml.testExecution.logTestStep('should display the enabled "Overview" tab'); + await ml.navigation.assertOverviewTabEnabled(true); + + await ml.testExecution.logTestStep( + 'should display the enabled "Anomaly Detection" tab' + ); + await ml.navigation.assertAnomalyDetectionTabEnabled(true); + + await ml.testExecution.logTestStep( + 'should display the enabled "Data Frame Analytics" tab' + ); + await ml.navigation.assertDataFrameAnalyticsTabEnabled(true); + + await ml.testExecution.logTestStep('should display the enabled "Data Visualizer" tab'); + await ml.navigation.assertDataVisualizerTabEnabled(true); + + await ml.testExecution.logTestStep('should display the enabled "Settings" tab'); + await ml.navigation.assertSettingsTabEnabled(true); + }); + it('should display elements on ML Overview page correctly', async () => { await ml.testExecution.logTestStep('should load the ML overview page'); await ml.navigation.navigateToMl(); @@ -342,7 +366,7 @@ export default function ({ getService }: FtrProviderContext) { await ml.dataVisualizerFileBased.selectFile(uploadFilePath); await ml.testExecution.logTestStep( - 'should displays components of the file details page' + 'should display components of the file details page' ); await ml.dataVisualizerFileBased.assertFileTitle(expectedUploadFileTitle); await ml.dataVisualizerFileBased.assertFileContentPanelExists(); diff --git a/x-pack/test/functional/services/ml/data_visualizer.ts b/x-pack/test/functional/services/ml/data_visualizer.ts index 976410d43a28f..f4a553cf80edf 100644 --- a/x-pack/test/functional/services/ml/data_visualizer.ts +++ b/x-pack/test/functional/services/ml/data_visualizer.ts @@ -20,6 +20,10 @@ export function MachineLearningDataVisualizerProvider({ getService }: FtrProvide await testSubjects.existOrFail('mlDataVisualizerCardIndexData'); }, + async assertDataVisualizerStartTrialCardExists() { + await testSubjects.existOrFail('mlDataVisualizerCardStartTrial'); + }, + async assertSelectIndexButtonEnabled(expectedValue: boolean) { const isEnabled = await testSubjects.isEnabled('mlDataVisualizerSelectIndexButton'); expect(isEnabled).to.eql( @@ -40,6 +44,16 @@ export function MachineLearningDataVisualizerProvider({ getService }: FtrProvide ); }, + async assertStartTrialButtonEnabled(expectedValue: boolean) { + const isEnabled = await testSubjects.isEnabled('mlDataVisualizerStartTrialButton'); + expect(isEnabled).to.eql( + expectedValue, + `Expected "start trial" button to be '${expectedValue ? 'enabled' : 'disabled'}' (got '${ + isEnabled ? 'enabled' : 'disabled' + }')` + ); + }, + async navigateToIndexPatternSelection() { await testSubjects.click('mlDataVisualizerSelectIndexButton'); await testSubjects.existOrFail('mlPageSourceSelection'); diff --git a/x-pack/test/functional/services/ml/navigation.ts b/x-pack/test/functional/services/ml/navigation.ts index e564c03f62d58..66a0710b172b0 100644 --- a/x-pack/test/functional/services/ml/navigation.ts +++ b/x-pack/test/functional/services/ml/navigation.ts @@ -19,7 +19,7 @@ export function MachineLearningNavigationProvider({ async navigateToMl() { await retry.tryForTime(60 * 1000, async () => { await PageObjects.common.navigateToApp('ml'); - await testSubjects.existOrFail('mlPageOverview', { timeout: 2000 }); + await testSubjects.existOrFail('mlApp', { timeout: 2000 }); }); }, @@ -64,6 +64,36 @@ export function MachineLearningNavigationProvider({ ]); }, + async assertTabEnabled(tabSubject: string, expectedValue: boolean) { + const isEnabled = await testSubjects.isEnabled(tabSubject); + expect(isEnabled).to.eql( + expectedValue, + `Expected ML tab '${tabSubject}' to be '${expectedValue ? 'enabled' : 'disabled'}' (got '${ + isEnabled ? 'enabled' : 'disabled' + }')` + ); + }, + + async assertOverviewTabEnabled(expectedValue: boolean) { + await this.assertTabEnabled('~mlMainTab & ~overview', expectedValue); + }, + + async assertAnomalyDetectionTabEnabled(expectedValue: boolean) { + await this.assertTabEnabled('~mlMainTab & ~anomalyDetection', expectedValue); + }, + + async assertDataFrameAnalyticsTabEnabled(expectedValue: boolean) { + await this.assertTabEnabled('~mlMainTab & ~dataFrameAnalytics', expectedValue); + }, + + async assertDataVisualizerTabEnabled(expectedValue: boolean) { + await this.assertTabEnabled('~mlMainTab & ~dataVisualizer', expectedValue); + }, + + async assertSettingsTabEnabled(expectedValue: boolean) { + await this.assertTabEnabled('~mlMainTab & ~settings', expectedValue); + }, + async navigateToOverview() { await this.navigateToArea('~mlMainTab & ~overview', 'mlPageOverview'); }, diff --git a/x-pack/test/functional_basic/apps/index.ts b/x-pack/test/functional_basic/apps/index.ts new file mode 100644 index 0000000000000..1704990505a3f --- /dev/null +++ b/x-pack/test/functional_basic/apps/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('apps', function () { + this.tags('ciGroup2'); + + loadTestFile(require.resolve('./ml')); + loadTestFile(require.resolve('./transform')); + }); +} diff --git a/x-pack/test/functional_basic/apps/ml/data_visualizer/index.ts b/x-pack/test/functional_basic/apps/ml/data_visualizer/index.ts new file mode 100644 index 0000000000000..fd15daf44254f --- /dev/null +++ b/x-pack/test/functional_basic/apps/ml/data_visualizer/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('data visualizer', function () { + // The file data visualizer should work the same as with a trial license + loadTestFile( + require.resolve('../../../../functional/apps/ml/data_visualizer/file_data_visualizer') + ); + + // The data visualizer should work the same as with a trial license, except the missing create actions + // That's why 'index_data_visualizer_actions_panel' is not loaded here + loadTestFile( + require.resolve('../../../../functional/apps/ml/data_visualizer/index_data_visualizer') + ); + }); +} diff --git a/x-pack/test/functional_basic/apps/ml/index.ts b/x-pack/test/functional_basic/apps/ml/index.ts new file mode 100644 index 0000000000000..0e0c8cff17a4a --- /dev/null +++ b/x-pack/test/functional_basic/apps/ml/index.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const ml = getService('ml'); + + describe('machine learning basic license', function () { + this.tags(['skipFirefox', 'mlqa']); + + before(async () => { + await ml.securityCommon.createMlRoles(); + await ml.securityCommon.createMlUsers(); + }); + + after(async () => { + await ml.securityCommon.cleanMlUsers(); + await ml.securityCommon.cleanMlRoles(); + + await ml.testResources.deleteIndexPatternByTitle('ft_farequote'); + + await esArchiver.unload('ml/farequote'); + + await ml.testResources.resetKibanaTimeZone(); + }); + + loadTestFile(require.resolve('./permissions')); + loadTestFile(require.resolve('./data_visualizer')); + }); +} diff --git a/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts b/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts new file mode 100644 index 0000000000000..7a8a58a359b4e --- /dev/null +++ b/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts @@ -0,0 +1,163 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import path from 'path'; + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +import { USER } from '../../../../functional/services/ml/security_common'; + +export default function ({ getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const ml = getService('ml'); + + const testUsers = [USER.ML_POWERUSER, USER.ML_POWERUSER_SPACES]; + + describe('for user with full ML access', function () { + for (const user of testUsers) { + describe(`(${user})`, function () { + const ecIndexPattern = 'ft_module_sample_ecommerce'; + const ecExpectedTotalCount = 287; + const ecExpectedFieldPanelCount = 2; + const ecExpectedModuleId = 'sample_data_ecommerce'; + + const uploadFilePath = path.join( + __dirname, + '..', + '..', + '..', + '..', + 'functional', + 'apps', + 'ml', + 'data_visualizer', + 'files_to_import', + 'artificial_server_log' + ); + const expectedUploadFileTitle = 'artificial_server_log'; + + before(async () => { + await ml.api.cleanMlIndices(); + + await esArchiver.loadIfNeeded('ml/module_sample_ecommerce'); + await ml.testResources.createIndexPatternIfNeeded(ecIndexPattern, 'order_date'); + + await ml.securityUI.loginAs(user); + }); + + after(async () => { + await ml.securityUI.logout(); + }); + + it('should display the ML file data vis link on the Kibana home page', async () => { + await ml.testExecution.logTestStep('should load the Kibana home page'); + await ml.navigation.navigateToKibanaHome(); + + await ml.testExecution.logTestStep('should display the ML file data vis link'); + await ml.commonUI.assertKibanaHomeFileDataVisLinkExists(); + }); + + it('should display the ML entry in Kibana app menu', async () => { + await ml.testExecution.logTestStep('should open the Kibana app menu'); + await ml.navigation.openKibanaNav(); + + await ml.testExecution.logTestStep('should display the ML nav link'); + await ml.navigation.assertKibanaNavMLEntryExists(); + }); + + it('should display tabs in the ML app correctly', async () => { + await ml.testExecution.logTestStep('should load the ML app'); + await ml.navigation.navigateToMl(); + + await ml.testExecution.logTestStep('should display the disabled "Overview" tab'); + await ml.navigation.assertOverviewTabEnabled(false); + + await ml.testExecution.logTestStep('should display the disabled "Anomaly Detection" tab'); + await ml.navigation.assertAnomalyDetectionTabEnabled(false); + + await ml.testExecution.logTestStep( + 'should display the disabled "Data Frame Analytics" tab' + ); + await ml.navigation.assertDataFrameAnalyticsTabEnabled(false); + + await ml.testExecution.logTestStep('should display the enabled "Data Visualizer" tab'); + await ml.navigation.assertDataVisualizerTabEnabled(true); + + await ml.testExecution.logTestStep('should display the disabled "Settings" tab'); + await ml.navigation.assertSettingsTabEnabled(false); + }); + + it('should display elements on Data Visualizer home page correctly', async () => { + await ml.testExecution.logTestStep('should load the data visualizer page'); + await ml.navigation.navigateToDataVisualizer(); + + await ml.testExecution.logTestStep( + 'should display the "import data" card with enabled button' + ); + await ml.dataVisualizer.assertDataVisualizerImportDataCardExists(); + await ml.dataVisualizer.assertUploadFileButtonEnabled(true); + + await ml.testExecution.logTestStep( + 'should display the "select index pattern" card with enabled button' + ); + await ml.dataVisualizer.assertDataVisualizerIndexDataCardExists(); + await ml.dataVisualizer.assertSelectIndexButtonEnabled(true); + + await ml.testExecution.logTestStep( + 'should display the "start trial" card with enabled button' + ); + await ml.dataVisualizer.assertDataVisualizerStartTrialCardExists(); + await ml.dataVisualizer.assertStartTrialButtonEnabled(true); + }); + + it('should display elements on Index Data Visualizer page correctly', async () => { + await ml.testExecution.logTestStep('should load an index into the data visualizer page'); + await ml.dataVisualizer.navigateToIndexPatternSelection(); + await ml.jobSourceSelection.selectSourceForIndexBasedDataVisualizer(ecIndexPattern); + + await ml.testExecution.logTestStep('should display the time range step'); + await ml.dataVisualizerIndexBased.assertTimeRangeSelectorSectionExists(); + + await ml.testExecution.logTestStep('should load data for full time range'); + await ml.dataVisualizerIndexBased.clickUseFullDataButton(ecExpectedTotalCount); + + await ml.testExecution.logTestStep('should display the panels of fields'); + await ml.dataVisualizerIndexBased.assertFieldsPanelsExist(ecExpectedFieldPanelCount); + + await ml.testExecution.logTestStep('should not display the actions panel with cards'); + await ml.dataVisualizerIndexBased.assertActionsPanelNotExists(); + await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardNotExists(); + await ml.dataVisualizerIndexBased.assertRecognizerCardNotExists(ecExpectedModuleId); + }); + + it('should display elements on File Data Visualizer page correctly', async () => { + await ml.testExecution.logTestStep('should load the file data visualizer file selection'); + await ml.navigation.navigateToDataVisualizer(); + await ml.dataVisualizer.navigateToFileUpload(); + + await ml.testExecution.logTestStep( + 'should select a file and load visualizer result page' + ); + await ml.dataVisualizerFileBased.selectFile(uploadFilePath); + + await ml.testExecution.logTestStep('should display components of the file details page'); + await ml.dataVisualizerFileBased.assertFileTitle(expectedUploadFileTitle); + await ml.dataVisualizerFileBased.assertFileContentPanelExists(); + await ml.dataVisualizerFileBased.assertSummaryPanelExists(); + await ml.dataVisualizerFileBased.assertFileStatsPanelExists(); + await ml.dataVisualizerFileBased.assertImportButtonEnabled(true); + }); + + it('should not allow access to the Stack Management ML page', async () => { + await ml.testExecution.logTestStep( + 'should load the stack management with the ML menu item being absent' + ); + await ml.navigation.navigateToStackManagement({ expectMlLink: false }); + }); + }); + } + }); +} diff --git a/x-pack/test/functional_basic/apps/ml/permissions/index.ts b/x-pack/test/functional_basic/apps/ml/permissions/index.ts new file mode 100644 index 0000000000000..d80943fb36d61 --- /dev/null +++ b/x-pack/test/functional_basic/apps/ml/permissions/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('permissions', function () { + loadTestFile(require.resolve('./full_ml_access')); + loadTestFile(require.resolve('./read_ml_access')); + loadTestFile(require.resolve('./no_ml_access')); + }); +} diff --git a/x-pack/test/functional_basic/apps/ml/permissions/no_ml_access.ts b/x-pack/test/functional_basic/apps/ml/permissions/no_ml_access.ts new file mode 100644 index 0000000000000..aab9db7208683 --- /dev/null +++ b/x-pack/test/functional_basic/apps/ml/permissions/no_ml_access.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +import { USER } from '../../../../functional/services/ml/security_common'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const PageObjects = getPageObjects(['common', 'error']); + const ml = getService('ml'); + + const testUsers = [USER.ML_UNAUTHORIZED, USER.ML_UNAUTHORIZED_SPACES]; + + describe('for user with no ML access', function () { + for (const user of testUsers) { + describe(`(${user})`, function () { + before(async () => { + await ml.securityUI.loginAs(user); + }); + + after(async () => { + await ml.securityUI.logout(); + }); + + it('should not allow access to the ML app', async () => { + await ml.testExecution.logTestStep('should not load the ML overview page'); + await PageObjects.common.navigateToUrl('ml', '', { + shouldLoginIfPrompted: false, + ensureCurrentUrl: false, + }); + + await PageObjects.error.expectForbidden(); + }); + + it('should not display the ML file data vis link on the Kibana home page', async () => { + await ml.testExecution.logTestStep('should load the Kibana home page'); + await ml.navigation.navigateToKibanaHome(); + + await ml.testExecution.logTestStep('should not display the ML file data vis link'); + await ml.commonUI.assertKibanaHomeFileDataVisLinkNotExists(); + }); + + it('should not display the ML entry in Kibana app menu', async () => { + await ml.testExecution.logTestStep('should open the Kibana app menu'); + await ml.navigation.openKibanaNav(); + + await ml.testExecution.logTestStep('should not display the ML nav link'); + await ml.navigation.assertKibanaNavMLEntryNotExists(); + }); + + it('should not allow access to the Stack Management ML page', async () => { + await ml.testExecution.logTestStep( + 'should load the stack management with the ML menu item being absent' + ); + await ml.navigation.navigateToStackManagement({ expectMlLink: false }); + }); + }); + } + }); +} diff --git a/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts b/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts new file mode 100644 index 0000000000000..331f2c83639fc --- /dev/null +++ b/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts @@ -0,0 +1,163 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import path from 'path'; + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +import { USER } from '../../../../functional/services/ml/security_common'; + +export default function ({ getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const ml = getService('ml'); + + const testUsers = [USER.ML_VIEWER, USER.ML_VIEWER_SPACES]; + + describe('for user with read ML access', function () { + for (const user of testUsers) { + describe(`(${user})`, function () { + const ecIndexPattern = 'ft_module_sample_ecommerce'; + const ecExpectedTotalCount = 287; + const ecExpectedFieldPanelCount = 2; + const ecExpectedModuleId = 'sample_data_ecommerce'; + + const uploadFilePath = path.join( + __dirname, + '..', + '..', + '..', + '..', + 'functional', + 'apps', + 'ml', + 'data_visualizer', + 'files_to_import', + 'artificial_server_log' + ); + const expectedUploadFileTitle = 'artificial_server_log'; + + before(async () => { + await ml.api.cleanMlIndices(); + + await esArchiver.loadIfNeeded('ml/module_sample_ecommerce'); + await ml.testResources.createIndexPatternIfNeeded(ecIndexPattern, 'order_date'); + + await ml.securityUI.loginAs(user); + }); + + after(async () => { + await ml.securityUI.logout(); + }); + + it('should not display the ML file data vis link on the Kibana home page', async () => { + await ml.testExecution.logTestStep('should load the Kibana home page'); + await ml.navigation.navigateToKibanaHome(); + + await ml.testExecution.logTestStep('should not display the ML file data vis link'); + await ml.commonUI.assertKibanaHomeFileDataVisLinkNotExists(); + }); + + it('should display the ML entry in Kibana app menu', async () => { + await ml.testExecution.logTestStep('should open the Kibana app menu'); + await ml.navigation.openKibanaNav(); + + await ml.testExecution.logTestStep('should display the ML nav link'); + await ml.navigation.assertKibanaNavMLEntryExists(); + }); + + it('should display tabs in the ML app correctly', async () => { + await ml.testExecution.logTestStep('should load the ML app'); + await ml.navigation.navigateToMl(); + + await ml.testExecution.logTestStep('should display the disabled "Overview" tab'); + await ml.navigation.assertOverviewTabEnabled(false); + + await ml.testExecution.logTestStep('should display the disabled "Anomaly Detection" tab'); + await ml.navigation.assertAnomalyDetectionTabEnabled(false); + + await ml.testExecution.logTestStep( + 'should display the disabled "Data Frame Analytics" tab' + ); + await ml.navigation.assertDataFrameAnalyticsTabEnabled(false); + + await ml.testExecution.logTestStep('should display the enabled "Data Visualizer" tab'); + await ml.navigation.assertDataVisualizerTabEnabled(true); + + await ml.testExecution.logTestStep('should display the disabled "Settings" tab'); + await ml.navigation.assertSettingsTabEnabled(false); + }); + + it('should display elements on Data Visualizer home page correctly', async () => { + await ml.testExecution.logTestStep('should load the data visualizer page'); + await ml.navigation.navigateToDataVisualizer(); + + await ml.testExecution.logTestStep( + 'should display the "import data" card with enabled button' + ); + await ml.dataVisualizer.assertDataVisualizerImportDataCardExists(); + await ml.dataVisualizer.assertUploadFileButtonEnabled(true); + + await ml.testExecution.logTestStep( + 'should display the "select index pattern" card with enabled button' + ); + await ml.dataVisualizer.assertDataVisualizerIndexDataCardExists(); + await ml.dataVisualizer.assertSelectIndexButtonEnabled(true); + + await ml.testExecution.logTestStep( + 'should display the "start trial" card with enabled button' + ); + await ml.dataVisualizer.assertDataVisualizerStartTrialCardExists(); + await ml.dataVisualizer.assertStartTrialButtonEnabled(true); + }); + + it('should display elements on Index Data Visualizer page correctly', async () => { + await ml.testExecution.logTestStep('should load an index into the data visualizer page'); + await ml.dataVisualizer.navigateToIndexPatternSelection(); + await ml.jobSourceSelection.selectSourceForIndexBasedDataVisualizer(ecIndexPattern); + + await ml.testExecution.logTestStep('should display the time range step'); + await ml.dataVisualizerIndexBased.assertTimeRangeSelectorSectionExists(); + + await ml.testExecution.logTestStep('should load data for full time range'); + await ml.dataVisualizerIndexBased.clickUseFullDataButton(ecExpectedTotalCount); + + await ml.testExecution.logTestStep('should display the panels of fields'); + await ml.dataVisualizerIndexBased.assertFieldsPanelsExist(ecExpectedFieldPanelCount); + + await ml.testExecution.logTestStep('should not display the actions panel with cards'); + await ml.dataVisualizerIndexBased.assertActionsPanelNotExists(); + await ml.dataVisualizerIndexBased.assertCreateAdvancedJobCardNotExists(); + await ml.dataVisualizerIndexBased.assertRecognizerCardNotExists(ecExpectedModuleId); + }); + + it('should display elements on File Data Visualizer page correctly', async () => { + await ml.testExecution.logTestStep('should load the file data visualizer file selection'); + await ml.navigation.navigateToDataVisualizer(); + await ml.dataVisualizer.navigateToFileUpload(); + + await ml.testExecution.logTestStep( + 'should select a file and load visualizer result page' + ); + await ml.dataVisualizerFileBased.selectFile(uploadFilePath); + + await ml.testExecution.logTestStep('should display components of the file details page'); + await ml.dataVisualizerFileBased.assertFileTitle(expectedUploadFileTitle); + await ml.dataVisualizerFileBased.assertFileContentPanelExists(); + await ml.dataVisualizerFileBased.assertSummaryPanelExists(); + await ml.dataVisualizerFileBased.assertFileStatsPanelExists(); + await ml.dataVisualizerFileBased.assertImportButtonEnabled(false); + }); + + it('should not allow access to the Stack Management ML page', async () => { + await ml.testExecution.logTestStep( + 'should load the stack management with the ML menu item being absent' + ); + await ml.navigation.navigateToStackManagement({ expectMlLink: false }); + }); + }); + } + }); +} diff --git a/x-pack/test/functional_basic/apps/transform/index.ts b/x-pack/test/functional_basic/apps/transform/index.ts new file mode 100644 index 0000000000000..61a4408e5ff5e --- /dev/null +++ b/x-pack/test/functional_basic/apps/transform/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('transform basic license', function () { + this.tags(['skipFirefox', 'transform']); + + // The transform UI should work the same as with a trial license + loadTestFile(require.resolve('../../../functional/apps/transform')); + }); +} diff --git a/x-pack/test/functional_basic/config.ts b/x-pack/test/functional_basic/config.ts new file mode 100644 index 0000000000000..8f162853c8f4b --- /dev/null +++ b/x-pack/test/functional_basic/config.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + + return { + // default to the xpack functional config + ...xpackFunctionalConfig.getAll(), + esTestCluster: { + ...xpackFunctionalConfig.get('esTestCluster'), + license: 'basic', + serverArgs: [ + 'xpack.license.self_generated.type=basic', + 'xpack.security.enabled=true', + 'xpack.security.authc.api_key.enabled=true', + ], + }, + testFiles: [require.resolve('./apps')], + junit: { + ...xpackFunctionalConfig.get('junit'), + reportName: 'Chrome X-Pack UI Functional Tests Basic License', + }, + }; +} diff --git a/x-pack/test/functional_basic/ftr_provider_context.d.ts b/x-pack/test/functional_basic/ftr_provider_context.d.ts new file mode 100644 index 0000000000000..d8f146e4c6f6b --- /dev/null +++ b/x-pack/test/functional_basic/ftr_provider_context.d.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { GenericFtrProviderContext } from '@kbn/test/types/ftr'; + +import { pageObjects } from '../functional/page_objects'; +import { services } from '../functional/services'; + +export type FtrProviderContext = GenericFtrProviderContext;