Установка значения для значений контекста React с помощью библиотеки тестирования React

#reactjs #react-hooks #react-testing-library

Вопрос:

Я работаю над тестированием компонента с использованием библиотеки реактивного тестирования. Компонент имеет оповещение, которое принимает опору, исходящую из контекста, чтобы определить, открыто ли оповещение или нет.

 const PersonRecord = () => {

  const {
    personSuccessAlert,
    setPersonSuccessAlert,
    updatePersonSuccessAlert,
    setUpdatePersonSuccessAlert,
  } = useContext(PeopleContext);

  return (
      {personSuccessAlert amp;amp; (
        <div className="person-alert-container">
          <Alert
            ariaLabel="person-create-success-alert"
            icon="success"
            open={personSuccessAlert}
          />
        </div>
      )}
   )
 }
 

Таким образом, приведенный выше код использует контекст для извлечения значения personSuccessAlert from PeopleContext . Если personSuccessAlert это правда, появится предупреждение. Мой контекстный файл настроен следующим образом:

 import React, { createContext, useState } from 'react';

export const PeopleContext = createContext();

const PeopleContextProvider = ({ children }) => {
  const [personSuccessAlert, setPersonSuccessAlert] = useState(false);
  const [updatePersonSuccessAlert, setUpdatePersonSuccessAlert] = useState(
    false,
  );

  return (
    <PeopleContext.Provider
      value={{
        personSuccessAlert,
        updatePersonSuccessAlert,
        setPersonSuccessAlert,
        setUpdatePersonSuccessAlert,
      }}>
      {children}
    </PeopleContext.Provider>
  );
};

export default PeopleContextProvider;
 

Сейчас я пытаюсь разработать тест, который переходит personSuccessAlert = true к PersonRecord компоненту.

Вот что я пытался сделать:

 export function renderWithEmptyPerson(
  ui,
  {
    providerProps,
    path = '/',
    route = '/',
    history = createMemoryHistory({ initialEntries: [route] }),
  },
) {
  return {
    ...render(
      <MockedProvider mocks={getEmptyPerson} addTypename={false}>
        <PeopleContextProvider {...providerProps}>
          <Router history={history}>
            <Route path={path} component={ui} />
          </Router>
        </PeopleContextProvider>
      </MockedProvider>,
    ),
  };
}

describe('empty person record rendering', () => {
  afterEach(cleanup);
  test('empty person', async () => {

    const providerProps = { value: true };

    const { getByText, queryByText, queryByLabelText } = renderWithEmptyPerson(
      PersonRecord,
      {
        providerProps,
        route: 'people/6d6ed1f4-8294-44de-9855-2999bdf9e3a7',
        path: 'people/:slug',
      },
    );
    expect(getByText('Loading...')).toBeInTheDocument();
  });
});
 

Я пробовал разные варианты const providerProps = { value: true }; . Замена value на personSuccessAlert не сработала.

Мы будем признательны за любой совет или помощь.

Ответ №1:

Вы переходите providerProps к тому PeopleContextProvider , но тот PeopleContextProvider ничего не делает с реквизитом. Вам нужно будет на самом деле использовать эти реквизиты, например, для установки начального состояния. Вы могли бы попробовать что-то вроде:

 const PeopleContextProvider = ({ children, initialPersonSuccessAlert = false }) => {
  const [personSuccessAlert, setPersonSuccessAlert] = useState(initialPersonSuccessAlert);
  const [updatePersonSuccessAlert, setUpdatePersonSuccessAlert] = useState(
    false,
  );

  return (
    <PeopleContext.Provider
      value={{
        personSuccessAlert,
        updatePersonSuccessAlert,
        setPersonSuccessAlert,
        setUpdatePersonSuccessAlert,
      }}>
      {children}
    </PeopleContext.Provider>
  );
};
 

Это позволит вам установить начальное состояние personSuccessAlert , передав initialPersonSuccessAlert опору. Вы могли бы обновить свой тест следующим образом:

 const providerProps = { initialPersonSuccessAlert: true };
 

В качестве альтернативы, если вы хотите внести изменения только в свой тестовый файл, вы можете рассмотреть возможность обновления функции renderWithEmptyPerson для использования PeopleContext.Поставщик напрямую вместо компонента PeopleContextProvider. Это позволит вам установить значение контекста так, как вам нравится.

Комментарии:

1. Хм, я думаю, это может сработать, но это требует, чтобы я изменил свой фактический код, а не только свои тесты. Я надеялся, что есть какой-то способ высмеять ценность personSuccessAlert только в моем наборе тестов.

2. Если вы твердо намерены не изменять код, то вы могли бы рассмотреть возможность обновления renderWithEmptyPerson функции для использования PeopleContext.Provider непосредственно вместо PeopleContextProvider компонента. Это позволит вам установить контекст value так, как вам нравится. Нет другого хорошего способа сделать это, кроме PeopleContextProvider как издеваться useContext , или useState , все это я бы настоятельно не рекомендовал , так как это сделало бы ваши тесты чрезвычайно хрупкими.