I'm currently having a lot of trouble running tests on my redux actions. The test passes but I get the following error each time it is ran:
ReferenceError: localStorage is not defined
I also got an error before which was:
ReferenceError: fetch is not defined
I fixed this by using isomorphic-fetch. Anyway I am unsure on how I should configure Mocha to run these front end tests. Any help would be much appreciated.
Mocha test command:
mocha -w test/test_helper.js test/*.spec.js
test_helper.js:
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;
auth.actions.spec.js
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import * as actions from '../client/app/actions/auth'
import * as types from '../client/app/constants/ActionTypes'
import nock from 'nock'
import chai from 'chai'
import sinon from 'sinon'
var expect = chai.expect
import { SERVER_API } from './config'
const middlewares = [ thunk ]
const mockStore = configureMockStore(middlewares)
describe('auth actions', () => {
afterEach(() => {
nock.cleanAll()
})
it('creates LOGIN_REQUEST and LOGINSUCCESS when correct username and password provided', () => {
nock(SERVER_API)
.post('/login', {
username: 'test',
password: 'password'
})
.reply(200, {
token: 'TOKEN'
});
const expectedActions = [
{
type: types.LOGIN_REQUEST,
isFetching: true,
isAuthenticated: false,
creds: {
username: 'test',
password: 'password'
}
},
{
type: types.LOGIN_SUCCESS,
isFetching: false,
isAuthenticated: true,
token: 'TOKEN'
}
]
const INITAL_STATE = {
isFetching: false,
isAuthenticated: false
}
const store = mockStore(INITAL_STATE)
return store.dispatch(actions.loginUser({username:'test',password:'password'}))
.then(() => {
expect(store.getActions()).to.deep.equal(expectedActions)
})
})
})
auth.js
import { push } from 'react-router-redux'
import 'es6-promise'
import fetch from 'isomorphic-fetch'
import {
LOGIN_REQUEST, LOGIN_SUCCESS, LOGIN_FAILURE
} from '../constants/ActionTypes.js'
import { SERVER_PORT } from '../constants/config'
function requestLogin(creds) {
return {
type: LOGIN_REQUEST,
isFetching: true,
isAuthenticated: false,
creds
}
}
function receiveLogin(user) {
return {
type: LOGIN_SUCCESS,
isFetching: false,
isAuthenticated: true,
token: user.token
}
}
function loginError(message) {
return {
type: LOGIN_FAILURE,
isFetching: false,
isAuthenticated: false,
message
}
}
export function loginUser(creds) {
let config = {
method: 'POST',
headers: { 'Content-Type':'application/x-www-form-urlencoded' },
body: `username=${creds.username}&password=${creds.password}`
}
return dispatch => {
dispatch(requestLogin(creds))
return fetch('http://localhost:'+SERVER_PORT+'/api/login', config)
.then(response =>
response.json()
.then(user => ({ user, response }))
).then(({ user, response }) => {
if (!response.ok) {
dispatch(loginError(user.message))
return Promise.reject(user)
}
else {
dispatch(receiveLogin(user))
localStorage.setItem('token', user.token) //offending line
dispatch(push('foo'))
}
}).catch(err => console.log("Error: ", err))
}
}
Thanks.
Pretty straightforward error, you can't use localStorage
on your mocha tests because window.localStorage
isn't defined. There are two ways to fix this. The more "canon" way would be to move that localStorage
call from your action because this is a side-effect which is an anti-pattern in redux actions. Instead you should have middleware that catches this action and sets the localStorage
.
By doing that, you already eliminate the issue of testing this action.
If, however, you don't know how to do that and don't think it wise, then you can "fake" localStorage
by making a global variable at the top of your mocha test file which creates a fake localStorage
. I recommend against this one but it's definitely a solution that could work in your case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With