mardi 18 février 2020

How to test useEffect hook using Jasmine clock to mock the time of setTimeout

I can't figure out how to use jasmine.clock() to mock the setTimeOut in my useEffect hook.

Basically, I'm doing some validation in a simple component. For optimization, I want to validate my value only after some delay. So I validate some debouncedValue instead of the real value.

const [debouncedValue, setDebouncedValue] = React.useState(props.value);
const [isValid, setIsValid] = React.useState(true);

React.useEffect(() => {
    setTimeout(() => {
        setDebouncedValue(props.value);
    }, 300);
}, [props.value]);

React.useEffect(() => {
    setIsValid(props.validate?.(debouncedValue));
}, [debouncedValue]);

Everything is working like expected, the value of the input is only validate after 300 millisecondes.

but I have a lot of difficulty to test this new behaviour.

To test our components, we use Jasmine and Enzyme. So I'm trying to use jasmine.clock() feature --> https://jasmine.github.io/api/2.7/Clock.html

Somehow, It's not working when we use a setTimeout in useEffect hook like in this example.

This is my current test :

jasmine.clock().install();
const validation = (value: string) => value !== '';
const validationMessage = 'invalid value';
const invalidValue = '';
hookWrapper = mount(
<TextArea
id="textarea-id"
validate={validation}
validationMessage={validationMessage}
value="valid value"
/>
);
// so here i'm mounting valid component that is wrapped with
act(() => {
    hookWrapper.mount();
    hookWrapper.setProps({value: invalidValue});
    jasmine.clock().tick(400);
    hookWrapper.update();
});

expect(hookWrapper.contains(invalidValue)).toBeTruthy();
jasmine.clock().uninstall();

When I remove the debouncedValue logic and the jasmine.clock(), the test work without problem.

So my problem really is with using jasmine.clock() to mock the setTimeout inside a useEffet hook.

Aucun commentaire:

Enregistrer un commentaire