Skip to content

Commit

Permalink
[Uptime] Add functional UI tests (#29667)
Browse files Browse the repository at this point in the history
* Refactor es queries and associated components/endpoints.

* Add unit tests, repair broken tests.

* [Uptime] Add API functional tests for uptime graphQL (#29128)

* Add API functional tests for uptime graphQL.

* Remove obsolete code.

* Add CI group for UI functional tests.

* Delete obsolete code, rename heartbeat es archive.

* Refactor adapter methods.

* Refactor adapter methods.

* Attempt to fix ci-group tag error.

* Skip functional app tests until later PR.

* Remove unused code.

* Optimize test runs.

* Add uptime to api test index.

* Fix formatting.

* Add HB 7.0 data for API tests.

* Configure first error_list test to work with 7.x data.

* Configure error_list filtered by id to work with 7.x data.

* Configure error_list functional tests to work with 7.x data.

* Update snapshot test to work with 7.x data.

* Update snapshot down filtered test to work with 7.x data.

* Configure snapshot up test to work with 7.x data.

* Configure ping list tests to work with 7.x data.

* Configure monitor list tests to work with 7.x data.

* Configure monitor status bar tests to work with 7.x data.

* Configure filterBar tests to work with 7.x data.

* Configure docCount tests to work with 7.x data.

* Simplify code based on PR feedback.

* Add loading spinner to monitor page title based on PR feedback.

* Rename GQL type based on PR feedback.

* Remove use of 'undefined' in ES query based on PR feedback.

* Simplify code based on PR feedback.

* Add definite size/shard_size for terms agg based on PR feedback.

* Simplify ES query based on PR feedback.

* Update x-pack/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts

Implement PR feedback.

Co-Authored-By: justinkambic <[email protected]>

* Increase size for ES errors query based on PR feedback.

* Fix hardcoded field in terms filter based on PR feedback.

* Simplify get code for monitors function.

* Reduce unnecessarily large size for terms agg based on PR feedback.

* Pluralize filter bar props.

* Refactor filter bar query based on PR feedback.

* Update test.

* Fix busted GQL query.

* Update functional test docs to use data without buggy values.

* Update index name in HB functional api test docs.

* Update snapshot base functional test.

* Make snapshot filter tests pass, fix associated bug.

* Configure remaining snapshot e2e tests to work with 7.x data.

* Give better variable names and comments for ugly code.

* Configure ping list query tests to work with updated 7.x data.

* Rename graphql describe block.

* Update monitor status bar query tests to work with updated 7.x data.

* Update monitor list query tests to work with updated 7.x data.

* Update filter bar query to work with updated 7.x data.

* Update error list query to work with updated 7.x data.

* Update doc count fixture to work with new 7.x data.

* Create functional UI tests for Overview and Monitor pages.

* Add additional waits to functional UI test to try to prevent flakiness.

* [ftr/services/superDatePicker] make specialized service

* Add data-test-subj value to monitor link.

* Remove wait calls from UI tests.

* Set default timezone for tests' kibana server.

* Add @types for mocha and expect.js.

* Implement PR feedback.

* Remove added types.

* Re-add mocha types.

* Remove obsolete comment.

* Disable timestamp on uptime app navigation for functional tests.

* Undo previous change for default value of function parameter.

* Add redirect hack to uptime client to change window location when expected router path is not satisfied.
  • Loading branch information
justinkambic authored Mar 13, 2019
1 parent efc1ca9 commit 39c0478
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 25 deletions.
14 changes: 14 additions & 0 deletions test/functional/page_objects/time_picker.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ export function TimePickerPageProvider({ getService, getPageObjects }) {
await find.waitForElementStale(panelElement);
}

async setAbsoluteStart(startTime) {
await this.showStartEndTimes();

await testSubjects.click('superDatePickerstartDatePopoverButton');
const panel = await this.getTimePickerPanel();
await testSubjects.click('superDatePickerAbsoluteTab');
await testSubjects.setValue('superDatePickerAbsoluteDateInput', startTime);
await testSubjects.click('superDatePickerstartDatePopoverButton');
await this.waitPanelIsGone(panel);
await PageObjects.header.awaitGlobalLoadingIndicatorHidden();
}

/**
* @param {String} fromTime YYYY-MM-DD HH:mm:ss.SSS
* @param {String} fromTime YYYY-MM-DD HH:mm:ss.SSS
Expand Down Expand Up @@ -110,6 +122,8 @@ export function TimePickerPageProvider({ getService, getPageObjects }) {
}

async showStartEndTimes() {
// This first await makes sure the superDatePicker has loaded before we check for the ShowDatesButton
await testSubjects.exists('superDatePickerToggleQuickMenuButton', { timeout: 20000 });
const isShowDatesButton = await testSubjects.exists('superDatePickerShowDatesButton');
if (isShowDatesButton) {
await testSubjects.click('superDatePickerShowDatesButton');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export const MonitorList = ({ dangerColor, loading, monitors, primaryColor }: Mo
defaultMessage: 'ID',
}),
render: (id: string, monitor: LatestMonitor) => (
<Link to={`/monitor/${id}`}>
<Link data-test-subj={`monitor-page-link-${id}`} to={`/monitor/${id}`}>
{monitor.ping && monitor.ping.monitor && monitor.ping.monitor.name
? monitor.ping.monitor.name
: id}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const MonitorPageTitle = ({ pageTitle: { name, url, id } }: MonitorPageTi
<EuiFlexGroup alignItems="baseline">
<EuiFlexItem grow={false}>
<EuiTitle>
<h2>{name ? name : url}</h2>
<h2 data-test-subj="monitor-page-title">{name ? name : url}</h2>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class UMKibanaFrameworkAdapter implements UMFrameworkAdapter {
const route = {
controllerAs: 'uptime',
// @ts-ignore angular
controller: ($scope, $route, $http, config) => {
controller: ($scope, $route, config, $location, $window) => {
const graphQLClient = createGraphQLClient(this.uriPath, this.xsrfHeader);
$scope.$$postDigest(() => {
const elem = document.getElementById('uptimeReactRoot');
Expand All @@ -57,6 +57,23 @@ export class UMKibanaFrameworkAdapter implements UMFrameworkAdapter {
const routerBasename = basePath.endsWith('/')
? `${basePath}/${PLUGIN.ROUTER_BASE_NAME}`
: basePath + PLUGIN.ROUTER_BASE_NAME;

/**
* TODO: this is a redirect hack to deal with a problem that largely
* in testing but rarely occurs in the real world, where the specified
* URL contains `.../app/uptime{SOME_URL_PARAM_TEXT}#` instead of
* a path like `.../app/uptime#{SOME_URL_PARAM_TEXT}`.
*
* This redirect will almost never be triggered in practice, but it makes more
* sense to include it here rather than altering the existing testing
* infrastructure underlying the rest of Kibana.
*
* We welcome a more permanent solution that will result in the deletion of the
* block below.
*/
if ($location.absUrl().indexOf(PLUGIN.ROUTER_BASE_NAME) === -1) {
$window.location.replace(routerBasename);
}
const persistedState = this.initializePersistedState();
const darkMode = config.get('theme:darkMode', false) || false;
const {
Expand Down
13 changes: 12 additions & 1 deletion x-pack/test/functional/apps/uptime/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,22 @@

import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';

const ARCHIVE = 'uptime/full_heartbeat';

// tslint:disable-next-line:no-default-export
export default ({ loadTestFile }: KibanaFunctionalTestDefaultProviders) => {
export default ({ loadTestFile, getService }: KibanaFunctionalTestDefaultProviders) => {
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');

describe('Uptime app', function() {
before(async () => {
await esArchiver.load(ARCHIVE);
await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'UTC' });
});
after(async () => await esArchiver.unload(ARCHIVE));
this.tags('ciGroup6');

loadTestFile(require.resolve('./overview'));
loadTestFile(require.resolve('./monitor'));
});
};
28 changes: 28 additions & 0 deletions x-pack/test/functional/apps/uptime/monitor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* 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-next-line:no-default-export
export default ({ getPageObjects, getService }: KibanaFunctionalTestDefaultProviders) => {
const esArchiver = getService('esArchiver');
const pageObjects = getPageObjects(['uptime']);
const archive = 'uptime/full_heartbeat';

describe('monitor page', () => {
before(async () => {
await esArchiver.load(archive);
});
after(async () => await esArchiver.unload(archive));
it('loads and displays uptime data based on date range', async () => {
await pageObjects.uptime.loadDataAndGoToMonitorPage(
'2019-01-28 12:40:08.078',
'auto-http-0X131221E73F825974',
'https://www.google.com/'
);
});
});
};
21 changes: 8 additions & 13 deletions x-pack/test/functional/apps/uptime/overview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,15 @@
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';

// tslint:disable-next-line:no-default-export
export default ({ getPageObjects, getService }: KibanaFunctionalTestDefaultProviders) => {
const esArchiver = getService('esArchiver');
export default ({ getPageObjects }: KibanaFunctionalTestDefaultProviders) => {
// TODO: add UI functional tests
// const pageObjects = getPageObjects(['uptime']);
const archive = 'uptime/full_heartbeat';

describe('Overview page', () => {
describe('this is a simple test', () => {
beforeEach(async () => {
await esArchiver.load(archive);
});
afterEach(async () => await esArchiver.unload(archive));

// TODO: add UI functional tests
const pageObjects = getPageObjects(['uptime']);
describe('overview page', () => {
it('loads and displays uptime data based on date range', async () => {
await pageObjects.uptime.goToUptimeOverviewAndLoadData(
'2019-01-28 12:40:08.078',
'monitor-page-link-auto-http-0X131221E73F825974'
);
});
});
};
31 changes: 24 additions & 7 deletions x-pack/test/functional/page_objects/uptime_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,30 @@ export const UptimePageProvider = ({
getPageObjects,
getService,
}: KibanaFunctionalTestDefaultProviders) => {
const pageObject = getPageObjects(['common']);
const pageObjects = getPageObjects(['common', 'timePicker']);
const uptimeService = getService('uptime');

return {
async goToUptimeOverview() {
await pageObject.common.navigateToApp('uptime');
await uptimeService.assertExists();
},
};
return new class UptimePage {
public async goToUptimeOverviewAndLoadData(
datePickerStartValue: string,
monitorIdToCheck: string
) {
await pageObjects.common.navigateToApp('uptime');
await pageObjects.timePicker.setAbsoluteStart(datePickerStartValue);
await uptimeService.monitorIdExists(monitorIdToCheck);
}

public async loadDataAndGoToMonitorPage(
datePickerStartValue: string,
monitorId: string,
monitorName: string
) {
await pageObjects.common.navigateToApp('uptime');
await pageObjects.timePicker.setAbsoluteStart(datePickerStartValue);
await uptimeService.navigateToMonitorWithId(monitorId);
if ((await uptimeService.getMonitorNameDisplayedOnPageTitle()) !== monitorName) {
throw new Error('Expected monitor name not found');
}
}
}();
};
10 changes: 9 additions & 1 deletion x-pack/test/functional/services/uptime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,20 @@ import { KibanaFunctionalTestDefaultProviders } from '../../types/providers';

export const UptimeProvider = ({ getService }: KibanaFunctionalTestDefaultProviders) => {
const testSubjects = getService('testSubjects');

return {
async assertExists(key: string) {
if (!(await testSubjects.exists(key))) {
throw new Error(`Couldn't find expected element with key "${key}".`);
}
},
async monitorIdExists(key: string) {
await testSubjects.existOrFail(key);
},
async navigateToMonitorWithId(monitorId: string) {
await testSubjects.click(`monitor-page-link-${monitorId}`);
},
async getMonitorNameDisplayedOnPageTitle() {
return await testSubjects.getVisibleText('monitor-page-title');
},
};
};
2 changes: 2 additions & 0 deletions x-pack/test/types/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
*/

import { EsArchiver } from '../../../src/es_archiver';
import { UptimeProvider } from '../functional/services/uptime';

export interface KibanaFunctionalTestDefaultProviders {
getService(serviceName: 'esArchiver'): EsArchiver;
getService(serviceName: 'uptime'): ReturnType<typeof UptimeProvider>;
getService(serviceName: string): any;
getPageObjects(pageObjectNames: string[]): any;
loadTestFile(path: string): void;
Expand Down

0 comments on commit 39c0478

Please sign in to comment.