Say I have the following reducer:
import {FOO} from '../const/Foo'
const myReducer = (initialState = {foo: ''}, action) => {
const state = {}
if (action) {
switch (action.type) {
case FOO:
state.foo = action.foo
};
}
return Object.assign({}, initialState, state)
}
and I test using jest with:
import FOO from '../const/Foo'
test('returns correct state when action is not "Foo"', () => {
expect(myReducer({foo: 'bar'}, {type: 'foo'})).toEqual({foo: 'bar'})
})
test("returns correct state when action is 'Foo'", () => {
expect(myReducer({}, {type: FOO, foo: 'bar'})).toEqual({foo: 'bar'})
})
test('when there is no action / testing the default', () => {
expect(myReducer()).toEqual({foo: ''})
})
This produces a branch coverage of 4/5
. After a little bit of thinking/removing and/or re-adding lines I've arrived at the branching logic being on the initialState
set. Which almost makes sense. Except:
1) Why doesn't the last test, with an empty myReducer()
call cover this case.
When the reducer is pared down to:
const myReducer = (initialState = {foo: ''}, action) => {
const state = {}
return Object.assign({}, initialState, state)
}
The tests (which now fail) have a branch coverage of 1/1.
What is going on here?
{
"bail": true,
"verbose": true,
"moduleNameMapper": {
"\\.(sass|jpg|png)$": "<rootDir>/src/main/js/config/emptyExport.js"
},
"testRegex": ".*(?<!snapshot)\\.(test|spec)\\.js$",
"collectCoverage": true,
"collectCoverageFrom": ["src/main/js/**/*.js"
, "!**/node_modules/**"
, "!**/*spec.js"
, "!src/main/js/config/emptyExport.js"
, "!**/coverage/**/*.js"
, "!src/main/js/app.js"
, "!src/main/js/store/configureStore.js"
, "!src/main/js/reducers/index.js"],
"coverageDirectory": "<rootDir>/src/main/js/coverage",
"coverageThreshold": {
"global": {
"branches": 85,
"function": 95,
"lines": 95,
"statements": 95
}
}
}
EDIT2: The following test also does not affect test coverage:
test('when there is no action / testing the default', () => {
expect(addressReducer(undefined, {foo: 'bar'})).toEqual({address: ''})
})
I still do not understand why the initial default test implementation was not equivalent from a branch coverage perspective.
Branch coverage is a requirement that, for each branch in the program (e.g., if statements, loops), each branch have been executed at least once during testing. (It is sometimes also described as saying that each branch condition must have been true at least once and false at least once during testing.)
State: The reducer function contains two parameters one of them is the state. The State is an object that holds some information that may change over the lifetime of the component. If the state of the object changes, the component has to re-render. In redux, Updation of state happens in the reducer function.
The reducer is a pure function that takes the previous state and an action, and returns the next state. (previousState, action) => newState. It's called a reducer because it's the type of function you would pass to Array.
Reducers, as the name suggests, take in two things: previous state and an action. Then they reduce it (read it return) to one entity: the new updated instance of state. So reducers are basically pure JS functions which take in the previous state and an action and return the newly updated state.
the last test with myReducer()
covers the case where the default value for initialState
which is in your case {foo: ''}
gets applied.
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