reactjsjestjsreact-test-renderer

React test Renderer - fails test after onClick


I have this component:

import React from 'react';

export const ThemeSwitch = ({ theme, themeToggler }) => {
    return (
        theme === 'light'
            ? <div onClick={themeToggler}><h2>dark</h2><img src="assets/icon-moon.svg" alt="icon of a moon" /></div>
            : <div onClick={themeToggler}><h2>light</h2><img src="assets/icon-sun.svg" alt="icon of a sun" /></div>
    );
};

I have this test suite:

describe("Theme Switch Test", () => {
    it('[1] Matches the snapshot', () => {
        const theme = "light";
        const component = renderer.create(<ThemeSwitch theme={theme} themeToggler={() => { }} />);

        expect(component.toJSON()).toMatchSnapshot();
    });

    it('[2] Renders - "dark" with moon icon - if theme is set to light', () => {
        const theme = "light";
        const component = renderer.create(<ThemeSwitch theme={theme} themeToggler={() => { }} />).root;

        const h2 = component.findByType('h2').props.children;
        const imgSource = component.findByType('img').props.src;

        expect(h2).toEqual('dark');
        expect(imgSource).toEqual('assets/icon-moon.svg');
    });

    it('[3] Renders - "light" with sun icon - if theme is set to dark', () => {
        const theme = "dark";
        const component = renderer.create(<ThemeSwitch theme={theme} themeToggler={() => { }} />).root;

        const h2 = component.findByType('h2').props.children;
        const imgSource = component.findByType('img').props.src;

        expect(h2).toEqual('light');
        expect(imgSource).toEqual('assets/icon-sun.svg');
    });

    it('[4] Changes theme on click from - "dark" with moon icon - to - "light" with sun icon - and back', () => {
        let theme = "light";

        const onClick = () => {
            theme = "dark";
        };

        const component = renderer.create(<ThemeSwitch theme={theme} themeToggler={() => onClick()} />).root;

        const wrapper = component.findByType('div');

        act(() => wrapper.props.onClick());

        let h2 = component.findByType('h2').props.children;
        let imgSource = component.findByType('img').props.src;

        expect(h2).toEqual('light');
        expect(imgSource).toEqual('assets/icon-sun.svg');
    });
});

The first 3 tests pass normally but the last one fails on expect(h2).toEqual('light');

I am confused why this happens as when testing manually I see the component behaving as expected so changing the text and icon after the onClick event.


Solution

  • The error was caused by not updating the component after the onClick.

        it('[4] Changes theme on click from - "dark" with moon icon - to - "light" with sun icon', () => {
           
            // Defining props
            let theme = "light";
    
            const onClick = () => {
                theme = "dark";
            };
    
            // Creating the TestRendererInstance
            const component = renderer.create(<ThemeSwitch theme={theme} themeToggler={() => onClick()} />);
    
            // repeting test [1] 
            let h2Text = component.root.findByType('h2').props.children;
            let imgSource = component.root.findByType('img').props.src;
    
            expect(h2Text).toEqual('dark');
            expect(imgSource).toEqual('assets/icon-moon.svg');
    
            // Triggering the onClick event of the component
            act(() => component.root.findByType('div').props.onClick());
    
            // Updating the testRenderer tree
            component.update(<ThemeSwitch />);
    
            // Test if text inside of h2 and src inside of img changed
            h2Text = component.root.findByType('h2').props.children;
            imgSource = component.root.findByType('img').props.src;
    
            expect(h2Text).toEqual('light');
            expect(imgSource).toEqual('assets/icon-sun.svg');
        });