diff --git a/src/fixtures/stubbed_search_source.js b/src/fixtures/stubbed_search_source.js index 08b43ed7d9676..1ba0239d61973 100644 --- a/src/fixtures/stubbed_search_source.js +++ b/src/fixtures/stubbed_search_source.js @@ -6,6 +6,7 @@ export default function stubSearchSource(Private, $q, Promise) { let deferedResult = $q.defer(); const indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); + let onResultsCount = 0; return { sort: sinon.spy(), size: sinon.spy(), @@ -24,11 +25,16 @@ export default function stubSearchSource(Private, $q, Promise) { deferedResult = $q.defer(); }, onResults: function () { + onResultsCount++; + // Up to the test to resolve this manually // For example: // someHandler.resolve(require('fixtures/search_response')) return deferedResult.promise; }, + getOnResultsCount: function () { + return onResultsCount; + }, onError: function () { return $q.defer().promise; }, _flatten: function () { return Promise.resolve({ index: indexPattern, body: {} }); diff --git a/src/ui/public/visualize/__tests__/visualize.js b/src/ui/public/visualize/__tests__/visualize.js new file mode 100644 index 0000000000000..40253f5e862cc --- /dev/null +++ b/src/ui/public/visualize/__tests__/visualize.js @@ -0,0 +1,78 @@ +import $ from 'jquery'; +import _ from 'lodash'; +import expect from 'expect.js'; +import ngMock from 'ng_mock'; +import sinon from 'auto-release-sinon'; +import AggResponseTabifyTableGroupProvider from 'ui/agg_response/tabify/_table_group'; +import VisProvider from 'ui/vis'; +import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; +import FixturesStubbedSearchSourceProvider from 'fixtures/stubbed_search_source'; +describe('visualize directive', function () { + + let $rootScope; + let TableGroup; + let $compile; + let $scope; + let $el; + let Vis; + let indexPattern; + let fixtures; + let searchSource; + + beforeEach(ngMock.module('kibana', 'kibana/table_vis')); + beforeEach(ngMock.inject(function (Private, $injector) { + $rootScope = $injector.get('$rootScope'); + $compile = $injector.get('$compile'); + fixtures = require('fixtures/fake_hierarchical_data'); + TableGroup = Private(AggResponseTabifyTableGroupProvider); + Vis = Private(VisProvider); + indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); + searchSource = Private(FixturesStubbedSearchSourceProvider); + })); + + // basically a parameterized beforeEach + function init(vis, esResponse) { + vis.aggs.forEach(function (agg, i) { agg.id = 'agg_' + (i + 1); }); + + $rootScope.vis = vis; + $rootScope.esResponse = esResponse; + $rootScope.uiState = require('fixtures/mock_ui_state'); + $rootScope.searchSource = searchSource; + $el = $(''); + $compile($el)($rootScope); + $rootScope.$apply(); + + $scope = $el.isolateScope(); + } + + function CreateVis(params, requiresSearch) { + return new Vis(indexPattern, { + type: 'table', + requiresSearch: requiresSearch, + params: params || {}, + aggs: [ + { type: 'count', schema: 'metric' }, + { + type: 'range', + schema: 'bucket', + params: { + field: 'bytes', + ranges: [ + { from: 0, to: 1000 }, + { from: 1000, to: 2000 } + ] + } + } + ] + }); + } + + it('searchSource.onResults should not be called when requiresSearch is false', function () { + const requiresSearch = false; + init(new CreateVis(null, requiresSearch), fixtures.oneRangeBucket); + + searchSource.crankResults(); + $scope.$digest(); + expect(searchSource.getOnResultsCount()).to.be(0); + }); +}); diff --git a/src/ui/public/visualize/visualize.js b/src/ui/public/visualize/visualize.js index 81e7bdfb48575..5ffd16799aa49 100644 --- a/src/ui/public/visualize/visualize.js +++ b/src/ui/public/visualize/visualize.js @@ -171,31 +171,33 @@ uiModules if ($scope.renderbot) $scope.renderbot.updateParams(); })); - $scope.$watch('searchSource', prereq(function (searchSource) { - if (!searchSource || attr.esResp) return; - - // TODO: we need to have some way to clean up result requests - searchSource.onResults().then(function onResults(resp) { - if ($scope.searchSource !== searchSource) return; - - $scope.esResp = resp; - - return searchSource.onResults().then(onResults); - }).catch(notify.fatal); - - searchSource.onError(e => { - $el.trigger('renderComplete'); - if (isTermSizeZeroError(e)) { - return notify.error( - `Your visualization ('${$scope.vis.title}') has an error: it has a term ` + - `aggregation with a size of 0. Please set it to a number greater than 0 to resolve ` + - `the error.` - ); - } + if (_.get($scope, 'vis.type.requiresSearch')) { + $scope.$watch('searchSource', prereq(function (searchSource) { + if (!searchSource || attr.esResp) return; + + // TODO: we need to have some way to clean up result requests + searchSource.onResults().then(function onResults(resp) { + if ($scope.searchSource !== searchSource) return; + + $scope.esResp = resp; + + return searchSource.onResults().then(onResults); + }).catch(notify.fatal); + + searchSource.onError(e => { + $el.trigger('renderComplete'); + if (isTermSizeZeroError(e)) { + return notify.error( + `Your visualization ('${$scope.vis.title}') has an error: it has a term ` + + `aggregation with a size of 0. Please set it to a number greater than 0 to resolve ` + + `the error.` + ); + } - notify.error(e); - }).catch(notify.fatal); - })); + notify.error(e); + }).catch(notify.fatal); + })); + } $scope.$watch('esResp', prereq(function (resp, prevResp) { if (!resp) return;