I am working on testing a component using react-testing-library. The component has an alert which accepts a prop that comes from context to determine whether the alert is open or not.
const PersonRecord = () => {
const {
personSuccessAlert,
setPersonSuccessAlert,
updatePersonSuccessAlert,
setUpdatePersonSuccessAlert,
} = useContext(PeopleContext);
return (
{personSuccessAlert && (
<div className="person-alert-container">
<Alert
ariaLabel="person-create-success-alert"
icon="success"
open={personSuccessAlert}
/>
</div>
)}
)
}
So the above code uses context to pull the value of personSuccessAlert
from PeopleContext
. If personSuccessAlert
is true the alert will display. My context file is set up as follows:
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;
Now I am trying to develop a test which passes personSuccessAlert = true
to the PersonRecord
component.
Here is what I have been trying:
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();
});
});
I have tried different variations of const providerProps = { value: true };
. Replacing value
with personSuccessAlert
did not work.
Any advice or help is appreciated.
CodePudding user response:
You are passing providerProps
to the PeopleContextProvider
, but the PeopleContextProvider
is not doing anything with the props. You'll need to actually use those props, for example to set the initial state. You could try something like:
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>
);
};
This would allow you to set the initial state of personSuccessAlert
by passing in a initialPersonSuccessAlert
prop. You could update your test like so:
const providerProps = { initialPersonSuccessAlert: true };
Alternatively, if you only wanted to make changes in your test file, you could consider updating the renderWithEmptyPerson function to use PeopleContext.Provider directly instead of the PeopleContextProvider component. That will allow you to set the context value however you like.