#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
, все это я бы настоятельно не рекомендовал , так как это сделало бы ваши тесты чрезвычайно хрупкими.