Search code examples
reactjsreduxreact-reduxcreate-react-app

Redux warning only appearing in tests


I have created a tic tac toe game with react redux.

I am using create-react-app.

I have the following store:

import {createStore, combineReducers} from 'redux';
import gameSettingsReducer from './reducers/gameSettings.js';
import gameStatusReducer from './reducers/gameStatus.js';


const rootReducer = combineReducers({gameSettings: gameSettingsReducer,
                   gameStatus: gameStatusReducer});

export const defaultGameStatus = {
      currentPlayerSymbol: "X",
      turnNumber: 0,
      currentView: "start-menu", //one of "start-menu", "in-game", "game-over"
      winner: "draw", //one of "X", "O", "draw"
      board: [["E", "E", "E"],
              ["E", "E", "E"],
              ["E", "E", "E"]],
      lastMove: []
};

const store = createStore(rootReducer, {
    gameSettings:{
        playerSymbol: "X",  //one of "X", "O"
        difficulty: "easy"  //one of "easy", "hard"
    },
    gameStatus: defaultGameStatus
});


export default store;

Everything runs as I expect. Except for when I am running tests (npm test) the following appears in the console:

console.error node_modules\redux\lib\utils\warning.js:14
  No reducer provided for key "gameStatus"
console.error node_modules\redux\lib\utils\warning.js:14
  Unexpected key "gameStatus" found in preloadedState argument passed to createStore. Expected to find one of the known reducer keys instead: "gameSettings". Unexpected keys will be ignored.

In the few tests I have, I am not even testing the store. So I guess this comes up while compiling the code. I tried putting console.log(gameStatusReducer) before the root reducer line. It shows that gameStatusReducer is undefined.

Since both the gameSettingsReducer and the gameStatusReducer are created in very similar ways, I do not know where this error comes from and do not even know how to investigate the issue further. This only shows up when running the tests. Running the app does not show this problem and the app works as expected.

So, the questions are:

  • Why is this just showing up in the tests?
  • How to investigate where the problem is coming from?

Solution

  • After a lot of banging my head against the keyboard, I've found some clues.

    Quick fix: make a normal export for gameStateReducer instead of a default and import it elsewhere with import { gameStateReducer } from // ....

    Jest does automatic mocking of some imports, and apparently it's buggy in this case, or it expects some sort of configuration that react-create-app hasn't provided.

    As to why Jest is even logging that error (considering the relevant code is not imported in any of the tests), I suppose it's due to its inner workings.

    Supporting this is the following evidence: adding a --testPathPattern flag to the npm test script matching only files ending in .test.js does not change the behaviour and the error still appears.

    How to investigate the problem: I started by figuring out whether the code causing the error log was in the tests or not (indirectly it could have been, with an import for example). After ruling this out, I started mocking the functions passed to combineReducers to make sure any changes affected the outcome of the error log, and they did. Simply adding this:

    gameStatus: gameStatusReducer || (() => ())
    

    ...already solves the issue, which means what's wrong is the import and how Jest/babel-jest handles it.

    If I were to investigate this issue further, I would create my own installation with Jest and provide my own configuration, to see if Jest still compiles the entire application. It seems non-trivial to pass configuration options to Jest if you use react-create-app.

    Good luck!