UNPKG

@salesforce/design-system-react

Version:

Salesforce Lightning Design System for React

639 lines (560 loc) 16.7 kB
/* eslint-disable max-lines */ import React from 'react'; import ReactDOM from 'react-dom'; import TestUtils from 'react-dom/test-utils'; import chai, { expect } from 'chai'; import Dropdown from '../../menu-dropdown'; import DataTable from '../../data-table'; import DataTableColumn from '../../data-table/column'; import DataTableRowActions from '../../data-table/row-actions'; import DataTableHighlightCell from '../../data-table/highlight-cell'; import IconSettings from '../../icon-settings'; chai.should(); const { Simulate, scryRenderedComponentsWithType, findRenderedDOMComponentWithClass, } = TestUtils; describe('DataTable: ', function describeFunction() { const items = [ { id: '8IKZHZZV80', name: 'Cloudhub', count: 100976, lastModified: 'Yesterday', }, { id: '5GJOOOPWU7', name: 'Cloudhub + Anypoint Connectors', count: 54976, lastModified: 'Today', }, { id: 'Q8Z71ZUCEZ', name: 'Cloud City', count: 101280, lastModified: 'Today', }, { id: '2FSH2DP0LY', name: 'IoT', count: 976, lastModified: 'Yesterday', }, { id: '8NE888QKV1', name: 'IoT + Anypoint Connectors', count: 54976, lastModified: 'Today', }, { id: 'M4D37GW83H', name: 'Salesforce Tower', count: 101280, lastModified: 'Today', }, ]; const columns = [ { label: 'Name', property: 'name', truncate: true, }, { label: 'Count', property: 'count', sortable: true, }, ]; const defaultProps = { id: 'DataTableExample-default', items, selectRows: true, }; const renderTable = (instance) => function renderTableFunction() { this.dom = document.createElement('div'); document.body.appendChild(this.dom); this.component = ReactDOM.render( <IconSettings iconPath="/assets/icons">{instance}</IconSettings>, this.dom ); }; function removeTable() { ReactDOM.unmountComponentAtNode(this.dom); document.body.removeChild(this.dom); } const getTable = (dom) => dom.querySelector('.slds-table'); const getRow = (dom, row) => { const tbody = getTable(dom).querySelectorAll('tbody')[0]; return tbody.querySelectorAll('tr')[row - 1]; }; const getCell = (dom, row, column) => { const tr = getRow(dom, row); return tr.querySelectorAll('td')[column]; }; const getMenu = (dom) => dom.querySelector('.slds-dropdown'); describe('Structure', function describeFunction2() { beforeEach( renderTable( <DataTable {...defaultProps}> {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} </DataTable> ) ); afterEach(removeTable); it('has a header', function() { const thead = getTable(this.dom).querySelectorAll('thead'); thead.should.have.length(1); thead[0].querySelectorAll('th').should.have.length(3); }); it('has a row for each item', function() { const tbody = getTable(this.dom).querySelectorAll('tbody'); tbody.should.have.length(1); tbody[0].querySelectorAll('tr').should.have.length(6); }); it('renders the correct contents in each cell', function() { const firstName = getCell(this.dom, 1, 1); firstName.innerHTML.should.equal( '<div class="" title="Cloudhub">Cloudhub</div>' ); const secondCount = getCell(this.dom, 2, 2); secondCount.innerHTML.should.equal( '<div class="" title="54976">54976</div>' ); }); it('has checkboxes when selectRows is true or "checkbox"', function() { let checkboxes = getTable(this.dom).querySelectorAll('.slds-checkbox'); checkboxes.should.have.length(7); removeTable.call(this); renderTable( <DataTable {...defaultProps} selectRows={false}> {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} </DataTable> ).call(this); checkboxes = getTable(this.dom).querySelectorAll('.slds-checkbox'); checkboxes.should.have.length(0); removeTable.call(this); renderTable( <DataTable {...defaultProps} selectRows="checkbox"> {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} </DataTable> ).call(this); checkboxes = getTable(this.dom).querySelectorAll('.slds-checkbox'); checkboxes.should.have.length(7); }); it('has radios only when selectRows is "radio"', function() { const checkboxes = getTable(this.dom).querySelectorAll('.slds-checkbox'); checkboxes.should.have.length(7); removeTable.call(this); renderTable( <DataTable {...defaultProps} selectRows="radio"> {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} </DataTable> ).call(this); const radios = getTable(this.dom).querySelectorAll('.slds-radio'); radios.should.have.length(6); }); }); describe('Selectable - Checkbox', function describeFunction2() { const defaultSelection = [ { id: '8IKZHZZV80', name: 'Cloudhub', count: 100976, lastModified: 'Yesterday', }, ]; afterEach(removeTable); it('can start with a row selected', function() { renderTable( <DataTable {...defaultProps} selection={defaultSelection}> {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} </DataTable> ).call(this); const tbody = getTable(this.dom).querySelectorAll('tbody')[0]; const selectedRows = tbody.querySelectorAll('tr.slds-is-selected'); selectedRows.should.have.length(1); const checkedBoxes = tbody.querySelectorAll( '.slds-checkbox input:checked' ); checkedBoxes.should.have.length(1); }); it('can deselect a row', function(done) { this.onRowChange = (event, { selection }) => { selection.should.have.length(0); done(); }; renderTable( <DataTable {...defaultProps} selection={defaultSelection} onRowChange={this.onRowChange} > {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} </DataTable> ).call(this); const tbody = getTable(this.dom).querySelectorAll('tbody')[0]; const selectedRow = tbody.querySelectorAll('tr.slds-is-selected')[0]; const checkbox = selectedRow.querySelectorAll('.slds-checkbox input')[0]; Simulate.change(checkbox, { target: { checked: false } }); }); it('can select a row', function(done) { this.onRowChange = (event, { selection }) => { selection.should.have.length(2); selection[1].id.should.equal('5GJOOOPWU7'); done(); }; renderTable( <DataTable {...defaultProps} selection={defaultSelection} onRowChange={this.onRowChange} > {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} </DataTable> ).call(this); const secondRow = getRow(this.dom, 2); const checkbox = secondRow.querySelectorAll('.slds-checkbox input')[0]; Simulate.change(checkbox, { target: { checked: true } }); }); it('can select all rows', function(done) { this.onRowChange = (event, { selection }) => { selection.should.have.length(6); done(); }; renderTable( <DataTable {...defaultProps} onRowChange={this.onRowChange}> {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} </DataTable> ).call(this); const thead = getTable(this.dom).querySelectorAll('thead')[0]; const checkAll = thead.querySelectorAll('.slds-checkbox input')[0]; Simulate.change(checkAll, { target: { checked: true } }); }); it('can deselect all rows', function(done) { this.onRowChange = (event, { selection }) => { selection.should.have.length(0); done(); }; renderTable( <DataTable {...defaultProps} selection={items} onRowChange={this.onRowChange} > {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} </DataTable> ).call(this); const thead = getTable(this.dom).querySelectorAll('thead')[0]; const checkAll = thead.querySelectorAll('.slds-checkbox input')[0]; Simulate.change(checkAll, { target: { checked: false } }); }); }); describe('Selectable - Radio', function describeFunction2() { const defaultSelection = [ { id: '8IKZHZZV80', name: 'Cloudhub', count: 100976, lastModified: 'Yesterday', }, ]; afterEach(removeTable); it('can start with a row selected', function() { renderTable( <DataTable {...defaultProps} selection={defaultSelection} selectRows="radio" > {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} </DataTable> ).call(this); const tbody = getTable(this.dom).querySelectorAll('tbody')[0]; const selectedRows = tbody.querySelectorAll('tr.slds-is-selected'); selectedRows.should.have.length(1); const radios = tbody.querySelectorAll('.slds-radio input:checked'); radios.should.have.length(1); }); it('can select a row', function(done) { this.onRowChange = (event, { selection }) => { selection.should.have.length(1); selection[0].id.should.equal('5GJOOOPWU7'); done(); }; renderTable( <DataTable {...defaultProps} selection={defaultSelection} selectRows="radio" onRowChange={this.onRowChange} > {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} </DataTable> ).call(this); const secondRow = getRow(this.dom, 2); const radio = secondRow.querySelectorAll('.slds-radio input')[0]; Simulate.change(radio, { target: { checked: true } }); }); }); describe('Sortable', function describeFunction2() { afterEach(removeTable); it('first clicked on sortable column header should result in ascending sort by default', function(done) { this.onSort = (data) => { data.property.should.equal('count'); data.sortDirection.should.equal('asc'); done(); }; renderTable( <DataTable {...defaultProps} fixedLayout onSort={this.onSort}> {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} </DataTable> ).call(this); const thead = getTable(this.dom).querySelectorAll('thead')[0]; const sortButton = thead.querySelectorAll('a')[0]; Simulate.click(sortButton, {}); }); it('if isDefaultSortDescending is true, first click on sortable column header should result in descending order', function(done) { this.onSort = (data) => { data.property.should.equal('count'); data.sortDirection.should.equal('desc'); done(); }; renderTable( <DataTable {...defaultProps} fixedLayout onSort={this.onSort}> {columns.map((columnProps) => ( <DataTableColumn {...columnProps} isDefaultSortDescending key={columnProps.property} /> ))} </DataTable> ).call(this); const thead = getTable(this.dom).querySelectorAll('thead')[0]; const sortButton = thead.querySelectorAll('a')[0]; Simulate.click(sortButton, {}); }); it('does not call onSort when a non-sortable column is clicked', function(done) { this.onSort = () => { done('sort called'); }; renderTable( <DataTable {...defaultProps} onSort={this.onSort}> {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} </DataTable> ).call(this); const thead = getTable(this.dom).querySelectorAll('thead')[0]; const secondColumn = thead.querySelectorAll('th')[1]; Simulate.click(secondColumn, {}); setTimeout(done, 0); }); }); describe('w/ RowActions', function describeFunction2() { afterEach(removeTable); it('renders the RowActions and uses dropdown override property', function() { renderTable( <DataTable {...defaultProps}> {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} <DataTableRowActions dropdown={ <Dropdown options={[ { id: 0, label: 'Add to Group', value: '1', }, { id: 1, label: 'Publish', value: '2', }, ]} /> } /> </DataTable> ).call(this); const rowActionMenus = scryRenderedComponentsWithType( this.component, DataTableRowActions ); rowActionMenus.should.have.length(6); }); it('calls onAction & onSelect when an action is clicked', function(done) { let expectedCalbacks = 2; this.onAction = (item, action) => { item.id.should.equal('8IKZHZZV80'); action.value.should.equal('1'); // eslint-disable-next-line no-plusplus if (!--expectedCalbacks) done(); }; this.onSelect = (action) => { action.value.should.equal('1'); // eslint-disable-next-line no-plusplus if (!--expectedCalbacks) done(); }; renderTable( <DataTable {...defaultProps}> {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property} /> ))} <DataTableRowActions onAction={this.onAction} options={[ { id: 0, label: 'Add to Group', value: '1', }, { id: 1, label: 'Publish', value: '2', }, ]} dropdown={<Dropdown onSelect={this.onSelect} />} /> </DataTable> ).call(this); const rowActionMenu = scryRenderedComponentsWithType( this.component, DataTableRowActions )[0]; const trigger = findRenderedDOMComponentWithClass( rowActionMenu, 'slds-button' ); Simulate.click(trigger, {}); setTimeout(() => { const menu = getMenu(document.body); const firstAction = menu.querySelectorAll('.slds-dropdown__item')[0]; Simulate.click(firstAction.querySelector('a'), {}); }, 0); }); }); describe('w/ HighlightCell', function describeFunction2() { afterEach(removeTable); it('marks the appropriate text in a cell', function() { renderTable( <DataTable {...defaultProps} search="Cloud"> {columns.map((columnProps) => ( <DataTableColumn {...columnProps} key={columnProps.property}> <DataTableHighlightCell /> </DataTableColumn> ))} </DataTable> ).call(this); const secondRow = getRow(this.dom, 2); const markedText = secondRow.querySelectorAll('mark')[0]; markedText.innerHTML.should.equal('Cloud'); }); }); describe('w/ Fixed Headers', function describeFunction2() { afterEach(removeTable); it('Renders a fixedHeader table as expected', function() { renderTable( <DataTable {...defaultProps} fixedHeader fixedLayout id="DataTable-FixedHeader-Test" onFixedHeaderResize={(event, data) => { expect(Array.isArray(data.headerRefs)).to.eql(true); expect(data.headerRefs.length).to.eql(4); data.headerRefs.forEach((ref) => { expect(typeof ref).to.eql('object'); }); expect(typeof data.scrollerRef).to.eql('object'); expect( data.scrollerRef.className.search( 'slds-table_header-fixed_scroller' ) >= 0 ).to.eql(true); }} onToggleFixedHeaderListeners={(event, data) => { expect(typeof data.attach).to.eql('boolean'); expect(typeof data.resizeHandler).to.eql('function'); expect(typeof data.scrollerRef).to.eql('object'); expect( data.scrollerRef.className.search( 'slds-table_header-fixed_scroller' ) >= 0 ).to.eql(true); }} selectRows="checkbox" > <DataTableColumn isSorted label="Name" primaryColumn property="name" sortable sortDirection="asc" /> <DataTableColumn label="Count" property="count" /> <DataTableRowActions options={[ { id: 0, label: 'Add to Group', value: '1', }, { id: 1, label: 'Publish', value: '2', }, ]} onAction={() => {}} dropdown={<Dropdown length="5" />} /> </DataTable> ).call(this); expect( this.dom.querySelectorAll('.slds-table_header-fixed_container').length ).to.eql(1); expect( this.dom.querySelectorAll('.slds-table_header-fixed_scroller').length ).to.eql(1); expect( this.dom .querySelector('table.slds-table') .className.search('slds-table_header-fixed') >= 0 ).to.eql(true); expect(this.dom.querySelectorAll('thead .slds-cell-fixed').length).to.eql( 4 ); }); }); });