Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?
like image 320
zelite Avatar asked Apr 12 '17 16:04

zelite


People also ask

How do you fix an update was not wrapped in Act warnings which appears while unit testing the react app Mcq?

A general solution is to wrap the render in act to make sure all updates are done before proceeding with assertions and the end of the test. Also, those assertions won't need to waitFor anything.

Does Redux use context under the hood?

In fact, Redux uses the context API under the hood to pass data across multiple levels of the component hierarchy.

Can you use redux with TypeScript?

We strongly recommend using TypeScript in Redux applications. However, like all tools, TypeScript has tradeoffs. It adds complexity in terms of writing additional code, understanding TS syntax, and building the application.


2 Answers

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!

like image 68
fnune Avatar answered Sep 26 '22 02:09

fnune


Also had this error, but using TypeScript.

For the sake of argument, let's say our error was No reducer provided for key "favourites".

For the test causing this error, we imported an interface from that reducer's file, which in turn obviously runs the file to generate the exports.

Our favourites reducer imports our Redux store to query another bit of the state as part of one of its switch cases.

For some reason, commenting out the line where we access Store.getState().someOtherReducersState made the error go away.

So the fix was to simply jest.mock('../route/to/Store'); in the test file causing the error output.

like image 38
James King Avatar answered Sep 25 '22 02:09

James King