new react tests with enzyme library (#1116)
* move ImportDialogBox into a folder * install enzyme * start testing InfoAndHelp component * add star logic to tests * switch ImportDialogBox to using enzyme but tests are still failing * make `npm run test` work * tests pass again * eslint * try to fix travis by adding react-addons-test-utils again * eslintrc for test dir * remove duplicated code * fix * try to suppress 2 warnings
This commit is contained in:
parent
74df2559a4
commit
edce66c44d
9 changed files with 184 additions and 62 deletions
5
frontend/test/.eslintrc.js
Normal file
5
frontend/test/.eslintrc.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = {
|
||||||
|
"rules": {
|
||||||
|
"no-unused-expressions": "off"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,8 @@
|
||||||
/* global describe, it */
|
/* global describe, it */
|
||||||
|
|
||||||
import chai from 'chai'
|
import { expect } from 'chai'
|
||||||
|
|
||||||
import Import from '../src/Metamaps/Import'
|
import Import from '../../src/Metamaps/Import.js'
|
||||||
|
|
||||||
const { expect } = chai
|
|
||||||
|
|
||||||
describe('Metamaps.Import.js', function() {
|
describe('Metamaps.Import.js', function() {
|
||||||
it('has a topic whitelist', function() {
|
it('has a topic whitelist', function() {
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
/* global describe, it */
|
/* global describe, it */
|
||||||
|
|
||||||
import chai from 'chai'
|
import { expect } from 'chai'
|
||||||
|
|
||||||
import Util from '../src/Metamaps/Util'
|
import Util from '../../src/Metamaps/Util'
|
||||||
|
|
||||||
const { expect } = chai
|
|
||||||
|
|
||||||
describe('Metamaps.Util.js', function() {
|
describe('Metamaps.Util.js', function() {
|
||||||
describe('splitLine', function() {
|
describe('splitLine', function() {
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
/* global describe, it */
|
|
||||||
import React from 'react'
|
|
||||||
import TestUtils from 'react-addons-test-utils' // ES6
|
|
||||||
import ImportDialogBox from '../../src/components/ImportDialogBox.js'
|
|
||||||
import Dropzone from 'react-dropzone'
|
|
||||||
import chai from 'chai'
|
|
||||||
|
|
||||||
const { expect } = chai
|
|
||||||
|
|
||||||
describe('ImportDialogBox', function() {
|
|
||||||
it('has an Export CSV button', function(done) {
|
|
||||||
const onExport = format => {
|
|
||||||
if (format === 'csv') done()
|
|
||||||
}
|
|
||||||
const detachedComp = TestUtils.renderIntoDocument(<ImportDialogBox onExport={onExport} />)
|
|
||||||
const button = TestUtils.findRenderedDOMComponentWithClass(detachedComp, 'export-csv')
|
|
||||||
const buttonNode = React.findDOMNode(button)
|
|
||||||
expect(button).to.exist;
|
|
||||||
TestUtils.Simulate.click(buttonNode)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('has an Export JSON button', function(done) {
|
|
||||||
const onExport = format => {
|
|
||||||
if (format === 'json') done()
|
|
||||||
}
|
|
||||||
const detachedComp = TestUtils.renderIntoDocument(<ImportDialogBox onExport={onExport} />)
|
|
||||||
const button = TestUtils.findRenderedDOMComponentWithClass(detachedComp, 'export-json')
|
|
||||||
const buttonNode = React.findDOMNode(button)
|
|
||||||
expect(button).to.exist;
|
|
||||||
TestUtils.Simulate.click(buttonNode)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('has a Download screenshot button', function(done) {
|
|
||||||
const downloadScreenshot = () => { done() }
|
|
||||||
const detachedComp = TestUtils.renderIntoDocument(<ImportDialogBox downloadScreenshot={downloadScreenshot()} />)
|
|
||||||
const button = TestUtils.findRenderedDOMComponentWithClass(detachedComp, 'download-screenshot')
|
|
||||||
const buttonNode = React.findDOMNode(button)
|
|
||||||
expect(button).to.exist;
|
|
||||||
TestUtils.Simulate.click(buttonNode)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('has a file uploader', function(done) {
|
|
||||||
const uploadedFile = { file: 'mock a file' }
|
|
||||||
const onFileAdded = file => { if (file === uploadedFile) done() }
|
|
||||||
const detachedComp = TestUtils.renderIntoDocument(<ImportDialogBox onExport={() => {}} onFileAdded={onFileAdded} />)
|
|
||||||
const dropzone = TestUtils.findRenderedComponentWithType(detachedComp, Dropzone)
|
|
||||||
expect(dropzone).to.exist;
|
|
||||||
dropzone.props.onDropAccepted([uploadedFile], { preventDefault: () => {} })
|
|
||||||
})
|
|
||||||
})
|
|
58
frontend/test/components/MapView/ImportDialogBox.spec.js
Normal file
58
frontend/test/components/MapView/ImportDialogBox.spec.js
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/* global describe, it */
|
||||||
|
import React from 'react'
|
||||||
|
import ImportDialogBox from '../../../src/components/MapView/ImportDialogBox.js'
|
||||||
|
import Dropzone from 'react-dropzone'
|
||||||
|
import { expect } from 'chai'
|
||||||
|
import { shallow } from 'enzyme'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
|
||||||
|
describe('ImportDialogBox', function() {
|
||||||
|
const csvExport = sinon.spy()
|
||||||
|
const jsonExport = sinon.spy()
|
||||||
|
const onExport = format => () => {
|
||||||
|
if (format === 'csv') {
|
||||||
|
csvExport()
|
||||||
|
} else if (format === 'json') {
|
||||||
|
jsonExport()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testExportButton = ({ description, cssClass, exporter }) => {
|
||||||
|
it(description, () => {
|
||||||
|
const wrapper = shallow(<ImportDialogBox onExport={onExport} />)
|
||||||
|
const button = wrapper.find(cssClass)
|
||||||
|
expect(button).to.exist
|
||||||
|
button.simulate('click')
|
||||||
|
expect(exporter).to.have.property('callCount', 1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
testExportButton({
|
||||||
|
description: 'has an Export CSV button',
|
||||||
|
cssClass: '.export-csv',
|
||||||
|
exporter: csvExport
|
||||||
|
})
|
||||||
|
testExportButton({
|
||||||
|
description: 'has an Export JSON button',
|
||||||
|
cssClass: '.export-json',
|
||||||
|
exporter: jsonExport
|
||||||
|
})
|
||||||
|
|
||||||
|
it('has a Download screenshot button', () => {
|
||||||
|
const downloadScreenshot = sinon.spy()
|
||||||
|
const wrapper = shallow(<ImportDialogBox onExport={() => null} downloadScreenshot={downloadScreenshot} />)
|
||||||
|
const button = wrapper.find('.download-screenshot')
|
||||||
|
expect(button).to.exist
|
||||||
|
button.simulate('click')
|
||||||
|
expect(downloadScreenshot).to.have.property('callCount', 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('has a file uploader', () => {
|
||||||
|
const uploadedFile = {}
|
||||||
|
const onFileAdded = sinon.spy()
|
||||||
|
const wrapper = shallow(<ImportDialogBox onExport={() => null} onFileAdded={onFileAdded} />)
|
||||||
|
const dropzone = wrapper.find(Dropzone)
|
||||||
|
dropzone.props().onDropAccepted([uploadedFile], { preventDefault: () => {} })
|
||||||
|
expect(onFileAdded).to.have.property('callCount', 1)
|
||||||
|
expect(onFileAdded.calledWith(uploadedFile)).to.equal(true)
|
||||||
|
})
|
||||||
|
})
|
101
frontend/test/components/common/InfoAndHelp.spec.js
Normal file
101
frontend/test/components/common/InfoAndHelp.spec.js
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/* global describe, it */
|
||||||
|
import React from 'react'
|
||||||
|
import { expect } from 'chai'
|
||||||
|
import { shallow } from 'enzyme'
|
||||||
|
import sinon from 'sinon'
|
||||||
|
|
||||||
|
import InfoAndHelp from '../../../src/components/common/InfoAndHelp.js'
|
||||||
|
import MapInfoBox from '../../../src/components/MapView/MapInfoBox.js'
|
||||||
|
|
||||||
|
function assertTooltip({ wrapper, description, cssClass, tooltipText, callback }) {
|
||||||
|
it(description, function() {
|
||||||
|
expect(wrapper.find(cssClass)).to.exist
|
||||||
|
expect(wrapper.find(`${cssClass} .tooltipsAbove`).text()).to.equal(tooltipText)
|
||||||
|
wrapper.find(cssClass).simulate('click')
|
||||||
|
expect(callback).to.have.property('callCount', 1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertContent({ currentUser, map }) {
|
||||||
|
const onInfoClick = sinon.spy()
|
||||||
|
const onHelpClick = sinon.spy()
|
||||||
|
const onStarClick = sinon.spy()
|
||||||
|
const wrapper = shallow(
|
||||||
|
<InfoAndHelp map={map} currentUser={currentUser}
|
||||||
|
onInfoClick={onInfoClick}
|
||||||
|
onHelpClick={onHelpClick}
|
||||||
|
onMapStar={onStarClick}
|
||||||
|
mapIsStarred={false}
|
||||||
|
/>)
|
||||||
|
|
||||||
|
if (map) {
|
||||||
|
it('renders MapInfoBox', () => expect(wrapper.find(MapInfoBox)).to.exist)
|
||||||
|
assertTooltip({
|
||||||
|
wrapper,
|
||||||
|
description: 'renders Map Info icon',
|
||||||
|
cssClass: '.mapInfoIcon',
|
||||||
|
tooltipText: 'Map Info',
|
||||||
|
callback: onInfoClick
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
it('does not render MapInfoBox', () => expect(wrapper.find(MapInfoBox).length).to.equal(0))
|
||||||
|
it('does not render Map Info icon', () => expect(wrapper.find('.mapInfoIcon').length).to.equal(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map && currentUser) {
|
||||||
|
it('renders Star icon', () => {
|
||||||
|
expect(wrapper.find('.starMap')).to.exist
|
||||||
|
wrapper.find('.starMap').simulate('click')
|
||||||
|
expect(onStarClick).to.have.property('callCount', 1)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
it('does not render the Star icon', () => expect(wrapper.find('.starMap').length).to.equal(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
// common content
|
||||||
|
assertTooltip({
|
||||||
|
wrapper,
|
||||||
|
description: 'renders Help icon',
|
||||||
|
cssClass: '.openCheatsheet',
|
||||||
|
tooltipText: 'Help',
|
||||||
|
callback: onHelpClick
|
||||||
|
})
|
||||||
|
it('renders clearfloat at the end', function() {
|
||||||
|
const clearfloat = wrapper.find('.clearfloat')
|
||||||
|
expect(clearfloat).to.exist
|
||||||
|
expect(wrapper.find('.infoAndHelp').children().last()).to.eql(clearfloat)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertStarLogic({ mapIsStarred }) {
|
||||||
|
const onMapStar = sinon.spy()
|
||||||
|
const onMapUnstar = sinon.spy()
|
||||||
|
const wrapper = shallow(
|
||||||
|
<InfoAndHelp map={{}} currentUser={{}}
|
||||||
|
onMapStar={onMapStar}
|
||||||
|
onMapUnstar={onMapUnstar}
|
||||||
|
mapIsStarred={mapIsStarred}
|
||||||
|
/>)
|
||||||
|
const starWrapper = wrapper.find('.starMap')
|
||||||
|
starWrapper.simulate('click')
|
||||||
|
it(mapIsStarred ? 'has unstar content' : 'has star content', () => {
|
||||||
|
expect(starWrapper.hasClass('starred')).to.equal(mapIsStarred)
|
||||||
|
expect(starWrapper.find('.tooltipsAbove').text()).to.equal(mapIsStarred ? 'Unstar' : 'Star')
|
||||||
|
expect(onMapStar).to.have.property('callCount', mapIsStarred ? 0 : 1)
|
||||||
|
expect(onMapUnstar).to.have.property('callCount', mapIsStarred ? 1 : 0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('InfoAndHelp', function() {
|
||||||
|
describe('no currentUser, map is present', function() {
|
||||||
|
assertContent({ currentUser: null, map: {} })
|
||||||
|
})
|
||||||
|
describe('currentUser is present, map is present', function() {
|
||||||
|
assertContent({ currentUser: {}, map: {} })
|
||||||
|
})
|
||||||
|
describe('no currentUser, no map', function() {
|
||||||
|
assertContent({ currentUser: null, map: null })
|
||||||
|
})
|
||||||
|
assertStarLogic({ mapIsStarred: true })
|
||||||
|
assertStarLogic({ mapIsStarred: false })
|
||||||
|
})
|
|
@ -5,7 +5,7 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack",
|
"build": "webpack",
|
||||||
"build:watch": "webpack --watch",
|
"build:watch": "webpack --watch",
|
||||||
"test": "mocha-webpack --webpack-config webpack.test.config.js --require frontend/test/support/dom.js frontend/test",
|
"test": "mocha-webpack --webpack-config webpack.test.config.js --require frontend/test_support/dom.js --recursive frontend/test",
|
||||||
"eslint": "eslint frontend",
|
"eslint": "eslint frontend",
|
||||||
"eslint:fix": "eslint --fix frontend"
|
"eslint:fix": "eslint --fix frontend"
|
||||||
},
|
},
|
||||||
|
@ -58,6 +58,7 @@
|
||||||
"babel-eslint": "^7.1.1",
|
"babel-eslint": "^7.1.1",
|
||||||
"chai": "^3.5.0",
|
"chai": "^3.5.0",
|
||||||
"circular-dependency-plugin": "^2.0.0",
|
"circular-dependency-plugin": "^2.0.0",
|
||||||
|
"enzyme": "^2.8.2",
|
||||||
"eslint": "^3.11.1",
|
"eslint": "^3.11.1",
|
||||||
"eslint-config-standard": "^6.2.1",
|
"eslint-config-standard": "^6.2.1",
|
||||||
"eslint-plugin-promise": "^3.4.0",
|
"eslint-plugin-promise": "^3.4.0",
|
||||||
|
@ -66,7 +67,8 @@
|
||||||
"jsdom": "^9.11.0",
|
"jsdom": "^9.11.0",
|
||||||
"mocha": "^3.2.0",
|
"mocha": "^3.2.0",
|
||||||
"mocha-webpack": "^0.7.0",
|
"mocha-webpack": "^0.7.0",
|
||||||
"react-addons-test-utils": "^15.4.2"
|
"react-addons-test-utils": "^15.5.1",
|
||||||
|
"sinon": "^2.2.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"raml2html": "4.0.5"
|
"raml2html": "4.0.5"
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
const config = require('./webpack.config')
|
const config = require('./webpack.config')
|
||||||
|
|
||||||
config.target = 'node'
|
config.target = 'node'
|
||||||
|
config.externals = config.externals.concat([
|
||||||
|
'react/lib/ExecutionEnvironment',
|
||||||
|
'react/lib/ReactContext',
|
||||||
|
'react/addons',
|
||||||
|
'react-test-renderer/shallow',
|
||||||
|
'react-dom/test-utils',
|
||||||
|
'canvas',
|
||||||
|
'bufferutil',
|
||||||
|
'utf-8-validate'
|
||||||
|
])
|
||||||
|
|
||||||
module.exports = config
|
module.exports = config
|
||||||
|
|
Loading…
Reference in a new issue