Port #8880 to master Support Cloud testing (#8915)

* Support Cloud Kibana UI testing master

* Add xpack file

* cherry-pick 9f63224e77
This commit is contained in:
Lee Drengenberg 2016-11-01 10:44:12 -05:00 committed by GitHub
parent 59d65fd672
commit 8ed3b333b0
12 changed files with 144 additions and 30 deletions

View file

@ -258,6 +258,24 @@ To execute the front-end browser tests, enter the following. This requires the s
npm run test:ui:runner
```
To run these browser tests against against some other Elasticsearch and Kibana instance you can set these environment variables and then run the test runner.
Here's an example to run against an Elastic Cloud instance (note that you should run the same branch of tests as the version of Kibana you're testing);
```bash
export TEST_KIBANA_PROTOCOL=https
export TEST_KIBANA_HOSTNAME=9249d04b1186b3e7bbe11ea60df4f963.us-east-1.aws.found.io
export TEST_KIBANA_PORT=443
export TEST_KIBANA_USER=elastic
export TEST_KIBANA_PASS=<your password here>
export TEST_ES_PROTOCOL=http
export TEST_ES_HOSTNAME=aaa5d22032d76805fcce724ed9d9f5a2.us-east-1.aws.found.io
export TEST_ES_PORT=9200
export TEST_ES_USER=elastic
export TEST_ES_PASS=<your password here>
npm run test:ui:runner
```
##### Browser Automation Notes
- Using Page Objects pattern (https://theintern.github.io/intern/#writing-functional-test)

View file

@ -62,12 +62,12 @@ module.exports = function (grunt) {
grunt.registerTask('test:ui:server', [
'esvm:ui',
'run:testUIDevServer',
'run:devChromeDriver:keepalive'
'run:testUIDevServer:keepalive'
]);
grunt.registerTask('test:ui:runner', [
'clean:screenshots',
'run:devChromeDriver',
'intern:dev'
]);

View file

@ -20,6 +20,11 @@ bdd.describe('shared links', function describeIndexTests() {
bdd.before(function () {
baseUrl = PageObjects.common.getHostPort();
PageObjects.common.debug('baseUrl = ' + baseUrl);
// browsers don't show the ':port' if it's 80 or 443 so we have to
// remove that part so we can get a match in the tests.
baseUrl = baseUrl.replace(':80','').replace(':443','');
PageObjects.common.debug('New baseUrl = ' + baseUrl);
var fromTime = '2015-09-19 06:31:44.000';
var toTime = '2015-09-23 18:31:44.000';

View file

@ -77,11 +77,13 @@ bdd.describe('visualize app', function describeIndexTests() {
'8,000 2,863', '10,000 147', '12,000 148', '14,000 129', '16,000 161', '18,000 137'
];
return PageObjects.visualize.getDataTableData()
.then(function showData(data) {
PageObjects.common.debug(data.split('\n'));
PageObjects.common.saveScreenshot('Visualize-data-table');
expect(data.split('\n')).to.eql(expectedChartData);
return PageObjects.common.try(function () {
return PageObjects.visualize.getDataTableData()
.then(function showData(data) {
PageObjects.common.debug(data.split('\n'));
PageObjects.common.saveScreenshot('Visualize-data-table');
expect(data.split('\n')).to.eql(expectedChartData);
});
});
});

View file

@ -0,0 +1,36 @@
import {
bdd,
remote,
defaultTimeout
} from '../../../support';
import PageObjects from '../../../support/page_objects';
bdd.describe('dismiss x-pack', function () {
this.timeout = defaultTimeout;
// Putting everything here in 'before' so it doesn't count as a test
// since x-pack may or may not be installed. We just want the banner closed.
bdd.before(function () {
PageObjects.common.debug('check for X-Pack welcome, opt-out, and dismiss it');
// find class toaster and see if there's any list items in it?
return PageObjects.settings.navigateTo()
.then(() => {
return PageObjects.monitoring.getToasterContents();
})
.then((contents) => {
// Welcome to X-Pack!
// Sharing your cluster statistics with us helps us improve. Your data is never shared with anyone. Not interested? Opt out here.
// Dismiss
PageObjects.common.debug('Toast banner contents = ' + contents);
if (contents.includes('X-Pack')) {
return PageObjects.monitoring.clickOptOut()
.then(() => {
return PageObjects.monitoring.dismissWelcome();
});
}
});
});
});

View file

@ -29,6 +29,7 @@ define(function (require) {
});
const apps = [
'intern/dojo/node!./apps/xpack',
'intern/dojo/node!./apps/discover',
'intern/dojo/node!./apps/management',
'intern/dojo/node!./apps/visualize',

View file

@ -5,21 +5,25 @@ var kibanaURL = '/app/kibana';
module.exports = {
servers: {
webdriver: {
protocol: process.env.TEST_UI_WEBDRIVER_PROTOCOL || 'http',
hostname: process.env.TEST_UI_WEBDRIVER_HOSTNAME || 'localhost',
port: parseInt(process.env.TEST_UI_WEBDRIVER_PORT, 10) || 4444
protocol: process.env.TEST_WEBDRIVER_PROTOCOL || 'http',
hostname: process.env.TEST_WEBDRIVER_HOSTNAME || 'localhost',
port: parseInt(process.env.TEST_WEBDRIVER_PORT, 10) || 4444
},
kibana: {
protocol: process.env.TEST_UI_KIBANA_PROTOCOL || 'http',
hostname: process.env.TEST_UI_KIBANA_HOSTNAME || 'localhost',
port: parseInt(process.env.TEST_UI_KIBANA_PORT, 10) || 5620,
auth: shield.kibanaUser.username + ':' + shield.kibanaUser.password
protocol: process.env.TEST_KIBANA_PROTOCOL || 'http',
hostname: process.env.TEST_KIBANA_HOSTNAME || 'localhost',
port: parseInt(process.env.TEST_KIBANA_PORT, 10) || 5620,
auth: shield.kibanaUser.username + ':' + shield.kibanaUser.password,
username: shield.kibanaUser.username,
password: shield.kibanaUser.password
},
elasticsearch: {
protocol: process.env.TEST_UI_ES_PROTOCOL || 'http',
hostname: process.env.TEST_UI_ES_HOSTNAME || 'localhost',
port: parseInt(process.env.TEST_UI_ES_PORT, 10) || 9220,
auth: shield.admin.username + ':' + shield.admin.password
protocol: process.env.TEST_ES_PROTOCOL || 'http',
hostname: process.env.TEST_ES_HOSTNAME || 'localhost',
port: parseInt(process.env.TEST_ES_PORT, 10) || 9220,
auth: shield.admin.username + ':' + shield.admin.password,
username: shield.admin.username,
password: shield.admin.password
}
},
apps: {

View file

@ -1,16 +1,16 @@
const env = process.env;
exports.kibanaUser = {
username: env.SHIELD_KIBANA_USER || 'user',
password: env.SHIELD_KIBANA_USER_PASS || 'notsecure'
username: env.TEST_KIBANA_USER || 'elastic',
password: env.TEST_KIBANA_PASS || 'changeme'
};
exports.kibanaServer = {
username: env.SHIELD_KIBANA_SERVER || 'kibana',
password: env.SHIELD_KIBANA_SERVER_PASS || 'notsecure'
username: env.TEST_KIBANA_SERVER_USER || 'kibana',
password: env.TEST_KIBANA_SERVER_PASS || 'changeme'
};
exports.admin = {
username: env.SHIELD_ADMIN || 'admin',
password: env.SHIELD_ADMIN_PASS || 'notsecure'
username: env.TEST_ES_USER || 'elastic',
password: env.TEST_ES_PASS || 'changeme'
};

View file

@ -26,6 +26,8 @@ import {
esClient
} from '../index';
import PageObjects from './index';
import {
Log,
Try
@ -116,10 +118,10 @@ export default class Common {
.then(function (currentUrl) {
var loginPage = new RegExp('login').test(currentUrl);
if (loginPage) {
self.debug('Found loginPage = ' + loginPage + ', username = '
+ config.servers.kibana.shield.username);
return shieldPage.login(config.servers.kibana.shield.username,
config.servers.kibana.shield.password)
self.debug('Found loginPage username = '
+ config.servers.kibana.username);
return PageObjects.shield.login(config.servers.kibana.username,
config.servers.kibana.password)
.then(function () {
return self.remote.getCurrentUrl();
});
@ -140,7 +142,11 @@ export default class Common {
// Navigating to Settings when there is a default index pattern has a URL length of 196
// (from debug output). Some other tabs may also be long. But a rather simple configured
// visualization is about 1000 chars long. So at least we catch that case.
var navSuccessful = new RegExp(appUrl + '.{0,' + maxAdditionalLengthOnNavUrl + '}$')
// Browsers don't show the ':port' if it's 80 or 443 so we have to
// remove that part so we can get a match in the tests.
var navSuccessful = new RegExp(appUrl.replace(':80','').replace(':443','')
+ '.{0,' + maxAdditionalLengthOnNavUrl + '}$')
.test(currentUrl);
if (!navSuccessful) {

View file

@ -47,7 +47,7 @@ export default class HeaderPage {
}
isTimepickerOpen() {
return this.remote.setFindTimeout(defaultFindTimeout)
return this.remote.setFindTimeout(2000)
.findDisplayedByCssSelector('.kbn-timepicker')
.then(() => true)
.catch(() => false);

View file

@ -7,6 +7,7 @@ import HeaderPage from './header_page';
import SettingsPage from './settings_page';
import ShieldPage from './shield_page';
import VisualizePage from './visualize_page';
import MonitoringPage from './monitoring_page';
const common = new Common();
const consolePage = new ConsolePage();
@ -16,6 +17,7 @@ const headerPage = new HeaderPage();
const settingsPage = new SettingsPage();
const shieldPage = new ShieldPage();
const visualizePage = new VisualizePage();
const monitoringPage = new MonitoringPage();
class PageObjects {
@ -35,6 +37,7 @@ class PageObjects {
settingsPage.init(remote);
shieldPage.init(remote);
visualizePage.init(remote);
monitoringPage.init(remote);
}
assertInitialized() {
@ -76,6 +79,10 @@ class PageObjects {
return this.assertInitialized() && visualizePage;
}
get monitoring() {
return this.assertInitialized() && monitoringPage;
}
}
export default new PageObjects();

View file

@ -0,0 +1,35 @@
import {
defaultFindTimeout,
} from '../';
export default class MonitoringPage {
init(remote) {
this.remote = remote;
this.findTimeout = this.remote.setFindTimeout(defaultFindTimeout);
}
getWelcome() {
return this.findTimeout
.findDisplayedByCssSelector('render-directive')
.getVisibleText();
}
dismissWelcome() {
return this.remote.setFindTimeout(3000)
.findDisplayedByCssSelector('button.btn-banner')
.click();
}
getToasterContents() {
return this.findTimeout
.findByCssSelector('div.toaster-container.ng-isolate-scope')
.getVisibleText();
}
clickOptOut() {
return this.findTimeout.findByLinkText('Opt out here').click();
}
}