diff --git a/.babelrc b/.babelrc index 6a8d7e6f93..a7f236c7f6 100644 --- a/.babelrc +++ b/.babelrc @@ -1,8 +1,12 @@ { - "presets": ["react", "es2015-loose"], - "plugins": [ - 'transform-class-properties', - 'transform-es3-member-expression-literals', - 'transform-es3-property-literals' - ] + "presets": [ + "es2015", + "react", + "stage-2" + ], + "plugins": [ + "transform-class-properties", + "transform-es3-member-expression-literals", + "transform-es3-property-literals" + ] } diff --git a/.gitignore b/.gitignore index 2a80f45d60..603cbbba15 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ dist npm-debug.log lerna-debug.log **.orig -.vscode \ No newline at end of file +.vscode +package-lock.json diff --git a/appveyor.yml b/appveyor.yml index 01980f51cd..6efd6ff970 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,6 +17,7 @@ environment: # Install scripts. (runs after repo cloning) install: + - ps: Install-Product node 6 # Decrypt .npmrc.enc file for publishing purposes if not pull request build and not scheduled build # Lerna needs to have a npmrc for each package folder as it does not use the root npmrc https://github.com/lerna/lerna/issues/296#issuecomment-261080345 - ps: >- @@ -25,9 +26,8 @@ install: ./ci/publish/copy-npmrc.ps1 } - set PATH=%APPDATA%\npm;%PATH% - - npm cache clean - - npm install -g gulp - npm install + - npm install gulp -g - ps: ./ci/buildScripts/build.ps1 # Post-install test scripts. diff --git a/lerna.json b/lerna.json index 23084d29e3..f139fa506c 100644 --- a/lerna.json +++ b/lerna.json @@ -1,4 +1,7 @@ { - "lerna": "2.0.0-beta.34", - "version": "4.0.8" + "lerna": "2.8.0", + "version": "4.0.8", + "packages": [ + "packages/*" + ] } diff --git a/package.json b/package.json index 3ee18d4df1..58fbecd215 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "fs-extra": "^0.30.0", "keymirror": "^0.1.1", "object-assign": "^4.1.1", - "prop-types": "^15.5.10", + "prop-types": "^15.6.1", "react-contextmenu": "^2.9.2", "react-dnd": "^2.5.4", "react-dnd-html5-backend": "^2.5.4", @@ -46,11 +46,9 @@ "babel-plugin-transform-class-properties": "^6.4.0", "babel-plugin-transform-es3-member-expression-literals": "^6.5.0", "babel-plugin-transform-es3-property-literals": "^6.5.0", - "babel-plugin-transform-react-jsx": "^6.4.0", - "babel-plugin-typecheck": "^3.6.1", "babel-preset-es2015": "^6.9.0", - "babel-preset-es2015-loose": "^7.0.0", "babel-preset-react": "^6.3.13", + "babel-preset-stage-2": "^6.24.1", "copy-dir": "^0.3.0", "css-loader": "^0.26.0", "del": "^1.2.1", @@ -81,7 +79,7 @@ "karma-phantomjs-launcher-nonet": "^0.1.3", "karma-sourcemap-loader": "^0.3.7", "karma-webpack": "^1.7.0", - "lerna": "2.0.0-beta.34", + "lerna": "^2.8.0", "minimist": "^1.1.0", "mkdirp": "^0.5.1", "moment": "^2.10.6", diff --git a/packages/react-data-grid-addons/src/__tests__/Grid.spec.js b/packages/react-data-grid-addons/src/__tests__/Grid.spec.js index 4b9a9c4438..b25db98412 100644 --- a/packages/react-data-grid-addons/src/__tests__/Grid.spec.js +++ b/packages/react-data-grid-addons/src/__tests__/Grid.spec.js @@ -199,22 +199,6 @@ describe('Grid', function() { }); }); - describe('When cell selection disabled', function() { - beforeEach(function() { - this.component = this.createComponent({ - enableCellSelect: false, - columns: this.columns, - rowGetter: this.rowGetter, - rowsCount: this._rows.length, - width: 300 - }).instance(); - }); - - it('grid should be initialized with selected state of {rowIdx : -1, idx : -1}', function() { - expect(this.component.state.selected).toEqual({ rowIdx: -1, idx: -1 }); - }); - }); - describe('When row selection enabled', function() { beforeEach(function() { this.component = this.createComponent({ enableRowSelect: true}).instance(); @@ -299,178 +283,6 @@ describe('Grid', function() { }); }); - describe('Cell Navigation', function() { - describe('when cell navigation is configured to default, none', function() { - beforeEach(function() { - this.component = this.createComponent({enableCellSelect: true}).instance(); - }); - - describe('when on last cell in a row', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 3, rowIdx: 1 } }); - }); - it('selection should stay on cell', function() { - this.simulateGridKeyDown('ArrowRight'); - expect(this.component.state.selected).toEqual({ idx: 3, rowIdx: 1 }); - }); - }); - describe('when on first cell in row', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 0, rowIdx: 1 } }); - }); - it('nothing should happen', function() { - this.simulateGridKeyDown('ArrowLeft'); - expect(this.component.state.selected).toEqual({ idx: 0, rowIdx: 1 }); - }); - }); - describe('when row selection is enabled and positioned on cell before last in row', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 2, rowIdx: 1 }, enableRowSelect: true }); - }); - it('selection should move to last cell', function() { - this.simulateGridKeyDown('ArrowRight'); - expect(this.component.state.selected).toEqual({ idx: 3, rowIdx: 1 }); - }); - }); - }); - - describe('when cell navigation is configured to change rows', function() { - beforeEach(function() { - this.component = this.createComponent({cellNavigationMode: 'changeRow', enableCellSelect: true}).instance(); - }); - - describe('when on last cell in a row that\'s not the last', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 3, rowIdx: 1 } }); - }); - it('selection should move to first cell in next row', function() { - this.simulateGridKeyDown('ArrowRight'); - expect(this.component.state.selected).toEqual({ idx: 0, rowIdx: 2 }); - }); - }); - describe('when on last cell in last row', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 3, rowIdx: 999 } }); - }); - it('nothing should happen', function() { - this.simulateGridKeyDown('ArrowRight'); - expect(this.component.state.selected).toEqual({ idx: 3, rowIdx: 999 }); - }); - }); - describe('when on first cell in a row that\'s not the first', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 0, rowIdx: 2 } }); - }); - it('selection should move to last cell in previous row', function() { - this.simulateGridKeyDown('ArrowLeft'); - expect(this.component.state.selected).toEqual({ idx: 3, rowIdx: 1 }); - }); - }); - describe('when on first cell in the first row', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 0, rowIdx: 0 } }); - }); - it('nothing should happen', function() { - this.simulateGridKeyDown('ArrowLeft'); - expect(this.component.state.selected).toEqual({ idx: 0, rowIdx: 0 }); - }); - }); - describe('when row selection is enabled and positioned on cell before last in row', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 2, rowIdx: 1 }, enableRowSelect: true }); - }); - it('selection should move to last cell', function() { - this.simulateGridKeyDown('ArrowRight'); - expect(this.component.state.selected).toEqual({ idx: 3, rowIdx: 1 }); - }); - }); - }); - - describe('when cell navigation is configured to loop over cells in row', function() { - beforeEach(function() { - this.component = this.createComponent({cellNavigationMode: 'loopOverRow', enableCellSelect: true}).instance(); - }); - - describe('when on last cell, looping enabled', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 3, rowIdx: 1 } }); - }); - it('selection should move to first cell in same row', function() { - this.simulateGridKeyDown('ArrowRight'); - expect(this.component.state.selected).toEqual({ idx: 0, rowIdx: 1 }); - }); - }); - describe('when on last cell in last row with looping enabled', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 3, rowIdx: 999 } }); - }); - it('selection should move to first cell in same row', function() { - this.simulateGridKeyDown('ArrowRight'); - expect(this.component.state.selected).toEqual({ idx: 0, rowIdx: 999 }); - }); - }); - describe('when on first cell with looping enabled', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 0, rowIdx: 2 } }); - }); - it('selection should move to last cell in same row', function() { - this.simulateGridKeyDown('ArrowLeft'); - expect(this.component.state.selected).toEqual({ idx: 3, rowIdx: 2 }); - }); - }); - describe('when on first cell in first row with looping enabled', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 0, rowIdx: 0 } }); - }); - it('selection should move to last cell in same row', function() { - this.simulateGridKeyDown('ArrowLeft'); - expect(this.component.state.selected).toEqual({ idx: 3, rowIdx: 0 }); - }); - }); - - describe('when row selection enabled and positioned on cell before last in row', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 2, rowIdx: 1 }, enableRowSelect: true }); - }); - it('selection should move to last cell', function() { - this.simulateGridKeyDown('ArrowRight'); - expect(this.component.state.selected).toEqual({ idx: 3, rowIdx: 1 }); - }); - }); - }); - }); - describe('Cell Selection/DeSelection handlers', function() { - describe('when cell selection/deselection handlers are passed', function() { - beforeEach(function() { - const extraProps = { onCellSelected: this.noop, onCellDeSelected: this.noop }; - spyOn(extraProps, 'onCellSelected'); - spyOn(extraProps, 'onCellDeSelected'); - this.component = this.createComponent(extraProps).instance(); - }); - - describe('cell is selected', function() { - beforeEach(function() { - this.component.setState({ selected: { rowIdx: 1, idx: 2 } }); - }); - it('deselection handler should have been called', function() { - this.simulateGridKeyDown('ArrowRight'); - expect(this.component.props.onCellDeSelected).toHaveBeenCalled(); - expect(this.component.props.onCellDeSelected.calls.mostRecent().args[0]).toEqual({ - rowIdx: 1, - idx: 2 - }); - }); - it('selection handler should have been called', function() { - this.simulateGridKeyDown('ArrowRight'); - expect(this.component.props.onCellSelected).toHaveBeenCalled(); - expect(this.component.props.onCellSelected.calls.mostRecent().args[0]).toEqual({ - rowIdx: 1, - idx: 3 - }); - }); - }); - }); - }); describe('When selection enabled and using rowSelection props', function() { beforeEach(function() { @@ -609,397 +421,6 @@ describe('Grid', function() { }); }); - describe('User Interaction', function() { - describe('When selected cell is in top corner of grid', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 0, rowIdx: 0 } }); - }); - - it('on ArrowUp keyboard event should not change selected index', function() { - this.simulateGridKeyDown('ArrowUp'); - expect(this.component.state.selected).toEqual({ idx: 0, rowIdx: 0 }); - }); - - it('on ArrowLeft keyboard event should not change selected index', function() { - this.simulateGridKeyDown('ArrowLeft'); - expect(this.component.state.selected).toEqual({ idx: 0, rowIdx: 0 }); - }); - }); - - describe('When selected cell has adjacent cells on all sides', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 1, rowIdx: 1 } }); - }); - - it('on ArrowRight keyboard event should increment selected cell index by 1', function() { - this.simulateGridKeyDown('ArrowRight'); - expect(this.component.state.selected).toEqual({ idx: 2, rowIdx: 1 }); - }); - - it('on ArrowDown keyboard event should increment selected row index by 1', function() { - this.simulateGridKeyDown('ArrowDown'); - expect(this.component.state.selected).toEqual({ idx: 1, rowIdx: 2 }); - }); - - it('on ArrowLeft keyboard event should decrement selected row index by 1', function() { - this.simulateGridKeyDown('ArrowLeft'); - expect(this.component.state.selected).toEqual({ idx: 0, rowIdx: 1 }); - }); - - it('on ArrowUp keyboard event should decrement selected row index by 1', function() { - this.simulateGridKeyDown('ArrowUp'); - expect(this.component.state.selected).toEqual({ idx: 1, rowIdx: 0 }); - }); - }); - - describe('When column is editable', function() { - beforeEach(function() { - const editableColumn = Object.assign({ editable: true }, this.columns[1]); - this.columns[1] = editableColumn; - this.component = this.createComponent({ columns: this.columns }).instance(); - }); - - describe('copy a cell value', function() { - beforeEach(function() { - const cCharacterKeyCode = 99; - this.component.setState({ selected: { idx: 1, rowIdx: 1 } }); - this.simulateGridKeyDown(cCharacterKeyCode, true); - }); - - it('should store the value in grid state', function() { - let expectedCellValue = this._rows[1].title; - expect(this.component.state.textToCopy).toEqual(expectedCellValue); - expect(this.component.state.copied).toEqual({ idx: 1, rowIdx: 1 }); - }); - }); - - describe('paste a cell value', function() { - beforeEach(function() { - let wrapper = this.createComponent(); - const vCharacterKeyCode = 118; - spyOn(this.testProps, 'onCellCopyPaste'); - wrapper.setProps({ onCellCopyPaste: this.testProps.onCellCopyPaste }); - this.component = wrapper.instance(); - this.component.setState({ - textToCopy: 'banana', - selected: { idx: 1, rowIdx: 5 }, - copied: { idx: 1, rowIdx: 1 } - }); - this.simulateGridKeyDown(vCharacterKeyCode, true); - }); - - it('should call onCellCopyPaste of component with correct params', function() { - expect(this.component.props.onCellCopyPaste).toHaveBeenCalled(); - expect(this.component.props.onCellCopyPaste.calls.mostRecent().args[0]).toEqual({ - cellKey: 'title', - rowIdx: 5, - value: 'banana', - fromRow: 1, - toRow: 5 - }); - }); - }); - - describe('cell commit cancel', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 1, rowIdx: 1, active: true } }); - this.getCellMetaData().onCommitCancel(); - }); - - it('should set grid state inactive', function() { - expect(this.component.state.selected).toEqual({ idx: 1, rowIdx: 1, active: false }); - }); - }); - - describe('pressing escape', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 1, rowIdx: 1, active: true } }); - this.simulateGridKeyDown('Escape'); - }); - - it('should set grid state inactive', function() { - expect(this.component.state.selected).toEqual({ idx: 1, rowIdx: 1, active: false }); - }); - }); - - describe('pressing enter', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 1, rowIdx: 1, active: false } }); - this.simulateGridKeyDown('Enter'); - }); - - it('should set grid state active', function() { - expect(this.component.state.selected).toEqual({ idx: 1, rowIdx: 1, active: true, initialKeyCode: 'Enter' }); - }); - }); - - describe('pressing delete', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 1, rowIdx: 1, active: false } }); - this.simulateGridKeyDown('Delete'); - }); - - it('should set grid state active', function() { - expect(this.component.state.selected).toEqual({ idx: 1, rowIdx: 1, active: true, initialKeyCode: 'Delete' }); - }); - }); - - describe('pressing backspace', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 1, rowIdx: 1, active: false } }); - this.simulateGridKeyDown('Backspace'); - }); - - it('should set grid state active', function() { - expect(this.component.state.selected).toEqual({ idx: 1, rowIdx: 1, active: true, initialKeyCode: 'Backspace' }); - }); - }); - - describe('typing a char', function() { - beforeEach(function() { - const fakeEvent = this.buildFakeEvent({ keyCode: 66, key: 'Unidentified' }); - this.component.setState({ selected: { idx: 1, rowIdx: 1, active: false } }); - this.getBaseGrid().props.onViewportKeydown(fakeEvent); - }); - - it('should set grid state active and store the typed value', function() { - expect(this.component.state.selected).toEqual({ idx: 1, rowIdx: 1, active: true, initialKeyCode: 66 }); - }); - }); - }); - - describe('Drag events', function() { - describe('dragging in grid', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 1, rowIdx: 2 } }); - const event = { target: { className: 'drag-handle' }}; - this.getBaseGrid().props.onViewportDragStart(event); - }); - - it('should store drag rowIdx, idx and value of cell in state', function() { - const thirdRowTitle = this._rows[2].title; - expect(this.component.state.dragged).toEqual({ idx: 1, rowIdx: 2, value: thirdRowTitle }); - }); - }); - - describe('dragging over a row', function() { - beforeEach(function() { - this.component.setState({ - selected: { idx: 1, rowIdx: 2 }, - dragged: { idx: 1, rowIdx: 2, value: 'apple', overRowIdx: 6 } - }); - this.getCellMetaData().handleDragEnterRow(4); - }); - - it('should store the current rowIdx in grid state', function() { - expect(this.component.state.dragged).toEqual({ idx: 1, rowIdx: 2, value: 'apple', overRowIdx: 4 }); - }); - }); - - describe('finishing drag', function() { - beforeEach(function() { - let wrapper = this.createComponent(); - spyOn(this.testProps, 'onCellsDragged'); - wrapper.setProps({ onCellsDragged: this.testProps.onCellsDragged }); - this.component = wrapper.instance(); - this.component.setState({ - selected: { idx: 1, rowIdx: 2 }, - dragged: { idx: 1, rowIdx: 2, value: 'apple', overRowIdx: 6 } - }); - this.getBaseGrid().props.onViewportDragEnd(); - }); - - it('should trigger onCellsDragged event and call it with correct params', function() { - expect(this.component.props.onCellsDragged).toHaveBeenCalled(); - expect(this.component.props.onCellsDragged.calls.argsFor(0)[0]).toEqual({ cellKey: 'title', fromRow: 2, toRow: 6, value: 'apple' }); - }); - }); - - describe('terminating drag', function() { - beforeEach(function() { - this.component.setState({ dragged: { idx: 1, rowIdx: 2, value: 'apple', overRowIdx: 6 } }); - this.getCellMetaData().handleTerminateDrag(); - }); - - it('should clear drag state', function() { - expect(this.component.state.dragged).toBe(null); - }); - }); - }); - - describe('Adding a new column', function() { - beforeEach(function() { - let wrapper = this.createComponent(); - const newColumn = { key: 'isodd', name: 'Is Odd', width: 100 }; - const newColumns = Object.assign([], this.columns); - newColumns.splice(2, 0, newColumn); - wrapper.setProps({ columns: newColumns }); - this.component = wrapper.instance(); - this.columns = this.component.state.columnMetrics.columns; - }); - - it('should add column', function() { - expect(this.columns.length).toEqual(5); - }); - - it('should calculate column metrics for added column', function() { - expect(this.columns[2]).toEqual(jasmine.objectContaining({ key: 'isodd', name: 'Is Odd', width: 100 })); - }); - }); - - describe('Remove a column', function() { - beforeEach(function() { - let wrapper = this.createComponent(); - const newColumns = Object.assign([], this.columns); - newColumns.splice(1, 1); - wrapper.setProps({ columns: newColumns }); - this.component = wrapper.instance(); - this.columns = this.component.state.columnMetrics.columns; - }); - - it('should remove column', function() { - expect(this.columns.length).toEqual(3); - }); - - it('should no longer include metrics for removed column', function() { - expect(this.columns[0]).toEqual(jasmine.objectContaining({ key: 'id', name: 'ID', width: 100 })); - expect(this.columns[1]).toEqual(jasmine.objectContaining({ key: 'count', name: 'Count', width: 100 })); - }); - }); - - describe('outside row/cell', function() { - beforeEach(function() { - this.component.setState({ selected: { idx: 1, rowIdx: 1 } }); - }); - - it('should deselect currently selected cell on click', function() { - this.getBaseGrid().props.onViewportClick(); - expect(this.component.state.selected).toEqual(jasmine.objectContaining({ idx: -1, rowIdx: -1 })); - }); - - it('should deselect currently selected cell on double-click', function() { - this.getBaseGrid().props.onViewportDoubleClick(); - expect(this.component.state.selected).toEqual(jasmine.objectContaining({ idx: -1, rowIdx: -1 })); - }); - }); - }); - - describe('Cell Meta Data', function() { - it('should create a cellMetaData object and pass to baseGrid as props', function() { - let meta = this.getCellMetaData(); - expect(meta).toEqual(jasmine.objectContaining({ - selected: { rowIdx: 0, idx: 0 }, - dragged: null, - copied: null - })); - expect(meta.onCellClick).toEqual(jasmine.any(Function)); - expect(meta.onCommit).toEqual(jasmine.any(Function)); - expect(meta.onCommitCancel).toEqual(jasmine.any(Function)); - expect(meta.handleDragEnterRow).toEqual(jasmine.any(Function)); - expect(meta.handleTerminateDrag).toEqual(jasmine.any(Function)); - }); - - describe('Changing Grid state', function() { - beforeEach(function() { - let newState = { - selected: { idx: 2, rowIdx: 2 }, - dragged: { idx: 2, rowIdx: 2 } - }; - this.component.setState(newState); - }); - - it(' should update cellMetaData', function() { - expect(this.getCellMetaData()).toEqual(jasmine.objectContaining({ - selected: { idx: 2, rowIdx: 2 }, - dragged: { idx: 2, rowIdx: 2 } - })); - }); - }); - - describe('cell commit', function() { - beforeEach(function() { - let wrapper = this.createComponent(); - spyOn(this.testProps, 'onRowUpdated'); - wrapper.setProps({ onRowUpdated: this.testProps.onRowUpdated }); - this.component = wrapper.instance(); - this.component.setState({ selected: { idx: 3, rowIdx: 3, active: true } }); - this.getCellMetaData().onCommit(this.buildFakeCellUodate()); - }); - - it('should trigger onRowUpdated with correct params', function() { - const onRowUpdated = this.component.props.onRowUpdated; - expect(onRowUpdated.calls.mostRecent().args[0]).toEqual(this.buildFakeCellUodate()); - }); - - it('should deactivate selected cell', function() { - expect(this.component.state.selected).toEqual(jasmine.objectContaining({ idx: 3, rowIdx: 3, active: false })); - }); - }); - - describe('Cell click', function() { - beforeEach(function() { - this.getCellMetaData().onCellClick({ idx: 2, rowIdx: 2 }); - }); - - it('should set selected state of grid', function() { - expect(this.component.state.selected).toEqual({ idx: 2, rowIdx: 2 }); - }); - }); - - describe('Column events', function() { - let columnWithEvent; - const eventColumnIdx = 3; - const eventColumnRowIdx = 2; - const eventColumnRowId = 2; - - beforeEach(function() { - columnWithEvent = this.component.state.columnMetrics.columns[3]; - let events = this.testProps.columns[3].events; - spyOn(events, 'onClick'); - spyOn(events, 'onDoubleClick'); - spyOn(events, 'onDragOver'); - }); - - it('should call an event when there is one', function() { - this.getCellMetaData().onColumnEvent({}, {idx: eventColumnIdx, rowIdx: eventColumnRowIdx, name: 'onClick'}); - expect(columnWithEvent.events.onClick).toHaveBeenCalled(); - }); - - it('should call the correct event', function() { - this.getCellMetaData().onColumnEvent({}, {idx: eventColumnIdx, rowIdx: eventColumnRowIdx, name: 'onClick'}); - expect(columnWithEvent.events.onClick).toHaveBeenCalled(); - expect(columnWithEvent.events.onDoubleClick).not.toHaveBeenCalled(); - }); - - it('should call double click event on double click', function() { - this.getCellMetaData().onColumnEvent({}, {idx: eventColumnIdx, rowIdx: eventColumnRowIdx, name: 'onDoubleClick'}); - - expect(columnWithEvent.events.onDoubleClick).toHaveBeenCalled(); - }); - - it('should call drag over event on drag over click', function() { - this.getCellMetaData().onColumnEvent({}, {idx: eventColumnIdx, rowIdx: eventColumnRowIdx, name: 'onDragOver'}); - - expect(columnWithEvent.events.onDragOver).toHaveBeenCalled(); - }); - - it('should call the event when there is one with the correct args', function() { - this.getCellMetaData().onColumnEvent({}, {idx: eventColumnIdx, rowIdx: eventColumnRowIdx, rowId: eventColumnRowId, name: 'onClick'}); - expect(columnWithEvent.events.onClick.calls.mostRecent().args).toEqual([{}, {column: columnWithEvent, idx: eventColumnIdx, rowIdx: eventColumnRowIdx, rowId: eventColumnRowId }]); - }); - - it('events should work for the first column', function() { - const firstColumnIdx = 0; - let firstColumn = this.component.state.columnMetrics.columns[firstColumnIdx]; - let firstColumnEvents = this.testProps.columns[firstColumnIdx].events; - spyOn(firstColumnEvents, 'onClick'); - this.getCellMetaData().onColumnEvent({}, {idx: firstColumnIdx, rowIdx: eventColumnRowIdx, rowId: eventColumnRowId, name: 'onClick'}); - - expect(firstColumn.events.onClick).toHaveBeenCalled(); - }); - }); - }); - describe('changes to non metric column data', function() { beforeEach(function() { let wrapper = this.createComponent(); diff --git a/packages/react-data-grid-addons/src/__tests__/RowsContainerWithAddons.spec.js b/packages/react-data-grid-addons/src/__tests__/RowsContainerWithAddons.spec.js deleted file mode 100644 index c0aac0df72..0000000000 --- a/packages/react-data-grid-addons/src/__tests__/RowsContainerWithAddons.spec.js +++ /dev/null @@ -1,37 +0,0 @@ -import React from 'react'; -import ReactTestUtils from 'react-dom/test-utils'; -import { RowsContainer } from 'react-data-grid'; -import { Menu } from '../../'; -const { ContextMenu } = Menu; - -describe('RowsContainer with addons', () => { - describe('with context menu', () => { - let componentWithContextMenu; - const fakeRowIdx = 1; - const fakeIdx = 5; - - beforeEach(() => { - componentWithContextMenu = ReactTestUtils.renderIntoDocument( - } - rowIdx={fakeRowIdx} - idx={fakeIdx} /> - ); - }); - - it('should create a new RowsContainer instance', () => { - expect(componentWithContextMenu).toBeDefined(); - }); - - it('should render the context menu', () => { - let contextMenu = ReactTestUtils.findRenderedComponentWithType(componentWithContextMenu, ContextMenu); - expect(contextMenu).toBeDefined(); - }); - - it('should propagate the row idx and idx props to the context menu', () => { - let contextMenu = ReactTestUtils.findRenderedComponentWithType(componentWithContextMenu, ContextMenu); - expect(contextMenu.props.rowIdx).toEqual(fakeRowIdx); - expect(contextMenu.props.idx).toEqual(fakeIdx); - }); - }); -}); diff --git a/packages/react-data-grid-addons/src/__tests__/data/MockStateObject.js b/packages/react-data-grid-addons/src/__tests__/data/MockStateObject.js index 5908ed96b7..6f7820ead8 100644 --- a/packages/react-data-grid-addons/src/__tests__/data/MockStateObject.js +++ b/packages/react-data-grid-addons/src/__tests__/data/MockStateObject.js @@ -29,17 +29,11 @@ module.exports = function(stateValues, events) { minColumnWidth: 80 }, selectedRows: [], - selected: { - rowIdx: 0, - idx: 0 - }, - copied: null, canFilter: false, expandedRows: [], columnFilters: {}, sortDirection: null, sortColumn: null, - dragged: null, scrollOffset: 0, lastRowIdxUiSelected: -1 }, stateValues); diff --git a/packages/react-data-grid-examples/src/__tests__/Grid.integration-spec.js b/packages/react-data-grid-examples/src/__tests__/Grid.integration-spec.js index 0d4796cf10..2dc9d326c8 100644 --- a/packages/react-data-grid-examples/src/__tests__/Grid.integration-spec.js +++ b/packages/react-data-grid-examples/src/__tests__/Grid.integration-spec.js @@ -32,210 +32,4 @@ describe('Grid Integration', () => { expect(gridRunner.getRenderedRows().length).toEqual(expectedNumberOfRows); }); }); - - describe('Copy and paste', () => { - it('copies a cell', () => { - gridRunner - .selectCell({cellIdx: 3, rowIdx: 3}) - .copy() - .hasCopied({cellIdx: 3, rowIdx: 3}); - }); - - it('copying a second cell removes the copying style from first cell', () => { - let firstCellIdx = 3; - gridRunner.selectCell({cellIdx: firstCellIdx, rowIdx: 1}).copy(); - - let firstCell = gridRunner.getCell({cellIdx: firstCellIdx, rowIdx: 1}); - expect(firstCell.getDOMNode().className.indexOf('copied') > -1).toBe(true); - - gridRunner.selectCell({cellIdx: 4, rowIdx: 1}) - .copy(); - expect(firstCell.getDOMNode().className.indexOf('copied') > -1).toBe(false); - }); - }); - - describe('Drag', () => { - it('Shows drag selector', () => { - gridRunner.drag({ - from: 0, - to: 4, - col: 4, - beforeEnd: () => { - // check we have the right classes - expect(TestUtils.scryRenderedDOMComponentsWithClass(component, 'is-dragged-over-down').length).toEqual(1); - expect(TestUtils.scryRenderedDOMComponentsWithClass(component, 'was-dragged-over').length).toEqual(2); - } - }); - }); - - it('Drags a column down', () => { - gridRunner.drag({from: 0, to: 4, col: 4}) - .hasDragged({from: 0, to: 4, col: 4, cellKey: 'title'}); - }); - - it('Drags a column up', () => { - // React-data-grid treats a drag up as a drag down, so need to assert using the - // drag down equivalent of our drag event. - gridRunner.drag({from: 4, to: 0, col: 5}) - .hasDragged({ from: 0, to: 4, col: 5, cellKey: 'firstName' }); - }); - }); - - describe('Selection', () => { - it('Selects on click', () => { - gridRunner.selectCell({cellIdx: 3, rowIdx: 3}) - .hasSelected({cellIdx: 3, rowIdx: 3}) - .dispose(); - }); - }); - - describe('Editors', () => { - it('Readonly columns are NOT Editable', () => { - gridRunner.clickIntoEditor({cellIdx: 0, rowIdx: 3}) - .isNotEditable(); - }); - - it('Enter commits an edit', () => { - gridRunner.changeCell({ - select: {row: 3, cell: 5}, - val: 'Test', - ev: {key: 'Enter'}, - expectToSelect: {row: 3, cell: 5} - }); - }); - - it('Start editing by pressing a key', () => { - const letterEKeyCode = 69; - const coords = {rowIdx: 3, cellIdx: 5}; - gridRunner.selectCell(coords) - .keyDown({ - keyCode: letterEKeyCode - }, gridRunner.cell ) - .resetCell(coords) - .isEditable() - .resetCell(coords) - .keyDown({key: 'Enter'}) - .resetCell(coords) - .hasCommitted('E') // keydown ALWAYS upper case http://stackoverflow.com/questions/2263889/why-always-uppercase-in-my-code - .isNotEditable() - .dispose(); - }); - - it('Start editing by pressing enter', () => { - const coords = {rowIdx: 3, cellIdx: 5}; - gridRunner.selectCell(coords) - .resetCell(coords) - .keyDown({key: 'Enter'}, gridRunner.cell) - .resetCell(coords) - .isEditable() - .dispose(); - }); - - it('Can tab out of an Editor', () => { - gridRunner.changeCell({ - select: {row: 3, cell: 5}, - val: 'Test', - ev: {key: 'Tab'}, - expectToSelect: {row: 3, cell: 6} - }); - }); - - it('Can shift+tab out of an Editor', () => { - gridRunner.changeCell({ - select: {row: 3, cell: 5}, - val: 'Test', - ev: {key: 'Tab', shiftKey: true}, - expectToSelect: {row: 3, cell: 4} - }); - }); - - it('should commit editor changes on blur', () => { - gridRunner = new GridRunner({}); - gridRunner.clickIntoEditor({ rowIdx: 3, cellIdx: 5}) - .resetCell({ rowIdx: 3, cellIdx: 5}) - .setValue('Test') - .selectCell({ rowIdx: 4, cellIdx: 3 }) - .selectCell({ rowIdx: 3, cellIdx: 5 }) - .hasCommitted('Test') - .dispose(); - }); - - it('Arrow Left doesnt commit your change if you are not at the start of the text', () => { - gridRunner = new GridRunner({renderIntoBody: true}); - const coords = {rowIdx: 3, cellIdx: 4}; - gridRunner.clickIntoEditor(coords) - .resetCell(coords) - .setValue('Test') - .resetCell(coords) - .setCursor(2) - .resetCell(coords) - .keyDown({key: 'ArrowLeft'}) - .isEditable() - // Need to escape the editor here since dispose will prompt componentWillUnmount, - // committing the text and causing a re-render as the grid unmounts. - .keyDown({ key: 'Escape' }) - .dispose(); - }); - - it('Arrow Left does commit your change if you are at the start of the text', () => { - // by default we are at pos 0 with a blank value - gridRunner.changeCell({ - select: {row: 3, cell: 4}, - val: '', - ev: {key: 'ArrowLeft'}, - expectToSelect: {row: 3, cell: 3} - }); - }); - - it('Arrow Right commits your change when you are at the end of the text', () => { - gridRunner = new GridRunner({renderIntoBody: true}); - const coords = {rowIdx: 3, cellIdx: 4}; - gridRunner.clickIntoEditor(coords) - .resetCell(coords) - .setValue('Test') - .resetCell(coords) - .setCursor(4) - .resetCell(coords) - .keyDown({key: 'ArrowRight'}) - .resetCell(coords) - .hasCommitted('Test') - .hasSelected({rowIdx: 3, cellIdx: 5}) - .dispose(); - }); - - it('Arrow Right doesnt commit your change when you are not at the end of the text', () => { - gridRunner = new GridRunner({renderIntoBody: true}); - const coords = {rowIdx: 3, cellIdx: 4}; - gridRunner.clickIntoEditor(coords) - .resetCell(coords) - .setValue('Test') - .resetCell(coords) - .setCursor(2) - .resetCell(coords) - .keyDown({key: 'ArrowRight'}) - .isEditable() - // Need to escape the editor here since dispose will prompt componentWillUnmount, - // committing the text and causing a re-render as the grid unmounts. - .keyDown({ key: 'Escape' }) - .dispose(); - }); - - it('Arrow Up commits your change', () => { - gridRunner.changeCell({ - select: {row: 3, cell: 4}, - val: 'Test', - ev: {key: 'ArrowUp'}, - expectToSelect: {row: 2, cell: 4} - }); - }); - - it('Arrow Down commits your change', () => { - gridRunner.changeCell({ - select: {row: 3, cell: 4}, - val: 'Test', - ev: {key: 'ArrowDown'}, - expectToSelect: {row: 4, cell: 4} - }); - }); - }); }); diff --git a/packages/react-data-grid-examples/src/assets/fonts/fontawesome-webfont.ttf b/packages/react-data-grid-examples/src/assets/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000000..35acda2fa1 Binary files /dev/null and b/packages/react-data-grid-examples/src/assets/fonts/fontawesome-webfont.ttf differ diff --git a/packages/react-data-grid-examples/src/assets/fonts/fontawesome-webfont.woff b/packages/react-data-grid-examples/src/assets/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000000..400014a4b0 Binary files /dev/null and b/packages/react-data-grid-examples/src/assets/fonts/fontawesome-webfont.woff differ diff --git a/packages/react-data-grid-examples/src/assets/fonts/fontawesome-webfont.woff2 b/packages/react-data-grid-examples/src/assets/fonts/fontawesome-webfont.woff2 new file mode 100644 index 0000000000..4d13fc6040 Binary files /dev/null and b/packages/react-data-grid-examples/src/assets/fonts/fontawesome-webfont.woff2 differ diff --git a/packages/react-data-grid-examples/src/components/Home.js b/packages/react-data-grid-examples/src/components/Home.js index 35aad423d5..ae869b5b55 100644 --- a/packages/react-data-grid-examples/src/components/Home.js +++ b/packages/react-data-grid-examples/src/components/Home.js @@ -23,25 +23,25 @@ function Home() {
-
+

Lightning Fast Rendering

Combines the performance power of React as well as partial rendering techniques in order to smoothly scroll though hundreds of thousands of rows.

-
+

Rich Editing and Formatting

View and edit cells using a wide range of formatters and editors. If these don't suit your needs, you can easily create and plugin your own

-
+

Configurable & Customizable

Quickly configure and customise features such as grid and column properties, row and cell renderers. As the Grid is a React component it is easy to extend and add custom functionality.

-
+

Packed full of Excel Features

Full keyboard navigation, cell copy & paste, cell drag down, frozen columns, column resizing, sorting, filtering and many more features on the way.

diff --git a/packages/react-data-grid-examples/src/index.html b/packages/react-data-grid-examples/src/index.html index a4fda9b6eb..fb74c66d7a 100644 --- a/packages/react-data-grid-examples/src/index.html +++ b/packages/react-data-grid-examples/src/index.html @@ -21,11 +21,12 @@ + - + @@ -37,7 +38,7 @@ -
+