redux-toolkit: test slice and actions

How to write a simple test for the store

Photo by Arnold Francisca on Unsplash
export const fetchUser = createAsyncThunk(
'fetchUser',
async(param: {id}, thunkAPI) => {
const user = await getUserById(param.id);
if(user && user.age >= 18){
thunkAPI.dispatch(action_A());
}
return user;
});
export const action_A = createAction(
'action_A', () => {
// do something
})
const middlewares = [thunk]
export const mockStore = configureMockStore(middlewares);
describe('ACTION TESTS', () => {it('should fetchUser: age > 18', () => {
const user = {id: 1, name: 'John', age: 20}
const expectedActions = [
{
type: fetchUser.pending.type
},
{
type: action_A.type,
payload: {}
},
{
type: fetchUser.fulfilled.type,
payload: user
}
];
const store = mockStore({});
// mock API returns
jest.spyOn(importFile,'getUserById').mockImplementation(() =>
Promise.resolve(user));
return store.dispatch(fetchUser({id: 1})).then(() => {
expect(store.getActions().map(action =>
({
type: action.type,
payload: action.payload
})
)).toEqual(expectedActions)
})
})

it('should fetchUser: age < 18', () => {
const user = {id: 2, name: 'Jack', age: 16}
const expectedActions = [
{
type: fetchUser.pending.type
},
{
type: fetchUser.fulfilled.type,
payload: user
}
];
const store = mockStore({});
// mock API returns
jest.spyOn(importFile,'getUserById').mockImplementation(() =>
Promise.resolve(user));
return store.dispatch(fetchUser({id: 2})).then(() => {
expect(store.getActions().map(action =>
({
type: action.type,
payload: action.payload
})
)).toEqual(expectedActions)
})
})

})
const initialState = { isLoading: false, isError: false}

const userSlice = createSlice({
name: 'user',
initialState,
reducers: {},
extraReducers: (builder) => {
builder.addCase(fetchUser.pending, (state, action) => {
return {
...state,
isLoading: true,
isError: false
}
})
builder.addCase(fetchUser.fulfilled, (state, action) => {
return {
...state,
isLoading: false,
isError: false,
[action.payload.id]: {...action.payload}
}
})
builder.addCase(fetchUser.rejected, (state, action) => {
return {
...state,
isLoading: false,
isError: true
}
})
}
})

export default userSlice.reducer
// A simple test could be

describe('USER SLICE TESTS', () => {

it('should set loading true while action is pending', () => {
const action = {type: fetchUser.pending};
const initialState = conversionSlice(
{
isLoading: false, isError: false
}, action);
expect(state).toEqual({isError: false, isLoading: true})
})

it('should set user when action is fulfilled', () => {
const action = {
type: fetchUser.fulfilled,
payload:{ id:1, name: 'John', age: 20 }
};
const initialState = conversionSlice(
{
isLoading: false, isError: false
}, action);
expect(state).toEqual({
isError: false,
isLoading: false,
1: { id:1, name: 'John', age: 20 }
})
})

it('should set error true when action is rejected', () => {
const action = {type: fetchUser.rejected};
const initialState = conversionSlice(
{
isLoading: false, isError: false
}, action);
expect(state).toEqual({isError: true, isLoading: false})
})

})

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store