I want to create a couple of tests for my components, but since I'm using Redux I need to send a provider, according to the documentation I need to do something like a renderWithProviders
so I can re use it for different components and that's what I'm trying to do, I'm using Vite and TypeScript for this project, but I'm getting the following errors and I don't know how to fix it.
This is the custom render that I'm trying to create:
import React, { PropsWithChildren } from 'react'
import { render } from '@testing-library/react'
import { configureStore } from '@reduxjs/toolkit'
import { Provider } from 'react-redux'
import favsReducer from '../../store/favs/slice'
export function renderWithProviders(
ui: React.ReactElement,
{
preloadedState = {},
// Automatically create a store instance if no store was passed in
store = configureStore({
reducer: { favs: favsReducer },
preloadedState,
}),
...renderOptions
} = {}
) {
function Wrapper({ children }: PropsWithChildren) {
return <Provider store={store}>{children}</Provider>;
}
// Return an object with the store and all of RTL's query functions
return { store, ...render(ui, { wrapper: Wrapper, ...renderOptions }) };
}
My store is this one:
import { Middleware, configureStore } from "@reduxjs/toolkit"
import favsReducer from './favs/slice'
const persistanceLocalStorageMiddleware: Middleware = (store) => (next) => (action) => {
next(action);
localStorage.setItem('__favorite__redux__state__', JSON.stringify(store.getState()));
};
export const store = configureStore({
reducer: {
favs: favsReducer
},
middleware: (getDefaultMiddleware) => {
return getDefaultMiddleware().concat(persistanceLocalStorageMiddleware)
}
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
and the slice for favorites is this one:
import { createSlice, PayloadAction } from "@reduxjs/toolkit"
import { Favorite, Id, FavoriteWithId } from "../../interfaces/FavoritesInterface"
const DEFAULT_STATE: FavoriteWithId[] = []
const initialState: FavoriteWithId[] = (() => {
const persistedState = localStorage.getItem('__favorite__redux__state__')
if (persistedState) return JSON.parse(persistedState).favs
return DEFAULT_STATE
})()
export const favsSlice = createSlice({
name: 'favs',
initialState: initialState,
reducers: {
addNewFavorite: (state, action: PayloadAction<Favorite>) => {
const id = crypto.randomUUID();
return [...state, { id, ...action.payload }]
},
deleteFavoriteById: (state, action: PayloadAction<Id>) => {
const id = action.payload;
return state.filter((fav) => fav.id !== id)
}
}
})
export default favsSlice.reducer
export const { addNewFavorite, deleteFavoriteById } = favsSlice.actions
So, I don't know why I'm getting the message
'favs' does not exist in type 'Reducer<{ favs: FavoriteWithId[]; }, UnknownAction, any>'
I thought the reducer in the tests should have the 'favs' property as the one on the store I configure but I'm not sure anymore, can someone provide me a clue or something on how to proceed?
The unit test that I'm trying to write is this one:
import '@testing-library/jest-dom/jest-globals'
import '@testing-library/jest-dom'
import { screen } from '@testing-library/react'
import DogCard from '../components/profile-card/DogCard'
import { renderWithProviders } from './utils/test-utils'
describe('DogCard component', () => {
test('renders the DogCard component', () => {
renderWithProviders(<DogCard />)
const dogImage = screen.getByTestId('dog-image')
expect(dogImage).toBeInTheDocument()
})
})
This fix it
const preloadedState: FavoriteWithId[] = []
export function renderWithProviders(
ui: React.ReactElement,
{
// Automatically create a store instance if no store was passed in
store = configureStore({
reducer: favsReducer,
preloadedState,
}),
...renderOptions
} = {}
) {
function Wrapper({ children }: PropsWithChildren) {
return <Provider store={store}>{children}</Provider>;
}
// Return an object with the store and all of RTL's query functions
return { store, ...render(ui, { wrapper: Wrapper, ...renderOptions }) };
}