I'm having issues while testing a slice with React Testing Library. I was running the following simple test:
import reducer from "states/slices";
test("should return the initial state", () => {
expect(reducer(undefined, {})).toEqual({
loading: true,
libraries: [],
books: [],
error: {
error: false,
variant: "error",
message: "",
},
});
});
The slice under test is the following:
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { getLibraries, getBooks } from "api";
const initialState = {
loading: true,
libraries: [],
books: [],
error: {
error: false,
variant: "error",
message: "",
},
};
export const fetchLibraries = createAsyncThunk("books/libraries", async () => {
const res = await getLibraries();
return res.data;
});
export const fetchBooks = createAsyncThunk(
"books/books",
async ({ title, libraryId, page }) => {
const res = await getBooks(title, libraryId, page);
return res.data;
}
);
const booksSlice = createSlice({
name: "books",
initialState,
reducers: {
unsetError: (state) => {
state.error = { error: false, variant: "error", message: "" };
},
},
extraReducers: (builder) => {
builder
.addCase(fetchLibraries.fulfilled, (state, action) => {
state.loading = false;
state.libraries = action.payload;
})
.addCase(fetchBooks.fulfilled, (state, action) => {
state.loading = false;
state.books = action.payload;
})
// .addCase(fetchBooks.pending, (state, action) => {
// state.loading = true;
// state.error = { error: false, variant: "error", message: "" };
// })
// .addCase(fetchLibraries.pending, (state, action) => {
// state.loading = true;
// state.error = { error: false, variant: "error", message: "" };
// })
// .addCase(fetchBooks.rejected, (state, action) => {
// state.loading = false;
// state.error.error = true;
// state.error.variant = "error";
// state.error.message =
// "Error. Try again.";
// })
// .addCase(fetchLibraries.rejected, (state, action) => {
// state.loading = false;
// state.error.error = true;
// state.error.variant = "error";
// state.error.message =
// "Error. Try again.";
// });
.addMatcher(
(action) => action.type.endsWith("/pending"),
(state, action) => {
state.loading = true;
state.error = { error: false, variant: "error", message: "" };
}
)
.addMatcher(
(action) => action.type.endsWith("/rejected"),
(state, action) => {
state.loading = false;
state.error.error = true;
state.error.variant = "error";
state.error.message =
"Error. Try again.";
}
);
},
});
const { actions, reducer } = booksSlice;
export const { unsetError } = actions;
export default reducer;
I'm getting back TypeError: Cannot read property 'endsWith' of undefined
when running the test with the addMatcher
s in the slice. If I replace them with the addCase
s (the commented ones), the test works as expected.
Instead, if I normally launch the application, everything works correctly in either case.
Why does this happen? I am defining wrongly the matchers?
CodePudding user response:
In your test case you are using {}
as an action. Therefore when you are checking in the matcher action.type.endsWith()
the action.type
is not defined.
You can probably fix this if you use action.type?.endsWith
in your matcher.