d2-ui
Version:
235 lines (177 loc) • 9.09 kB
JavaScript
import React from 'react';
import { describeWithDOM, shallow } from 'enzyme';
import DataTable from '../DataTable.component';
import DataTableHeader from '../DataTableHeader.component';
import DataTableContextMenu from '../DataTableContextMenu.component';
import Popover from 'material-ui/Popover/Popover';
describe('DataTable component', () => {
let dataTableComponent;
const cma = {
edit(...args) {
console.log('Edit', ...args);
},
remove(...args) {
console.log('Remove', ...args);
},
};
function renderComponent(props = {}) {
return shallow(<DataTable {...Object.assign({ contextMenuActions: cma }, props)} />);
}
beforeEach(() => {
dataTableComponent = renderComponent();
});
describe('initial state', () => {
it('should have set the default columns', () => {
expect(dataTableComponent.state('columns')).toEqual(['name', 'lastUpdated']);
});
it('should have a data-table row', () => {
expect(dataTableComponent.hasClass('data-table')).toBe(true);
});
});
describe('with headers', () => {
it('should have set the passed columns', () => {
const columns = ['name', 'code', 'lastUpdated'];
dataTableComponent = renderComponent({ columns });
expect(dataTableComponent.state('columns')).toEqual(['name', 'code', 'lastUpdated']);
});
it('should not set the columns if the column value is not an array of strings', () => {
const columns = ['name', 'code', 'lastUpdated', {}];
dataTableComponent = renderComponent({ columns });
expect(dataTableComponent.state('columns')).toEqual(['name', 'lastUpdated']);
});
it('should generate the headers wrap', () => {
expect(dataTableComponent.find('.data-table__headers')).toHaveLength(1);
});
it('should generate the correct number of headers', () => {
expect(dataTableComponent.find(DataTableHeader)).toHaveLength(3);
});
});
it('should have a property for rows that is empty', () => {
expect(Array.isArray(dataTableComponent.state().dataRows)).toBe(true);
});
describe('with source', () => {
beforeEach(() => {
const dataTableSource = [
{ uid: 'b1', name: 'BDC', lastUpdated: 'Tomorrow' },
{ uid: 'f1', name: 'BFG', lastUpdated: 'Last year' },
{ uid: 'c1', name: 'BFG', lastUpdated: 'Today' },
];
dataTableComponent = renderComponent({ rows: dataTableSource });
});
it('should have set the dataRows onto the state', () => {
expect(dataTableComponent.state('dataRows')).toHaveLength(3);
});
it('should not set the dataRows when the received value is not iterable', () => {
dataTableComponent = renderComponent({ rows: {} });
expect(dataTableComponent.state('dataRows')).toHaveLength(0);
});
it('should generate a row wrap', () => {
expect(dataTableComponent.find('.data-table__rows')).toHaveLength(1);
});
it('should update the source when the rows property changes', () => {
dataTableComponent.setProps({ rows: [{ uid: 'b1', name: 'BDC', lastUpdated: 'Tomorrow' }] });
expect(dataTableComponent.state('dataRows').length).toBe(1);
});
it('should correctly render a map', () => {
dataTableComponent.setProps({
rows: new Map([
['b1', { uid: 'b1', name: 'BDC', lastUpdated: 'Tomorrow' }],
['f1', { uid: 'f1', name: 'BFG', lastUpdated: 'Last year' }],
['c1', { uid: 'c1', name: 'BFG', lastUpdated: 'Today' }],
]),
});
expect(dataTableComponent.state('dataRows')).toHaveLength(3);
});
});
describe('interaction', () => {
beforeEach(() => {
const dataTableSource = [
{ uid: 'b1', name: 'BDC', lastUpdated: 'Tomorrow' },
{ uid: 'f1', name: 'BFG', lastUpdated: 'Last year' },
{ uid: 'c1', name: 'BFG', lastUpdated: 'Today' },
];
dataTableComponent = renderComponent({ source: dataTableSource });
});
it('should show the context menu when the activeRow state is set', () => {
const fakeRowSource = { name: 'My item' };
expect(dataTableComponent.find('.data-table__context-menu')).toHaveLength(0);
dataTableComponent.instance()
.handleRowClick(
{ currentTarget: dataTableComponent },
fakeRowSource,
);
dataTableComponent.update();
const contextMenuComponent = dataTableComponent.find(DataTableContextMenu);
expect(contextMenuComponent).toHaveLength(1);
expect(contextMenuComponent.props().target).toEqual(dataTableComponent);
});
it('should hide the context menu when handleRowClick is called twice with the same source', () => {
const fakeRowSource = { name: 'My item' };
dataTableComponent.instance().handleRowClick({ clientY: 100, clientX: 100 }, fakeRowSource);
dataTableComponent.update();
dataTableComponent.instance().handleRowClick({ clientY: 100, clientX: 100 }, fakeRowSource);
dataTableComponent.update();
const contextMenuComponent = dataTableComponent.find('.data-table__context-menu');
expect(contextMenuComponent).toHaveLength(0);
});
it('should not render the context menu when the activeRow is undefined', () => {
const fakeRowSource = { name: 'My item' };
dataTableComponent.setState({ contextMenuTarget: {}, activeRow: fakeRowSource });
dataTableComponent.instance().hideContextMenu();
dataTableComponent.update();
const contextMenuComponent = dataTableComponent.find('.data-table__context-menu');
expect(contextMenuComponent).toHaveLength(0);
expect(dataTableComponent.state('activeRow')).toBe(undefined);
});
it('should initially not show the contextmenu', () => {
expect(dataTableComponent.find('.data-table__context-menu')).toHaveLength(0);
});
// TODO: The Popover requires a dom element as a targetEl prop. Figure out how to test this without a DOM.
xit('should hide the contextmenu when left clicking outside the contextmenu', () => {
const fakeRowSource = { name: 'My item' };
dataTableComponent.instance()
.handleRowClick(
{ currentTarget: dataTableComponent },
fakeRowSource,
);
dataTableComponent.update();
expect(dataTableComponent.find('.data-table__context-menu')).toHaveLength(1);
// onRequestClose is called when clicking outside the menu
dataTableComponent.find(Popover).props().onRequestClose();
dataTableComponent.update();
expect(dataTableComponent.find('.data-table__context-menu')).toHaveLength(0);
});
});
describe('context menu action filtering', () => {
let isContextActionAllowed;
let contextMenuActions;
let fakeRowSource;
beforeEach(() => {
fakeRowSource = { name: 'My item' };
isContextActionAllowed = jest.fn().mockReturnValue(true);
contextMenuActions = {
edit: () => {},
delete: () => {},
translate: () => {},
};
dataTableComponent = renderComponent({ isContextActionAllowed, contextMenuActions });
});
it('should pass through when the actions are allowed', () => {
// Show context menu initially
dataTableComponent.setState({ contextMenuTarget: {}, activeRow: fakeRowSource });
const passedContextMenuActions = dataTableComponent.find(DataTableContextMenu).props().actions;
expect(Object.keys(passedContextMenuActions)).toEqual(['edit', 'delete', 'translate']);
});
it('should not pass actions that are not allowed', () => {
const falseForDeleteActionType = (source, action) => action !== 'delete';
isContextActionAllowed
.mockReset()
.mockImplementation(falseForDeleteActionType);
dataTableComponent = renderComponent({ isContextActionAllowed, contextMenuActions });
// Show context menu initially
dataTableComponent.setState({ contextMenuTarget: {}, activeRow: fakeRowSource });
const passedContextMenuActions = dataTableComponent.find(DataTableContextMenu).props().actions;
expect(Object.keys(passedContextMenuActions)).toEqual(['edit', 'translate']);
});
});
});