diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..4a7ea30 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore index a1cff2f..1907c07 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,10 @@ +*~ .DS_Store + npm-debug.log node_modules dist _translations + +*.iml +.idea diff --git a/README.md b/README.md index 878f3fa..c6d64b3 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ This is a boilerplate example showcasing _mostly_ [Redux](https://github.com/gae ```bash $ npm install $ npm start +$ npm test ``` ### I18n support diff --git a/package.json b/package.json index 11cce92..2574ad6 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "lint": "eslint lib", "start": "npm run build && node server.js", "start:devtools": "npm run build && DEVTOOLS=true node server.js", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "mocha test/setup.js test/**/*-test.js" }, "dependencies": { "classnames": "~2.2.3", @@ -55,8 +55,10 @@ "babel-preset-react": "^6.3.13", "babel-preset-stage-0": "^6.3.13", "babel-runtime": "^6.3.19", + "chai": "^3.5.0", "css-loader": "^0.23.1", "cssnext-loader": "^1.0.1", + "enzyme": "^2.1.0", "eslint": "^1.10.3", "eslint-plugin-react": "^3.14.0", "express": "^4.13.3", @@ -64,7 +66,10 @@ "gh-pages": "^0.8.0", "glob": "^6.0.4", "html-webpack-plugin": "^1.7.0", + "jsdom": "^8.1.0", "mkdirp": "^0.5.1", + "mocha": "^2.4.5", + "react-addons-test-utils": "^0.14.7", "react-transform-catch-errors": "^1.0.1", "react-transform-hmr": "^1.0.1", "redbox-react": "^1.2.0", @@ -72,6 +77,8 @@ "redux-devtools-dock-monitor": "~1.0.1", "redux-devtools-log-monitor": "~1.0.1", "rimraf": "^2.5.0", + "sinon": "^1.17.3", + "sinon-chai": "^2.8.0", "style-loader": "^0.13.0", "webpack": "^1.12.10", "webpack-dev-middleware": "^1.4.0", diff --git a/test/actions/application-test.js b/test/actions/application-test.js new file mode 100644 index 0000000..f4066e1 --- /dev/null +++ b/test/actions/application-test.js @@ -0,0 +1,47 @@ +import { createStore, combineReducers, applyMiddleware } from 'redux' +import thunk from 'redux-thunk' + +import chai from 'chai'; +import sinon from 'sinon'; +import sinonChai from 'sinon-chai'; +import * as constants from '../../lib/constants' +import * as applicationActions from '../../lib/actions/application' +import * as reducers from '../../lib/reducers' + +const expect = chai.expect; +chai.use(sinonChai); + +describe('application actions', () => { + + it('test login', () => { + const clock = sinon.useFakeTimers(); + + const store = createStore(combineReducers(reducers), {}, applyMiddleware(thunk)) + const dispatch = sinon.spy(store, 'dispatch') + const fn = applicationActions.login() + fn(dispatch, store.getState) + + clock.tick(350) + + expect(dispatch).to.be.spy + expect(dispatch).to.have.been.called.once + expect(dispatch).to.have.been.calledWith({ payload: { token: sinon.match.any }, type: 'LOGGED_IN' }) + }); + + it('test switchLocale', () => { + const LOCALE = 'myLocale' + const expectedAction = { + type: constants.LOCALE_SWITCHED, + payload: LOCALE + } + expect(applicationActions.switchLocale(LOCALE)).to.deep.equal(expectedAction) + }); + + it('test hideError', () => { + const expectedAction = { + type: constants.HIDE_ERROR + } + expect(applicationActions.hideError()).to.deep.equal(expectedAction) + }); + +}); diff --git a/test/setup.js b/test/setup.js new file mode 100644 index 0000000..ae5d912 --- /dev/null +++ b/test/setup.js @@ -0,0 +1,20 @@ +require('babel-register')(); + +var jsdom = require('jsdom').jsdom; + +var exposedProperties = ['window', 'navigator', 'document']; + +global.document = jsdom(''); +global.window = document.defaultView; +Object.keys(document.defaultView).forEach((property) => { + if (typeof global[property] === 'undefined') { + exposedProperties.push(property); + global[property] = document.defaultView[property]; + } +}); + +global.navigator = { + userAgent: 'node.js' +}; + +documentRef = document; \ No newline at end of file