diff --git a/README.md b/README.md index ac077c92a2eb..a30b031815eb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Kibana 4.4.0-snapshot +# Kibana 5.0.0-snapshot [![Build Status](https://travis-ci.org/elastic/kibana.svg?branch=master)](https://travis-ci.org/elastic/kibana?branch=master) @@ -37,7 +37,7 @@ For the daring, snapshot builds are available. These builds are created after ea | platform | | | | --- | --- | --- | -| OSX | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-4.4.0-snapshot-darwin-x64.tar.gz) | [zip](http://download.elastic.co/kibana/kibana-snapshot/kibana-4.4.0-snapshot-darwin-x64.zip) | -| Linux x64 | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-4.4.0-snapshot-linux-x64.tar.gz) | [zip](http://download.elastic.co/kibana/kibana-snapshot/kibana-4.4.0-snapshot-linux-x64.zip) | -| Linux x86 | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-4.4.0-snapshot-linux-x86.tar.gz) | [zip](http://download.elastic.co/kibana/kibana-snapshot/kibana-4.4.0-snapshot-linux-x86.zip) | -| Windows | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-4.4.0-snapshot-windows.tar.gz) | [zip](http://download.elastic.co/kibana/kibana-snapshot/kibana-4.4.0-snapshot-windows.zip) | +| OSX | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-snapshot-darwin-x64.tar.gz) | [zip](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-snapshot-darwin-x64.zip) | +| Linux x64 | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-snapshot-linux-x64.tar.gz) | [zip](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-snapshot-linux-x64.zip) | +| Linux x86 | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-snapshot-linux-x86.tar.gz) | [zip](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-snapshot-linux-x86.zip) | +| Windows | [tar](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-snapshot-windows.tar.gz) | [zip](http://download.elastic.co/kibana/kibana-snapshot/kibana-5.0.0-snapshot-windows.zip) | diff --git a/package.json b/package.json index 82d78b030057..9a71d138a483 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "dashboarding" ], "private": false, - "version": "4.4.0-snapshot", + "version": "5.0.0-snapshot", "build": { "number": 8467, "sha": "6cb7fec4e154faa0a4a3fee4b33dfef91b9870d9" diff --git a/src/plugins/kibana/public/discover/controllers/discover.js b/src/plugins/kibana/public/discover/controllers/discover.js index f144362cd7a8..88b40cd678f5 100644 --- a/src/plugins/kibana/public/discover/controllers/discover.js +++ b/src/plugins/kibana/public/discover/controllers/discover.js @@ -191,6 +191,9 @@ define(function (require) { }); $scope.$watch('vis.aggs', function () { + // no timefield, no vis, nothing to update + if (!$scope.opts.timefield) return; + var buckets = $scope.vis.aggs.bySchemaGroup.buckets; if (buckets && buckets.length === 1) { diff --git a/src/ui/public/courier/__tests__/requestQueue.js b/src/ui/public/courier/__tests__/requestQueue.js new file mode 100644 index 000000000000..723f0f016ccd --- /dev/null +++ b/src/ui/public/courier/__tests__/requestQueue.js @@ -0,0 +1,92 @@ +import ngMock from 'ngMock'; +import expect from 'expect.js'; +import sinon from 'auto-release-sinon'; + +import RequestQueueProv from '../_request_queue'; +import SearchStrategyProv from '../fetch/strategy/search'; +import DocStrategyProv from '../fetch/strategy/doc'; + +describe('Courier Request Queue', function () { + let docStrategy; + let requestQueue; + let searchStrategy; + + beforeEach(ngMock.module('kibana')); + beforeEach(ngMock.inject(function (Private) { + docStrategy = Private(DocStrategyProv); + requestQueue = Private(RequestQueueProv); + searchStrategy = Private(SearchStrategyProv); + })); + + class MockReq { + constructor(strategy, startable = true) { + this.strategy = strategy; + this.source = {}; + this.canStart = sinon.stub().returns(startable); + } + } + + describe('#getStartable(strategy)', function () { + it('only returns requests that match one of the passed strategies', function () { + requestQueue.push( + new MockReq(docStrategy), + new MockReq(searchStrategy), + new MockReq(searchStrategy), + new MockReq(searchStrategy) + ); + + expect(requestQueue.getStartable(docStrategy)).to.have.length(1); + expect(requestQueue.getStartable(searchStrategy)).to.have.length(3); + }); + + it('returns all requests when no strategy passed', function () { + requestQueue.push( + new MockReq(docStrategy), + new MockReq(searchStrategy) + ); + + expect(requestQueue.getStartable()).to.have.length(2); + }); + + it('returns only startable requests', function () { + requestQueue.push( + new MockReq(docStrategy, true), + new MockReq(searchStrategy, false) + ); + + expect(requestQueue.getStartable()).to.have.length(1); + }); + }); + + describe('#get(strategy)', function () { + it('only returns requests that match one of the passed strategies', function () { + requestQueue.push( + new MockReq(docStrategy), + new MockReq(searchStrategy), + new MockReq(searchStrategy), + new MockReq(searchStrategy) + ); + + expect(requestQueue.get(docStrategy)).to.have.length(1); + expect(requestQueue.get(searchStrategy)).to.have.length(3); + }); + + it('returns all requests when no strategy passed', function () { + requestQueue.push( + new MockReq(docStrategy), + new MockReq(searchStrategy) + ); + + expect(requestQueue.get()).to.have.length(2); + }); + + it('returns startable and not-startable requests', function () { + requestQueue.push( + new MockReq(docStrategy, true), + new MockReq(searchStrategy, false) + ); + + expect(requestQueue.get()).to.have.length(2); + }); + }); +}); diff --git a/src/ui/public/courier/_request_queue.js b/src/ui/public/courier/_request_queue.js index ca8ce4ad793b..e6dcf78957c6 100644 --- a/src/ui/public/courier/_request_queue.js +++ b/src/ui/public/courier/_request_queue.js @@ -16,8 +16,11 @@ define(function (require) { }); }; - queue.get = function (/* strategies.. */) { - var strategies = _.toArray(arguments); + queue.getStartable = function (...strategies) { + return queue.get(...strategies).filter(req => req.canStart()); + }; + + queue.get = function (...strategies) { return queue.filter(function (req) { var strategyMatch = !strategies.length; if (!strategyMatch) { @@ -26,7 +29,7 @@ define(function (require) { }); } - return strategyMatch && req.canStart(); + return strategyMatch; }); }; diff --git a/src/ui/public/courier/data_source/__tests__/DocSource.js b/src/ui/public/courier/data_source/__tests__/DocSource.js new file mode 100644 index 000000000000..6ff86a2c80c0 --- /dev/null +++ b/src/ui/public/courier/data_source/__tests__/DocSource.js @@ -0,0 +1,59 @@ +import ngMock from 'ngMock'; +import expect from 'expect.js'; +import sinon from 'auto-release-sinon'; + +import RequestQueueProv from '../../_request_queue'; +import DocSourceProv from '../doc_source'; + +describe('DocSource', function () { + require('testUtils/noDigestPromises').activateForSuite(); + + let requestQueue; + let DocSource; + + beforeEach(ngMock.module('kibana')); + beforeEach(ngMock.inject(function (Private) { + requestQueue = Private(RequestQueueProv); + DocSource = Private(DocSourceProv); + })); + + describe('#onUpdate()', function () { + it('adds a request to the requestQueue', function () { + const source = new DocSource(); + + expect(requestQueue).to.have.length(0); + source.onUpdate(); + expect(requestQueue).to.have.length(1); + }); + + it('returns a promise that is resolved with the results', function () { + const source = new DocSource(); + const fakeResults = {}; + + const promise = source.onUpdate().then((results) => { + expect(results).to.be(fakeResults); + }); + + requestQueue[0].defer.resolve(fakeResults); + return promise; + }); + }); + + describe('#destroy()', function () { + it('aborts all startable requests', function () { + const source = new DocSource(); + source.onUpdate(); + sinon.stub(requestQueue[0], 'canStart').returns(true); + source.destroy(); + expect(requestQueue).to.have.length(0); + }); + + it('aborts all non-startable requests', function () { + const source = new DocSource(); + source.onUpdate(); + sinon.stub(requestQueue[0], 'canStart').returns(false); + source.destroy(); + expect(requestQueue).to.have.length(0); + }); + }); +}); diff --git a/src/ui/public/courier/data_source/__tests__/SearchSource.js b/src/ui/public/courier/data_source/__tests__/SearchSource.js new file mode 100644 index 000000000000..02f4f73d2aa2 --- /dev/null +++ b/src/ui/public/courier/data_source/__tests__/SearchSource.js @@ -0,0 +1,59 @@ +import ngMock from 'ngMock'; +import expect from 'expect.js'; +import sinon from 'auto-release-sinon'; + +import RequestQueueProv from '../../_request_queue'; +import SearchSourceProv from '../search_source'; + +describe('SearchSource', function () { + require('testUtils/noDigestPromises').activateForSuite(); + + let requestQueue; + let SearchSource; + + beforeEach(ngMock.module('kibana')); + beforeEach(ngMock.inject(function (Private) { + requestQueue = Private(RequestQueueProv); + SearchSource = Private(SearchSourceProv); + })); + + describe('#onResults()', function () { + it('adds a request to the requestQueue', function () { + const source = new SearchSource(); + + expect(requestQueue).to.have.length(0); + source.onResults(); + expect(requestQueue).to.have.length(1); + }); + + it('returns a promise that is resolved with the results', function () { + const source = new SearchSource(); + const fakeResults = {}; + + const promise = source.onResults().then((results) => { + expect(results).to.be(fakeResults); + }); + + requestQueue[0].defer.resolve(fakeResults); + return promise; + }); + }); + + describe('#destroy()', function () { + it('aborts all startable requests', function () { + const source = new SearchSource(); + source.onResults(); + sinon.stub(requestQueue[0], 'canStart').returns(true); + source.destroy(); + expect(requestQueue).to.have.length(0); + }); + + it('aborts all non-startable requests', function () { + const source = new SearchSource(); + source.onResults(); + sinon.stub(requestQueue[0], 'canStart').returns(false); + source.destroy(); + expect(requestQueue).to.have.length(0); + }); + }); +}); diff --git a/src/ui/public/courier/data_source/_abstract.js b/src/ui/public/courier/data_source/_abstract.js index e7692d088d38..f66996048e1c 100644 --- a/src/ui/public/courier/data_source/_abstract.js +++ b/src/ui/public/courier/data_source/_abstract.js @@ -167,7 +167,7 @@ define(function (require) { */ SourceAbstract.prototype.fetch = function () { var self = this; - var req = _.first(self._myQueued()); + var req = _.first(self._myStartableQueued()); if (!req) { req = self._createRequest(); @@ -183,7 +183,7 @@ define(function (require) { * @async */ SourceAbstract.prototype.fetchQueued = function () { - return courierFetch.these(this._myQueued()); + return courierFetch.these(this._myStartableQueued()); }; /** @@ -191,7 +191,10 @@ define(function (require) { * @return {undefined} */ SourceAbstract.prototype.cancelQueued = function () { - _.invoke(this._myQueued(), 'abort'); + requestQueue + .get(this._fetchStrategy) + .filter(req => req.source === this) + .forEach(req => req.abort()); }; /** @@ -206,9 +209,10 @@ define(function (require) { * PRIVATE API *****/ - SourceAbstract.prototype._myQueued = function () { - var reqs = requestQueue.get(this._fetchStrategy); - return _.where(reqs, { source: this }); + SourceAbstract.prototype._myStartableQueued = function () { + return requestQueue + .getStartable(this._fetchStrategy) + .filter(req => req.source === this); }; SourceAbstract.prototype._createRequest = function () { diff --git a/src/ui/public/courier/fetch/fetch.js b/src/ui/public/courier/fetch/fetch.js index 03ce8199aa43..adf1871bb425 100644 --- a/src/ui/public/courier/fetch/fetch.js +++ b/src/ui/public/courier/fetch/fetch.js @@ -9,7 +9,7 @@ define(function (require) { var INCOMPLETE = Private(require('ui/courier/fetch/_req_status')).INCOMPLETE; function fetchQueued(strategy) { - var requests = requestQueue.get(strategy); + var requests = requestQueue.getStartable(strategy); if (!requests.length) return Promise.resolve(); else return fetchThese(requests); } diff --git a/src/ui/public/courier/fetch/request/segmented.js b/src/ui/public/courier/fetch/request/segmented.js index 8289c16d1b97..a2291b3b99c6 100644 --- a/src/ui/public/courier/fetch/request/segmented.js +++ b/src/ui/public/courier/fetch/request/segmented.js @@ -2,7 +2,6 @@ define(function (require) { return function CourierSegmentedReqProvider(es, Private, Promise, Notifier, timefilter, config) { var _ = require('lodash'); var SearchReq = Private(require('ui/courier/fetch/request/search')); - var requestQueue = Private(require('ui/courier/_request_queue')); var SegmentedHandle = Private(require('ui/courier/fetch/request/_segmented_handle')); var notify = new Notifier({ diff --git a/test/fixtures/scenarioManager.js b/test/fixtures/scenarioManager.js index 84376c0f70ca..bc5c8dc59071 100644 --- a/test/fixtures/scenarioManager.js +++ b/test/fixtures/scenarioManager.js @@ -60,6 +60,7 @@ ScenarioManager.prototype.unload = function (id) { return bulk.indexName; }); + console.log('DELETING INDEX: ' + indices); return this.client.indices.delete({ index: indices }) diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js index ef7c264cc1dc..6e3797a64e88 100644 --- a/test/functional/apps/discover/_discover.js +++ b/test/functional/apps/discover/_discover.js @@ -85,12 +85,10 @@ define(function (require) { bdd.it('load query should show query name', function () { return discoverPage.loadSavedSearch(queryName1) .then(function () { - return common.tryForTime(15000, function () { - return discoverPage.getCurrentQueryName() - .then(function (actualQueryNameString) { - expect(actualQueryNameString).to.be(queryName1); - }); - }); + return discoverPage.getCurrentQueryName(); + }) + .then(function (actualQueryNameString) { + expect(actualQueryNameString).to.be(queryName1); }) .catch(common.handleError(this)); }); diff --git a/test/functional/apps/settings/_index_pattern_results_sort.js b/test/functional/apps/settings/_index_pattern_results_sort.js index be1167b8fa85..72d7474356fe 100644 --- a/test/functional/apps/settings/_index_pattern_results_sort.js +++ b/test/functional/apps/settings/_index_pattern_results_sort.js @@ -1,4 +1,5 @@ define(function (require) { + var config = require('intern').config; var Common = require('../../../support/pages/Common'); var SettingsPage = require('../../../support/pages/SettingsPage'); var expect = require('intern/dojo/node!expect.js'); @@ -9,7 +10,7 @@ define(function (require) { var common; var settingsPage; var remote; - var longTimeout = 60000; + var defaultTimeout = config.timeouts.default; bdd.before(function () { common = new Common(this.remote); @@ -94,7 +95,7 @@ define(function (require) { }); bdd.it('makelogs data should have expected number of fields', function () { - return common.tryForTime(longTimeout, function () { + return common.tryForTime(defaultTimeout, function () { return settingsPage.getFieldsTabCount() .then(function (tabCount) { expect(tabCount).to.be('' + expectedFieldCount); diff --git a/test/functional/apps/visualize/_area_chart.js b/test/functional/apps/visualize/_area_chart.js index 24492be32f01..0a955c0df586 100644 --- a/test/functional/apps/visualize/_area_chart.js +++ b/test/functional/apps/visualize/_area_chart.js @@ -177,30 +177,8 @@ define(function (require) { '2015-09-22 00:00', '2015-09-23 00:00' ]; var yAxisLabels = ['0','200','400','600','800','1,000','1,200','1,400','1,600']; - var expectedAreaChartData = [37, - 202, - 740, - 1437, - 1371, - 751, - 188, - 31, - 42, - 202, - 683, - 1361, - 1415, - 707, - 177, - 27, - 32, - 175, - 707, - 1408, - 1355, - 726, - 201, - 29 + var expectedAreaChartData = [37, 202, 740, 1437, 1371, 751, 188, 31, 42, 202, + 683, 1361, 1415, 707, 177, 27, 32, 175, 707, 1408, 1355, 726, 201, 29 ]; return visualizePage.getXAxisLabels() diff --git a/test/functional/apps/visualize/index.js b/test/functional/apps/visualize/index.js index 83e9d27ba2f9..7d184cb5a52b 100644 --- a/test/functional/apps/visualize/index.js +++ b/test/functional/apps/visualize/index.js @@ -36,14 +36,10 @@ define(function (require) { }); bdd.before(function () { - common.debug('running bdd.beforeEach'); + common.debug('running bdd.before'); this.timeout = 120000; return remote.setWindowSize(1200,800) - .then(function () { - // start each test with an empty kibana index - return scenarioManager.reload('emptyKibana'); - }) - // and load a minimal set of makelogs data + // load a minimal set of makelogs data .then(function loadIfEmptyMakelogs() { return scenarioManager.loadIfEmpty('logstashFunctional'); }); diff --git a/test/intern.js b/test/intern.js index 12db28ffc11b..870375644324 100644 --- a/test/intern.js +++ b/test/intern.js @@ -24,6 +24,9 @@ define(function (require) { 'bluebird': './node_modules/bluebird/js/browser/bluebird.js', 'moment': './node_modules/moment/moment.js' } - } + }, + timeouts: { + default: 90000 + }, }, serverConfig); }); diff --git a/test/support/pages/Common.js b/test/support/pages/Common.js index b3dfa630f77b..7ce47eb37be2 100644 --- a/test/support/pages/Common.js +++ b/test/support/pages/Common.js @@ -11,7 +11,7 @@ define(function (require) { this.remote = remote; } - var defaultTimeout = 60000; + var defaultTimeout = config.timeouts.default; Common.prototype = { constructor: Common, @@ -19,6 +19,7 @@ define(function (require) { navigateToApp: function (appName, testStatusPage) { var self = this; var appUrl = getUrl(config.servers.kibana, config.apps[appName]); + self.debug('navigating to ' + appName + ' url: ' + appUrl); var doNavigation = function (url) { return self.tryForTime(defaultTimeout, function () { @@ -51,14 +52,13 @@ define(function (require) { self.debug(msg); throw new Error(msg); } + + return currentUrl; }); }); }; return doNavigation(appUrl) - .then(function () { - return self.remote.getCurrentUrl(); - }) .then(function (currentUrl) { var lastUrl = currentUrl; return self.tryForTime(defaultTimeout, function () { @@ -149,13 +149,9 @@ define(function (require) { return Promise .try(block) - .then(function tryForTimeSuccess() { - self.debug('tryForTime success in about ' + (lastTry - start) + ' milliseconds'); - return (lastTry - start); - }) .catch(function tryForTimeCatch(err) { - self.debug('failed with "' + err.message + '"'); - self.debug('trying again in 1/2 second'); + self.debug('tryForTime failure: ' + err.message); + tempMessage = err.message; return Promise.delay(retryDelay).then(attempt); }); } diff --git a/test/support/pages/DiscoverPage.js b/test/support/pages/DiscoverPage.js index aea6387e2b55..d2e7c2ed7dbd 100644 --- a/test/support/pages/DiscoverPage.js +++ b/test/support/pages/DiscoverPage.js @@ -1,11 +1,9 @@ // in test/support/pages/DiscoverPage.js define(function (require) { - // the page object is created as a constructor - // so we can provide the remote Command object - // at runtime + var config = require('intern').config; var Common = require('./Common'); - var defaultTimeout = 20000; + var defaultTimeout = config.timeouts.default; var common; var thisTime; @@ -76,10 +74,11 @@ define(function (require) { }, getCurrentQueryName: function getCurrentQueryName() { - return thisTime - .findByCssSelector('span.discover-info-title') - // .findByCssSelector('span[bo-bind="opts.savedSearch.title"]') - .getVisibleText(); + return common.tryForTime(defaultTimeout, function () { + return thisTime + .findByCssSelector('span.discover-info-title') + .getVisibleText(); + }); }, getBarChartData: function getBarChartData() { diff --git a/test/support/pages/HeaderPage.js b/test/support/pages/HeaderPage.js index 8225191d6b0f..7789cbd46734 100644 --- a/test/support/pages/HeaderPage.js +++ b/test/support/pages/HeaderPage.js @@ -1,6 +1,6 @@ // in test/support/pages/HeaderPage.js define(function (require) { - + var config = require('intern').config; var Common = require('./Common'); var common; @@ -13,14 +13,14 @@ define(function (require) { common = new Common(this.remote); } - var defaultTimeout = 5000; + var defaultTimeout = config.timeouts.default; HeaderPage.prototype = { constructor: HeaderPage, clickSelector: function (selector) { var self = this.remote; - return common.tryForTime(5000, function () { + return common.tryForTime(defaultTimeout, function () { return self.setFindTimeout(defaultTimeout) .findByCssSelector(selector) .then(function (tab) { @@ -118,16 +118,21 @@ define(function (require) { waitForToastMessageGone: function waitForToastMessageGone() { var self = this; - return common.tryForTime(defaultTimeout * 5, function tryingForTime() { - return self.remote.setFindTimeout(1000) - .findAllByCssSelector('kbn-truncated.toast-message.ng-isolate-scope') + return common.tryForTime(defaultTimeout, function () { + return self.remote.setFindTimeout(500) + .findAllByCssSelector('kbn-truncated.toast-message') .then(function toastMessage(messages) { if (messages.length > 0) { + common.debug('toast message found, waiting...'); throw new Error('waiting for toast message to clear'); } else { - common.debug('now messages = 0 "' + messages + '"'); + common.debug('toast message clear'); return messages; } + }) + .catch(function () { + common.debug('toast message not found'); + return; }); }); }, diff --git a/test/support/pages/SettingsPage.js b/test/support/pages/SettingsPage.js index 0d1a2d22333f..92b6da577b72 100644 --- a/test/support/pages/SettingsPage.js +++ b/test/support/pages/SettingsPage.js @@ -1,13 +1,10 @@ // in test/support/pages/SettingsPage.js define(function (require) { - // the page object is created as a constructor - // so we can provide the remote Command object - // at runtime - + var config = require('intern').config; var Promise = require('bluebird'); var Common = require('./Common'); - var defaultTimeout = 6000; + var defaultTimeout = config.timeouts.default; var common; function SettingsPage(remote) { @@ -88,12 +85,22 @@ define(function (require) { selectTimeFieldOption: function (selection) { var self = this; + // open dropdown return self.getTimeFieldNameField().click() .then(function () { + // close dropdown, keep focus return self.getTimeFieldNameField().click(); }) .then(function () { - return self.getTimeFieldOption(selection); + return common.tryForTime(defaultTimeout, function () { + return self.getTimeFieldOption(selection).click() + .then(function () { + return self.getTimeFieldOption(selection).isSelected(); + }) + .then(function (selected) { + if (!selected) throw new Error('option not selected: ' + selected); + }); + }); }); }, @@ -167,11 +174,13 @@ define(function (require) { var self = this; var selector = 'li.kbn-settings-tab.active a small'; - return self.remote.setFindTimeout(defaultTimeout) - .findByCssSelector(selector).getVisibleText() - .then(function (theText) { - // the value has () around it, remove them - return theText.replace(/\((.*)\)/, '$1'); + return common.tryForTime(defaultTimeout, function () { + return self.remote.setFindTimeout(defaultTimeout / 10) + .findByCssSelector(selector).getVisibleText() + .then(function (theText) { + // the value has () around it, remove them + return theText.replace(/\((.*)\)/, '$1'); + }); }); },