diff --git a/src/ui/public/timefilter/__tests__/timefilter.js b/src/ui/public/timefilter/__tests__/timefilter.js new file mode 100644 index 0000000000000..90fe09476655d --- /dev/null +++ b/src/ui/public/timefilter/__tests__/timefilter.js @@ -0,0 +1,65 @@ +import sinon from 'sinon'; +import expect from 'expect.js'; +import ngMock from 'ng_mock'; + +describe('Timefilter service', function () { + + describe('calculateBounds', function () { + beforeEach(ngMock.module('kibana')); + + const fifteenMinutesInMilliseconds = 15 * 60 * 1000; + const clockNowTicks = new Date(2000, 1, 1, 0, 0, 0, 0).valueOf(); + + let timefilter; + let $location; + let clock; + + beforeEach(ngMock.inject(function (_timefilter_, _$location_) { + timefilter = _timefilter_; + $location = _$location_; + + clock = sinon.useFakeTimers(clockNowTicks); + })); + + afterEach(function () { + clock.restore(); + }); + + it('uses clock time by default', function () { + const timeRange = { + from: 'now-15m', + to: 'now' + }; + + const result = timefilter.calculateBounds(timeRange); + expect(result.min.valueOf()).to.eql(clockNowTicks - fifteenMinutesInMilliseconds); + expect(result.max.valueOf()).to.eql(clockNowTicks); + }); + + it('uses forceNow string', function () { + const timeRange = { + from: 'now-15m', + to: 'now' + }; + + const forceNowString = '1999-01-01T00:00:00.000Z'; + $location.search('forceNow', forceNowString); + const result = timefilter.calculateBounds(timeRange); + + const forceNowTicks = Date.parse(forceNowString); + expect(result.min.valueOf()).to.eql(forceNowTicks - fifteenMinutesInMilliseconds); + expect(result.max.valueOf()).to.eql(forceNowTicks); + }); + + it(`throws Error if forceNow can't be parsed`, function () { + const timeRange = { + from: 'now-15m', + to: 'now' + }; + + $location.search('forceNow', 'malformed%20string'); + expect(() => timefilter.calculateBounds(timeRange)).to.throwError(); + }); + }); + +}); diff --git a/src/ui/public/timefilter/timefilter.js b/src/ui/public/timefilter/timefilter.js index a13f54b38a4c1..fca2d2842766b 100644 --- a/src/ui/public/timefilter/timefilter.js +++ b/src/ui/public/timefilter/timefilter.js @@ -16,7 +16,7 @@ uiRoutes uiModules .get('kibana') - .service('timefilter', function (Private, globalState, $rootScope, config) { + .service('timefilter', function (Private, globalState, $rootScope, config, $location) { const Events = Private(EventsProvider); function convertISO8601(stringTime) { @@ -105,10 +105,25 @@ uiModules return this.calculateBounds(this.time); }; + Timefilter.prototype.getForceNow = function () { + const query = $location.search().forceNow; + if (!query) { + return; + } + + const ticks = Date.parse(query); + if (isNaN(ticks)) { + throw new Error(`forceNow query parameter can't be parsed`); + } + return new Date(ticks); + }; + Timefilter.prototype.calculateBounds = function (timeRange) { + const forceNow = this.getForceNow(); + return { - min: dateMath.parse(timeRange.from), - max: dateMath.parse(timeRange.to, { roundUp: true }) + min: dateMath.parse(timeRange.from, { forceNow }), + max: dateMath.parse(timeRange.to, { roundUp: true, forceNow }) }; }; diff --git a/src/ui/public/timepicker/__tests__/toggle.js b/src/ui/public/timepicker/__tests__/toggle.js index 35e2967475b30..f9c366fdccfb0 100644 --- a/src/ui/public/timepicker/__tests__/toggle.js +++ b/src/ui/public/timepicker/__tests__/toggle.js @@ -1,3 +1,4 @@ +import moment from 'moment'; import expect from 'expect.js'; import ngMock from 'ng_mock'; import $ from 'jquery'; @@ -24,28 +25,60 @@ describe('kbnGlobalTimepicker', function () { expect($el.attr('data-test-subj')).to.be('globalTimepicker'); }); - it('sets data-shared-timefilter to true when auto-refresh selector is enabled', function () { + it('sets data-shared-timefilter-* using the timefilter when auto-refresh selector is enabled', function () { + const minString = '2000-01-01T00:00:00Z'; + const maxString = '2001-01-01T00:00:00Z'; + const bounds = { + min: moment(minString), + max: moment(maxString), + }; scope.timefilter = { isAutoRefreshSelectorEnabled: true, - isTimeRangeSelectorEnabled: false + isTimeRangeSelectorEnabled: false, + getBounds: () => bounds }; + const $el = compile(); - expect($el.attr('data-shared-timefilter')).to.eql('true'); + + expect($el.attr('data-shared-timefilter-from')).to.eql(minString); + expect($el.attr('data-shared-timefilter-to')).to.eql(maxString); }); - it('sets data-shared-timefilter to true when time range selector is enabled', function () { + + it('sets data-shared-timefilter-* using the timefilter when time range selector is enabled', function () { + const minString = '2000-01-01T00:00:00Z'; + const maxString = '2001-01-01T00:00:00Z'; + const bounds = { + min: moment(minString), + max: moment(maxString), + }; scope.timefilter = { isAutoRefreshSelectorEnabled: false, - isTimeRangeSelectorEnabled: true + isTimeRangeSelectorEnabled: true, + getBounds: () => bounds }; + const $el = compile(); - expect($el.attr('data-shared-timefilter')).to.eql('true'); + + expect($el.attr('data-shared-timefilter-from')).to.eql(minString); + expect($el.attr('data-shared-timefilter-to')).to.eql(maxString); }); - it(`sets data-shared-timefilter to false when auto-refresh and time range selectors are both disabled`, function () { + + it(`doesn't set data-shared-timefilter-* when auto-refresh and time range selectors are both disabled`, function () { + const minString = '2000-01-01T00:00:00Z'; + const maxString = '2001-01-01T00:00:00Z'; + const bounds = { + min: moment(minString), + max: moment(maxString), + }; scope.timefilter = { isAutoRefreshSelectorEnabled: false, - isTimeRangeSelectorEnabled: false + isTimeRangeSelectorEnabled: false, + getBounds: () => bounds }; + const $el = compile(); - expect($el.attr('data-shared-timefilter')).to.eql('false'); + + expect($el.attr('data-shared-timefilter-from')).to.eql(''); + expect($el.attr('data-shared-timefilter-to')).to.eql(''); }); }); diff --git a/src/ui/public/timepicker/kbn_global_timepicker.html b/src/ui/public/timepicker/kbn_global_timepicker.html index 9bf1811615db0..912bdacc88b3c 100644 --- a/src/ui/public/timepicker/kbn_global_timepicker.html +++ b/src/ui/public/timepicker/kbn_global_timepicker.html @@ -1,4 +1,10 @@ -
+