TimeSrv.test.ts 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. import * as H from 'history';
  2. import { ContextSrvStub } from 'test/specs/helpers';
  3. import { dateTime, isDateTime } from '@grafana/data';
  4. import { HistoryWrapper, locationService, setLocationService } from '@grafana/runtime';
  5. import { beforeEach } from '../../../../test/lib/common';
  6. import { TimeSrv } from './TimeSrv';
  7. jest.mock('app/core/core', () => ({
  8. appEvents: {
  9. subscribe: () => {},
  10. },
  11. }));
  12. describe('timeSrv', () => {
  13. let timeSrv: TimeSrv;
  14. let _dashboard: any;
  15. let locationUpdates: H.Location[] = [];
  16. beforeEach(() => {
  17. _dashboard = {
  18. time: { from: 'now-6h', to: 'now' },
  19. getTimezone: jest.fn(() => 'browser'),
  20. refresh: false,
  21. timeRangeUpdated: jest.fn(() => {}),
  22. };
  23. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  24. timeSrv.init(_dashboard);
  25. locationUpdates = [];
  26. const history = new HistoryWrapper();
  27. history.getHistory().listen((x) => locationUpdates.push(x));
  28. setLocationService(history);
  29. });
  30. describe('timeRange', () => {
  31. it('should return unparsed when parse is false', () => {
  32. timeSrv.setTime({ from: 'now', to: 'now-1h' });
  33. const time = timeSrv.timeRange();
  34. expect(time.raw.from).toBe('now');
  35. expect(time.raw.to).toBe('now-1h');
  36. });
  37. it('should return parsed when parse is true', () => {
  38. timeSrv.setTime({ from: 'now', to: 'now-1h' });
  39. const time = timeSrv.timeRange();
  40. expect(isDateTime(time.from)).toBe(true);
  41. expect(isDateTime(time.to)).toBe(true);
  42. });
  43. });
  44. describe('init time from url', () => {
  45. it('should handle relative times', () => {
  46. locationService.push('/d/id?from=now-2d&to=now');
  47. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  48. timeSrv.init(_dashboard);
  49. const time = timeSrv.timeRange();
  50. expect(time.raw.from).toBe('now-2d');
  51. expect(time.raw.to).toBe('now');
  52. });
  53. it('should handle formatted dates', () => {
  54. locationService.push('/d/id?from=20140410T052010&to=20140520T031022');
  55. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  56. timeSrv.init(_dashboard);
  57. const time = timeSrv.timeRange();
  58. expect(time.from.valueOf()).toEqual(new Date('2014-04-10T05:20:10Z').getTime());
  59. expect(time.to.valueOf()).toEqual(new Date('2014-05-20T03:10:22Z').getTime());
  60. });
  61. it('should ignore refresh if time absolute', () => {
  62. locationService.push('/d/id?from=20140410T052010&to=20140520T031022');
  63. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  64. // dashboard saved with refresh on
  65. _dashboard.refresh = true;
  66. timeSrv.init(_dashboard);
  67. expect(timeSrv.refresh).toBe(false);
  68. });
  69. it('should handle formatted dates without time', () => {
  70. locationService.push('/d/id?from=20140410&to=20140520');
  71. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  72. timeSrv.init(_dashboard);
  73. const time = timeSrv.timeRange();
  74. expect(time.from.valueOf()).toEqual(new Date('2014-04-10T00:00:00Z').getTime());
  75. expect(time.to.valueOf()).toEqual(new Date('2014-05-20T00:00:00Z').getTime());
  76. });
  77. it('should handle epochs', () => {
  78. locationService.push('/d/id?from=1410337646373&to=1410337665699');
  79. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  80. timeSrv.init(_dashboard);
  81. const time = timeSrv.timeRange();
  82. expect(time.from.valueOf()).toEqual(1410337646373);
  83. expect(time.to.valueOf()).toEqual(1410337665699);
  84. });
  85. it('should handle epochs that look like formatted date without time', () => {
  86. locationService.push('/d/id?from=20149999&to=20159999');
  87. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  88. timeSrv.init(_dashboard);
  89. const time = timeSrv.timeRange();
  90. expect(time.from.valueOf()).toEqual(20149999);
  91. expect(time.to.valueOf()).toEqual(20159999);
  92. });
  93. it('should handle epochs that look like formatted date', () => {
  94. locationService.push('/d/id?from=201499991234567&to=201599991234567');
  95. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  96. timeSrv.init(_dashboard);
  97. const time = timeSrv.timeRange();
  98. expect(time.from.valueOf()).toEqual(201499991234567);
  99. expect(time.to.valueOf()).toEqual(201599991234567);
  100. });
  101. it('should handle bad dates', () => {
  102. locationService.push('/d/id?from=20151126T00010%3C%2Fp%3E%3Cspan%20class&to=now');
  103. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  104. _dashboard.time.from = 'now-6h';
  105. timeSrv.init(_dashboard);
  106. expect(timeSrv.time.from).toEqual('now-6h');
  107. expect(timeSrv.time.to).toEqual('now');
  108. });
  109. it('should handle refresh_intervals=null when refresh is enabled', () => {
  110. locationService.push('/d/id?refresh=30s');
  111. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  112. _dashboard.timepicker = {
  113. refresh_intervals: null,
  114. };
  115. expect(() => timeSrv.init(_dashboard)).not.toThrow();
  116. });
  117. describe('data point windowing', () => {
  118. it('handles time window specfied as interval string', () => {
  119. locationService.push('/d/id?time=1410337645000&time.window=10s');
  120. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  121. timeSrv.init(_dashboard);
  122. const time = timeSrv.timeRange();
  123. expect(time.from.valueOf()).toEqual(1410337640000);
  124. expect(time.to.valueOf()).toEqual(1410337650000);
  125. });
  126. it('handles time window specified in ms', () => {
  127. locationService.push('/d/id?time=1410337645000&time.window=10000');
  128. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  129. timeSrv.init(_dashboard);
  130. const time = timeSrv.timeRange();
  131. expect(time.from.valueOf()).toEqual(1410337640000);
  132. expect(time.to.valueOf()).toEqual(1410337650000);
  133. });
  134. it('corrects inverted from/to dates in ms', () => {
  135. locationService.push('/d/id?from=1621436828909&to=1621436818909');
  136. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  137. timeSrv.init(_dashboard);
  138. const time = timeSrv.timeRange();
  139. expect(time.from.valueOf()).toEqual(1621436818909);
  140. expect(time.to.valueOf()).toEqual(1621436828909);
  141. });
  142. it('corrects inverted from/to dates as relative times', () => {
  143. locationService.push('/d/id?from=now&to=now-1h');
  144. timeSrv = new TimeSrv(new ContextSrvStub() as any);
  145. timeSrv.init(_dashboard);
  146. const time = timeSrv.timeRange();
  147. expect(time.raw.from).toBe('now-1h');
  148. expect(time.raw.to).toBe('now');
  149. });
  150. });
  151. });
  152. describe('setTime', () => {
  153. it('should return disable refresh if refresh is disabled for any range', () => {
  154. _dashboard.refresh = false;
  155. timeSrv.setTime({ from: '2011-01-01', to: '2015-01-01' });
  156. expect(_dashboard.refresh).toBe(false);
  157. });
  158. it('should restore refresh for absolute time range', () => {
  159. _dashboard.refresh = '30s';
  160. timeSrv.setTime({ from: '2011-01-01', to: '2015-01-01' });
  161. expect(_dashboard.refresh).toBe('30s');
  162. });
  163. it('should restore refresh after relative time range is set', () => {
  164. _dashboard.refresh = '10s';
  165. timeSrv.setTime({
  166. from: dateTime([2011, 1, 1]),
  167. to: dateTime([2015, 1, 1]),
  168. });
  169. expect(_dashboard.refresh).toBe(false);
  170. timeSrv.setTime({ from: '2011-01-01', to: 'now' });
  171. expect(_dashboard.refresh).toBe('10s');
  172. });
  173. it('should keep refresh after relative time range is changed and now delay exists', () => {
  174. _dashboard.refresh = '10s';
  175. timeSrv.setTime({ from: 'now-1h', to: 'now-10s' });
  176. expect(_dashboard.refresh).toBe('10s');
  177. });
  178. it('should update location only once for consecutive calls with the same range', () => {
  179. timeSrv.setTime({ from: 'now-1h', to: 'now-10s' });
  180. timeSrv.setTime({ from: 'now-1h', to: 'now-10s' });
  181. expect(locationUpdates.length).toBe(1);
  182. });
  183. it('should update location so that bool params are preserved', () => {
  184. locationService.partial({ kiosk: true });
  185. timeSrv.setTime({ from: 'now-1h', to: 'now-10s' });
  186. timeSrv.setTime({ from: 'now-1h', to: 'now-10s' });
  187. expect(locationUpdates[1].search).toEqual('?kiosk&from=now-1h&to=now-10s');
  188. });
  189. it('should not change the URL if the updateUrl param is false', () => {
  190. timeSrv.setTime({ from: '1644340584281', to: '1644340584281' }, false);
  191. expect(locationUpdates.length).toBe(0);
  192. });
  193. });
  194. describe('pauseAutoRefresh', () => {
  195. it('should set autoRefreshPaused to true', () => {
  196. _dashboard.refresh = '10s';
  197. timeSrv.pauseAutoRefresh();
  198. expect(timeSrv.autoRefreshPaused).toBe(true);
  199. });
  200. });
  201. describe('resumeAutoRefresh', () => {
  202. it('should set refresh to empty value', () => {
  203. timeSrv.autoRefreshPaused = true;
  204. timeSrv.resumeAutoRefresh();
  205. expect(timeSrv.autoRefreshPaused).toBe(false);
  206. });
  207. });
  208. describe('isRefreshOutsideThreshold', () => {
  209. const originalNow = Date.now;
  210. beforeEach(() => {
  211. Date.now = jest.fn(() => 60000);
  212. });
  213. afterEach(() => {
  214. Date.now = originalNow;
  215. });
  216. describe('when called and current time range is absolute', () => {
  217. it('then it should return false', () => {
  218. timeSrv.setTime({ from: dateTime(), to: dateTime() });
  219. expect(timeSrv.isRefreshOutsideThreshold(0, 0.05)).toBe(false);
  220. });
  221. });
  222. describe('when called and current time range is relative', () => {
  223. describe('and last refresh is within threshold', () => {
  224. it('then it should return false', () => {
  225. timeSrv.setTime({ from: 'now-1m', to: 'now' });
  226. expect(timeSrv.isRefreshOutsideThreshold(57001, 0.05)).toBe(false);
  227. });
  228. });
  229. describe('and last refresh is outside the threshold', () => {
  230. it('then it should return true', () => {
  231. timeSrv.setTime({ from: 'now-1m', to: 'now' });
  232. expect(timeSrv.isRefreshOutsideThreshold(57000, 0.05)).toBe(true);
  233. });
  234. });
  235. });
  236. });
  237. });