From 6b276145e2b7c91e371a448b97f068d83abaade6 Mon Sep 17 00:00:00 2001 From: Neil Fenton Date: Sat, 22 Aug 2015 16:29:53 -0400 Subject: [PATCH] added tests --- README.md | 4 +- karma.conf.js | 40 ++++++++++ package.json | 10 ++- src/__tests__/index.js | 2 + src/__tests__/router-actions.test.js | 24 ++++++ src/__tests__/router-state-reducer.test.js | 35 +++++++++ src/__tests__/state-change-error.test.js | 15 ++++ src/__tests__/state-change-start.test.js | 14 ++++ src/__tests__/state-change-success.test.js | 14 ++++ src/__tests__/state-go.test.js | 20 +++++ src/__tests__/state-middleware.test.js | 85 ++++++++++++++++++++++ src/__tests__/state-not-found.test.js | 14 ++++ src/__tests__/state-reload.test.js | 10 +++ src/__tests__/state-transition-to.test.js | 20 +++++ 14 files changed, 301 insertions(+), 6 deletions(-) create mode 100644 karma.conf.js create mode 100644 src/__tests__/router-actions.test.js create mode 100644 src/__tests__/router-state-reducer.test.js create mode 100644 src/__tests__/state-change-error.test.js create mode 100644 src/__tests__/state-change-start.test.js create mode 100644 src/__tests__/state-change-success.test.js create mode 100644 src/__tests__/state-go.test.js create mode 100644 src/__tests__/state-middleware.test.js create mode 100644 src/__tests__/state-not-found.test.js create mode 100644 src/__tests__/state-reload.test.js create mode 100644 src/__tests__/state-transition-to.test.js diff --git a/README.md b/README.md index 12ea743..12b833b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -[![Circle CI](https://circleci.com/gh/neilff/ng-redux-ui-router.svg?style=svg)](https://circleci.com/gh/neilff/ng-redux-ui-router) - #ng-redux-ui-router +[![Circle CI](https://circleci.com/gh/neilff/ng-redux-ui-router.svg?style=svg)](https://circleci.com/gh/neilff/ng-redux-ui-router) + This package contains a middleware for performing UI Router methods such as `$state.go` as well as a reducer for storing Angular UI state inside your store. Inspired by [Redux React Router](https://github.com/acdlite/redux-react-router) by [Andrew Clark](https://github.com/acdlite) diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..bebcd08 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,40 @@ +// Karma configuration +// Generated on Sat Aug 22 2015 14:55:12 GMT-0400 (EDT) + +module.exports = function(config) { + config.set({ + basePath: './', + frameworks: ['mocha'], + files: [ + 'src/**/*.js' + ], + exclude: [ + ], + plugins: [ + 'karma-babel-preprocessor', + 'karma-mocha', + 'karma-phantomjs-launcher' + ], + preprocessors: { + 'src/**/*.js': ['babel'] + }, + babelPreprocessor: { + options: { + sourceMap: 'inline' + }, + filename: function (file) { + return file.originalPath.replace(/\.js$/, '.es5.js'); + }, + sourceFileName: function (file) { + return file.originalPath; + } + }, + reporters: ['progress'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['PhantomJS'], + singleRun: false + }); +}; diff --git a/package.json b/package.json index 7eaedd9..6e714eb 100644 --- a/package.json +++ b/package.json @@ -15,10 +15,11 @@ "dependencies": { "angular": "^1.4.4", "angular-ui-router": "^0.2.15", - "babel": "^5.8.21", - "immutable": "^3.7.4" + "immutable": "^3.7.4", + "redux": "1.0.0-alpha" }, "devDependencies": { + "babel": "^5.8.21", "babel-core": "5.6.15", "babel-eslint": "^3.1.20", "babel-loader": "^5.3.1", @@ -26,7 +27,8 @@ "eslint": "^0.24.0", "mocha": "^2.2.5", "node-libs-browser": "^0.5.2", - "redux": "1.0.0-alpha", - "sinon": "^1.15.4" + "q": "^1.4.1", + "sinon": "^1.16.1", + "sinon-as-promised": "^4.0.0" } } diff --git a/src/__tests__/index.js b/src/__tests__/index.js index e69de29..d923aaa 100644 --- a/src/__tests__/index.js +++ b/src/__tests__/index.js @@ -0,0 +1,2 @@ +import chai from 'chai'; +global.expect = chai.expect; diff --git a/src/__tests__/router-actions.test.js b/src/__tests__/router-actions.test.js new file mode 100644 index 0000000..5e8c78e --- /dev/null +++ b/src/__tests__/router-actions.test.js @@ -0,0 +1,24 @@ +import 'chai'; +import routerActions from '../router-actions'; + +let $ngReduxMock = { + getStore: () => { + return { + dispatch: () => {} + }; + } +}; + +describe('routerActions', () => { + it('should bind the action creators', () => { + let actions = routerActions($ngReduxMock); + + expect(actions.onStateChangeStart).to.be.a('function'); + expect(actions.onStateChangeSuccess).to.be.a('function'); + expect(actions.onStateChangeError).to.be.a('function'); + expect(actions.onStateNotFound).to.be.a('function'); + expect(actions.stateGo).to.be.a('function'); + expect(actions.stateReload).to.be.a('function'); + expect(actions.stateTransitionTo).to.be.a('function'); + }); +}); diff --git a/src/__tests__/router-state-reducer.test.js b/src/__tests__/router-state-reducer.test.js new file mode 100644 index 0000000..7580e03 --- /dev/null +++ b/src/__tests__/router-state-reducer.test.js @@ -0,0 +1,35 @@ +import 'chai'; +import routerStateReducer from '../router-state-reducer'; + +describe('routerStateReducer', () => { + it('should return the initial state', () => { + let action = { + type: 'null', + payload: {} + }; + + let state = routerStateReducer(undefined, action); + expect(state.toJS().currentState).to.equal(null); + expect(state.toJS().currentParams).to.equal(null); + expect(state.toJS().prevState).to.equal(null); + expect(state.toJS().prevParams).to.equal(null); + }); + + it('should set the provided state if the $stateChangeSuccess type is used', () => { + let action = { + type: '@@reduxUiRouter/$stateChangeSuccess', + payload: { + currentState: 'currentState', + currentParams: 'currentParams', + prevState: 'prevState', + prevParams: 'prevParams' + } + }; + + let state = routerStateReducer(undefined, action); + expect(state.toJS().currentState).to.equal('currentState'); + expect(state.toJS().currentParams).to.equal('currentParams'); + expect(state.toJS().prevState).to.equal('prevState'); + expect(state.toJS().prevParams).to.equal('prevParams'); + }); +}); diff --git a/src/__tests__/state-change-error.test.js b/src/__tests__/state-change-error.test.js new file mode 100644 index 0000000..5449c22 --- /dev/null +++ b/src/__tests__/state-change-error.test.js @@ -0,0 +1,15 @@ +import 'chai'; +import stateChangeError from '../state-change-error'; + +describe('stateChangeError', () => { + it('should create an action with the provided params', () => { + let action = stateChangeError('evt', 'toState', 'toParams', 'fromState', 'fromParams', 'err'); + + expect(action.payload.toState).to.equal('toState'); + expect(action.payload.toParams).to.equal('toParams'); + expect(action.payload.fromState).to.equal('fromState'); + expect(action.payload.fromParams).to.equal('fromParams'); + expect(action.payload.err).to.equal('err'); + expect(action.type).to.equal('@@reduxUiRouter/$stateChangeError'); + }); +}); diff --git a/src/__tests__/state-change-start.test.js b/src/__tests__/state-change-start.test.js new file mode 100644 index 0000000..003a3d6 --- /dev/null +++ b/src/__tests__/state-change-start.test.js @@ -0,0 +1,14 @@ +import 'chai'; +import stateChangeStart from '../state-change-start'; + +describe('stateChangeStart', () => { + it('should create an action with the provided params', () => { + let action = stateChangeStart('evt', 'toState', 'toParams', 'fromState', 'fromParams'); + + expect(action.payload.toState).to.equal('toState'); + expect(action.payload.toParams).to.equal('toParams'); + expect(action.payload.fromState).to.equal('fromState'); + expect(action.payload.fromParams).to.equal('fromParams'); + expect(action.type).to.equal('@@reduxUiRouter/$stateChangeStart'); + }); +}); diff --git a/src/__tests__/state-change-success.test.js b/src/__tests__/state-change-success.test.js new file mode 100644 index 0000000..ac609fe --- /dev/null +++ b/src/__tests__/state-change-success.test.js @@ -0,0 +1,14 @@ +import 'chai'; +import stateChangeSuccess from '../state-change-success'; + +describe('stateChangeSuccess', () => { + it('should create an action with the provided params', () => { + let action = stateChangeSuccess('evt', 'currentState', 'currentParams', 'prevState', 'prevParams'); + + expect(action.payload.currentState).to.equal('currentState'); + expect(action.payload.currentParams).to.equal('currentParams'); + expect(action.payload.prevState).to.equal('prevState'); + expect(action.payload.prevParams).to.equal('prevParams'); + expect(action.type).to.equal('@@reduxUiRouter/$stateChangeSuccess'); + }); +}); diff --git a/src/__tests__/state-go.test.js b/src/__tests__/state-go.test.js new file mode 100644 index 0000000..c9bb908 --- /dev/null +++ b/src/__tests__/state-go.test.js @@ -0,0 +1,20 @@ +import 'chai'; +import stateGo from '../state-go'; + +describe('stateGo', () => { + it('should create an action containing the state to go to', () => { + let action = stateGo('example', { test: 'hello' }, { option: 'world' }); + expect(action.payload.to).to.equal('example'); + expect(action.payload.params.test).to.equal('hello'); + expect(action.payload.options.option).to.equal('world'); + expect(action.type).to.equal('@@reduxUiRouter/stateGo'); + }); + + it('should create an action when to params are undefined', () => { + let action = stateGo('example', undefined, undefined); + expect(action.payload.to).to.equal('example'); + expect(action.payload.params).to.equal(undefined); + expect(action.payload.options).to.equal(undefined); + expect(action.type).to.equal('@@reduxUiRouter/stateGo'); + }); +}); diff --git a/src/__tests__/state-middleware.test.js b/src/__tests__/state-middleware.test.js new file mode 100644 index 0000000..2c5a2e6 --- /dev/null +++ b/src/__tests__/state-middleware.test.js @@ -0,0 +1,85 @@ +import 'chai'; +import Q from 'q'; +import sinon from 'sinon'; +import 'sinon-as-promised'; +import routerMiddleware from '../router-middleware'; + +import { + STATE_GO, + STATE_RELOAD, + STATE_TRANSITION_TO +} from '../action-types'; + +let $state; +let nextSpy; + +describe('routerMiddleware', () => { + beforeEach(() => { + $state = { + go: () => {}, + reload: () => {}, + transitionTo: () => {} + }; + + $state.go = sinon.stub().resolves('foo'); + $state.reload = sinon.stub().resolves('foo'); + $state.transitionTo = sinon.stub().resolves('foo'); + + nextSpy = sinon.stub(); + }); + + it('should call the next action if the router middleware doesn\'t care about it', () => { + let middleware = routerMiddleware($state)({})(nextSpy); + + middleware({ + payload: {} + }); + + expect(nextSpy.called).to.equal(true); + expect($state.go.called).to.equal(false); + expect($state.reload.called).to.equal(false); + expect($state.transitionTo.called).to.equal(false); + }); + + it('should call $state.go if the STATE_GO action is sent', () => { + let middleware = routerMiddleware($state)({})(nextSpy); + + middleware({ + type: STATE_GO, + payload: {} + }); + + expect(nextSpy.called).to.equal(true); + expect($state.go.called).to.equal(true); + expect($state.reload.called).to.equal(false); + expect($state.transitionTo.called).to.equal(false); + }); + + it('should call $state.reload if the STATE_GO action is sent', () => { + let middleware = routerMiddleware($state)({})(nextSpy); + + middleware({ + type: STATE_RELOAD, + payload: {} + }); + + expect(nextSpy.called).to.equal(true); + expect($state.reload.called).to.equal(true); + expect($state.go.called).to.equal(false); + expect($state.transitionTo.called).to.equal(false); + }); + + it('should call $state.transitionTo if the STATE_GO action is sent', () => { + let middleware = routerMiddleware($state)({})(nextSpy); + + middleware({ + type: STATE_TRANSITION_TO, + payload: {} + }); + + expect(nextSpy.called).to.equal(true); + expect($state.transitionTo.called).to.equal(true); + expect($state.go.called).to.equal(false); + expect($state.reload.called).to.equal(false); + }); +}); diff --git a/src/__tests__/state-not-found.test.js b/src/__tests__/state-not-found.test.js new file mode 100644 index 0000000..290d12c --- /dev/null +++ b/src/__tests__/state-not-found.test.js @@ -0,0 +1,14 @@ +import 'chai'; +import stateNotFound from '../state-not-found'; + +describe('stateNotFound', () => { + it('should create an action with the provided params', () => { + let action = stateNotFound('evt', 'unfoundState', 'fromState', 'fromParams'); + + expect(action.payload.evt).to.equal('evt'); + expect(action.payload.unfoundState).to.equal('unfoundState'); + expect(action.payload.fromState).to.equal('fromState'); + expect(action.payload.fromParams).to.equal('fromParams'); + expect(action.type).to.equal('@@reduxUiRouter/$stateNotFound'); + }); +}); diff --git a/src/__tests__/state-reload.test.js b/src/__tests__/state-reload.test.js new file mode 100644 index 0000000..f77bebb --- /dev/null +++ b/src/__tests__/state-reload.test.js @@ -0,0 +1,10 @@ +import 'chai'; +import stateReload from '../state-reload'; + +describe('stateReload', () => { + it('should create an action containing the state to reload', () => { + let action = stateReload('example'); + expect(action.payload).to.equal('example'); + expect(action.type).to.equal('@@reduxUiRouter/stateReload'); + }); +}); diff --git a/src/__tests__/state-transition-to.test.js b/src/__tests__/state-transition-to.test.js new file mode 100644 index 0000000..530149e --- /dev/null +++ b/src/__tests__/state-transition-to.test.js @@ -0,0 +1,20 @@ +import 'chai'; +import stateTransitionTo from '../state-transition-to'; + +describe('stateTransitionTo', () => { + it('should create an action containing the state to transition to', () => { + let action = stateTransitionTo('example', { test: 'hello' }, { option: 'world' }); + expect(action.payload.to).to.equal('example'); + expect(action.payload.toParams.test).to.equal('hello'); + expect(action.payload.options.option).to.equal('world'); + expect(action.type).to.equal('@@reduxUiRouter/transitionTo'); + }); + + it('should create an action when to params are undefined', () => { + let action = stateTransitionTo('example', undefined, undefined); + expect(action.payload.to).to.equal('example'); + expect(action.payload.toParams).to.equal(undefined); + expect(action.payload.options).to.equal(undefined); + expect(action.type).to.equal('@@reduxUiRouter/transitionTo'); + }); +});