singlestat.test.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. import { SingleStatCtrl } from '../module';
  2. import { dateTime } from '@grafana/data';
  3. import { LinkSrv } from 'app/features/panel/panellinks/link_srv';
  4. describe('SingleStatCtrl', () => {
  5. const ctx = {} as any;
  6. const epoch = 1505826363746;
  7. Date.now = () => epoch;
  8. const $scope = {
  9. $on: () => {},
  10. };
  11. const $injector = {
  12. get: () => {},
  13. };
  14. const $sanitize = {};
  15. SingleStatCtrl.prototype.panel = {
  16. events: {
  17. on: () => {},
  18. emit: () => {},
  19. },
  20. };
  21. SingleStatCtrl.prototype.dashboard = {
  22. isTimezoneUtc: jest.fn(() => true),
  23. };
  24. SingleStatCtrl.prototype.events = {
  25. on: () => {},
  26. };
  27. function singleStatScenario(desc: string, func: any) {
  28. describe(desc, () => {
  29. ctx.setup = (setupFunc: any) => {
  30. beforeEach(() => {
  31. // @ts-ignore
  32. ctx.ctrl = new SingleStatCtrl($scope, $injector, {} as LinkSrv, $sanitize);
  33. setupFunc();
  34. ctx.ctrl.onDataReceived(ctx.data);
  35. ctx.data = ctx.ctrl.data;
  36. });
  37. };
  38. func(ctx);
  39. });
  40. }
  41. singleStatScenario('with defaults', (ctx: any) => {
  42. ctx.setup(() => {
  43. ctx.data = [{ target: 'test.cpu1', datapoints: [[10, 1], [20, 2]] }];
  44. });
  45. it('Should use series avg as default main value', () => {
  46. expect(ctx.data.value).toBe(15);
  47. expect(ctx.data.valueRounded).toBe(15);
  48. });
  49. it('should set formatted falue', () => {
  50. expect(ctx.data.valueFormatted).toBe('15');
  51. });
  52. });
  53. singleStatScenario('showing serie name instead of value', (ctx: any) => {
  54. ctx.setup(() => {
  55. ctx.data = [{ target: 'test.cpu1', datapoints: [[10, 1], [20, 2]] }];
  56. ctx.ctrl.panel.valueName = 'name';
  57. });
  58. it('Should use series avg as default main value', () => {
  59. expect(ctx.data.value).toBe(0);
  60. expect(ctx.data.valueRounded).toBe(0);
  61. });
  62. it('should set formatted value', () => {
  63. expect(ctx.data.valueFormatted).toBe('test.cpu1');
  64. });
  65. });
  66. singleStatScenario('showing last iso time instead of value', (ctx: any) => {
  67. ctx.setup(() => {
  68. ctx.data = [{ target: 'test.cpu1', datapoints: [[10, 12], [20, 1505634997920]] }];
  69. ctx.ctrl.panel.valueName = 'last_time';
  70. ctx.ctrl.panel.format = 'dateTimeAsIso';
  71. ctx.ctrl.dashboard.isTimezoneUtc = () => false;
  72. });
  73. it('Should use time instead of value', () => {
  74. expect(ctx.data.value).toBe(1505634997920);
  75. expect(ctx.data.valueRounded).toBe(1505634997920);
  76. });
  77. it('should set formatted value', () => {
  78. expect(dateTime(ctx.data.valueFormatted).valueOf()).toBe(1505634997000);
  79. });
  80. });
  81. singleStatScenario('showing last iso time instead of value (in UTC)', (ctx: any) => {
  82. ctx.setup(() => {
  83. ctx.data = [{ target: 'test.cpu1', datapoints: [[10, 12], [20, 5000]] }];
  84. ctx.ctrl.panel.valueName = 'last_time';
  85. ctx.ctrl.panel.format = 'dateTimeAsIso';
  86. ctx.ctrl.dashboard.isTimezoneUtc = () => true;
  87. });
  88. it('should set value', () => {
  89. expect(ctx.data.valueFormatted).toBe('1970-01-01 00:00:05');
  90. });
  91. });
  92. singleStatScenario('showing last us time instead of value', (ctx: any) => {
  93. ctx.setup(() => {
  94. ctx.data = [{ target: 'test.cpu1', datapoints: [[10, 12], [20, 1505634997920]] }];
  95. ctx.ctrl.panel.valueName = 'last_time';
  96. ctx.ctrl.panel.format = 'dateTimeAsUS';
  97. ctx.ctrl.dashboard.isTimezoneUtc = () => false;
  98. });
  99. it('Should use time instead of value', () => {
  100. expect(ctx.data.value).toBe(1505634997920);
  101. expect(ctx.data.valueRounded).toBe(1505634997920);
  102. });
  103. it('should set formatted value', () => {
  104. expect(ctx.data.valueFormatted).toBe(dateTime(1505634997920).format('MM/DD/YYYY h:mm:ss a'));
  105. });
  106. });
  107. singleStatScenario('showing last us time instead of value (in UTC)', (ctx: any) => {
  108. ctx.setup(() => {
  109. ctx.data = [{ target: 'test.cpu1', datapoints: [[10, 12], [20, 5000]] }];
  110. ctx.ctrl.panel.valueName = 'last_time';
  111. ctx.ctrl.panel.format = 'dateTimeAsUS';
  112. ctx.ctrl.dashboard.isTimezoneUtc = () => true;
  113. });
  114. it('should set formatted value', () => {
  115. expect(ctx.data.valueFormatted).toBe('01/01/1970 12:00:05 am');
  116. });
  117. });
  118. singleStatScenario('showing last time from now instead of value', (ctx: any) => {
  119. ctx.setup(() => {
  120. ctx.data = [{ target: 'test.cpu1', datapoints: [[10, 12], [20, 1505634997920]] }];
  121. ctx.ctrl.panel.valueName = 'last_time';
  122. ctx.ctrl.panel.format = 'dateTimeFromNow';
  123. });
  124. it('Should use time instead of value', () => {
  125. expect(ctx.data.value).toBe(1505634997920);
  126. expect(ctx.data.valueRounded).toBe(1505634997920);
  127. });
  128. it('should set formatted value', () => {
  129. expect(ctx.data.valueFormatted).toBe('2 days ago');
  130. });
  131. });
  132. singleStatScenario('showing last time from now instead of value (in UTC)', (ctx: any) => {
  133. ctx.setup(() => {
  134. ctx.data = [{ target: 'test.cpu1', datapoints: [[10, 12], [20, 1505634997920]] }];
  135. ctx.ctrl.panel.valueName = 'last_time';
  136. ctx.ctrl.panel.format = 'dateTimeFromNow';
  137. });
  138. it('should set formatted value', () => {
  139. expect(ctx.data.valueFormatted).toBe('2 days ago');
  140. });
  141. });
  142. singleStatScenario(
  143. 'MainValue should use same number for decimals as displayed when checking thresholds',
  144. (ctx: any) => {
  145. ctx.setup(() => {
  146. ctx.data = [{ target: 'test.cpu1', datapoints: [[99.999, 1], [99.99999, 2]] }];
  147. ctx.ctrl.panel.valueName = 'avg';
  148. ctx.ctrl.panel.format = 'none';
  149. });
  150. it('Should be rounded', () => {
  151. expect(ctx.data.value).toBe(99.999495);
  152. expect(ctx.data.valueRounded).toBe(100);
  153. });
  154. it('should set formatted value', () => {
  155. expect(ctx.data.valueFormatted).toBe('100');
  156. });
  157. }
  158. );
  159. singleStatScenario('When value to text mapping is specified', (ctx: any) => {
  160. ctx.setup(() => {
  161. ctx.data = [{ target: 'test.cpu1', datapoints: [[9.9, 1]] }];
  162. ctx.ctrl.panel.valueMaps = [{ value: '10', text: 'OK' }];
  163. });
  164. it('value should remain', () => {
  165. expect(ctx.data.value).toBe(9.9);
  166. });
  167. it('round should be rounded up', () => {
  168. expect(ctx.data.valueRounded).toBe(10);
  169. });
  170. it('Should replace value with text', () => {
  171. expect(ctx.data.valueFormatted).toBe('OK');
  172. });
  173. });
  174. singleStatScenario('When range to text mapping is specified for first range', (ctx: any) => {
  175. ctx.setup(() => {
  176. ctx.data = [{ target: 'test.cpu1', datapoints: [[41, 50]] }];
  177. ctx.ctrl.panel.mappingType = 2;
  178. ctx.ctrl.panel.rangeMaps = [{ from: '10', to: '50', text: 'OK' }, { from: '51', to: '100', text: 'NOT OK' }];
  179. });
  180. it('Should replace value with text OK', () => {
  181. expect(ctx.data.valueFormatted).toBe('OK');
  182. });
  183. });
  184. singleStatScenario('When range to text mapping is specified for other ranges', (ctx: any) => {
  185. ctx.setup(() => {
  186. ctx.data = [{ target: 'test.cpu1', datapoints: [[65, 75]] }];
  187. ctx.ctrl.panel.mappingType = 2;
  188. ctx.ctrl.panel.rangeMaps = [{ from: '10', to: '50', text: 'OK' }, { from: '51', to: '100', text: 'NOT OK' }];
  189. });
  190. it('Should replace value with text NOT OK', () => {
  191. expect(ctx.data.valueFormatted).toBe('NOT OK');
  192. });
  193. });
  194. describe('When table data', () => {
  195. const tableData = [
  196. {
  197. columns: [{ text: 'Time', type: 'time' }, { text: 'test1' }, { text: 'mean' }, { text: 'test2' }],
  198. rows: [[1492759673649, 'ignore1', 15, 'ignore2']],
  199. type: 'table',
  200. },
  201. ];
  202. singleStatScenario('with default values', (ctx: any) => {
  203. ctx.setup(() => {
  204. ctx.data = tableData;
  205. ctx.ctrl.panel = {
  206. emit: () => {},
  207. };
  208. ctx.ctrl.panel.tableColumn = 'mean';
  209. ctx.ctrl.panel.format = 'none';
  210. });
  211. it('Should use first rows value as default main value', () => {
  212. expect(ctx.data.value).toBe(15);
  213. expect(ctx.data.valueRounded).toBe(15);
  214. });
  215. it('should set formatted value', () => {
  216. expect(ctx.data.valueFormatted).toBe('15');
  217. });
  218. });
  219. singleStatScenario('When table data has multiple columns', (ctx: any) => {
  220. ctx.setup(() => {
  221. ctx.data = tableData;
  222. ctx.ctrl.panel.tableColumn = '';
  223. });
  224. it('Should set column to first column that is not time', () => {
  225. expect(ctx.ctrl.panel.tableColumn).toBe('test1');
  226. });
  227. });
  228. singleStatScenario(
  229. 'MainValue should use same number for decimals as displayed when checking thresholds',
  230. (ctx: any) => {
  231. ctx.setup(() => {
  232. ctx.data = tableData;
  233. ctx.data[0].rows[0] = [1492759673649, 'ignore1', 99.99999, 'ignore2'];
  234. ctx.ctrl.panel.mappingType = 0;
  235. ctx.ctrl.panel.tableColumn = 'mean';
  236. });
  237. it('Should be rounded', () => {
  238. expect(ctx.data.value).toBe(99.99999);
  239. expect(ctx.data.valueRounded).toBe(100);
  240. });
  241. it('should set formatted falue', () => {
  242. expect(ctx.data.valueFormatted).toBe('100');
  243. });
  244. }
  245. );
  246. singleStatScenario('When value to text mapping is specified', (ctx: any) => {
  247. ctx.setup(() => {
  248. ctx.data = tableData;
  249. ctx.data[0].rows[0] = [1492759673649, 'ignore1', 9.9, 'ignore2'];
  250. ctx.ctrl.panel.mappingType = 2;
  251. ctx.ctrl.panel.tableColumn = 'mean';
  252. ctx.ctrl.panel.valueMaps = [{ value: '10', text: 'OK' }];
  253. });
  254. it('value should remain', () => {
  255. expect(ctx.data.value).toBe(9.9);
  256. });
  257. it('round should be rounded up', () => {
  258. expect(ctx.data.valueRounded).toBe(10);
  259. });
  260. it('Should replace value with text', () => {
  261. expect(ctx.data.valueFormatted).toBe('OK');
  262. });
  263. });
  264. singleStatScenario('When range to text mapping is specified for first range', (ctx: any) => {
  265. ctx.setup(() => {
  266. ctx.data = tableData;
  267. ctx.data[0].rows[0] = [1492759673649, 'ignore1', 41, 'ignore2'];
  268. ctx.ctrl.panel.tableColumn = 'mean';
  269. ctx.ctrl.panel.mappingType = 2;
  270. ctx.ctrl.panel.rangeMaps = [{ from: '10', to: '50', text: 'OK' }, { from: '51', to: '100', text: 'NOT OK' }];
  271. });
  272. it('Should replace value with text OK', () => {
  273. expect(ctx.data.valueFormatted).toBe('OK');
  274. });
  275. });
  276. singleStatScenario('When range to text mapping is specified for other ranges', (ctx: any) => {
  277. ctx.setup(() => {
  278. ctx.data = tableData;
  279. ctx.data[0].rows[0] = [1492759673649, 'ignore1', 65, 'ignore2'];
  280. ctx.ctrl.panel.tableColumn = 'mean';
  281. ctx.ctrl.panel.mappingType = 2;
  282. ctx.ctrl.panel.rangeMaps = [{ from: '10', to: '50', text: 'OK' }, { from: '51', to: '100', text: 'NOT OK' }];
  283. });
  284. it('Should replace value with text NOT OK', () => {
  285. expect(ctx.data.valueFormatted).toBe('NOT OK');
  286. });
  287. });
  288. singleStatScenario('When value is string', (ctx: any) => {
  289. ctx.setup(() => {
  290. ctx.data = tableData;
  291. ctx.data[0].rows[0] = [1492759673649, 'ignore1', 65, 'ignore2'];
  292. ctx.ctrl.panel.tableColumn = 'test1';
  293. });
  294. it('Should replace value with text NOT OK', () => {
  295. expect(ctx.data.valueFormatted).toBe('ignore1');
  296. });
  297. });
  298. singleStatScenario('When value is zero', (ctx: any) => {
  299. ctx.setup(() => {
  300. ctx.data = tableData;
  301. ctx.data[0].rows[0] = [1492759673649, 'ignore1', 0, 'ignore2'];
  302. ctx.ctrl.panel.tableColumn = 'mean';
  303. });
  304. it('Should return zero', () => {
  305. expect(ctx.data.value).toBe(0);
  306. });
  307. });
  308. });
  309. });