Skip to content

Commit

Permalink
Use forceNow query parameter when parsing timefilter (#16236)
Browse files Browse the repository at this point in the history
* Using "forceNow" parameter to adjust "now" and exposing timeRange

* Moving forceNow parameter to the hash, adding tests

* Renaming test
  • Loading branch information
kobelb authored Feb 13, 2018
1 parent 9062f11 commit b677848
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 13 deletions.
65 changes: 65 additions & 0 deletions src/ui/public/timefilter/__tests__/timefilter.js
Original file line number Diff line number Diff line change
@@ -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();
});
});

});
21 changes: 18 additions & 3 deletions src/ui/public/timefilter/timefilter.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 })
};
};

Expand Down
51 changes: 42 additions & 9 deletions src/ui/public/timepicker/__tests__/toggle.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import moment from 'moment';
import expect from 'expect.js';
import ngMock from 'ng_mock';
import $ from 'jquery';
Expand All @@ -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('');
});
});
8 changes: 7 additions & 1 deletion src/ui/public/timepicker/kbn_global_timepicker.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
<div ng-show="timefilter.isAutoRefreshSelectorEnabled || timefilter.isTimeRangeSelectorEnabled" data-shared-timefilter="{{timefilter.isAutoRefreshSelectorEnabled || timefilter.isTimeRangeSelectorEnabled}}" class="kuiLocalMenu" data-test-subj="globalTimepicker">
<div
ng-show="timefilter.isAutoRefreshSelectorEnabled || timefilter.isTimeRangeSelectorEnabled"
data-shared-timefilter-from="{{timefilter.isAutoRefreshSelectorEnabled || timefilter.isTimeRangeSelectorEnabled ? timefilter.getBounds().min.utc().format() : null }}"
data-shared-timefilter-to="{{timefilter.isAutoRefreshSelectorEnabled || timefilter.isTimeRangeSelectorEnabled ? timefilter.getBounds().max.utc().format() : null }}"
class="kuiLocalMenu"
data-test-subj="globalTimepicker"
>
<button
class="kuiLocalMenuItem"
aria-label="{{ timefilter.refreshInterval.pause ? 'Resume refreshing data' : 'Pause refreshing data' }}"
Expand Down

0 comments on commit b677848

Please sign in to comment.