Протестируйте компонент redux-toolkit с неудачным пользовательским рендерингом с поставщиками

Я хочу создать пару тестов для своих компонентов, но так как я использую Redux, мне нужно отправить провайдера, согласно документации мне нужно сделать что-то вроде renderWithProviders, чтобы я мог повторно использовать его для разных компонентов и вот что Я пытаюсь это сделать, я использую Vite и TypeScript для этого проекта, но получаю следующие ошибки и не знаю, как это исправить.

Это пользовательский рендеринг, который я пытаюсь создать:

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 }) };
}

Мой магазин такой:

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

и кусочек для фаворитов вот этот:

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

Итак, я не знаю, почему я получаю сообщение

'favs' не существует в типе 'Reducer<{ favs: FavoriteWithId[]; }, UnknownAction, любое>'

Я думал, что редуктор в тестах должен иметь свойство «favs», как и в магазине, который я настраиваю, но я больше не уверен, может ли кто-нибудь дать мне подсказку или что-то в этом роде, как действовать дальше?

Модульный тест, который я пытаюсь написать, следующий:

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()
  })
})

Вот репозиторий на github

Можете ли вы отредактировать , чтобы опубликовать полный минимально воспроизводимый пример, чтобы мы могли увидеть, что делает ваш код модульного тестирования?

Drew Reese 27.03.2024 01:32

@DrewReese Я также добавил модульный тест и репозиторий github, спасибо

Andree 27.03.2024 01:43

Лично я строю свой код так, чтобы была оболочка, которая подключалась к Redux, а затем все остальное использовало внедрение зависимостей, что вполне поддается тестированию. Я не удосужился протестировать уровень Redux, полагая, что redux и redux-toolkit уже имеют хорошие тесты. Но мне кажется, что вам просто нужно экспортировать свои типы, как описано здесь, и использовать экспортированный тип.

Amy Blankenship 27.03.2024 03:27
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
3
140
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это исправить

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 }) };
}

Другие вопросы по теме