Reputation: 475
I have code where user can click on the ingredient and then I store his selected ingredient inside context and redirect him to a details page:
const [, setSelectedItem] = useContext(itemContext);
const [, setSelectedMealNumber] = useContext(selectedMealNumberContext);
const editIngredient = (event: React.MouseEvent<HTMLElement>) => {
setSelectedItem(ingredient);
setSelectedMealNumber(mealNumber);
router.push(`/i/${ingredient?.uid}`);
};
However selectedItem is initialized as null in my context provider:
// Provider component
function ApiStore({ children }) {
const [selectedItem, setSelectedItem] = useState(null);
So when testing details page:
it("renders the selected item productName", () => {
const queryClient = new QueryClient();
render(
<ApiStore>
<QueryClientProvider client={queryClient}>
<IngredientExpanded />
</QueryClientProvider>
</ApiStore>
);
const productName = screen.getByText(FakeItem1.productName);
expect(productName).toBeInTheDocument();
});
Test fails, because selectedItem is null.
At the moment I manually initialize the value in my context provider like this and my test succeeds:
const [selectedItem, setSelectedItem] = useState(FakeItem1);
But since I need this value only for my tests and not the actual app, I have to remove it and set it back to null on my production app.
I don't need to mock everything since, everything else works. How can I simply inject the selectedItem during my test?
Upvotes: 2
Views: 7956
Reputation: 102672
The easiest way is to add value
props for ApiStore
component. Then you can provide the initial value for the context provider.
index.ts
:
import React, { useContext, useState } from 'react';
const ItemContext = React.createContext({
selectedItem: null,
setSelectedItem: (state) => {},
});
export const ApiStore = ({ children, value }) => {
const [selectedItem, setSelectedItem] = useState(value);
return <ItemContext.Provider value={{ selectedItem, setSelectedItem }}>{children}</ItemContext.Provider>;
};
export const IngredientExpanded = () => {
const { selectedItem } = useContext(ItemContext);
return <div>{selectedItem}</div>;
};
index.test.ts
:
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import React from 'react';
import { ApiStore, IngredientExpanded } from '.';
describe('72047880', () => {
test('should find the selected item', () => {
render(
<ApiStore value={'product name'}>
<IngredientExpanded />
</ApiStore>
);
const productName = screen.getByText('product name');
expect(productName).toBeInTheDocument();
});
test('should not find the selected item', () => {
render(
<ApiStore value={null}>
<IngredientExpanded />
</ApiStore>
);
const productName = screen.queryByText('product name');
expect(productName).not.toBeInTheDocument();
});
});
test result:
PASS stackoverflow/72047880/index.test.tsx (11.239 s)
72047880
✓ should find the selected item (23 ms)
✓ should not find the selected item (3 ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 12.855 s
Upvotes: 5