Search code examples
reactjsjestjsenzymereact-componentreact-state-management

how I test useEffect with isLoading state


I want to build test when the isLoading state change the component. I know in the class component there is the way by do setState with enzyme, but I would like to know how I can do it here.

const Spacex = () => {
    const [open, setOpen] = useState(false);
    const [upComingLaunches, setUpComingLaunches] = useState([]);
    const [Launchpad, setLaunchpad] = useState([])
    const [isLoading, setIsLoading] = useState(true);
    useEffect(() => {
        let tempData;
        SpaceXNextLaunche()
            .then(data => {
                setUpComingLaunches(data);
                tempData = data;
                return LaunchPad()
            }).then(dataLaunch => {
                const foundTheLaunch = dataLaunch.docs.filter((Launch, index) => {
                    return tempData.id === Launch.id
                });
                setLaunchpad(foundTheLaunch);
                setIsLoading(false);
            })
    }, [])
    if (isLoading) return <LoadingComp />
    return (
        <div>
            <div className="upcoming-launches">
                <h1 className={styles.title}>upcoming launche</h1>
                <div className={styles.CountDownWarrper}>
                    {Object.keys(upComingLaunches).length > 0 ?
                        <Card className={styles.CountDownCard}>
                            <div className={styles.MissionName}>{upComingLaunches.name}</div>
                            <div className={styles.gridBadges}>
                                <div className={styles.CountDown}><CountDownClock upComingLaunches={upComingLaunches} /></div>
                                <div className={styles.badgeFlex}><img className={styles.badge} src={upComingLaunches.links["patch"]["small"]} alt="mission patch" /></div>
                            </div>
                            <GoogleMap
                                mapVisiblity={(e) => setOpen(!open)}
                                open={open}
                                placeName={Launchpad[0].launchpad.full_name} />
                        </Card>
                        : null}
                </div>
            </div>
        </div>
    )
}
export default Spacex;

Solution

  • The proper way to test functional components is to test the actual functions' behaviour, not their implementation. In your case that would be mocking the SpaceXLaunche() to return its data after some timeout, eg:

    function SpaceXLauncheMock() {
        return new Promise(resolve => {
            setTimeout(resolve(data), 1500);
        });
    }
    
    const SpaceXLaunche = jest.spyOn(SpaceXLaunche.prototype, 'SpaceXLaunche')
        .mockImplementation(SpaceXLauncheMock);
    

    then, you'd test your consequence of isLoading - the presence or absence of LoadingComp, initially, and again after the timeout (don't forget to put done as the test case's argument):

    expect(component.contains(<LoadingComp />)).toBe(true);
    
    setTimeout(() => {
        expect(component.contains(<LoadingComp />)).toBe(false);
    
        done();
    }, 2000);