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