diff --git a/superset/assets/javascripts/components/FilterableTable/FilterableTable.jsx b/superset/assets/javascripts/components/FilterableTable/FilterableTable.jsx index 7874aab921c..e54a6fc4fd5 100644 --- a/superset/assets/javascripts/components/FilterableTable/FilterableTable.jsx +++ b/superset/assets/javascripts/components/FilterableTable/FilterableTable.jsx @@ -97,10 +97,16 @@ export default class FilterableTable extends PureComponent { const values = []; for (const key in row) { if (row.hasOwnProperty(key)) { - values.push(row[key].toLowerCase()); + const cellValue = row[key]; + if (typeof cellValue === 'string') { + values.push(cellValue.toLowerCase()); + } else if (typeof cellValue.toString === 'function') { + values.push(cellValue.toString()); + } } } - return values.some(v => v.includes(text.toLowerCase())); + const lowerCaseText = text.toLowerCase(); + return values.some(v => v.includes(lowerCaseText)); } headerRenderer({ dataKey, label, sortBy, sortDirection }) { diff --git a/superset/assets/javascripts/modules/visUtils.js b/superset/assets/javascripts/modules/visUtils.js index eef2babfb8f..974417966c3 100644 --- a/superset/assets/javascripts/modules/visUtils.js +++ b/superset/assets/javascripts/modules/visUtils.js @@ -1,9 +1,12 @@ export function getTextWidth(text, fontDetails = '12px Roboto') { const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); - context.font = fontDetails; - const metrics = context.measureText(text); - return metrics.width; + if (context) { + // Won't work outside of a browser context (ie unit tests) + context.font = fontDetails; + return context.measureText(text).width; + } + return 100; } export default { diff --git a/superset/assets/spec/javascripts/components/FilterableTable/FilterableTable_spec.jsx b/superset/assets/spec/javascripts/components/FilterableTable/FilterableTable_spec.jsx index 240a8e499a1..a4ca9141ccf 100644 --- a/superset/assets/spec/javascripts/components/FilterableTable/FilterableTable_spec.jsx +++ b/superset/assets/spec/javascripts/components/FilterableTable/FilterableTable_spec.jsx @@ -1,15 +1,43 @@ import React from 'react'; import { describe, it } from 'mocha'; import { expect } from 'chai'; +import { mount } from 'enzyme'; import FilterableTable from '../../../../javascripts/components/FilterableTable/FilterableTable'; describe('FilterableTable', () => { const mockedProps = { - orderedColumnKeys: [], - data: [], - height: 0, + orderedColumnKeys: ['a', 'b', 'c'], + data: [ + { a: 'a1', b: 'b1', c: 'c1', d: 0 }, + { a: 'a2', b: 'b2', c: 'c2', d: 100 }, + ], + height: 500, }; + let wrapper; + beforeEach(() => { + wrapper = mount(); + }); it('is valid element', () => { expect(React.isValidElement()).to.equal(true); }); + it('renders a grid with 2 rows', () => { + expect(wrapper.find('.ReactVirtualized__Grid')).to.have.length(1); + expect(wrapper.find('.ReactVirtualized__Table__row')).to.have.length(2); + }); + it('filters on a string', () => { + const props = { + ...mockedProps, + filterText: 'b1', + }; + wrapper = mount(); + expect(wrapper.find('.ReactVirtualized__Table__row')).to.have.length(1); + }); + it('filters on a number', () => { + const props = { + ...mockedProps, + filterText: '100', + }; + wrapper = mount(); + expect(wrapper.find('.ReactVirtualized__Table__row')).to.have.length(1); + }); });