superset/superset-frontend/plugins/plugin-chart-table/test/TableChart.test.tsx

347 lines
11 KiB
TypeScript

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React from 'react';
import { CommonWrapper } from 'enzyme';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import TableChart from '../src/TableChart';
import transformProps from '../src/transformProps';
import DateWithFormatter from '../src/utils/DateWithFormatter';
import testData from './testData';
import { mount, ProviderWrapper } from './enzyme';
describe('plugin-chart-table', () => {
describe('transformProps', () => {
it('should parse pageLength to pageSize', () => {
expect(transformProps(testData.basic).pageSize).toBe(20);
expect(
transformProps({
...testData.basic,
rawFormData: { ...testData.basic.rawFormData, page_length: '20' },
}).pageSize,
).toBe(20);
expect(
transformProps({
...testData.basic,
rawFormData: { ...testData.basic.rawFormData, page_length: '' },
}).pageSize,
).toBe(0);
});
it('should memoize data records', () => {
expect(transformProps(testData.basic).data).toBe(
transformProps(testData.basic).data,
);
});
it('should memoize columns meta', () => {
expect(transformProps(testData.basic).columns).toBe(
transformProps({
...testData.basic,
rawFormData: { ...testData.basic.rawFormData, pageLength: null },
}).columns,
);
});
it('should format timestamp', () => {
// eslint-disable-next-line no-underscore-dangle
const parsedDate = transformProps(testData.basic).data[0]
.__timestamp as DateWithFormatter;
expect(String(parsedDate)).toBe('2020-01-01 12:34:56');
expect(parsedDate.getTime()).toBe(1577882096000);
});
});
describe('TableChart', () => {
let wrap: CommonWrapper; // the ReactDataTable wrapper
let tree: Cheerio;
it('render basic data', () => {
wrap = mount(
<TableChart {...transformProps(testData.basic)} sticky={false} />,
);
tree = wrap.render(); // returns a CheerioWrapper with jQuery-like API
const cells = tree.find('td');
expect(cells).toHaveLength(12);
expect(cells.eq(0).text()).toEqual('2020-01-01 12:34:56');
expect(cells.eq(1).text()).toEqual('Michael');
// number is not in `metrics` list, so it should output raw value
// (in real world Superset, this would mean the column is used in GROUP BY)
expect(cells.eq(2).text()).toEqual('2467063');
// should not render column with `.` in name as `undefined`
expect(cells.eq(3).text()).toEqual('foo');
expect(cells.eq(6).text()).toEqual('2467');
expect(cells.eq(8).text()).toEqual('N/A');
});
it('render advanced data', () => {
wrap = mount(
<TableChart {...transformProps(testData.advanced)} sticky={false} />,
);
tree = wrap.render();
// should successful rerender with new props
const cells = tree.find('td');
expect(tree.find('th').eq(1).text()).toEqual('Sum of Num');
expect(cells.eq(0).text()).toEqual('Michael');
expect(cells.eq(2).text()).toEqual('12.346%');
expect(cells.eq(4).text()).toEqual('2.47k');
});
it('render advanced data with currencies', () => {
render(
ProviderWrapper({
children: (
<TableChart
{...transformProps(testData.advancedWithCurrency)}
sticky={false}
/>
),
}),
);
const cells = document.querySelectorAll('td');
expect(document.querySelectorAll('th')[1]).toHaveTextContent(
'Sum of Num',
);
expect(cells[0]).toHaveTextContent('Michael');
expect(cells[2]).toHaveTextContent('12.346%');
expect(cells[4]).toHaveTextContent('$ 2.47k');
});
it('render raw data', () => {
const props = transformProps({
...testData.raw,
rawFormData: { ...testData.raw.rawFormData },
});
render(
ProviderWrapper({
children: <TableChart {...props} sticky={false} />,
}),
);
const cells = document.querySelectorAll('td');
expect(document.querySelectorAll('th')[0]).toHaveTextContent('num');
expect(cells[0]).toHaveTextContent('1234');
expect(cells[1]).toHaveTextContent('10000');
expect(cells[1]).toHaveTextContent('0');
});
it('render raw data with currencies', () => {
const props = transformProps({
...testData.raw,
rawFormData: {
...testData.raw.rawFormData,
column_config: {
num: {
currencyFormat: { symbol: 'USD', symbolPosition: 'prefix' },
},
},
},
});
render(
ProviderWrapper({
children: <TableChart {...props} sticky={false} />,
}),
);
const cells = document.querySelectorAll('td');
expect(document.querySelectorAll('th')[0]).toHaveTextContent('num');
expect(cells[0]).toHaveTextContent('$ 1.23k');
expect(cells[1]).toHaveTextContent('$ 10k');
expect(cells[2]).toHaveTextContent('$ 0');
});
it('render small formatted data with currencies', () => {
const props = transformProps({
...testData.raw,
rawFormData: {
...testData.raw.rawFormData,
column_config: {
num: {
d3SmallNumberFormat: '.2r',
currencyFormat: { symbol: 'USD', symbolPosition: 'prefix' },
},
},
},
queriesData: [
{
...testData.raw.queriesData[0],
data: [
{
num: 1234,
},
{
num: 0.5,
},
{
num: 0.61234,
},
],
},
],
});
render(
ProviderWrapper({
children: <TableChart {...props} sticky={false} />,
}),
);
const cells = document.querySelectorAll('td');
expect(document.querySelectorAll('th')[0]).toHaveTextContent('num');
expect(cells[0]).toHaveTextContent('$ 1.23k');
expect(cells[1]).toHaveTextContent('$ 0.50');
expect(cells[2]).toHaveTextContent('$ 0.61');
});
it('render empty data', () => {
wrap.setProps({ ...transformProps(testData.empty), sticky: false });
tree = wrap.render();
expect(tree.text()).toContain('No records found');
});
it('render color with column color formatter', () => {
render(
ProviderWrapper({
children: (
<TableChart
{...transformProps({
...testData.advanced,
rawFormData: {
...testData.advanced.rawFormData,
conditional_formatting: [
{
colorScheme: '#ACE1C4',
column: 'sum__num',
operator: '>',
targetValue: 2467,
},
],
},
})}
/>
),
}),
);
expect(getComputedStyle(screen.getByTitle('2467063')).background).toBe(
'rgba(172, 225, 196, 1)',
);
expect(getComputedStyle(screen.getByTitle('2467')).background).toBe('');
});
it('render cell without color', () => {
const dataWithEmptyCell = testData.advanced.queriesData[0];
dataWithEmptyCell.data.push({
__timestamp: null,
name: 'Noah',
sum__num: null,
'%pct_nice': 0.643,
'abc.com': 'bazzinga',
});
render(
ProviderWrapper({
children: (
<TableChart
{...transformProps({
...testData.advanced,
queriesData: [dataWithEmptyCell],
rawFormData: {
...testData.advanced.rawFormData,
conditional_formatting: [
{
colorScheme: '#ACE1C4',
column: 'sum__num',
operator: '<',
targetValue: 12342,
},
],
},
})}
/>
),
}),
);
expect(getComputedStyle(screen.getByTitle('2467')).background).toBe(
'rgba(172, 225, 196, 0.812)',
);
expect(getComputedStyle(screen.getByTitle('2467063')).background).toBe(
'',
);
expect(getComputedStyle(screen.getByText('N/A')).background).toBe('');
});
});
it('render cell bars properly, and only when it is toggled on in both regular and percent metrics', () => {
const props = transformProps({
...testData.raw,
rawFormData: { ...testData.raw.rawFormData },
});
props.columns[0].isMetric = true;
render(
ProviderWrapper({
children: <TableChart {...props} sticky={false} />,
}),
);
let cells = document.querySelectorAll('div.cell-bar');
cells.forEach(cell => {
expect(cell).toHaveClass('positive');
});
props.columns[0].isMetric = false;
props.columns[0].isPercentMetric = true;
render(
ProviderWrapper({
children: <TableChart {...props} sticky={false} />,
}),
);
cells = document.querySelectorAll('div.cell-bar');
cells.forEach(cell => {
expect(cell).toHaveClass('positive');
});
props.showCellBars = false;
render(
ProviderWrapper({
children: <TableChart {...props} sticky={false} />,
}),
);
cells = document.querySelectorAll('td');
cells.forEach(cell => {
expect(cell).toHaveClass('test-c7w8t3');
});
props.columns[0].isPercentMetric = false;
props.columns[0].isMetric = true;
render(
ProviderWrapper({
children: <TableChart {...props} sticky={false} />,
}),
);
cells = document.querySelectorAll('td');
cells.forEach(cell => {
expect(cell).toHaveClass('test-c7w8t3');
});
});
});