My Component:
const Component = ({product, show = false}: Props) => {
const hook = useHook();
const rendered = useRef(false);
const [displayStyle, setDisplayStyle] = useState('none');
const [showBar, setShowBar] = useState(show);
const isInHook = () => hook.contains(product);
useEffect(() => {
if (!rendered.current) return;
if (isInHook()) {
setShowBar(false);
setTimeout(() => {
setDisplayStyle('none');
}, 100);
}
}, [isInHook()]); // Triggered when product is added to hook
useEffect(() => {
if (isInHook()) return;
if (show) {
setShowBar(true);
setDisplayStyle('flex');
} else if (!show && rendered.current) {
setShowBar(false);
setTimeout(() => {
setDisplayStyle('none');
}, 100);
}
if (!rendered.current) rendered.current = true;
}, [show]); // Triggered on show param change
return (
<StyledComponent show={showBar} displayStyle={displayStyle}>
<Button
title="Add product"
onClick={() => {
hook.add(product);
}}
>
Add product
</Button>
</StyledComponent>
);
};
export default Component;
Here we have isInHook that returns true/false for contains(product) and useEffect listening to it. It works perfectly and when product is added to hook, it triggers useEffect setting display of StyledComponent to none.
Problem comes when I tried testing it for disappearance using RTL:
const hook = [];
jest.mock('../hooks/use-hook', () => {
return jest.fn(() => ({
contains: (product) => hook.includes(product.slug),
add: (product) => hook.push(product.slug),
}));
});
it('is hidden once added to hook', async () => {
let show = !hook.includes(data.original.slug);
render(
<Component
show={show}
product={product}
/>,
);
const barEl = screen.getByRole('button').closest('div');
const addToHookBtn = screen.getByRole('button');
expect(barEl).toBeInTheDocument();
fireEvent.click(addToHookBtn);
expect(hook.includes(product.slug)).toBeTruthy();
await waitFor(() => {
expect(barEl).toHaveStyle(`display: none`);
});
});
When you click on the button, it adds product to array inside the hook and after that bar with the button disappears.
Here I mocked hook using jest, and expect(hook.includes(product.slug)).toBeTruthy() passes as true, which means that fireEvent.click(addToHookBtn) works properly. However, useEffect that supposed to get triggered on isInHook() not getting triggered. I also tried specifying show as false right before fireEvent, but I still can't get barEl display to be none. Why useEffect is not getting triggered on test even though expect(hook.includes(product.slug)).toBeTruthy() is passing?