2016-05-23 53 views
3

我目前在我的redux操作上運行測試時遇到了很多麻煩。測試通過,但我得到在每次運行時出現以下錯誤:Redux測試 - ReferenceError:localStorage未定義

ReferenceError: localStorage is not defined 

我也得到了錯誤之前這是:

ReferenceError: fetch is not defined 

我用固定該同構取。無論如何,我不確定我應該如何配置Mocha來運行這些前端測試。任何幫助將非常感激。


摩卡測試指令:

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)) 
    } 
} 

感謝。

回答

4

非常直接的錯誤,您不能在您的摩卡測試中使用localStorage,因爲window.localStorage未定義。有兩種方法可以解決這個問題。更「正典」的方式是將您的動作中的localStorage調用移除,因爲這是一種副作用,它是redux操作中的反模式。相反,您應該擁有捕獲此操作並設置localStorage的中間件。

通過這樣做,您已經消除了測試此操作的問題。

但是,如果你不知道如何做到這一點,並不認爲這是明智的,那麼你可以通過在你的摩卡測試文件的頂部創建一個全局變量來僞造localStorage 。我建議不要這樣做,但它絕對是一種解決方案,可以適用於您的情況。

+0

感謝您的回覆和建議。我認爲這是爲什麼,但不知道我是否可以使用test_helper來僞造本地存儲。我一定會嘗試使用中間件。謝謝。 – edcarr

+0

@ZekeDroid在這種情況下,還需要在localStorage全局變量中創建'setItem'方法嗎? – Emo

+0

其他方法,是的 – ZekeDroid