From f3712f748a159e9ba5e9fd53a0495326bfe4549e Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 5 Mar 2019 20:11:14 -0800 Subject: [PATCH] add test file (ignored) --- .../app/plugins/panel/table2/TablePanel.tsx | 28 +- .../panel/table2/specs/renderer.test.ts | 408 ++++++++++++++++++ 2 files changed, 422 insertions(+), 14 deletions(-) create mode 100644 public/app/plugins/panel/table2/specs/renderer.test.ts diff --git a/public/app/plugins/panel/table2/TablePanel.tsx b/public/app/plugins/panel/table2/TablePanel.tsx index c9669299125..2d5ef4bd695 100644 --- a/public/app/plugins/panel/table2/TablePanel.tsx +++ b/public/app/plugins/panel/table2/TablePanel.tsx @@ -1,7 +1,7 @@ // Libraries import _ from 'lodash'; import moment from 'moment'; -import React, { PureComponent } from 'react'; +import React, { PureComponent, CSSProperties } from 'react'; import ReactTable from 'react-table'; @@ -222,21 +222,21 @@ export class TablePanel extends PureComponent { value = column.formatter(value, column.style); } - const style = {}; + const style: CSSProperties = {}; const cellClasses = []; let cellClass = ''; if (this.colorState.cell) { - style['backgroundColor'] = this.colorState.cell; - style['color'] = 'white'; + style.backgroundColor = this.colorState.cell; + style.color = 'white'; this.colorState.cell = null; } else if (this.colorState.value) { - style['color'] = this.colorState.value; + style.color = this.colorState.value; this.colorState.value = null; } if (value === undefined) { - style['display'] = 'none'; + style.display = 'none'; column.hidden = true; } else { column.hidden = false; @@ -246,14 +246,14 @@ export class TablePanel extends PureComponent { cellClasses.push('table-panel-cell-pre'); } - let columnHtml; + let columnHtml: JSX.Element; if (column.style && column.style.link) { // Render cell as link - const scopedconsts = this.renderRowVariables(rowIndex); - scopedconsts['__cell'] = { value: value }; + const scopedVars = this.renderRowVariables(rowIndex); + scopedVars['__cell'] = { value: value }; - const cellLink = templateSrv.replace(column.style.linkUrl, scopedconsts, encodeURIComponent); - const cellLinkTooltip = templateSrv.replace(column.style.linkTooltip, scopedconsts); + const cellLink = templateSrv.replace(column.style.linkUrl, scopedVars, encodeURIComponent); + const cellLinkTooltip = templateSrv.replace(column.style.linkTooltip, scopedVars); const cellTarget = column.style.linkTargetBlank ? '_blank' : ''; cellClasses.push('table-panel-cell-link'); @@ -272,7 +272,7 @@ export class TablePanel extends PureComponent { columnHtml = {value}; } - let filterLink; + let filterLink: JSX.Element; if (column.filterable) { cellClasses.push('table-panel-cell-filterable'); filterLink = ( @@ -307,8 +307,8 @@ export class TablePanel extends PureComponent { cellClass = cellClasses.join(' '); } - style['width'] = '100%'; - style['height'] = '100%'; + style.width = '100%'; + style.height = '100%'; columnHtml = (
{columnHtml} diff --git a/public/app/plugins/panel/table2/specs/renderer.test.ts b/public/app/plugins/panel/table2/specs/renderer.test.ts new file mode 100644 index 00000000000..c76ccc8f716 --- /dev/null +++ b/public/app/plugins/panel/table2/specs/renderer.test.ts @@ -0,0 +1,408 @@ +import _ from 'lodash'; +import TableModel from 'app/core/table_model'; +import { TablePanel } from '../TablePanel'; +import { getColorDefinitionByName } from '@grafana/ui'; +import { Options } from '../types'; +import { PanelProps, LoadingState } from '@grafana/ui/src/types'; +import moment from 'moment'; + +// TODO: this is commented out with *x* describe! +// Essentially all the elements need to replace the with
+xdescribe('when rendering table', () => { + const SemiDarkOrange = getColorDefinitionByName('semi-dark-orange'); + + describe('given 13 columns', () => { + const table = new TableModel(); + table.columns = [ + { text: 'Time' }, + { text: 'Value' }, + { text: 'Colored' }, + { text: 'Undefined' }, + { text: 'String' }, + { text: 'United', unit: 'bps' }, + { text: 'Sanitized' }, + { text: 'Link' }, + { text: 'Array' }, + { text: 'Mapping' }, + { text: 'RangeMapping' }, + { text: 'MappingColored' }, + { text: 'RangeMappingColored' }, + ]; + table.rows = [ + [1388556366666, 1230, 40, undefined, '', '', 'my.host.com', 'host1', ['value1', 'value2'], 1, 2, 1, 2], + ]; + + const panel: Options = { + showHeader: true, + pageSize: 10, + styles: [ + { + pattern: 'Time', + type: 'date', + alias: 'Timestamp', + }, + { + pattern: '/(Val)ue/', + type: 'number', + unit: 'ms', + decimals: 3, + alias: '$1', + }, + { + pattern: 'Colored', + type: 'number', + unit: 'none', + decimals: 1, + colorMode: 'value', + thresholds: [50, 80], + colors: ['#00ff00', SemiDarkOrange.name, 'rgb(1,0,0)'], + }, + { + pattern: 'String', + type: 'string', + }, + { + pattern: 'String', + type: 'string', + }, + { + pattern: 'United', + type: 'number', + unit: 'ms', + decimals: 2, + }, + { + pattern: 'Sanitized', + type: 'string', + sanitize: true, + }, + { + pattern: 'Link', + type: 'string', + link: true, + linkUrl: '/dashboard?param=$__cell¶m_1=$__cell_1¶m_2=$__cell_2', + linkTooltip: '$__cell $__cell_1 $__cell_6', + linkTargetBlank: true, + }, + { + pattern: 'Array', + type: 'number', + unit: 'ms', + decimals: 3, + }, + { + pattern: 'Mapping', + type: 'string', + mappingType: 1, + valueMaps: [ + { + value: '1', + text: 'on', + }, + { + value: '0', + text: 'off', + }, + { + value: 'HELLO WORLD', + text: 'HELLO GRAFANA', + }, + { + value: 'value1, value2', + text: 'value3, value4', + }, + ], + }, + { + pattern: 'RangeMapping', + type: 'string', + mappingType: 2, + rangeMaps: [ + { + from: '1', + to: '3', + text: 'on', + }, + { + from: '3', + to: '6', + text: 'off', + }, + ], + }, + { + pattern: 'MappingColored', + type: 'string', + mappingType: 1, + valueMaps: [ + { + value: '1', + text: 'on', + }, + { + value: '0', + text: 'off', + }, + ], + colorMode: 'value', + thresholds: [1, 2], + colors: ['#00ff00', SemiDarkOrange.name, 'rgb(1,0,0)'], + }, + { + pattern: 'RangeMappingColored', + type: 'string', + mappingType: 2, + rangeMaps: [ + { + from: '1', + to: '3', + text: 'on', + }, + { + from: '3', + to: '6', + text: 'off', + }, + ], + colorMode: 'value', + thresholds: [2, 5], + colors: ['#00ff00', SemiDarkOrange.name, 'rgb(1,0,0)'], + }, + ], + }; + + // const sanitize = value => { + // return 'sanitized'; + // }; + + const props: PanelProps = { + panelData: { + tableData: table, + }, + width: 100, + height: 100, + timeRange: { + from: moment(), + to: moment(), + raw: { + from: moment(), + to: moment(), + }, + }, + loading: LoadingState.Done, + replaceVariables: (value, scopedVars) => { + if (scopedVars) { + // For testing variables replacement in link + _.each(scopedVars, (val, key) => { + value = value.replace('$' + key, val.value); + }); + } + return value; + }, + renderCounter: 1, + options: panel, + }; + + const renderer = new TablePanel(props); //panel, table, 'utc', sanitize, templateSrv); + renderer.render(); // This will initalize + + it('time column should be formated', () => { + const html = renderer.renderCell(0, 0, 1388556366666); + expect(html).toBe('2014-01-01T06:06:06Z'); + }); + + it('time column with epoch as string should be formatted', () => { + const html = renderer.renderCell(0, 0, '1388556366666'); + expect(html).toBe('2014-01-01T06:06:06Z'); + }); + + it('time column with RFC2822 date as string should be formatted', () => { + const html = renderer.renderCell(0, 0, 'Sat, 01 Dec 2018 01:00:00 GMT'); + expect(html).toBe('2018-12-01T01:00:00Z'); + }); + + it('time column with ISO date as string should be formatted', () => { + const html = renderer.renderCell(0, 0, '2018-12-01T01:00:00Z'); + expect(html).toBe('2018-12-01T01:00:00Z'); + }); + + it('undefined time column should be rendered as -', () => { + const html = renderer.renderCell(0, 0, undefined); + expect(html).toBe('-'); + }); + + it('null time column should be rendered as -', () => { + const html = renderer.renderCell(0, 0, null); + expect(html).toBe('-'); + }); + + it('number column with unit specified should ignore style unit', () => { + const html = renderer.renderCell(5, 0, 1230); + expect(html).toBe('1.23 kbps'); + }); + + it('number column should be formated', () => { + const html = renderer.renderCell(1, 0, 1230); + expect(html).toBe('1.230 s'); + }); + + it('number style should ignore string values', () => { + const html = renderer.renderCell(1, 0, 'asd'); + expect(html).toBe('asd'); + }); + + it('colored cell should have style (handles HEX color values)', () => { + const html = renderer.renderCell(2, 0, 40); + expect(html).toBe('40.0'); + }); + + it('colored cell should have style (handles named color values', () => { + const html = renderer.renderCell(2, 0, 55); + expect(html).toBe(`55.0`); + }); + + it('colored cell should have style handles(rgb color values)', () => { + const html = renderer.renderCell(2, 0, 85); + expect(html).toBe('85.0'); + }); + + it('unformated undefined should be rendered as string', () => { + const html = renderer.renderCell(3, 0, 'value'); + expect(html).toBe('value'); + }); + + it('string style with escape html should return escaped html', () => { + const html = renderer.renderCell(4, 0, '&breaking
the
row'); + expect(html).toBe('&breaking <br /> the <br /> row'); + }); + + it('undefined formater should return escaped html', () => { + const html = renderer.renderCell(3, 0, '&breaking
the
row'); + expect(html).toBe('&breaking <br /> the <br /> row'); + }); + + it('undefined value should render as -', () => { + const html = renderer.renderCell(3, 0, undefined); + expect(html).toBe(''); + }); + + it('sanitized value should render as', () => { + const html = renderer.renderCell(6, 0, 'text link'); + expect(html).toBe('sanitized'); + }); + + it('Time column title should be Timestamp', () => { + expect(table.columns[0].title).toBe('Timestamp'); + }); + + it('Value column title should be Val', () => { + expect(table.columns[1].title).toBe('Val'); + }); + + it('Colored column title should be Colored', () => { + expect(table.columns[2].title).toBe('Colored'); + }); + + it('link should render as', () => { + const html = renderer.renderCell(7, 0, 'host1'); + const expectedHtml = ` + + + host1 + + + `; + expect(normalize(html)).toBe(normalize(expectedHtml)); + }); + + it('Array column should not use number as formatter', () => { + const html = renderer.renderCell(8, 0, ['value1', 'value2']); + expect(html).toBe('value1, value2'); + }); + + it('numeric value should be mapped to text', () => { + const html = renderer.renderCell(9, 0, 1); + expect(html).toBe('on'); + }); + + it('string numeric value should be mapped to text', () => { + const html = renderer.renderCell(9, 0, '0'); + expect(html).toBe('off'); + }); + + it('string value should be mapped to text', () => { + const html = renderer.renderCell(9, 0, 'HELLO WORLD'); + expect(html).toBe('HELLO GRAFANA'); + }); + + it('array column value should be mapped to text', () => { + const html = renderer.renderCell(9, 0, ['value1', 'value2']); + expect(html).toBe('value3, value4'); + }); + + it('value should be mapped to text (range)', () => { + const html = renderer.renderCell(10, 0, 2); + expect(html).toBe('on'); + }); + + it('value should be mapped to text (range)', () => { + const html = renderer.renderCell(10, 0, 5); + expect(html).toBe('off'); + }); + + it('array column value should not be mapped to text', () => { + const html = renderer.renderCell(10, 0, ['value1', 'value2']); + expect(html).toBe('value1, value2'); + }); + + it('value should be mapped to text and colored cell should have style', () => { + const html = renderer.renderCell(11, 0, 1); + expect(html).toBe(`on`); + }); + + it('value should be mapped to text and colored cell should have style', () => { + const html = renderer.renderCell(11, 0, '1'); + expect(html).toBe(`on`); + }); + + it('value should be mapped to text and colored cell should have style', () => { + const html = renderer.renderCell(11, 0, 0); + expect(html).toBe('off'); + }); + + it('value should be mapped to text and colored cell should have style', () => { + const html = renderer.renderCell(11, 0, '0'); + expect(html).toBe('off'); + }); + + it('value should be mapped to text and colored cell should have style', () => { + const html = renderer.renderCell(11, 0, '2.1'); + expect(html).toBe('2.1'); + }); + + it('value should be mapped to text (range) and colored cell should have style', () => { + const html = renderer.renderCell(12, 0, 0); + expect(html).toBe('0'); + }); + + it('value should be mapped to text (range) and colored cell should have style', () => { + const html = renderer.renderCell(12, 0, 1); + expect(html).toBe('on'); + }); + + it('value should be mapped to text (range) and colored cell should have style', () => { + const html = renderer.renderCell(12, 0, 4); + expect(html).toBe(`off`); + }); + + it('value should be mapped to text (range) and colored cell should have style', () => { + const html = renderer.renderCell(12, 0, '7.1'); + expect(html).toBe('7.1'); + }); + }); +}); + +function normalize(str) { + return str.replace(/\s+/gm, ' ').trim(); +}