I have this component:
export const CityForm: FC = () => {
const { state: widgetState } = useContext(WidgetContext);
const { dispatch: geocodingDispatch } = useContext(GeocodingContext);
const [city, setCity] = useState<string>('');
const debouncedCity = useDebouncedValue<string>(city, 800);
const fetchCallback = useCallback(() => {
getLocationCoords(geocodingDispatch)(widgetState.appid, debouncedCity);
}, [debouncedCity]);
useEffect(() => {
if (debouncedCity && widgetState.appid) {
fetchCallback();
} else {
clearLocationCoords(geocodingDispatch)();
}
return () => {
clearLocationCoords(geocodingDispatch)();
}
}, [debouncedCity]);
const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
setCity(e.target.value);
};
return (
<Input
data-testid={TEST_ID.CITY_FORM}
type={'text'}
value={city}
onChange={handleOnChange}
placeholder={"Type your City's name..."}
/>
);
};
I'm trying to write a test to check if getLocationCoords function will be called after user input.
this is the test:
it('should call getLocationCoords action after 800 miliseconds', async () => {
const dispatch = jest.fn(() => null);
const testCity = 'city';
const getLocationCoords = jest.fn(() => null);
jest.spyOn(useDebouncedValueModule, 'useDebouncedValue')
.mockImplementation((value) => value);
const component = render(
<ThemeProvider theme={lightTheme}>
<WidgetContext.Provider value={{ state: { appid: 'test' } as IWidgetState, dispatch: dispatch }}>
<GeocodingContext.Provider value={{ state: {} as IGeocodingState, dispatch: dispatch }}>
<CityForm />
</GeocodingContext.Provider>
</WidgetContext.Provider>
</ThemeProvider >
);
const input = await component.findByTestId(TEST_ID.CITY_FORM);
expect(input).toHaveValue('');
await userEvent.type(input, testCity);
expect(input).toHaveValue(testCity);
expect(getLocationCoords).toHaveBeenCalledTimes(1);
});
expect(getLocationCoords).toHaveBeenCalledTimes(1); Received number of calls: 0.
I cannot figure out why this happens. As the component works properly during manual testing.
Since the useDebouncedValue is mocked and returns the value instantaneously the debouncedCity within the component should update and trigger the useEffect