mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
Merge branch 'feature/ingest' into ingest/addDataStart
This commit is contained in:
commit
9c27e3d52a
27 changed files with 879 additions and 83 deletions
|
@ -1,4 +1,4 @@
|
|||
Copyright 2012–2014 Elasticsearch BV
|
||||
Copyright 2012–2015 Elasticsearch BV
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
"good-squeeze": "2.1.0",
|
||||
"gridster": "0.5.6",
|
||||
"hapi": "8.8.1",
|
||||
"httpolyglot": "0.1.1",
|
||||
"imports-loader": "0.6.4",
|
||||
"jade": "1.11.0",
|
||||
"jade-loader": "0.7.1",
|
||||
|
|
|
@ -15,28 +15,38 @@ module.exports = class ClusterManager {
|
|||
this.log = new Log(opts.quiet, opts.silent);
|
||||
this.addedCount = 0;
|
||||
|
||||
this.basePathProxy = new BasePathProxy(this, settings);
|
||||
const serverArgv = [];
|
||||
const optimizerArgv = [
|
||||
'--plugins.initialize=false',
|
||||
'--server.autoListen=false',
|
||||
];
|
||||
|
||||
if (opts.basePath) {
|
||||
this.basePathProxy = new BasePathProxy(this, settings);
|
||||
|
||||
optimizerArgv.push(
|
||||
`--server.basePath=${this.basePathProxy.basePath}`
|
||||
);
|
||||
|
||||
serverArgv.push(
|
||||
`--server.port=${this.basePathProxy.targetPort}`,
|
||||
`--server.basePath=${this.basePathProxy.basePath}`
|
||||
);
|
||||
}
|
||||
|
||||
this.workers = [
|
||||
this.optimizer = new Worker({
|
||||
type: 'optmzr',
|
||||
title: 'optimizer',
|
||||
log: this.log,
|
||||
argv: compact([
|
||||
'--plugins.initialize=false',
|
||||
'--server.autoListen=false',
|
||||
`--server.basePath=${this.basePathProxy.basePath}`
|
||||
]),
|
||||
argv: optimizerArgv,
|
||||
watch: false
|
||||
}),
|
||||
|
||||
this.server = new Worker({
|
||||
type: 'server',
|
||||
log: this.log,
|
||||
argv: compact([
|
||||
`--server.port=${this.basePathProxy.targetPort}`,
|
||||
`--server.basePath=${this.basePathProxy.basePath}`
|
||||
])
|
||||
argv: serverArgv
|
||||
})
|
||||
];
|
||||
|
||||
|
@ -60,7 +70,9 @@ module.exports = class ClusterManager {
|
|||
startCluster() {
|
||||
this.setupManualRestart();
|
||||
invoke(this.workers, 'start');
|
||||
this.basePathProxy.listen();
|
||||
if (this.basePathProxy) {
|
||||
this.basePathProxy.listen();
|
||||
}
|
||||
}
|
||||
|
||||
setupWatching() {
|
||||
|
|
|
@ -107,6 +107,7 @@ module.exports = function (program) {
|
|||
command
|
||||
.option('--dev', 'Run the server with development mode defaults')
|
||||
.option('--no-ssl', 'Don\'t run the dev server using HTTPS')
|
||||
.option('--no-base-path', 'Don\'t put a proxy in front of the dev server, which adds a random basePath')
|
||||
.option('--no-watch', 'Prevents automatic restarts of the server in --dev mode');
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div dashboard-app class="app-container dashboard-container">
|
||||
<navbar ng-show="chrome.getVisible()">
|
||||
<navbar ng-show="chrome.getVisible()" name="dashboard">
|
||||
<span class="name" ng-if="dash.id" ng-bind="::dash.title" tooltip="{{::dash.title}}"></span>
|
||||
|
||||
<form name="queryInput"
|
||||
|
|
|
@ -10,6 +10,7 @@ define(function (require) {
|
|||
require('ui/config');
|
||||
require('ui/notify');
|
||||
require('ui/typeahead');
|
||||
require('ui/navbar');
|
||||
require('ui/share');
|
||||
|
||||
require('plugins/kibana/dashboard/directives/grid');
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div ng-controller="discover" class="app-container">
|
||||
<navbar>
|
||||
<navbar name="discover">
|
||||
<form role="form" class="fill inline-form" ng-submit="fetch()" name="discoverSearch">
|
||||
<div class="typeahead" kbn-typeahead="discover">
|
||||
<div class="input-group"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
define(function (require, module, exports) {
|
||||
require('plugins/kibana/discover/saved_searches/saved_searches');
|
||||
require('plugins/kibana/discover/directives/timechart');
|
||||
require('ui/navbar');
|
||||
require('ui/collapsible_sidebar');
|
||||
require('plugins/kibana/discover/components/field_chooser/field_chooser');
|
||||
require('plugins/kibana/discover/controllers/discover');
|
||||
|
@ -9,6 +10,6 @@ define(function (require, module, exports) {
|
|||
// preload
|
||||
require('ui/doc_table/components/table_row');
|
||||
|
||||
require('ui/saved_objects/saved_object_registry').register(require('plugins/kibana/discover/saved_searches/saved_search_register'));
|
||||
|
||||
var savedObjectRegistry = require('ui/saved_objects/saved_object_registry');
|
||||
savedObjectRegistry.register(require('plugins/kibana/discover/saved_searches/saved_search_register'));
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div ng-controller="VisEditor" class="vis-editor vis-type-{{ vis.type.name }}">
|
||||
<navbar ng-if="chrome.getVisible()">
|
||||
<navbar ng-if="chrome.getVisible()" name="visualize">
|
||||
<div class="fill bitty-modal-container">
|
||||
<div ng-if="vis.type.requiresSearch && $state.linked && !unlinking"
|
||||
ng-dblclick="unlink()"
|
||||
|
|
|
@ -4,6 +4,7 @@ define(function (require) {
|
|||
require('plugins/kibana/visualize/editor/sidebar');
|
||||
require('plugins/kibana/visualize/editor/agg_filter');
|
||||
|
||||
require('ui/navbar');
|
||||
require('ui/visualize');
|
||||
require('ui/collapsible_sidebar');
|
||||
require('ui/share');
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
import fs from 'fs';
|
||||
import { readFileSync } from 'fs';
|
||||
import { format as formatUrl } from 'url';
|
||||
import httpolyglot from 'httpolyglot';
|
||||
|
||||
import tlsCiphers from './tls_ciphers';
|
||||
|
||||
export default function (kbnServer, server, config) {
|
||||
// this mixin is used outside of the kbn server, so it MUST work without a full kbnServer object.
|
||||
kbnServer = null;
|
||||
|
||||
// Create a new connection
|
||||
var connectionOptions = {
|
||||
host: config.get('server.host'),
|
||||
port: config.get('server.port'),
|
||||
const host = config.get('server.host');
|
||||
const port = config.get('server.port');
|
||||
|
||||
const connectionOptions = {
|
||||
host,
|
||||
port,
|
||||
state: {
|
||||
strictHeader: false
|
||||
},
|
||||
|
@ -19,42 +25,39 @@ export default function (kbnServer, server, config) {
|
|||
}
|
||||
};
|
||||
|
||||
// enable tls if ssl key and cert are defined
|
||||
if (config.get('server.ssl.key') && config.get('server.ssl.cert')) {
|
||||
connectionOptions.tls = {
|
||||
key: fs.readFileSync(config.get('server.ssl.key')),
|
||||
cert: fs.readFileSync(config.get('server.ssl.cert')),
|
||||
// The default ciphers in node 0.12.x include insecure ciphers, so until
|
||||
// we enforce a more recent version of node, we craft our own list
|
||||
// @see https://github.com/nodejs/node/blob/master/src/node_constants.h#L8-L28
|
||||
ciphers: [
|
||||
'ECDHE-RSA-AES128-GCM-SHA256',
|
||||
'ECDHE-ECDSA-AES128-GCM-SHA256',
|
||||
'ECDHE-RSA-AES256-GCM-SHA384',
|
||||
'ECDHE-ECDSA-AES256-GCM-SHA384',
|
||||
'DHE-RSA-AES128-GCM-SHA256',
|
||||
'ECDHE-RSA-AES128-SHA256',
|
||||
'DHE-RSA-AES128-SHA256',
|
||||
'ECDHE-RSA-AES256-SHA384',
|
||||
'DHE-RSA-AES256-SHA384',
|
||||
'ECDHE-RSA-AES256-SHA256',
|
||||
'DHE-RSA-AES256-SHA256',
|
||||
'HIGH',
|
||||
'!aNULL',
|
||||
'!eNULL',
|
||||
'!EXPORT',
|
||||
'!DES',
|
||||
'!RC4',
|
||||
'!MD5',
|
||||
'!PSK',
|
||||
'!SRP',
|
||||
'!CAMELLIA'
|
||||
].join(':'),
|
||||
// We use the server's cipher order rather than the client's to prevent
|
||||
// the BEAST attack
|
||||
honorCipherOrder: true
|
||||
};
|
||||
// enable tlsOpts if ssl key and cert are defined
|
||||
const useSsl = config.get('server.ssl.key') && config.get('server.ssl.cert');
|
||||
|
||||
// not using https? well that's easy!
|
||||
if (!useSsl) {
|
||||
server.connection(connectionOptions);
|
||||
return;
|
||||
}
|
||||
|
||||
server.connection(connectionOptions);
|
||||
server.connection({
|
||||
...connectionOptions,
|
||||
tls: true,
|
||||
listener: httpolyglot.createServer({
|
||||
key: readFileSync(config.get('server.ssl.key')),
|
||||
cert: readFileSync(config.get('server.ssl.cert')),
|
||||
|
||||
ciphers: tlsCiphers,
|
||||
// We use the server's cipher order rather than the client's to prevent the BEAST attack
|
||||
honorCipherOrder: true
|
||||
})
|
||||
});
|
||||
|
||||
server.ext('onRequest', function (req, reply) {
|
||||
if (req.raw.req.socket.encrypted) {
|
||||
reply.continue();
|
||||
} else {
|
||||
reply.redirect(formatUrl({
|
||||
port,
|
||||
protocol: 'https',
|
||||
hostname: host,
|
||||
pathname: req.url.pathname,
|
||||
search: req.url.search,
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
26
src/server/http/tls_ciphers.js
Normal file
26
src/server/http/tls_ciphers.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
// The default ciphers in node 0.12.x include insecure ciphers, so until
|
||||
// we enforce a more recent version of node, we craft our own list
|
||||
// @see https://github.com/nodejs/node/blob/master/src/node_constants.h#L8-L28
|
||||
export default [
|
||||
'ECDHE-RSA-AES128-GCM-SHA256',
|
||||
'ECDHE-ECDSA-AES128-GCM-SHA256',
|
||||
'ECDHE-RSA-AES256-GCM-SHA384',
|
||||
'ECDHE-ECDSA-AES256-GCM-SHA384',
|
||||
'DHE-RSA-AES128-GCM-SHA256',
|
||||
'ECDHE-RSA-AES128-SHA256',
|
||||
'DHE-RSA-AES128-SHA256',
|
||||
'ECDHE-RSA-AES256-SHA384',
|
||||
'DHE-RSA-AES256-SHA384',
|
||||
'ECDHE-RSA-AES256-SHA256',
|
||||
'DHE-RSA-AES256-SHA256',
|
||||
'HIGH',
|
||||
'!aNULL',
|
||||
'!eNULL',
|
||||
'!EXPORT',
|
||||
'!DES',
|
||||
'!RC4',
|
||||
'!MD5',
|
||||
'!PSK',
|
||||
'!SRP',
|
||||
'!CAMELLIA'
|
||||
].join(':');
|
|
@ -14,6 +14,7 @@ module.exports = function (kbnServer, server, config) {
|
|||
else if (config.get('logging.quiet')) {
|
||||
_.defaults(events, {
|
||||
log: ['listening', 'error', 'fatal'],
|
||||
request: ['error'],
|
||||
error: '*'
|
||||
});
|
||||
}
|
||||
|
@ -30,6 +31,7 @@ module.exports = function (kbnServer, server, config) {
|
|||
_.defaults(events, {
|
||||
log: ['info', 'warning', 'error', 'fatal'],
|
||||
response: config.get('logging.json') ? '*' : '!',
|
||||
request: ['info', 'warning', 'error', 'fatal'],
|
||||
error: '*'
|
||||
});
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ require('ui/storage');
|
|||
require('ui/stringify/register');
|
||||
require('ui/styleCompile');
|
||||
require('ui/timefilter');
|
||||
require('ui/timepicker');
|
||||
require('ui/tooltip');
|
||||
require('ui/typeahead');
|
||||
require('ui/url');
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
*
|
||||
* In the scenario below, require.js would load directive.js first because it is a
|
||||
* dependency of app.js. This would cause the call to `angular.module('app')` to
|
||||
* execute before the module is actually created. This causes angular to through an
|
||||
* error. This effect is magnifies when app.js links off to many different modules.
|
||||
* execute before the module is actually created. This causes angular to throw an
|
||||
* error. This effect is magnified when app.js links off to many different modules.
|
||||
*
|
||||
* This is normally solved by creating unique modules per file, listed as the 1st
|
||||
* alternate solution below. Unfortunately this solution would have required that
|
||||
|
|
140
src/ui/public/navbar/__tests__/navbar.js
Normal file
140
src/ui/public/navbar/__tests__/navbar.js
Normal file
|
@ -0,0 +1,140 @@
|
|||
const ngMock = require('ngMock');
|
||||
const sinon = require('sinon');
|
||||
const expect = require('expect.js');
|
||||
const angular = require('angular');
|
||||
const _ = require('lodash');
|
||||
|
||||
require('ui/navbar');
|
||||
const navbarExtensionsRegistry = require('ui/registry/navbar_extensions');
|
||||
const Registry = require('ui/registry/_registry');
|
||||
|
||||
const defaultMarkup = `
|
||||
<navbar name="testing">
|
||||
<div class="button-group" role="toolbar">
|
||||
<button>
|
||||
<i aria-hidden="true" class="fa fa-file-new-o"></i>
|
||||
</button>
|
||||
<button>
|
||||
<i aria-hidden="true" class="fa fa-save"></i>
|
||||
</button>
|
||||
<button>
|
||||
<i aria-hidden="true" class="fa fa-folder-open-o"></i>
|
||||
</button>
|
||||
</div>
|
||||
</navbar>`;
|
||||
|
||||
|
||||
describe('navbar directive', function () {
|
||||
let $rootScope;
|
||||
let $compile;
|
||||
let stubRegistry;
|
||||
|
||||
beforeEach(function () {
|
||||
ngMock.module('kibana', function (PrivateProvider) {
|
||||
stubRegistry = new Registry({
|
||||
index: ['name'],
|
||||
group: ['appName'],
|
||||
order: ['order']
|
||||
});
|
||||
|
||||
PrivateProvider.swap(navbarExtensionsRegistry, stubRegistry);
|
||||
});
|
||||
|
||||
ngMock.module('kibana/navbar');
|
||||
|
||||
// Create the scope
|
||||
ngMock.inject(function ($injector) {
|
||||
$rootScope = $injector.get('$rootScope');
|
||||
$compile = $injector.get('$compile');
|
||||
});
|
||||
});
|
||||
|
||||
function init(markup = defaultMarkup) {
|
||||
// Give us a scope
|
||||
const $el = angular.element(markup);
|
||||
$compile($el)($rootScope);
|
||||
$el.scope().$digest();
|
||||
return $el;
|
||||
}
|
||||
|
||||
describe('incorrect use', function () {
|
||||
it('should throw if missing a name property', function () {
|
||||
const markup = `<navbar><div class="button-group" role="toolbar"></div></navbar>`;
|
||||
expect(() => init(markup)).to.throwException(/requires a name attribute/);
|
||||
});
|
||||
|
||||
it('should throw if missing a button group', function () {
|
||||
const markup = `<navbar name="testing"></navbar>`;
|
||||
expect(() => init(markup)).to.throwException(/must have exactly 1 button group/);
|
||||
});
|
||||
|
||||
it('should throw if multiple button groups', function () {
|
||||
const markup = ` <navbar name="testing">
|
||||
<div class="button-group" role="toolbar">
|
||||
<button>
|
||||
<i aria-hidden="true" class="fa fa-file-new-o"></i>
|
||||
</button>
|
||||
<button>
|
||||
<i aria-hidden="true" class="fa fa-save"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="button-group" role="toolbar">
|
||||
<button>
|
||||
<i aria-hidden="true" class="fa fa-folder-open-o"></i>
|
||||
</button>
|
||||
</div>
|
||||
</navbar>`;
|
||||
expect(() => init(markup)).to.throwException(/must have exactly 1 button group/);
|
||||
});
|
||||
|
||||
it('should throw if button group not direct child', function () {
|
||||
const markup = `<navbar><div><div class="button-group" role="toolbar"></div></div></navbar>`;
|
||||
expect(() => init(markup)).to.throwException(/must have exactly 1 button group/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('injecting extensions', function () {
|
||||
function registerExtension(def = {}) {
|
||||
stubRegistry.register(function () {
|
||||
return _.defaults(def, {
|
||||
name: 'exampleButton',
|
||||
appName: 'testing',
|
||||
order: 0,
|
||||
template: `
|
||||
<button class="test-button">
|
||||
<i aria-hidden="true" class="fa fa-rocket"></i>
|
||||
</button>`
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
it('should use the default markup', function () {
|
||||
var $el = init();
|
||||
expect($el.find('.button-group button').length).to.equal(3);
|
||||
});
|
||||
|
||||
it('should append to end then order == 0', function () {
|
||||
registerExtension({ order: 0 });
|
||||
var $el = init();
|
||||
|
||||
expect($el.find('.button-group button').length).to.equal(4);
|
||||
expect($el.find('.button-group button').last().hasClass('test-button')).to.be.ok();
|
||||
});
|
||||
|
||||
it('should append to end then order > 0', function () {
|
||||
registerExtension({ order: 1 });
|
||||
var $el = init();
|
||||
|
||||
expect($el.find('.button-group button').length).to.equal(4);
|
||||
expect($el.find('.button-group button').last().hasClass('test-button')).to.be.ok();
|
||||
});
|
||||
|
||||
it('should append to end then order < 0', function () {
|
||||
registerExtension({ order: -1 });
|
||||
var $el = init();
|
||||
|
||||
expect($el.find('.button-group button').length).to.equal(4);
|
||||
expect($el.find('.button-group button').first().hasClass('test-button')).to.be.ok();
|
||||
});
|
||||
});
|
||||
});
|
56
src/ui/public/navbar/navbar.js
Normal file
56
src/ui/public/navbar/navbar.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
const _ = require('lodash');
|
||||
const $ = require('jquery');
|
||||
const navbar = require('ui/modules').get('kibana/navbar');
|
||||
|
||||
require('ui/render_directive');
|
||||
|
||||
navbar.directive('navbar', function (Private, $compile) {
|
||||
const navbarExtensions = Private(require('ui/registry/navbar_extensions'));
|
||||
const getExtensions = _.memoize(function (name) {
|
||||
if (!name) throw new Error('navbar directive requires a name attribute');
|
||||
return _.sortBy(navbarExtensions.byAppName[name], 'order');
|
||||
});
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: function ($el, $attrs) {
|
||||
const $buttonGroup = $el.children('.button-group');
|
||||
if ($buttonGroup.length !== 1) throw new Error('navbar must have exactly 1 button group');
|
||||
|
||||
const extensions = getExtensions($attrs.name);
|
||||
const buttons = $buttonGroup.children().detach().toArray();
|
||||
const controls = [
|
||||
...buttons.map(function (button) {
|
||||
return {
|
||||
order: 0,
|
||||
$el: $(button),
|
||||
};
|
||||
}),
|
||||
...extensions.map(function (extension, i) {
|
||||
return {
|
||||
order: extension.order,
|
||||
index: i,
|
||||
extension: extension,
|
||||
};
|
||||
}),
|
||||
];
|
||||
|
||||
_.sortBy(controls, 'order').forEach(function (control) {
|
||||
if (control.$el) {
|
||||
return $buttonGroup.append(control.$el);
|
||||
}
|
||||
|
||||
const { extension, index } = control;
|
||||
const $ext = $(`<render-directive definition="navbar.extensions[${index}]"></render-directive>`);
|
||||
$ext.html(extension.template);
|
||||
$buttonGroup.append($ext);
|
||||
});
|
||||
|
||||
return $el.html();
|
||||
},
|
||||
controllerAs: 'navbar',
|
||||
controller: function ($attrs) {
|
||||
this.extensions = getExtensions($attrs.name);
|
||||
}
|
||||
};
|
||||
});
|
|
@ -457,3 +457,14 @@ fieldset {
|
|||
overflow-y: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.list-group {
|
||||
.list-group-item {
|
||||
&.active,
|
||||
&.active:hover,
|
||||
&.active:focus {
|
||||
background-color: @list-group-menu-item-active-bg;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,6 +86,8 @@ module.exports = function (grunt) {
|
|||
args: [
|
||||
'--dev',
|
||||
'--no-watch',
|
||||
'--no-ssl',
|
||||
'--no-base-path',
|
||||
'--server.port=5610',
|
||||
'--optimize.lazyPort=5611',
|
||||
'--optimize.lazyPrebuild=true',
|
||||
|
|
|
@ -48,10 +48,11 @@ define(function (require) {
|
|||
|
||||
bdd.describe('query', function () {
|
||||
var queryName1 = 'Query # 1';
|
||||
var fromTimeString = 'September 19th 2015, 06:31:44.000';
|
||||
var toTimeString = 'September 23rd 2015, 18:31:44.000';
|
||||
|
||||
bdd.it('should show correct time range string', function () {
|
||||
var expectedTimeRangeString =
|
||||
'September 19th 2015, 06:31:44.000 to September 23rd 2015, 18:31:44.000';
|
||||
bdd.it('should show correct time range string by timepicker', function () {
|
||||
var expectedTimeRangeString = fromTimeString + ' to ' + toTimeString;
|
||||
return discoverPage.getTimespanText()
|
||||
.then(function (actualTimeString) {
|
||||
expect(actualTimeString).to.be(expectedTimeRangeString);
|
||||
|
@ -59,6 +60,7 @@ define(function (require) {
|
|||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
|
||||
bdd.it('save query should show toast message and display query name', function () {
|
||||
var expectedSavedQueryMessage = 'Discover: Saved Data Source "' + queryName1 + '"';
|
||||
return discoverPage.saveSearch(queryName1)
|
||||
|
@ -91,6 +93,19 @@ define(function (require) {
|
|||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('should show the correct hit count', function () {
|
||||
var expectedHitCount = '14,004';
|
||||
return common.tryForTime(20 * 1000, function tryingForTime() {
|
||||
return discoverPage.getHitCount()
|
||||
.then(function compareData(hitCount) {
|
||||
expect(hitCount).to.be(expectedHitCount);
|
||||
});
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
|
||||
|
||||
bdd.it('should show the correct bar chart', function () {
|
||||
var expectedBarChartData = [ '0', '0', '0', '0', '0', '0',
|
||||
'2.7056249999999977', '14.771249999999995', '54.112500000000004',
|
||||
|
@ -104,25 +119,176 @@ define(function (require) {
|
|||
];
|
||||
return common.sleep(4000)
|
||||
.then(function () {
|
||||
return common.tryForTime(20 * 1000, function tryingForTime() {
|
||||
return discoverPage.getBarChartData()
|
||||
.then(function compareData(paths) {
|
||||
// the largest bars are over 100 pixels high so this is less than 1% tolerance
|
||||
var barHeightTolerance = 1;
|
||||
for (var y = 0; y < expectedBarChartData.length; y++) {
|
||||
common.debug(y + ': expected = ' + expectedBarChartData[y] + ', actual = ' + paths[y] +
|
||||
', Pass = ' + (Math.abs(expectedBarChartData[y] - paths[y]) < barHeightTolerance));
|
||||
};
|
||||
for (var x = 0; x < expectedBarChartData.length; x++) {
|
||||
expect(Math.abs(expectedBarChartData[x] - paths[x]) < barHeightTolerance).to.be.ok();
|
||||
}
|
||||
});
|
||||
});
|
||||
return verifyChartData(expectedBarChartData);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('should show correct time range string in chart', function () {
|
||||
var expectedTimeRangeString = fromTimeString + ' - ' + toTimeString;
|
||||
return discoverPage.getChartTimespan()
|
||||
.then(function (actualTimeString) {
|
||||
expect(actualTimeString).to.be(expectedTimeRangeString);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('should show correct initial chart interval of 3 hours', function () {
|
||||
var expectedChartInterval = 'by 3 hours';
|
||||
return discoverPage.getChartInterval()
|
||||
.then(function (actualInterval) {
|
||||
expect(actualInterval).to.be(expectedChartInterval);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('should show correct data for chart interval Hourly', function () {
|
||||
var chartInterval = 'Hourly';
|
||||
var expectedBarChartData = [ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
||||
'0', '0', '0', '0', '0', '0', '0', '0', '1.2763636363636266', '1.914545454545447',
|
||||
'4.680000000000007', '6.594545454545454', '11.061818181818168', '25.314545454545453',
|
||||
'38.50363636363636', '46.374545454545455', '72.53999999999999', '93.60000000000001',
|
||||
'102.10909090909091', '109.97999999999999', '111.04363636363637', '94.87636363636364',
|
||||
'85.72909090909091', '68.28545454545454', '54.88363636363636', '36.58909090909091',
|
||||
'20.209090909090904', '11.700000000000003', '8.083636363636359', '5.105454545454549',
|
||||
'0.6381818181818204', '0.8509090909090986', '2.3400000000000034', '2.978181818181824',
|
||||
'3.61636363636363', '8.083636363636359', '10.423636363636362', '24.46363636363637',
|
||||
'32.33454545454545', '45.94909090909091', '67.00909090909092', '85.51636363636365',
|
||||
'94.87636363636364', '109.1290909090909', '110.61818181818181', '100.83272727272727',
|
||||
'89.55818181818182', '65.30727272727273', '48.92727272727274', '36.16363636363636',
|
||||
'21.059999999999988', '10.210909090909098', '6.38181818181819', '3.190909090909088',
|
||||
'2.127272727272725', '0.4254545454545422', '1.701818181818183', '1.4890909090909048',
|
||||
'3.61636363636363', '7.232727272727274', '7.870909090909095', '22.123636363636365',
|
||||
'32.54727272727273', '51.267272727272726', '66.58363636363637', '85.94181818181818',
|
||||
'104.66181818181818', '108.91636363636364', '107.00181818181818', '100.62',
|
||||
'80.62363636363636', '62.32909090909091', '58.92545454545455', '33.18545454545455',
|
||||
'21.059999999999988', '11.274545454545446', '10.423636363636362', '3.403636363636366',
|
||||
'1.914545454545447', '0.8509090909090986', '0', '0', '0', '0', '0', '0',
|
||||
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
|
||||
];
|
||||
return discoverPage.setChartInterval(chartInterval)
|
||||
.then(function () {
|
||||
return common.sleep(8000);
|
||||
})
|
||||
.then(function () {
|
||||
return verifyChartData(expectedBarChartData);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('should show correct data for chart interval Daily', function () {
|
||||
var chartInterval = 'Daily';
|
||||
var expectedBarChartData = [ '0', '111.3138', '107.96759999999999', '108.4122', '0'];
|
||||
return discoverPage.setChartInterval(chartInterval)
|
||||
.then(function () {
|
||||
return common.sleep(8000);
|
||||
})
|
||||
.then(function () {
|
||||
return verifyChartData(expectedBarChartData);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('should show correct data for chart interval Weekly', function () {
|
||||
var chartInterval = 'Weekly';
|
||||
var expectedBarChartData = [ '55.6569', '108.1899'];
|
||||
return discoverPage.setChartInterval(chartInterval)
|
||||
.then(function () {
|
||||
return common.sleep(2000);
|
||||
})
|
||||
.then(function () {
|
||||
return verifyChartData(expectedBarChartData);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('should show correct data for chart interval Monthly', function () {
|
||||
var chartInterval = 'Monthly';
|
||||
var expectedBarChartData = [ '102.404'];
|
||||
return discoverPage.setChartInterval(chartInterval)
|
||||
.then(function () {
|
||||
return common.sleep(2000);
|
||||
})
|
||||
.then(function () {
|
||||
return verifyChartData(expectedBarChartData);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('should show correct data for chart interval Yearly', function () {
|
||||
var chartInterval = 'Yearly';
|
||||
var expectedBarChartData = [ '102.404'];
|
||||
return discoverPage.setChartInterval(chartInterval)
|
||||
.then(function () {
|
||||
return common.sleep(2000);
|
||||
})
|
||||
.then(function () {
|
||||
return verifyChartData(expectedBarChartData);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
|
||||
|
||||
bdd.it('should show correct data for chart interval Auto', function () {
|
||||
var chartInterval = 'Auto';
|
||||
var expectedBarChartData = [ '0', '0', '0', '0', '0', '0',
|
||||
'2.7056249999999977', '14.771249999999995', '54.112500000000004',
|
||||
'105.080625', '100.25437500000001', '54.916875', '13.747499999999988',
|
||||
'2.266874999999999', '3.0712500000000063', '14.771249999999995',
|
||||
'49.944374999999994', '99.523125', '103.471875', '51.699375',
|
||||
'12.943124999999995', '1.9743749999999949', '2.3400000000000034',
|
||||
'12.796875', '51.699375', '102.96000000000001', '99.08437500000001',
|
||||
'53.08875', '14.698125000000005', '2.1206249999999898', '0', '0',
|
||||
'0', '0', '0', '0', '0'
|
||||
];
|
||||
return discoverPage.setChartInterval(chartInterval)
|
||||
.then(function () {
|
||||
return common.sleep(4000);
|
||||
})
|
||||
.then(function () {
|
||||
return verifyChartData(expectedBarChartData);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('should show Auto chart interval of 3 hours', function () {
|
||||
var expectedChartInterval = 'by 3 hours';
|
||||
return discoverPage.getChartInterval()
|
||||
.then(function (actualInterval) {
|
||||
expect(actualInterval).to.be(expectedChartInterval);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
|
||||
function verifyChartData(expectedBarChartData) {
|
||||
return common.tryForTime(20 * 1000, function tryingForTime() {
|
||||
return discoverPage.getBarChartData()
|
||||
.then(function compareData(paths) {
|
||||
// the largest bars are over 100 pixels high so this is less than 1% tolerance
|
||||
var barHeightTolerance = 1;
|
||||
var stringResults = '';
|
||||
var hasFailure = false;
|
||||
for (var y = 0; y < expectedBarChartData.length; y++) {
|
||||
stringResults += y + ': expected = ' + expectedBarChartData[y] + ', actual = ' + paths[y] +
|
||||
', Pass = ' + (Math.abs(expectedBarChartData[y] - paths[y]) < barHeightTolerance);
|
||||
if ((Math.abs(expectedBarChartData[y] - paths[y]) > barHeightTolerance)) {
|
||||
hasFailure = true;
|
||||
};
|
||||
};
|
||||
if (hasFailure) {
|
||||
common.log(stringResults);
|
||||
common.log(paths);
|
||||
}
|
||||
for (var x = 0; x < expectedBarChartData.length; x++) {
|
||||
expect(Math.abs(expectedBarChartData[x] - paths[x]) < barHeightTolerance).to.be.ok();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
268
test/functional/apps/discover/_field_data.js
Normal file
268
test/functional/apps/discover/_field_data.js
Normal file
|
@ -0,0 +1,268 @@
|
|||
define(function (require) {
|
||||
var Common = require('../../../support/pages/Common');
|
||||
var HeaderPage = require('../../../support/pages/HeaderPage');
|
||||
var SettingsPage = require('../../../support/pages/settings_page');
|
||||
var DiscoverPage = require('../../../support/pages/DiscoverPage');
|
||||
var expect = require('intern/dojo/node!expect.js');
|
||||
|
||||
return function (bdd, scenarioManager) {
|
||||
bdd.describe('discover app', function describeIndexTests() {
|
||||
var common;
|
||||
var headerPage;
|
||||
var settingsPage;
|
||||
var discoverPage;
|
||||
|
||||
bdd.before(function () {
|
||||
common = new Common(this.remote);
|
||||
headerPage = new HeaderPage(this.remote);
|
||||
settingsPage = new SettingsPage(this.remote);
|
||||
discoverPage = new DiscoverPage(this.remote);
|
||||
var fromTime = '2015-09-19 06:31:44.000';
|
||||
var toTime = '2015-09-23 18:31:44.000';
|
||||
|
||||
// start each test with an empty kibana index
|
||||
return scenarioManager.reload('emptyKibana')
|
||||
// and load a set of makelogs data
|
||||
.then(function loadIfEmptyMakelogs() {
|
||||
return scenarioManager.loadIfEmpty('logstashFunctional');
|
||||
})
|
||||
.then(function (navigateTo) {
|
||||
common.debug('navigateTo');
|
||||
return settingsPage.navigateTo();
|
||||
})
|
||||
.then(function () {
|
||||
common.debug('createIndexPattern');
|
||||
return settingsPage.createIndexPattern();
|
||||
})
|
||||
.then(function () {
|
||||
common.debug('discover');
|
||||
return common.navigateToApp('discover');
|
||||
})
|
||||
.then(function () {
|
||||
common.debug('setAbsoluteRange');
|
||||
return headerPage.setAbsoluteRange(fromTime, toTime);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
|
||||
bdd.describe('field data', function () {
|
||||
var queryName1 = 'Query # 1';
|
||||
var fromTimeString = 'September 19th 2015, 06:31:44.000';
|
||||
var toTimeString = 'September 23rd 2015, 18:31:44.000';
|
||||
|
||||
|
||||
bdd.it('search php should show the correct hit count', function () {
|
||||
var expectedHitCount = '445';
|
||||
return discoverPage.query('php')
|
||||
.then(function () {
|
||||
return common.tryForTime(20 * 1000, function tryingForTime() {
|
||||
return discoverPage.getHitCount()
|
||||
.then(function compareData(hitCount) {
|
||||
expect(hitCount).to.be(expectedHitCount);
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('the search term should be highlighted in the field data', function () {
|
||||
// marks is the style that highlights the text in yellow
|
||||
return discoverPage.getMarks()
|
||||
.then(function (marks) {
|
||||
expect(marks.length).to.be(50);
|
||||
expect(marks.indexOf('php')).to.be(0);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
|
||||
bdd.it('search _type:apache should show the correct hit count', function () {
|
||||
var expectedHitCount = '11,156';
|
||||
return discoverPage.query('_type:apache')
|
||||
.then(function () {
|
||||
return common.tryForTime(20 * 1000, function tryingForTime() {
|
||||
return discoverPage.getHitCount()
|
||||
.then(function compareData(hitCount) {
|
||||
expect(hitCount).to.be(expectedHitCount);
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('doc view should show Time and _source columns', function () {
|
||||
var expectedHeader = 'Time _source';
|
||||
return discoverPage.getDocHeader()
|
||||
.then(function (header) {
|
||||
expect(header).to.be(expectedHeader);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('doc view should show oldest time first', function () {
|
||||
// Note: Could just check the timestamp, but might as well check that the whole doc is as expected.
|
||||
var ExpectedDoc =
|
||||
'September 22nd 2015, 23:50:13.253 index:logstash-2015.09.22 @timestamp:September 22nd 2015, 23:50:13.253'
|
||||
+ ' ip:238.171.34.42 extension:jpg response:200 geo.coordinates:{ "lat": 38.66494528, "lon": -88.45299556'
|
||||
+ ' } geo.src:FR geo.dest:KH geo.srcdest:FR:KH @tags:success, info utc_time:September 22nd 2015,'
|
||||
+ ' 23:50:13.253 referer:http://twitter.com/success/nancy-currie agent:Mozilla/4.0 (compatible; MSIE 6.0;'
|
||||
+ ' Windows NT 5.1; SV1; .NET CLR 1.1.4322) clientip:238.171.34.42 bytes:7,124'
|
||||
+ ' host:media-for-the-masses.theacademyofperformingartsandscience.org request:/uploads/karl-henize.jpg'
|
||||
+ ' url:https://media-for-the-masses.theacademyofperformingartsandscience.org/uploads/karl-henize.jpg'
|
||||
+ ' @message:238.171.34.42 - - [2015-09-22T23:50:13.253Z] "GET /uploads/karl-henize.jpg HTTP/1.1" 200 7124'
|
||||
+ ' "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" spaces:this is a'
|
||||
+ ' thing with lots of spaces wwwwoooooo xss:<script>console.log("xss")</script>'
|
||||
+ ' headings:<h3>alexander-viktorenko</h5>, http://nytimes.com/warning/michael-massimino'
|
||||
+ ' links:@www.slate.com, http://www.slate.com/security/frederick-w-leslie, www.www.slate.com'
|
||||
+ ' relatedContent:{ "url": "http://www.laweekly.com/music/bjork-at-the-nokia-theatre-12-12-2408191",'
|
||||
+ ' "og:type": "article", "og:title": "Bjork at the Nokia Theatre, 12/12", "og:description": "Bjork at the'
|
||||
+ ' Nokia Theater, December 12 By Randall Roberts Last night’s Bjork show at the Dystopia –'
|
||||
+ ' er, I mean Nokia -- Theatre downtown di...", "og:url": "'
|
||||
+ 'http://www.laweekly.com/music/bjork-at-the-nokia-theatre-12-12-2408191", "article:published_time":'
|
||||
+ ' "2007-12-13T12:19:35-08:00", "article:modified_time": "2014-11-27T08:28:42-08:00", "article:section":'
|
||||
+ ' "Music", "og:image": "'
|
||||
+ 'http://IMAGES1.laweekly.com/imager/bjork-at-the-nokia-theatre-12-12/u/original/2470701/bjorktn003.jpg",'
|
||||
+ ' "og:image:height": "334", "og:image:width": "480", "og:site_name": "LA Weekly", "twitter:title":'
|
||||
+ ' "Bjork at the Nokia Theatre, 12/12", "twitter:description": "Bjork at the Nokia Theater, December 12'
|
||||
+ ' By Randall Roberts Last night’s Bjork show at the Dystopia – er, I mean Nokia -- Theatre'
|
||||
+ ' downtown di...", "twitter:card": "summary", "twitter:image": "'
|
||||
+ 'http://IMAGES1.laweekly.com/imager/bjork-at-the-nokia-theatre-12-12/u/original/2470701/bjorktn003.jpg",'
|
||||
+ ' "twitter:site": "@laweekly" }, { "url": "'
|
||||
+ 'http://www.laweekly.com/music/the-rapture-at-the-mayan-7-25-2401011", "og:type": "article", "og:title":'
|
||||
+ ' "The Rapture at the Mayan, 7/25", "og:description": "If you haven’t yet experienced the'
|
||||
+ ' phenomenon of people walk-dancing, apparently the best place to witness this is at a Rapture show.'
|
||||
+ ' Here’s...", "og:url": "http://www.laweekly.com/music/the-rapture-at-the-mayan-7-25-2401011",'
|
||||
+ ' "article:published_time": "2007-07-26T12:42:30-07:00", "article:modified_time":'
|
||||
+ ' "2014-11-27T08:00:51-08:00", "article:section": "Music", "og:image": "'
|
||||
+ 'http://IMAGES1.laweekly.com/imager/the-rapture-at-the-mayan-7-25/u/original/2463272/rapturetn05.jpg",'
|
||||
+ ' "og:image:height": "321", "og:image:width": "480", "og:site_name": "LA Weekly", "twitter:title": "The'
|
||||
+ ' Rapture at the Mayan, 7/25", "twitter:description": "If you haven’t yet experienced the'
|
||||
+ ' phenomenon of people walk-dancing, apparently the best place to witness this is at a Rapture show.'
|
||||
+ ' Here’s...", "twitter:card": "summary", "twitter:image": "'
|
||||
+ 'http://IMAGES1.laweekly.com/imager/the-rapture-at-the-mayan-7-25/u/original/2463272/rapturetn05.jpg",'
|
||||
+ ' "twitter:site": "@laweekly" } machine.os:win 7 machine.ram:7,516,192,768 _id:AU_x3_g4GFA8no6QjkYX'
|
||||
+ ' _type:apache _index:logstash-2015.09.22 _score: relatedContent.article:modified_time:November 27th'
|
||||
+ ' 2014, 16:00:51.000, November 27th 2014, 16:28:42.000 relatedContent.article:published_time:July 26th'
|
||||
+ ' 2007, 19:42:30.000, December 13th 2007, 20:19:35.000';
|
||||
return discoverPage.getDocTableIndex(1)
|
||||
.then(function (rowData) {
|
||||
expect(rowData).to.be(ExpectedDoc);
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('doc view should sort ascending', function () {
|
||||
// Note: Could just check the timestamp, but might as well check that the whole doc is as expected.
|
||||
var ExpectedDoc =
|
||||
'September 20th 2015, 00:00:00.000 index:logstash-2015.09.20 @timestamp:September 20th 2015, 00:00:00.000'
|
||||
+ ' ip:143.84.142.7 extension:jpg response:200 geo.coordinates:{ "lat": 38.68407028, "lon": -120.9871642 }'
|
||||
+ ' geo.src:ES geo.dest:US geo.srcdest:ES:US @tags:error, info utc_time:September 20th 2015, 00:00:00.000'
|
||||
+ ' referer:http://www.slate.com/success/vladimir-kovalyonok agent:Mozilla/4.0 (compatible; MSIE 6.0;'
|
||||
+ ' Windows NT 5.1; SV1; .NET CLR 1.1.4322) clientip:143.84.142.7 bytes:1,623'
|
||||
+ ' host:media-for-the-masses.theacademyofperformingartsandscience.org request:/uploads/steven-hawley.jpg'
|
||||
+ ' url:https://media-for-the-masses.theacademyofperformingartsandscience.org/uploads/steven-hawley.jpg'
|
||||
+ ' @message:143.84.142.7 - - [2015-09-20T00:00:00.000Z] "GET /uploads/steven-hawley.jpg HTTP/1.1" 200'
|
||||
+ ' 1623 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" spaces:this is a'
|
||||
+ ' thing with lots of spaces wwwwoooooo xss:<script>console.log("xss")</script>'
|
||||
+ ' headings:<h3>kimiya-yui</h5>, http://www.slate.com/success/koichi-wakata'
|
||||
+ ' links:thomas-marshburn@twitter.com, http://www.slate.com/info/michael-p-anderson, www.twitter.com'
|
||||
+ ' relatedContent:{ "url":'
|
||||
+ ' "http://www.laweekly.com/music/jay-electronica-much-better-than-his-name-would-suggest-2412364",'
|
||||
+ ' "og:type": "article", "og:title": "Jay Electronica: Much Better Than His Name Would Suggest",'
|
||||
+ ' "og:description": "You may not know who Jay Electronica is yet, but I'm willing to bet that you'
|
||||
+ ' would had he chosen a better name. Jay Electronica does not sound like the ...", "og:url":'
|
||||
+ ' "http://www.laweekly.com/music/jay-electronica-much-better-than-his-name-would-suggest-2412364",'
|
||||
+ ' "article:published_time": "2008-04-04T16:00:00-07:00", "article:modified_time":'
|
||||
+ ' "2014-11-27T08:01:03-08:00", "article:section": "Music", "og:site_name": "LA Weekly", "twitter:title":'
|
||||
+ ' "Jay Electronica: Much Better Than His Name Would Suggest", "twitter:description": "You may not know'
|
||||
+ ' who Jay Electronica is yet, but I'm willing to bet that you would had he chosen a better name.'
|
||||
+ ' Jay Electronica does not sound like the ...", "twitter:card": "summary", "twitter:site": "@laweekly"'
|
||||
+ ' }, { "url": "http://www.laweekly.com/news/mandoe-on-gower-near-fountain-2368123", "og:type":'
|
||||
+ ' "article", "og:title": "MANDOE On Gower Near Fountain", "og:description": "MANDOE has a stunner on a'
|
||||
+ ' wall north of an east-west street crossing Gower around Fountain (but not on Fountain). MADNOE, PROSE'
|
||||
+ ' and FUKM are listed on t...", "og:url": "'
|
||||
+ 'http://www.laweekly.com/news/mandoe-on-gower-near-fountain-2368123", "article:published_time":'
|
||||
+ ' "2008-04-25T07:26:41-07:00", "article:modified_time": "2014-10-28T15:00:08-07:00", "article:section":'
|
||||
+ ' "News", "og:image": "'
|
||||
+ 'http://images1.laweekly.com/imager/mandoe-on-gower-near-fountain/u/original/2430891/img_6648.jpg",'
|
||||
+ ' "og:image:height": "640", "og:image:width": "480", "og:site_name": "LA Weekly", "twitter:title": '
|
||||
+ '"MANDOE On Gower Near Fountain", "twitter:description": "MANDOE has a stunner on a wall north of an'
|
||||
+ ' east-west street crossing Gower around Fountain (but not on Fountain). MADNOE, PROSE and FUKM are'
|
||||
+ ' listed on t...", "twitter:card": "summary", "twitter:image": "'
|
||||
+ 'http://images1.laweekly.com/imager/mandoe-on-gower-near-fountain/u/original/2430891/img_6648.jpg", '
|
||||
+ '"twitter:site": "@laweekly" }, { "url": "http://www.laweekly.com/arts/meghan-finds-the-love-2373346",'
|
||||
+ ' "og:type": "article", "og:title": "Meghan Finds The Love", "og:description": "LA Weekly is the'
|
||||
+ ' definitive source of information for news, music, movies, restaurants, reviews, and events in Los'
|
||||
+ ' Angeles.", "og:url": "http://www.laweekly.com/arts/meghan-finds-the-love-2373346",'
|
||||
+ ' "article:published_time": "2005-10-20T18:10:25-07:00", "article:modified_time":'
|
||||
+ ' "2014-11-25T19:52:35-08:00", "article:section": "Arts", "og:site_name": "LA Weekly", "twitter:title":'
|
||||
+ ' "Meghan Finds The Love", "twitter:description": "LA Weekly is the definitive source of information for'
|
||||
+ ' news, music, movies, restaurants, reviews, and events in Los Angeles.", "twitter:card": "summary",'
|
||||
+ ' "twitter:site": "@laweekly" }, { "url": "http://www.laweekly.com/arts/these-clowns-are-with-me-2371051'
|
||||
+ '", "og:type": "article", "og:title": "These Clowns Are With Me", "og:description": " I'
|
||||
+ ' didn't mean to blow off all my responsibilities yesterday, but when a schmoozy Hollywood luncheon'
|
||||
+ ' turns into a full-on party by 3pm, and...", "og:url": "'
|
||||
+ 'http://www.laweekly.com/arts/these-clowns-are-with-me-2371051", "article:published_time": '
|
||||
+ '"2006-03-04T17:03:42-08:00", "article:modified_time": "2014-11-25T17:05:47-08:00", "article:section":'
|
||||
+ ' "Arts", "og:image": "'
|
||||
+ 'http://images1.laweekly.com/imager/these-clowns-are-with-me/u/original/2434556/e4b8scd.jpg",'
|
||||
+ ' "og:image:height": "375", "og:image:width": "500", "og:site_name": "LA Weekly", "twitter:title":'
|
||||
+ ' "These Clowns Are With Me", "twitter:description": " I didn't mean to blow off all'
|
||||
+ ' my responsibilities yesterday, but when a schmoozy Hollywood luncheon turns into a full-on party by'
|
||||
+ ' 3pm, and...", "twitter:card": "summary", "twitter:image": "'
|
||||
+ 'http://images1.laweekly.com/imager/these-clowns-are-with-me/u/original/2434556/e4b8scd.jpg",'
|
||||
+ ' "twitter:site": "@laweekly" }, { "url": "http://www.laweekly.com/arts/shopping-daze-2373807",'
|
||||
+ ' "og:type": "article", "og:title": "Shopping Daze", "og:description": "LA Weekly is the definitive '
|
||||
+ 'source of information for news, music, movies, restaurants, reviews, and events in Los Angeles.",'
|
||||
+ ' "og:url": "http://www.laweekly.com/arts/shopping-daze-2373807", "article:published_time":'
|
||||
+ ' "2006-12-13T12:12:04-08:00", "article:modified_time": "2014-11-25T20:15:21-08:00", "article:section":'
|
||||
+ ' "Arts", "og:site_name": "LA Weekly", "twitter:title": "Shopping Daze", "twitter:description": "LA'
|
||||
+ ' Weekly is the definitive source of information for news, music, movies, restaurants, reviews, and'
|
||||
+ ' events in Los Angeles.", "twitter:card": "summary", "twitter:site": "@laweekly" } machine.os:osx'
|
||||
+ ' machine.ram:15,032,385,536 _id:AU_x3_g3GFA8no6QjkFm _type:apache _index:logstash-2015.09.20 _score:'
|
||||
+ ' relatedContent.article:modified_time:October 28th 2014, 22:00:08.000, November 26th 2014,'
|
||||
+ ' 01:05:47.000, November 26th 2014, 03:52:35.000, November 26th 2014, 04:15:21.000, November 27th 2014,'
|
||||
+ ' 16:01:03.000 relatedContent.article:published_time:October 21st 2005, 01:10:25.000, March 5th 2006,'
|
||||
+ ' 01:03:42.000, December 13th 2006, 20:12:04.000, April 4th 2008, 23:00:00.000, April 25th 2008,'
|
||||
+ ' 14:26:41.000';
|
||||
return discoverPage.clickDocSortDown()
|
||||
.then(function () {
|
||||
// we don't technically need this sleep here because the tryForTime will retry and the
|
||||
// results will match on the 2nd or 3rd attempt, but that debug output is huge in this
|
||||
// case and it can be avoided with just a few seconds sleep.
|
||||
return common.sleep(2000);
|
||||
})
|
||||
.then(function () {
|
||||
return common.tryForTime(20 * 1000, function tryingForTime() {
|
||||
return discoverPage.getDocTableIndex(1)
|
||||
.then(function (rowData) {
|
||||
expect(rowData).to.be(ExpectedDoc);
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
|
||||
bdd.it('a bad syntax query should show an error message', function () {
|
||||
var expectedHitCount = '1011,156';
|
||||
var expectedError = 'Discover: Failed to parse query [xxx(yyy]';
|
||||
return discoverPage.query('xxx(yyy')
|
||||
.then(function () {
|
||||
return headerPage.getToastMessage();
|
||||
})
|
||||
.then(function (toastMessage) {
|
||||
expect(toastMessage).to.be(expectedError);
|
||||
})
|
||||
.then(function () {
|
||||
return headerPage.clickToastOK();
|
||||
})
|
||||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
|
@ -4,6 +4,7 @@ define(function (require) {
|
|||
var url = require('intern/dojo/node!url');
|
||||
var ScenarioManager = require('intern/dojo/node!../../../fixtures/scenarioManager');
|
||||
var discoverTest = require('./_discover');
|
||||
var fieldData = require('./_field_data');
|
||||
|
||||
bdd.describe('discover app', function () {
|
||||
var scenarioManager;
|
||||
|
@ -22,5 +23,7 @@ define(function (require) {
|
|||
|
||||
discoverTest(bdd, scenarioManager);
|
||||
|
||||
fieldData(bdd, scenarioManager);
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
var shield = require('./shield');
|
||||
|
||||
var kibanaURL = '/app/kibana';
|
||||
|
||||
module.exports = {
|
||||
|
@ -11,13 +13,13 @@ module.exports = {
|
|||
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: 'user:notsecure'
|
||||
auth: shield.kibanaUser.username + ':' + 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: 'admin:notsecure'
|
||||
auth: shield.admin.username + ':' + shield.admin.password
|
||||
}
|
||||
},
|
||||
apps: {
|
||||
|
|
16
test/shield.js
Normal file
16
test/shield.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
const env = process.env;
|
||||
|
||||
exports.kibanaUser = {
|
||||
username: env.SHIELD_KIBANA_USER || 'user',
|
||||
password: env.SHIELD_KIBANA_USER_PASS || 'notsecure'
|
||||
};
|
||||
|
||||
exports.kibanaServer = {
|
||||
username: env.SHIELD_KIBANA_SERVER || 'kibana',
|
||||
password: env.SHIELD_KIBANA_SERVER_PASS || 'notsecure'
|
||||
};
|
||||
|
||||
exports.admin = {
|
||||
username: env.SHIELD_ADMIN || 'admin',
|
||||
password: env.SHIELD_ADMIN_PASS || 'notsecure'
|
||||
};
|
|
@ -32,6 +32,12 @@ define(function (require) {
|
|||
.getVisibleText();
|
||||
},
|
||||
|
||||
getChartTimespan: function getChartTimespan() {
|
||||
return thisTime
|
||||
.findByCssSelector('center.small > span:nth-child(1)')
|
||||
.getVisibleText();
|
||||
},
|
||||
|
||||
saveSearch: function saveSearch(searchName) {
|
||||
var self = this;
|
||||
return self.clickSaveSearchButton()
|
||||
|
@ -85,7 +91,6 @@ define(function (require) {
|
|||
},
|
||||
|
||||
getBarChartData: function getBarChartData() {
|
||||
common.debug('in getBarChartData');
|
||||
return thisTime
|
||||
.findAllByCssSelector('rect[data-label="Count"]')
|
||||
.then(function (chartData) {
|
||||
|
@ -101,6 +106,75 @@ define(function (require) {
|
|||
.then(function (bars) {
|
||||
return bars;
|
||||
});
|
||||
},
|
||||
|
||||
getChartInterval: function getChartInterval() {
|
||||
return thisTime
|
||||
.findByCssSelector('span.results-interval:nth-child(2) > a:nth-child(1)')
|
||||
.getVisibleText();
|
||||
},
|
||||
|
||||
setChartInterval: function setChartInterval(interval) {
|
||||
return thisTime
|
||||
.findByCssSelector('span.results-interval:nth-child(2) > a:nth-child(1)')
|
||||
.click()
|
||||
.catch(function () {
|
||||
// in some cases we have the link above, but after we've made a
|
||||
// selection we just have a select list.
|
||||
})
|
||||
.then(function () {
|
||||
return thisTime
|
||||
.findByCssSelector('option[label="' + interval + '"]')
|
||||
.click();
|
||||
});
|
||||
},
|
||||
|
||||
getHitCount: function getHitCount() {
|
||||
return thisTime
|
||||
.findByCssSelector('strong.discover-info-hits')
|
||||
.getVisibleText();
|
||||
},
|
||||
|
||||
query: function query(queryString) {
|
||||
return thisTime
|
||||
.findByCssSelector('input[aria-label="Search input"]')
|
||||
.clearValue()
|
||||
.type(queryString)
|
||||
.then(function () {
|
||||
return thisTime
|
||||
.findByCssSelector('button[aria-label="Search"]')
|
||||
.click();
|
||||
});
|
||||
},
|
||||
|
||||
getDocHeader: function getDocHeader() {
|
||||
return thisTime
|
||||
.findByCssSelector('thead.ng-isolate-scope > tr:nth-child(1)')
|
||||
.getVisibleText();
|
||||
},
|
||||
|
||||
getDocTableIndex: function getDocTableIndex(index) {
|
||||
return thisTime
|
||||
.findByCssSelector('tr.discover-table-row:nth-child(' + (index) + ')')
|
||||
.getVisibleText();
|
||||
},
|
||||
|
||||
clickDocSortDown: function clickDocSortDown() {
|
||||
return thisTime
|
||||
.findByCssSelector('.fa-sort-down')
|
||||
.click();
|
||||
},
|
||||
|
||||
clickDocSortUp: function clickDocSortUp() {
|
||||
return thisTime
|
||||
.findByCssSelector('.fa-sort-up')
|
||||
.click();
|
||||
},
|
||||
|
||||
getMarks: function getMarks() {
|
||||
return thisTime
|
||||
.findAllByCssSelector('mark')
|
||||
.getVisibleText();
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -137,6 +137,13 @@ define(function (require) {
|
|||
});
|
||||
},
|
||||
|
||||
clickToastOK: function clickToastOK() {
|
||||
return this.remote
|
||||
.setFindTimeout(defaultTimeout)
|
||||
.findByCssSelector('button[ng-if="notif.accept"]')
|
||||
.click();
|
||||
},
|
||||
|
||||
getSpinnerDone: function getSpinnerDone() {
|
||||
var self = this;
|
||||
return this.remote
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { defaultsDeep, set } from 'lodash';
|
||||
import requirefrom from 'requirefrom';
|
||||
import { header as basicAuthHeader } from './base_auth';
|
||||
import { kibanaUser, kibanaServer } from '../shield';
|
||||
|
||||
const src = requirefrom('src');
|
||||
const KbnServer = src('server/KbnServer');
|
||||
|
@ -26,8 +27,8 @@ const SERVER_DEFAULTS = {
|
|||
},
|
||||
elasticsearch: {
|
||||
url: 'http://localhost:9210',
|
||||
username: 'kibana',
|
||||
password: 'notsecure'
|
||||
username: kibanaServer.username,
|
||||
password: kibanaServer.password
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -46,7 +47,8 @@ export function createServer(params = {}) {
|
|||
* Creates request configuration with a basic auth header
|
||||
*/
|
||||
export function authOptions() {
|
||||
const authHeader = basicAuthHeader('user', 'notsecure');
|
||||
const { username, password } = kibanaUser;
|
||||
const authHeader = basicAuthHeader(username, password);
|
||||
return set({}, 'headers.Authorization', authHeader);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue