mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[6.8] [ML] Functional tests - Basic page navigation (#66431)
This PR adds basic page navigation tests for the ML app in the 6.8 branch.
This commit is contained in:
parent
93e09d23e6
commit
5a6577f5f6
19 changed files with 192 additions and 21 deletions
|
@ -14,35 +14,35 @@
|
|||
<!-- Tabs -->
|
||||
<div data-transclude-slot="bottomRow">
|
||||
<div ng-if="showTabs" class="kuiLocalTabs" role="tablist">
|
||||
<a kbn-href="#/jobs" class="kuiLocalTab" role="tab"
|
||||
<a kbn-href="#/jobs" class="kuiLocalTab" role="tab" data-test-subj="mlTabJobManagement"
|
||||
ng-class="{'kuiLocalTab-isSelected': isActiveTab('jobs'), 'disabled-nav-link': disableLinks}">
|
||||
<span
|
||||
i18n-id="xpack.ml.navMenu.jobManagementTabLinkText"
|
||||
i18n-default-message="Job Management"
|
||||
></span>
|
||||
</a>
|
||||
<a kbn-href="#/explorer" class="kuiLocalTab" role="tab"
|
||||
<a kbn-href="#/explorer" class="kuiLocalTab" role="tab" data-test-subj="mlTabAnomalyExplorer"
|
||||
ng-class="{'kuiLocalTab-isSelected': isActiveTab('explorer'), 'disabled-nav-link': disableLinks}">
|
||||
<span
|
||||
i18n-id="xpack.ml.navMenu.anomalyExplorerTabLinkText"
|
||||
i18n-default-message="Anomaly Explorer"
|
||||
></span>
|
||||
</a>
|
||||
<a kbn-href="#/timeseriesexplorer" class="kuiLocalTab" role="tab"
|
||||
<a kbn-href="#/timeseriesexplorer" class="kuiLocalTab" role="tab" data-test-subj="mlTabSingleMetricViewer"
|
||||
ng-class="{'kuiLocalTab-isSelected': isActiveTab('timeseriesexplorer'), 'disabled-nav-link': disableLinks}">
|
||||
<span
|
||||
i18n-id="xpack.ml.navMenu.singleMetricViewerTabLinkText"
|
||||
i18n-default-message="Single Metric Viewer"
|
||||
></span>
|
||||
</a>
|
||||
<a kbn-href="#/datavisualizer" class="kuiLocalTab" role="tab"
|
||||
<a kbn-href="#/datavisualizer" class="kuiLocalTab" role="tab" data-test-subj="mlTabDataVisualizer"
|
||||
ng-class="{'kuiLocalTab-isSelected': isActiveTab('datavisualizer')}">
|
||||
<span
|
||||
i18n-id="xpack.ml.navMenu.dataVisualizerTabLinkText"
|
||||
i18n-default-message="Data Visualizer"
|
||||
></span>
|
||||
</a>
|
||||
<a kbn-href="#/settings" class="kuiLocalTab" role="tab"
|
||||
<a kbn-href="#/settings" class="kuiLocalTab" role="tab" data-test-subj="mlTabSettings"
|
||||
ng-class="{'kuiLocalTab-isSelected': isActiveTab('settings'), 'disabled-nav-link': disableLinks}">
|
||||
<span
|
||||
i18n-id="xpack.ml.navMenu.settingsTabLinkText"
|
||||
|
|
|
@ -121,6 +121,7 @@ export const DatavisualizerSelector = injectI18n(function (props) {
|
|||
/>
|
||||
</EuiButton>
|
||||
}
|
||||
data-test-subj="mlDataVisualizerCardImportData"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
|
@ -149,6 +150,7 @@ export const DatavisualizerSelector = injectI18n(function (props) {
|
|||
/>
|
||||
</EuiButton>
|
||||
}
|
||||
data-test-subj="mlDataVisualizerCardIndexData"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -15,7 +15,10 @@ import { checkFindFileStructurePrivilege } from 'plugins/ml/privilege/check_priv
|
|||
|
||||
import uiRoutes from 'ui/routes';
|
||||
|
||||
const template = `<ml-nav-menu name="datavisualizer" /><datavisualizer-selector class="ml-datavisualizer-selector"/>`;
|
||||
const template = `
|
||||
<ml-nav-menu name="datavisualizer" />
|
||||
<datavisualizer-selector class="ml-datavisualizer-selector" data-test-subj="mlPageDataVisualizerSelector"/>
|
||||
`;
|
||||
|
||||
uiRoutes
|
||||
.when('/datavisualizer', {
|
||||
|
|
|
@ -17,6 +17,7 @@ exports[`ExplorerNoInfluencersFound snapshot 1`] = `
|
|||
/>
|
||||
</EuiButton>
|
||||
}
|
||||
data-test-subj="mlNoJobsFound"
|
||||
iconColor="subdued"
|
||||
iconType="alert"
|
||||
title={
|
||||
|
|
|
@ -29,5 +29,6 @@ export const ExplorerNoJobsFound = () => (
|
|||
/>
|
||||
</EuiButton>
|
||||
}
|
||||
data-test-subj="mlNoJobsFound"
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<ml-nav-menu name="explorer"></ml-nav-menu>
|
||||
<ml-chart-tooltip></ml-chart-tooltip>
|
||||
<div class="ml-explorer" ng-controller="MlExplorerController">
|
||||
<div class="ml-explorer" ng-controller="MlExplorerController" data-test-subj="mlPageAnomalyExplorer">
|
||||
<navbar ng-show="jobs.length > 0 && chrome.getVisible()">
|
||||
<job-select-button></job-select-button>
|
||||
</navbar>
|
||||
|
|
|
@ -255,6 +255,7 @@ class JobsListUI extends Component {
|
|||
|
||||
return (
|
||||
<EuiBasicTable
|
||||
data-test-subj="mlJobListTable"
|
||||
loading={loading === true}
|
||||
noItemsMessage={loading ?
|
||||
intl.formatMessage({
|
||||
|
|
|
@ -115,7 +115,7 @@ export const JobStatsBar = ({ jobsSummaryList }) => {
|
|||
const stats = Object.keys(jobStats).map(k => jobStats[k]);
|
||||
|
||||
return (
|
||||
<div className="jobs-stats-bar">
|
||||
<div className="jobs-stats-bar" data-test-subj="mlJobStatsBar">
|
||||
{
|
||||
stats.filter(s => (s.show)).map(s => <Stat key={s.label} stat={s} />)
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ export function NewJobButton() {
|
|||
const buttonEnabled = (checkPermission('canCreateJob') && mlNodesAvailable());
|
||||
return (
|
||||
<EuiButton
|
||||
data-test-subj="mlCreateNewJobButton"
|
||||
onClick={newJob}
|
||||
size="s"
|
||||
disabled={(buttonEnabled === false)}
|
||||
|
|
|
@ -19,7 +19,7 @@ import { loadNewJobDefaults } from 'plugins/ml/jobs/new_job/utils/new_job_defaul
|
|||
|
||||
import uiRoutes from 'ui/routes';
|
||||
|
||||
const template = `<ml-nav-menu name="jobs" /><jobs-page />`;
|
||||
const template = `<ml-nav-menu name="jobs" /><jobs-page data-test-subj="mlPageJobManagement" />`;
|
||||
|
||||
uiRoutes
|
||||
.when('/jobs/?', {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
exports[`Settings Renders settings page 1`] = `
|
||||
<EuiPage
|
||||
className="mlSettingsPage"
|
||||
data-test-subj="mlPageSettings"
|
||||
restrictWidth={false}
|
||||
>
|
||||
<EuiPageBody
|
||||
|
@ -45,7 +46,7 @@ exports[`Settings Renders settings page 1`] = `
|
|||
>
|
||||
<EuiButtonEmpty
|
||||
color="primary"
|
||||
data-testid="ml_calendar_mng_button"
|
||||
data-test-subj="ml_calendar_mng_button"
|
||||
href="undefined/app/ml#/settings/calendars_list"
|
||||
iconSide="left"
|
||||
isDisabled={false}
|
||||
|
@ -65,7 +66,7 @@ exports[`Settings Renders settings page 1`] = `
|
|||
>
|
||||
<EuiButtonEmpty
|
||||
color="primary"
|
||||
data-testid="ml_filter_lists_button"
|
||||
data-test-subj="ml_filter_lists_button"
|
||||
href="undefined/app/ml#/settings/filter_lists"
|
||||
iconSide="left"
|
||||
isDisabled={false}
|
||||
|
|
|
@ -29,7 +29,7 @@ export function Settings({
|
|||
canGetCalendars
|
||||
}) {
|
||||
return (
|
||||
<EuiPage className="mlSettingsPage">
|
||||
<EuiPage className="mlSettingsPage" data-test-subj="mlPageSettings">
|
||||
<EuiPageBody className="mlSettingsPage__body">
|
||||
<EuiPageContent
|
||||
className="mlSettingsPage__content"
|
||||
|
@ -49,7 +49,7 @@ export function Settings({
|
|||
<EuiFlexGroup gutterSize="xl">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
data-testid="ml_calendar_mng_button"
|
||||
data-test-subj="ml_calendar_mng_button"
|
||||
size="l"
|
||||
color="primary"
|
||||
href={`${chrome.getBasePath()}/app/ml#/settings/calendars_list`}
|
||||
|
@ -64,7 +64,7 @@ export function Settings({
|
|||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
data-testid="ml_filter_lists_button"
|
||||
data-test-subj="ml_filter_lists_button"
|
||||
size="l"
|
||||
color="primary"
|
||||
href={`${chrome.getBasePath()}/app/ml#/settings/filter_lists`}
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('Settings', () => {
|
|||
<Settings canGetFilters={false} canGetCalendars={true}/>
|
||||
);
|
||||
|
||||
const button = wrapper.find('[data-testid="ml_filter_lists_button"]');
|
||||
const button = wrapper.find('[data-test-subj="ml_filter_lists_button"]');
|
||||
const filterButton = button.find('EuiButtonEmpty');
|
||||
expect(filterButton.prop('isDisabled')).toBe(true);
|
||||
});
|
||||
|
@ -41,7 +41,7 @@ describe('Settings', () => {
|
|||
<Settings canGetFilters={true} canGetCalendars={false} />
|
||||
);
|
||||
|
||||
const button = wrapper.find('[data-testid="ml_calendar_mng_button"]');
|
||||
const button = wrapper.find('[data-test-subj="ml_calendar_mng_button"]');
|
||||
const calendarButton = button.find('EuiButtonEmpty');
|
||||
expect(calendarButton.prop('isDisabled')).toBe(true);
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<ml-nav-menu name="timeseriesexplorer"></ml-nav-menu>
|
||||
<ml-chart-tooltip></ml-chart-tooltip>
|
||||
<div class="ml-time-series-explorer" ng-controller="MlTimeSeriesExplorerController">
|
||||
<div class="ml-time-series-explorer" ng-controller="MlTimeSeriesExplorerController" data-test-subj="mlPageSingleMetricViewer">
|
||||
<navbar ng-show="jobs.length > 0 && chrome.getVisible()">
|
||||
<job-select-button
|
||||
timeseriesonly="true"
|
||||
|
@ -8,7 +8,7 @@
|
|||
</job-select-button>
|
||||
</navbar>
|
||||
|
||||
<div class="no-results-container" ng-if="jobs.length === 0 && loading === false">
|
||||
<div class="no-results-container" ng-if="jobs.length === 0 && loading === false" data-test-subj="mlNoSingleMetricJobsFound">
|
||||
<div class="no-results">
|
||||
<div
|
||||
i18n-id="xpack.ml.timeSeriesExplorer.noSingleMetricJobsFoundLabel"
|
||||
|
@ -189,7 +189,7 @@
|
|||
i18n-id="xpack.ml.timeSeriesExplorer.annotationsTitle"
|
||||
i18n-default-message="Annotations"
|
||||
></span>
|
||||
|
||||
|
||||
<ml-annotation-table
|
||||
annotations="focusAnnotationData"
|
||||
drill-down="false"
|
||||
|
|
16
x-pack/test/functional/apps/ml/index.ts
Normal file
16
x-pack/test/functional/apps/ml/index.ts
Normal file
|
@ -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 { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function({ loadTestFile }: KibanaFunctionalTestDefaultProviders) {
|
||||
describe('machine learning', function() {
|
||||
this.tags(['ciGroup3', 'mlqa']);
|
||||
|
||||
loadTestFile(require.resolve('./pages'));
|
||||
});
|
||||
}
|
56
x-pack/test/functional/apps/ml/pages.ts
Normal file
56
x-pack/test/functional/apps/ml/pages.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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 { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
|
||||
|
||||
// tslint:disable:no-default-export
|
||||
export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const ml = getService('ml');
|
||||
|
||||
describe('page navigation', () => {
|
||||
before(async () => {
|
||||
await esArchiver.load('empty_kibana');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await esArchiver.unload('empty_kibana');
|
||||
});
|
||||
|
||||
it('loads the home page', async () => {
|
||||
await ml.navigateTo();
|
||||
});
|
||||
|
||||
it('loads the job management page', async () => {
|
||||
await ml.navigateToJobManagement();
|
||||
await ml.assertJobStatsBarExists();
|
||||
await ml.assertJobTableExists();
|
||||
await ml.assertCreateNewJobButtonExists();
|
||||
});
|
||||
|
||||
it('loads the anomaly explorer page', async () => {
|
||||
await ml.navigateToAnomalyExplorert();
|
||||
await ml.assertAnomalyExplorerEmptyListMessageExists();
|
||||
});
|
||||
|
||||
it('loads the single metric viewer page', async () => {
|
||||
await ml.navigateToSingleMetricViewer();
|
||||
await ml.assertSingleMetricViewerEmptyListMessageExsist();
|
||||
});
|
||||
|
||||
it('loads the data visualizer page', async () => {
|
||||
await ml.navigateToDataVisualizer();
|
||||
await ml.assertDataVisualizerImportDataCardExists();
|
||||
await ml.assertDataVisualizerIndexDataCardExists();
|
||||
});
|
||||
|
||||
it('loads the settings page', async () => {
|
||||
await ml.navigateToSettings();
|
||||
await ml.assertSettingsCalendarLinkExists();
|
||||
await ml.assertSettingsFilterlistLinkExists();
|
||||
});
|
||||
});
|
||||
}
|
|
@ -54,6 +54,7 @@ import {
|
|||
AceEditorProvider,
|
||||
GrokDebuggerProvider,
|
||||
UptimeProvider,
|
||||
MachineLearningProvider,
|
||||
|
||||
} from './services';
|
||||
|
||||
|
@ -87,7 +88,8 @@ export default async function ({ readConfigFile }) {
|
|||
resolve(__dirname, './apps/maps'),
|
||||
resolve(__dirname, './apps/status_page'),
|
||||
resolve(__dirname, './apps/upgrade_assistant'),
|
||||
resolve(__dirname, './apps/uptime')
|
||||
resolve(__dirname, './apps/uptime'),
|
||||
resolve(__dirname, './apps/ml'),
|
||||
],
|
||||
|
||||
// define the name and providers for services that should be
|
||||
|
@ -124,6 +126,7 @@ export default async function ({ readConfigFile }) {
|
|||
grokDebugger: GrokDebuggerProvider,
|
||||
uptime: UptimeProvider,
|
||||
rollup: RollupPageProvider,
|
||||
ml: MachineLearningProvider,
|
||||
},
|
||||
|
||||
// just like services, PageObjects are defined as a map of
|
||||
|
@ -213,7 +216,10 @@ export default async function ({ readConfigFile }) {
|
|||
rollupJob: {
|
||||
pathname: '/app/kibana',
|
||||
hash: '/management/elasticsearch/rollup_jobs/'
|
||||
}
|
||||
},
|
||||
ml: {
|
||||
pathname: '/app/ml'
|
||||
},
|
||||
},
|
||||
|
||||
// choose where esArchiver should load archives from
|
||||
|
|
|
@ -11,3 +11,4 @@ export { RandomProvider } from './random';
|
|||
export { AceEditorProvider } from './ace_editor';
|
||||
export { GrokDebuggerProvider } from './grok_debugger';
|
||||
export { UptimeProvider } from './uptime';
|
||||
export { MachineLearningProvider } from './ml';
|
||||
|
|
82
x-pack/test/functional/services/ml.ts
Normal file
82
x-pack/test/functional/services/ml.ts
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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 { KibanaFunctionalTestDefaultProviders } from '../../types/providers';
|
||||
|
||||
export function MachineLearningProvider({
|
||||
getService,
|
||||
getPageObjects,
|
||||
}: KibanaFunctionalTestDefaultProviders) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
const PageObjects = getPageObjects(['common']);
|
||||
|
||||
return {
|
||||
async navigateTo() {
|
||||
return await PageObjects.common.navigateToApp('ml');
|
||||
},
|
||||
|
||||
async navigateToJobManagement() {
|
||||
await testSubjects.click('mlTabJobManagement');
|
||||
await testSubjects.exists('mlPageJobManagement');
|
||||
},
|
||||
|
||||
async navigateToAnomalyExplorert() {
|
||||
await testSubjects.click('mlTabAnomalyExplorer');
|
||||
await testSubjects.exists('mlPageAnomalyExplorer');
|
||||
},
|
||||
|
||||
async navigateToSingleMetricViewer() {
|
||||
await testSubjects.click('mlTabSingleMetricViewer');
|
||||
await testSubjects.exists('mlPageSingleMetricViewer');
|
||||
},
|
||||
|
||||
async navigateToDataVisualizer() {
|
||||
await testSubjects.click('mlTabDataVisualizer');
|
||||
await testSubjects.exists('mlPageDataVisualizerSelector');
|
||||
},
|
||||
|
||||
async navigateToSettings() {
|
||||
await testSubjects.click('mlTabSettings');
|
||||
await testSubjects.exists('mlPageSettings');
|
||||
},
|
||||
|
||||
async assertJobTableExists() {
|
||||
await testSubjects.existOrFail('mlJobListTable');
|
||||
},
|
||||
|
||||
async assertCreateNewJobButtonExists() {
|
||||
await testSubjects.existOrFail('mlCreateNewJobButton');
|
||||
},
|
||||
|
||||
async assertJobStatsBarExists() {
|
||||
await testSubjects.existOrFail('mlJobStatsBar');
|
||||
},
|
||||
|
||||
async assertAnomalyExplorerEmptyListMessageExists() {
|
||||
await testSubjects.existOrFail('mlNoJobsFound');
|
||||
},
|
||||
|
||||
async assertSingleMetricViewerEmptyListMessageExsist() {
|
||||
await testSubjects.existOrFail('mlNoSingleMetricJobsFound');
|
||||
},
|
||||
|
||||
async assertDataVisualizerImportDataCardExists() {
|
||||
await testSubjects.existOrFail('mlDataVisualizerCardImportData');
|
||||
},
|
||||
|
||||
async assertDataVisualizerIndexDataCardExists() {
|
||||
await testSubjects.existOrFail('mlDataVisualizerCardIndexData');
|
||||
},
|
||||
|
||||
async assertSettingsCalendarLinkExists() {
|
||||
await testSubjects.existOrFail('ml_calendar_mng_button');
|
||||
},
|
||||
|
||||
async assertSettingsFilterlistLinkExists() {
|
||||
await testSubjects.existOrFail('ml_filter_lists_button');
|
||||
},
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue