From 54b98f41f43cddf016ac6a69b8c654843c39a8e9 Mon Sep 17 00:00:00 2001 From: AllenFang Date: Sun, 5 Aug 2018 16:05:07 +0800 Subject: [PATCH] implement shouldComponentUpdate on cell component --- packages/react-bootstrap-table2/src/cell.js | 67 +- packages/react-bootstrap-table2/src/row.js | 40 ++ .../react-bootstrap-table2/test/cell.test.js | 611 ++++++++---------- .../react-bootstrap-table2/test/row.test.js | 458 ++++++++++++- 4 files changed, 779 insertions(+), 397 deletions(-) diff --git a/packages/react-bootstrap-table2/src/cell.js b/packages/react-bootstrap-table2/src/cell.js index bfd61d5..db32d05 100644 --- a/packages/react-bootstrap-table2/src/cell.js +++ b/packages/react-bootstrap-table2/src/cell.js @@ -10,6 +10,25 @@ class Cell extends Component { this.handleEditingCell = this.handleEditingCell.bind(this); } + shouldComponentUpdate(nextProps) { + const shouldUpdate = + _.get(this.props.row, this.props.column.dataField) + !== _.get(nextProps.row, nextProps.column.dataField) || + this.props.column.hidden !== nextProps.column.hidden || + this.props.rowIndex !== nextProps.rowIndex || + this.props.columnIndex !== nextProps.columnIndex || + this.props.className !== nextProps.className || + this.props.title !== nextProps.title || + this.props.editable !== nextProps.editable || + this.props.clickToEdit !== nextProps.clickToEdit || + this.props.dbclickToEdit !== nextProps.dbclickToEdit || + !_.isEqual(this.props.style, nextProps.style) || + !_.isEqual(this.props.column.formatExtraData, nextProps.column.formatExtraData) || + !_.isEqual(this.props.column.events, nextProps.column.events) || + !_.isEqual(this.props.column.attrs, nextProps.column.attrs); + return shouldUpdate; + } + handleEditingCell(e) { const { column, onStart, rowIndex, columnIndex, clickToEdit, dbclickToEdit } = this.props; const { events } = column; @@ -33,62 +52,32 @@ class Cell extends Component { rowIndex, column, columnIndex, + onStart, editable, clickToEdit, - dbclickToEdit + dbclickToEdit, + ...rest } = this.props; const { dataField, formatter, - formatExtraData, - style, - classes, - title, - events, - align, - attrs + formatExtraData } = column; - let cellTitle; - let cellStyle = {}; + const attrs = { ...rest }; let content = _.get(row, dataField); - const cellAttrs = { - ..._.isFunction(attrs) ? attrs(content, row, rowIndex, columnIndex) : attrs, - ...events - }; - - const cellClasses = _.isFunction(classes) - ? classes(content, row, rowIndex, columnIndex) - : classes; - - if (style) { - cellStyle = _.isFunction(style) ? style(content, row, rowIndex, columnIndex) : style; - } - - if (title) { - cellTitle = _.isFunction(title) ? title(content, row, rowIndex, columnIndex) : content; - cellAttrs.title = cellTitle; - } - if (formatter) { content = column.formatter(content, row, rowIndex, formatExtraData); } - if (align) { - cellStyle.textAlign = - _.isFunction(align) ? align(content, row, rowIndex, columnIndex) : align; - } - - if (cellClasses) cellAttrs.className = cellClasses; - - if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle; if (clickToEdit && editable) { - cellAttrs.onClick = this.handleEditingCell; + attrs.onClick = this.handleEditingCell; } else if (dbclickToEdit && editable) { - cellAttrs.onDoubleClick = this.handleEditingCell; + attrs.onDoubleClick = this.handleEditingCell; } + return ( - + { typeof content === 'boolean' ? `${content}` : content } ); diff --git a/packages/react-bootstrap-table2/src/row.js b/packages/react-bootstrap-table2/src/row.js index 1196716..84a3ea4 100644 --- a/packages/react-bootstrap-table2/src/row.js +++ b/packages/react-bootstrap-table2/src/row.js @@ -102,6 +102,45 @@ class Row extends eventDelegater(Component) { /> ); } + // render cell + let cellTitle; + let cellStyle = {}; + const cellAttrs = { + ..._.isFunction(column.attrs) + ? column.attrs(content, row, rowIndex, index) + : column.attrs, + ...column.events + }; + + const cellClasses = _.isFunction(column.classes) + ? column.classes(content, row, rowIndex, index) + : column.classes; + + if (column.style) { + cellStyle = _.isFunction(column.style) + ? column.style(content, row, rowIndex, index) + : column.style; + cellStyle = cellStyle || {}; + } + + + if (column.title) { + cellTitle = _.isFunction(column.title) + ? column.title(content, row, rowIndex, index) + : content; + cellAttrs.title = cellTitle; + } + + if (column.align) { + cellStyle.textAlign = + _.isFunction(column.align) + ? column.align(content, row, rowIndex, index) + : column.align; + } + + if (cellClasses) cellAttrs.className = cellClasses; + if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle; + return ( ); } diff --git a/packages/react-bootstrap-table2/test/cell.test.js b/packages/react-bootstrap-table2/test/cell.test.js index 1695240..86bf393 100644 --- a/packages/react-bootstrap-table2/test/cell.test.js +++ b/packages/react-bootstrap-table2/test/cell.test.js @@ -79,362 +79,6 @@ describe('Cell', () => { }); }); - describe('when column.style prop is defined', () => { - let column; - const columnIndex = 1; - const rowIndex = 1; - - beforeEach(() => { - column = { - dataField: 'id', - text: 'ID' - }; - }); - - describe('when style is an object', () => { - beforeEach(() => { - column.style = { backgroundColor: 'red' }; - wrapper = shallow( - ); - }); - - it('should render successfully', () => { - expect(wrapper.length).toBe(1); - expect(wrapper.find('td').prop('style')).toEqual(column.style); - }); - }); - - describe('when style is a function', () => { - const returnStyle = { backgroundColor: 'red' }; - let styleCallBack; - - beforeEach(() => { - styleCallBack = sinon.stub() - .withArgs(row[column.dataField], row, rowIndex, columnIndex) - .returns(returnStyle); - column.style = styleCallBack; - wrapper = shallow( - ); - }); - - afterEach(() => { styleCallBack.reset(); }); - - it('should render successfully', () => { - expect(wrapper.length).toBe(1); - expect(wrapper.find('td').prop('style')).toEqual(returnStyle); - }); - - it('should call custom style function correctly', () => { - expect(styleCallBack.callCount).toBe(1); - expect( - styleCallBack.calledWith(row[column.dataField], row, rowIndex, columnIndex) - ).toBe(true); - }); - }); - }); - - describe('when column.classes prop is defined', () => { - let column; - const columnIndex = 1; - const rowIndex = 1; - - beforeEach(() => { - column = { - dataField: 'id', - text: 'ID' - }; - }); - - describe('when classes is an object', () => { - beforeEach(() => { - column.classes = 'td-test-class'; - wrapper = shallow( - ); - }); - - it('should render successfully', () => { - expect(wrapper.length).toBe(1); - expect(wrapper.hasClass(column.classes)).toBe(true); - }); - }); - - describe('when classes is a function', () => { - const returnClasses = 'td-test-class'; - let classesCallBack; - - beforeEach(() => { - classesCallBack = sinon.stub() - .withArgs(row[column.dataField], row, rowIndex, columnIndex) - .returns(returnClasses); - column.classes = classesCallBack; - wrapper = shallow( - ); - }); - - afterEach(() => { classesCallBack.reset(); }); - - it('should render successfully', () => { - expect(wrapper.length).toBe(1); - expect(wrapper.hasClass(returnClasses)).toBe(true); - }); - - it('should call custom classes function correctly', () => { - expect(classesCallBack.callCount).toBe(1); - expect( - classesCallBack.calledWith(row[column.dataField], row, rowIndex, columnIndex) - ).toBe(true); - }); - }); - }); - - describe('when column.title prop is defined', () => { - let column; - const columnIndex = 1; - const rowIndex = 1; - - beforeEach(() => { - column = { - dataField: 'id', - text: 'ID' - }; - }); - - describe('when title is boolean', () => { - beforeEach(() => { - column.title = true; - wrapper = shallow( - ); - }); - - it('should render title as cell value as default', () => { - expect(wrapper.length).toBe(1); - expect(wrapper.find('td').prop('title')).toEqual(row[column.dataField]); - }); - }); - - describe('when title is custom function', () => { - const customTitle = 'test_title'; - let titleCallBack; - - beforeEach(() => { - titleCallBack = sinon.stub() - .withArgs(row[column.dataField], row, rowIndex, columnIndex) - .returns(customTitle); - column.title = titleCallBack; - wrapper = shallow( - ); - }); - - it('should render title correctly by custom title function', () => { - expect(wrapper.length).toBe(1); - expect(wrapper.find('td').prop('title')).toBe(customTitle); - }); - - it('should call custom title function correctly', () => { - expect(titleCallBack.callCount).toBe(1); - expect( - titleCallBack.calledWith(row[column.dataField], row, rowIndex, columnIndex) - ).toBe(true); - }); - }); - }); - - describe('when column.events prop is defined', () => { - let column; - const columnIndex = 1; - const rowIndex = 1; - - beforeEach(() => { - column = { - dataField: 'id', - text: 'ID', - events: { - onClick: sinon.stub() - } - }; - - wrapper = shallow( - ); - }); - - it('should attachs DOM event successfully', () => { - expect(wrapper.length).toBe(1); - expect(wrapper.find('td').prop('onClick')).toBeDefined(); - }); - - it('event hook should be called when triggering', () => { - wrapper.find('td').simulate('click'); - expect(column.events.onClick.callCount).toBe(1); - }); - }); - - describe('when column.align prop is defined', () => { - let column; - const columnIndex = 1; - const rowIndex = 1; - - beforeEach(() => { - column = { - dataField: 'id', - text: 'ID' - }; - }); - - describe('when align is string', () => { - beforeEach(() => { - column.align = 'center'; - wrapper = shallow( - ); - }); - - it('should render style.textAlign correctly', () => { - expect(wrapper.length).toBe(1); - expect(wrapper.find('td').prop('style').textAlign).toEqual(column.align); - }); - }); - - describe('when align is custom function', () => { - const customAlign = 'center'; - let alignCallBack; - - beforeEach(() => { - alignCallBack = sinon.stub() - .withArgs(row[column.dataField], row, rowIndex, columnIndex) - .returns(customAlign); - column.align = alignCallBack; - wrapper = shallow( - ); - }); - - it('should render style.textAlign correctly', () => { - expect(wrapper.length).toBe(1); - expect(wrapper.find('td').prop('style').textAlign).toEqual(customAlign); - }); - - it('should call custom headerAlign function correctly', () => { - expect(alignCallBack.callCount).toBe(1); - expect( - alignCallBack.calledWith(row[column.dataField], row, rowIndex, columnIndex) - ).toBe(true); - }); - }); - }); - - describe('when column.attrs prop is defined', () => { - let column; - const columnIndex = 1; - const rowIndex = 1; - - beforeEach(() => { - column = { - dataField: 'id', - text: 'ID' - }; - }); - - describe('when attrs is an object', () => { - it('should render column.attrs correctly', () => { - column.attrs = { - 'data-test': 'test', - title: 'title', - className: 'attrs-class', - style: { - backgroundColor: 'attrs-style-test', - display: 'none', - textAlign: 'right' - } - }; - wrapper = shallow( - ); - - expect(wrapper.length).toBe(1); - expect(wrapper.find('td').prop('data-test')).toEqual(column.attrs['data-test']); - expect(wrapper.find('td').prop('title')).toEqual(column.attrs.title); - expect(wrapper.hasClass(column.attrs.className)).toBe(true); - expect(wrapper.find('td').prop('style')).toEqual(column.attrs.style); - expect(wrapper.find('td').prop('style').textAlign).toEqual(column.attrs.style.textAlign); - }); - - describe('when column.title prop is defined', () => { - it('attrs.title should be overwrited', () => { - column.title = true; - column.attrs = { title: 'title' }; - - wrapper = shallow( - ); - - expect(wrapper.find('td').prop('title')).toEqual(row[column.dataField]); - }); - }); - - describe('when column.classes prop is defined', () => { - it('attrs.class should be overwrited', () => { - column.classes = 'td-test-class'; - column.attrs = { className: 'attrs-class' }; - - wrapper = shallow( - ); - - expect(wrapper.hasClass(column.classes)).toBe(true); - }); - }); - - describe('when column.style prop is defined', () => { - it('attrs.style should be overwrited', () => { - column.style = { backgroundColor: 'red' }; - column.attrs = { style: { backgroundColor: 'attrs-style-test' } }; - - wrapper = shallow( - ); - - expect(wrapper.find('td').prop('style')).toEqual(column.style); - }); - }); - - describe('when column.align prop is defined', () => { - it('attrs.style.textAlign should be overwrited', () => { - column.align = 'center'; - column.attrs = { style: { textAlign: 'right' } }; - - wrapper = shallow( - ); - - expect(wrapper.find('td').prop('style').textAlign).toEqual(column.align); - }); - }); - }); - - describe('when attrs is custom function', () => { - let attrsCallBack; - const customAttrs = { - title: 'title', - 'data-test': 'test' - }; - - beforeEach(() => { - attrsCallBack = sinon.stub() - .withArgs(row[column.dataField], row, rowIndex, columnIndex) - .returns(customAttrs); - column.attrs = attrsCallBack; - wrapper = shallow( - ); - }); - - it('should render style.attrs correctly', () => { - expect(wrapper.length).toBe(1); - expect(wrapper.find('td').prop('data-test')).toEqual(customAttrs['data-test']); - expect(wrapper.find('td').prop('title')).toEqual(customAttrs.title); - }); - - it('should call custom attrs function correctly', () => { - expect(attrsCallBack.callCount).toBe(1); - expect( - attrsCallBack.calledWith(row[column.dataField], row, rowIndex, columnIndex) - ).toBe(true); - }); - }); - }); - describe('when editable prop is true', () => { let onStartCallBack; const rowIndex = 1; @@ -528,4 +172,259 @@ describe('Cell', () => { }); }); }); + + describe('shouldComponentUpdate', () => { + let props; + let nextProps; + + describe('when content is change', () => { + const column = { dataField: 'name', text: 'Product Name' }; + beforeEach(() => { + props = { + row, + columnIndex: 1, + rowIndex: 1, + column + }; + wrapper = shallow( + ); + }); + + it('should return true', () => { + nextProps = { ...props, row: { id: 1, name: 'CDE' } }; + expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true); + }); + }); + + describe('when column.hidden is change', () => { + const column = { dataField: 'name', text: 'Product Name' }; + beforeEach(() => { + props = { + row, + columnIndex: 1, + rowIndex: 1, + column + }; + wrapper = shallow( + ); + }); + + it('should return true', () => { + nextProps = { ...props, column: { ...column, hidden: true } }; + expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true); + }); + }); + + describe('when props.rowIndex is change', () => { + const column = { dataField: 'name', text: 'Product Name' }; + beforeEach(() => { + props = { + row, + columnIndex: 1, + rowIndex: 1, + column + }; + wrapper = shallow( + ); + }); + + it('should return true', () => { + nextProps = { ...props, rowIndex: 2 }; + expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true); + }); + }); + + describe('when props.columnIndex is change', () => { + const column = { dataField: 'name', text: 'Product Name' }; + beforeEach(() => { + props = { + row, + columnIndex: 1, + rowIndex: 1, + column + }; + wrapper = shallow( + ); + }); + + it('should return true', () => { + nextProps = { ...props, columnIndex: 2 }; + expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true); + }); + }); + + describe('when props.className is change', () => { + const column = { dataField: 'name', text: 'Product Name' }; + beforeEach(() => { + props = { + row, + columnIndex: 1, + rowIndex: 1, + column, + className: 'test' + }; + wrapper = shallow( + ); + }); + + it('should return true', () => { + nextProps = { ...props, className: null }; + expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true); + }); + }); + + describe('when props.title is change', () => { + const column = { dataField: 'name', text: 'Product Name' }; + beforeEach(() => { + props = { + row, + columnIndex: 1, + rowIndex: 1, + column, + title: 'test' + }; + wrapper = shallow( + ); + }); + + it('should return true', () => { + nextProps = { ...props, title: '123' }; + expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true); + }); + }); + + describe('when props.title is change', () => { + const column = { dataField: 'name', text: 'Product Name' }; + beforeEach(() => { + props = { + row, + columnIndex: 1, + rowIndex: 1, + column + }; + wrapper = shallow( + ); + }); + + it('should return true', () => { + nextProps = { ...props, editable: true }; + expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true); + }); + }); + + describe('when props.clickToEdit is change', () => { + const column = { dataField: 'name', text: 'Product Name' }; + beforeEach(() => { + props = { + row, + columnIndex: 1, + rowIndex: 1, + column + }; + wrapper = shallow( + ); + }); + + it('should return true', () => { + nextProps = { ...props, clickToEdit: true }; + expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true); + }); + }); + + describe('when props.dbclickToEdit is change', () => { + const column = { dataField: 'name', text: 'Product Name' }; + beforeEach(() => { + props = { + row, + columnIndex: 1, + rowIndex: 1, + column + }; + wrapper = shallow( + ); + }); + + it('should return true', () => { + nextProps = { ...props, dbclickToEdit: true }; + expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true); + }); + }); + + describe('when props.style is change', () => { + const column = { dataField: 'name', text: 'Product Name' }; + beforeEach(() => { + props = { + row, + columnIndex: 1, + rowIndex: 1, + column, + style: {} + }; + wrapper = shallow( + ); + }); + + it('should return true', () => { + nextProps = { ...props, style: { color: 'red' } }; + expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true); + }); + }); + + describe('when column.formatExtraData is change', () => { + const column = { dataField: 'name', text: 'Product Name', formatExtraData: { a: 1 } }; + beforeEach(() => { + props = { + row, + columnIndex: 1, + rowIndex: 1, + column + }; + wrapper = shallow( + ); + }); + + it('should return true', () => { + nextProps = { ...props, column: { ...column, formatExtraData: { b: 2 } } }; + expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true); + }); + }); + + describe('when column.events is change', () => { + const column = { dataField: 'name', text: 'Product Name', events: { a: jest.fn() } }; + beforeEach(() => { + props = { + row, + columnIndex: 1, + rowIndex: 1, + column + }; + wrapper = shallow( + ); + }); + + it('should return true', () => { + nextProps = { ...props, column: { ...column, events: { b: jest.fn() } } }; + expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true); + }); + }); + + describe('when column.attrs is change', () => { + const column = { dataField: 'name', text: 'Product Name', attrs: { 'data-att': 1 } }; + beforeEach(() => { + props = { + row, + columnIndex: 1, + rowIndex: 1, + column + }; + wrapper = shallow( + ); + }); + + it('should return true', () => { + nextProps = { ...props, column: { ...column, attrs: null } }; + expect(wrapper.instance().shouldComponentUpdate(nextProps)).toBe(true); + }); + }); + }); }); diff --git a/packages/react-bootstrap-table2/test/row.test.js b/packages/react-bootstrap-table2/test/row.test.js index 117a24f..621f140 100644 --- a/packages/react-bootstrap-table2/test/row.test.js +++ b/packages/react-bootstrap-table2/test/row.test.js @@ -8,7 +8,7 @@ import Const from '../src/const'; import SelectionCell from '../src//row-selection/selection-cell'; import mockBodyResolvedProps from './test-helpers/mock/body-resolved-props'; -const defaultColumns = [{ +let defaultColumns = [{ dataField: 'id', text: 'ID' }, { @@ -31,6 +31,19 @@ describe('Row', () => { price: 1000 }; + beforeEach(() => { + defaultColumns = [{ + dataField: 'id', + text: 'ID' + }, { + dataField: 'name', + text: 'Name' + }, { + dataField: 'price', + text: 'Price' + }]; + }); + describe('simplest row', () => { beforeEach(() => { wrapper = shallow( @@ -502,7 +515,7 @@ describe('Row', () => { }); }); - describe('when cloumn.hidden is true', () => { + describe('when column.hidden is true', () => { beforeEach(() => { const newColumns = [{ dataField: 'id', @@ -870,4 +883,445 @@ describe('Row', () => { }); }); }); + + describe('when column.style prop is defined', () => { + let columns; + const columnIndex = 1; + + beforeEach(() => { + columns = [...defaultColumns]; + }); + + describe('when style is an object', () => { + beforeEach(() => { + columns[columnIndex].style = { backgroundColor: 'red' }; + wrapper = shallow( + + ); + }); + + it('should render Cell correctly', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.find(Cell).get(columnIndex).props.style).toEqual(columns[columnIndex].style); + }); + }); + + describe('when style is a function', () => { + const returnStyle = { backgroundColor: 'red' }; + let styleCallBack; + + beforeEach(() => { + styleCallBack = sinon.stub().returns(returnStyle); + columns[columnIndex].style = styleCallBack; + wrapper = shallow( + + ); + }); + + afterEach(() => { styleCallBack.reset(); }); + + it('should render Cell correctly', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.find(Cell).get(columnIndex).props.style).toEqual(returnStyle); + }); + + it('should call custom style function correctly', () => { + expect(styleCallBack.callCount).toBe(1); + expect( + styleCallBack.calledWith(row[columns[columnIndex].dataField], row, rowIndex, columnIndex) + ).toBe(true); + }); + }); + }); + + describe('when column.classes prop is defined', () => { + let columns; + const columnIndex = 1; + + beforeEach(() => { + columns = [...defaultColumns]; + }); + + describe('when classes is an object', () => { + beforeEach(() => { + columns[columnIndex].classes = 'td-test-class'; + wrapper = shallow( + + ); + }); + + it('should render Cell correctly', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.find(Cell).get(columnIndex).props.className) + .toEqual(columns[columnIndex].classes); + }); + }); + + describe('when classes is a function', () => { + const returnClasses = 'td-test-class'; + let classesCallBack; + + beforeEach(() => { + classesCallBack = sinon.stub().returns(returnClasses); + columns[columnIndex].classes = classesCallBack; + wrapper = shallow( + + ); + }); + + afterEach(() => { classesCallBack.reset(); }); + + it('should render Cell correctly', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.find(Cell).get(columnIndex).props.className).toEqual(returnClasses); + }); + + it('should call custom classes function correctly', () => { + expect(classesCallBack.callCount).toBe(1); + expect( + classesCallBack.calledWith( + row[columns[columnIndex].dataField], row, rowIndex, columnIndex) + ).toBe(true); + }); + }); + }); + + describe('when column.title prop is defined', () => { + let columns; + const columnIndex = 1; + + beforeEach(() => { + columns = [...defaultColumns]; + }); + + describe('when title is an string', () => { + beforeEach(() => { + columns[columnIndex].title = true; + wrapper = shallow( + + ); + }); + + it('should render Cell correctly', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.find(Cell).get(columnIndex).props.title) + .toEqual(row[columns[columnIndex].dataField]); + }); + }); + + describe('when title is a function', () => { + const returnTitle = 'test title'; + let titleCallBack; + + beforeEach(() => { + titleCallBack = sinon.stub().returns(returnTitle); + columns[columnIndex].title = titleCallBack; + wrapper = shallow( + + ); + }); + + afterEach(() => { titleCallBack.reset(); }); + + it('should render Cell correctly', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.find(Cell).get(columnIndex).props.title).toEqual(returnTitle); + }); + + it('should call custom title function correctly', () => { + expect(titleCallBack.callCount).toBe(1); + expect( + titleCallBack.calledWith( + row[columns[columnIndex].dataField], row, rowIndex, columnIndex) + ).toBe(true); + }); + }); + }); + + describe('when column.events prop is defined', () => { + let columns; + const columnIndex = 1; + + beforeEach(() => { + columns = [...defaultColumns]; + columns[columnIndex].events = { + onClick: sinon.stub() + }; + + wrapper = shallow( + + ); + }); + + it('should attachs DOM event successfully', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.find(Cell).get(columnIndex).props.onClick).toBeDefined(); + }); + }); + + describe('when column.align prop is defined', () => { + let columns; + const columnIndex = 1; + + beforeEach(() => { + columns = [...defaultColumns]; + }); + + describe('when align is a string', () => { + beforeEach(() => { + columns[columnIndex].align = 'right'; + wrapper = shallow( + + ); + }); + + it('should render Cell correctly', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.find(Cell).get(columnIndex).props.style.textAlign) + .toEqual(columns[columnIndex].align); + }); + }); + + describe('when align is a function', () => { + const returnAlign = 'right'; + let alignCallBack; + + beforeEach(() => { + alignCallBack = sinon.stub().returns(returnAlign); + columns[columnIndex].align = alignCallBack; + wrapper = shallow( + + ); + }); + + afterEach(() => { alignCallBack.reset(); }); + + it('should render Cell correctly', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.find(Cell).get(columnIndex).props.style.textAlign).toEqual(returnAlign); + }); + + it('should call custom align function correctly', () => { + expect(alignCallBack.callCount).toBe(1); + expect( + alignCallBack.calledWith(row[columns[columnIndex].dataField], row, rowIndex, columnIndex) + ).toBe(true); + }); + }); + }); + + describe('when column.attrs prop is defined', () => { + let columns; + const columnIndex = 1; + + beforeEach(() => { + columns = [...defaultColumns]; + }); + + describe('when attrs is an object', () => { + it('should render Cell correctly', () => { + columns[columnIndex].attrs = { + 'data-test': 'test', + title: 'title', + className: 'attrs-class', + style: { + backgroundColor: 'attrs-style-test', + display: 'none', + textAlign: 'right' + } + }; + + wrapper = shallow( + + ); + + expect(wrapper.length).toBe(1); + expect(wrapper.find(Cell).get(columnIndex).props['data-test']) + .toEqual(columns[columnIndex].attrs['data-test']); + expect(wrapper.find(Cell).get(columnIndex).props.title) + .toEqual(columns[columnIndex].attrs.title); + expect(wrapper.find(Cell).get(columnIndex).props.className) + .toEqual(columns[columnIndex].attrs.className); + expect(wrapper.find(Cell).get(columnIndex).props.style) + .toEqual(columns[columnIndex].attrs.style); + }); + + describe('when column.title prop is defined', () => { + it('attrs.title should be overwrited', () => { + columns[columnIndex].title = true; + columns[columnIndex].attrs = { title: 'title' }; + + wrapper = shallow( + + ); + + expect(wrapper.find(Cell).get(columnIndex).props.title) + .toEqual(row[columns[columnIndex].dataField]); + }); + }); + + describe('when column.classes prop is defined', () => { + it('attrs.className should be overwrited', () => { + columns[columnIndex].classes = 'td-test-class'; + columns[columnIndex].attrs = { className: 'attrs-class' }; + + wrapper = shallow( + + ); + + expect(wrapper.find(Cell).get(columnIndex).props.className) + .toEqual(columns[columnIndex].classes); + }); + }); + + describe('when column.style prop is defined', () => { + it('attrs.style should be overwrited', () => { + columns[columnIndex].style = { backgroundColor: 'red' }; + columns[columnIndex].attrs = { style: { backgroundColor: 'attrs-style-test' } }; + + wrapper = shallow( + + ); + + expect(wrapper.find(Cell).get(columnIndex).props.style) + .toEqual(columns[columnIndex].style); + }); + }); + + describe('when column.align prop is defined', () => { + it('attrs.style.textAlign should be overwrited', () => { + columns[columnIndex].align = 'center'; + columns[columnIndex].attrs = { style: { textAlign: 'right' } }; + + wrapper = shallow( + + ); + + expect(wrapper.find(Cell).get(columnIndex).props.style.textAlign) + .toEqual(columns[columnIndex].align); + }); + }); + }); + + describe('when attrs is custom function', () => { + let attrsCallBack; + const customAttrs = { + 'data-test': 'test', + title: 'title' + }; + + beforeEach(() => { + attrsCallBack = sinon.stub().returns(customAttrs); + columns[columnIndex].attrs = attrsCallBack; + wrapper = shallow( + + ); + }); + + it('should render style.attrs correctly', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.find(Cell).get(columnIndex).props['data-test']) + .toEqual(customAttrs['data-test']); + expect(wrapper.find(Cell).get(columnIndex).props.title) + .toEqual(customAttrs.title); + }); + + it('should call custom attrs function correctly', () => { + expect(attrsCallBack.callCount).toBe(1); + expect( + attrsCallBack.calledWith(row[columns[columnIndex].dataField], row, rowIndex, columnIndex) + ).toBe(true); + }); + }); + }); });