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:
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.
In fact, Redux uses the context API under the hood to pass data across multiple levels of the component hierarchy.
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.
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!
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.
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