renderer.jest.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. import _ from 'lodash';
  2. import TableModel from 'app/core/table_model';
  3. import { TableRenderer } from '../renderer';
  4. describe('when rendering table', () => {
  5. describe('given 13 columns', () => {
  6. var table = new TableModel();
  7. table.columns = [
  8. { text: 'Time' },
  9. { text: 'Value' },
  10. { text: 'Colored' },
  11. { text: 'Undefined' },
  12. { text: 'String' },
  13. { text: 'United', unit: 'bps' },
  14. { text: 'Sanitized' },
  15. { text: 'Link' },
  16. { text: 'Array' },
  17. { text: 'Mapping' },
  18. { text: 'RangeMapping' },
  19. { text: 'MappingColored' },
  20. { text: 'RangeMappingColored' },
  21. ];
  22. table.rows = [
  23. [1388556366666, 1230, 40, undefined, '', '', 'my.host.com', 'host1', ['value1', 'value2'], 1, 2, 1, 2],
  24. ];
  25. var panel = {
  26. pageSize: 10,
  27. styles: [
  28. {
  29. pattern: 'Time',
  30. type: 'date',
  31. format: 'LLL',
  32. alias: 'Timestamp',
  33. },
  34. {
  35. pattern: '/(Val)ue/',
  36. type: 'number',
  37. unit: 'ms',
  38. decimals: 3,
  39. alias: '$1',
  40. },
  41. {
  42. pattern: 'Colored',
  43. type: 'number',
  44. unit: 'none',
  45. decimals: 1,
  46. colorMode: 'value',
  47. thresholds: [50, 80],
  48. colors: ['green', 'orange', 'red'],
  49. },
  50. {
  51. pattern: 'String',
  52. type: 'string',
  53. },
  54. {
  55. pattern: 'String',
  56. type: 'string',
  57. },
  58. {
  59. pattern: 'United',
  60. type: 'number',
  61. unit: 'ms',
  62. decimals: 2,
  63. },
  64. {
  65. pattern: 'Sanitized',
  66. type: 'string',
  67. sanitize: true,
  68. },
  69. {
  70. pattern: 'Link',
  71. type: 'string',
  72. link: true,
  73. linkUrl: '/dashboard?param=$__cell&param_1=$__cell_1&param_2=$__cell_2',
  74. linkTooltip: '$__cell $__cell_1 $__cell_6',
  75. linkTargetBlank: true,
  76. },
  77. {
  78. pattern: 'Array',
  79. type: 'number',
  80. unit: 'ms',
  81. decimals: 3,
  82. },
  83. {
  84. pattern: 'Mapping',
  85. type: 'string',
  86. mappingType: 1,
  87. valueMaps: [
  88. {
  89. value: '1',
  90. text: 'on',
  91. },
  92. {
  93. value: '0',
  94. text: 'off',
  95. },
  96. {
  97. value: 'HELLO WORLD',
  98. text: 'HELLO GRAFANA',
  99. },
  100. {
  101. value: 'value1, value2',
  102. text: 'value3, value4',
  103. },
  104. ],
  105. },
  106. {
  107. pattern: 'RangeMapping',
  108. type: 'string',
  109. mappingType: 2,
  110. rangeMaps: [
  111. {
  112. from: '1',
  113. to: '3',
  114. text: 'on',
  115. },
  116. {
  117. from: '3',
  118. to: '6',
  119. text: 'off',
  120. },
  121. ],
  122. },
  123. {
  124. pattern: 'MappingColored',
  125. type: 'string',
  126. mappingType: 1,
  127. valueMaps: [
  128. {
  129. value: '1',
  130. text: 'on',
  131. },
  132. {
  133. value: '0',
  134. text: 'off',
  135. },
  136. ],
  137. colorMode: 'value',
  138. thresholds: [1, 2],
  139. colors: ['green', 'orange', 'red'],
  140. },
  141. {
  142. pattern: 'RangeMappingColored',
  143. type: 'string',
  144. mappingType: 2,
  145. rangeMaps: [
  146. {
  147. from: '1',
  148. to: '3',
  149. text: 'on',
  150. },
  151. {
  152. from: '3',
  153. to: '6',
  154. text: 'off',
  155. },
  156. ],
  157. colorMode: 'value',
  158. thresholds: [2, 5],
  159. colors: ['green', 'orange', 'red'],
  160. },
  161. ],
  162. };
  163. var sanitize = function(value) {
  164. return 'sanitized';
  165. };
  166. var templateSrv = {
  167. replace: function(value, scopedVars) {
  168. if (scopedVars) {
  169. // For testing variables replacement in link
  170. _.each(scopedVars, function(val, key) {
  171. value = value.replace('$' + key, val.value);
  172. });
  173. }
  174. return value;
  175. },
  176. };
  177. var renderer = new TableRenderer(panel, table, 'utc', sanitize, templateSrv);
  178. it('time column should be formated', () => {
  179. var html = renderer.renderCell(0, 0, 1388556366666);
  180. expect(html).toBe('<td>2014-01-01T06:06:06Z</td>');
  181. });
  182. it('undefined time column should be rendered as -', () => {
  183. var html = renderer.renderCell(0, 0, undefined);
  184. expect(html).toBe('<td>-</td>');
  185. });
  186. it('null time column should be rendered as -', () => {
  187. var html = renderer.renderCell(0, 0, null);
  188. expect(html).toBe('<td>-</td>');
  189. });
  190. it('number column with unit specified should ignore style unit', () => {
  191. var html = renderer.renderCell(5, 0, 1230);
  192. expect(html).toBe('<td>1.23 kbps</td>');
  193. });
  194. it('number column should be formated', () => {
  195. var html = renderer.renderCell(1, 0, 1230);
  196. expect(html).toBe('<td>1.230 s</td>');
  197. });
  198. it('number style should ignore string values', () => {
  199. var html = renderer.renderCell(1, 0, 'asd');
  200. expect(html).toBe('<td>asd</td>');
  201. });
  202. it('colored cell should have style', () => {
  203. var html = renderer.renderCell(2, 0, 40);
  204. expect(html).toBe('<td style="color:green">40.0</td>');
  205. });
  206. it('colored cell should have style', () => {
  207. var html = renderer.renderCell(2, 0, 55);
  208. expect(html).toBe('<td style="color:orange">55.0</td>');
  209. });
  210. it('colored cell should have style', () => {
  211. var html = renderer.renderCell(2, 0, 85);
  212. expect(html).toBe('<td style="color:red">85.0</td>');
  213. });
  214. it('unformated undefined should be rendered as string', () => {
  215. var html = renderer.renderCell(3, 0, 'value');
  216. expect(html).toBe('<td>value</td>');
  217. });
  218. it('string style with escape html should return escaped html', () => {
  219. var html = renderer.renderCell(4, 0, '&breaking <br /> the <br /> row');
  220. expect(html).toBe('<td>&amp;breaking &lt;br /&gt; the &lt;br /&gt; row</td>');
  221. });
  222. it('undefined formater should return escaped html', () => {
  223. var html = renderer.renderCell(3, 0, '&breaking <br /> the <br /> row');
  224. expect(html).toBe('<td>&amp;breaking &lt;br /&gt; the &lt;br /&gt; row</td>');
  225. });
  226. it('undefined value should render as -', () => {
  227. var html = renderer.renderCell(3, 0, undefined);
  228. expect(html).toBe('<td></td>');
  229. });
  230. it('sanitized value should render as', () => {
  231. var html = renderer.renderCell(6, 0, 'text <a href="http://google.com">link</a>');
  232. expect(html).toBe('<td>sanitized</td>');
  233. });
  234. it('Time column title should be Timestamp', () => {
  235. expect(table.columns[0].title).toBe('Timestamp');
  236. });
  237. it('Value column title should be Val', () => {
  238. expect(table.columns[1].title).toBe('Val');
  239. });
  240. it('Colored column title should be Colored', () => {
  241. expect(table.columns[2].title).toBe('Colored');
  242. });
  243. it('link should render as', () => {
  244. var html = renderer.renderCell(7, 0, 'host1');
  245. var expectedHtml = `
  246. <td class="table-panel-cell-link">
  247. <a href="/dashboard?param=host1&param_1=1230&param_2=40"
  248. target="_blank" data-link-tooltip data-original-title="host1 1230 my.host.com" data-placement="right">
  249. host1
  250. </a>
  251. </td>
  252. `;
  253. expect(normalize(html)).toBe(normalize(expectedHtml));
  254. });
  255. it('Array column should not use number as formatter', () => {
  256. var html = renderer.renderCell(8, 0, ['value1', 'value2']);
  257. expect(html).toBe('<td>value1, value2</td>');
  258. });
  259. it('numeric value should be mapped to text', () => {
  260. var html = renderer.renderCell(9, 0, 1);
  261. expect(html).toBe('<td>on</td>');
  262. });
  263. it('string numeric value should be mapped to text', () => {
  264. var html = renderer.renderCell(9, 0, '0');
  265. expect(html).toBe('<td>off</td>');
  266. });
  267. it('string value should be mapped to text', () => {
  268. var html = renderer.renderCell(9, 0, 'HELLO WORLD');
  269. expect(html).toBe('<td>HELLO GRAFANA</td>');
  270. });
  271. it('array column value should be mapped to text', () => {
  272. var html = renderer.renderCell(9, 0, ['value1', 'value2']);
  273. expect(html).toBe('<td>value3, value4</td>');
  274. });
  275. it('value should be mapped to text (range)', () => {
  276. var html = renderer.renderCell(10, 0, 2);
  277. expect(html).toBe('<td>on</td>');
  278. });
  279. it('value should be mapped to text (range)', () => {
  280. var html = renderer.renderCell(10, 0, 5);
  281. expect(html).toBe('<td>off</td>');
  282. });
  283. it('array column value should not be mapped to text', () => {
  284. var html = renderer.renderCell(10, 0, ['value1', 'value2']);
  285. expect(html).toBe('<td>value1, value2</td>');
  286. });
  287. it('value should be mapped to text and colored cell should have style', () => {
  288. var html = renderer.renderCell(11, 0, 1);
  289. expect(html).toBe('<td style="color:orange">on</td>');
  290. });
  291. it('value should be mapped to text and colored cell should have style', () => {
  292. var html = renderer.renderCell(11, 0, '1');
  293. expect(html).toBe('<td style="color:orange">on</td>');
  294. });
  295. it('value should be mapped to text and colored cell should have style', () => {
  296. var html = renderer.renderCell(11, 0, 0);
  297. expect(html).toBe('<td style="color:green">off</td>');
  298. });
  299. it('value should be mapped to text and colored cell should have style', () => {
  300. var html = renderer.renderCell(11, 0, '0');
  301. expect(html).toBe('<td style="color:green">off</td>');
  302. });
  303. it('value should be mapped to text and colored cell should have style', () => {
  304. var html = renderer.renderCell(11, 0, '2.1');
  305. expect(html).toBe('<td style="color:red">2.1</td>');
  306. });
  307. it('value should be mapped to text (range) and colored cell should have style', () => {
  308. var html = renderer.renderCell(12, 0, 0);
  309. expect(html).toBe('<td style="color:green">0</td>');
  310. });
  311. it('value should be mapped to text (range) and colored cell should have style', () => {
  312. var html = renderer.renderCell(12, 0, 1);
  313. expect(html).toBe('<td style="color:green">on</td>');
  314. });
  315. it('value should be mapped to text (range) and colored cell should have style', () => {
  316. var html = renderer.renderCell(12, 0, 4);
  317. expect(html).toBe('<td style="color:orange">off</td>');
  318. });
  319. it('value should be mapped to text (range) and colored cell should have style', () => {
  320. var html = renderer.renderCell(12, 0, '7.1');
  321. expect(html).toBe('<td style="color:red">7.1</td>');
  322. });
  323. });
  324. });
  325. function normalize(str) {
  326. return str.replace(/\s+/gm, ' ').trim();
  327. }