Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React testing - How can I mock or inject data in the store to be provided as props to component

Tags:

I'm using jest and react-testing-library to provide unit test coverage for my app.

I use this handy helper function Kent C. Dodds showed in one of his videos:

const renderWithRedux = ui => ({
    ...render(<Provider store={store}>{ui}</Provider>),
    store,
});

I use when I am testing connected components.

I am running into an issue where in order to render a component I needed some data fetched to accuaratly resolve a test, or atleast inject mock data into the store. I am failing to do so

this is my test:

test('navbar accepts props', async () => {
    /**
     * Something I was testing
     */
    const functionToTest = () => async dispatch => {
        dispatch(fetchTickets());
    };

    functionToTest();
    const isReady = true;
    const mockData = {
        sessionInformation: {
            ticket: { label: 'Total Tickets' },
            sessionDuration: { sessionLabel: 'Session Duration', duration: 42 },
            equipment: { type: 'Desktop', operatingSystem: 'Windows' },
        },
        component: { isReady },
        tickets: {
            ticketPayload: [
                {
                    number: '1020312039',
                    shortDescription: 'Accessories',
                    status: 'Active',
                    createdOnEpoch: 1512322200000,
                },
            ],
        },
    };

    const data = renderWithRedux(<Navbar props={mockData} />);
});

The component I am testing:

const NavBar = ({
    openTickets: { label },
    sessionDuration: { sessionLabel, duration },
    tickets: { ticketPayload = [] },
    isReady,
}) => (!isReady ? (
    <Container>
        <LogoContainer>
            <Logo src={logo} alt="logo" />
            <Header>Service Desk</Header>
        </LogoContainer>

        <SessionInformation className="session">
            <NavbarInfo className="session-info">
                <p>
                    <FontAwesomeIcon icon="ticket-alt" className="ticketIcon" />
                    {label}
                </p>
                <p>{`${ticketPayload.length} tickets`}</p>
            </NavbarInfo>
            <NavbarInfo last className="session-info">
                <p>
                    <FontAwesomeIcon icon="clock" className="ticketIcon" />
                    {sessionLabel}
                </p>
                <p>{`${duration} minutes`}</p>
            </NavbarInfo>
            {hasTokens() && (
                <Button type="submit" onClick={() => console.log('notes')}>
                        Notepad
                </Button>
            )}
        </SessionInformation>
    </Container>
) : (
    <LoaderContainer>
        <RingLoader size={100} />
    </LoaderContainer>
));

I need to make length calculations with ticketPayload however the main store is taking priority. Since that information has not been fetched, ticketPayload's is 0. I want to be able to atleast mock the data to be passed but haven't had any luck using props, as the store takes precedence.

Hope anyone can beam a light of help or share some guidance. Thanks in Advance!

like image 701
aromanarguello Avatar asked Mar 26 '19 22:03

aromanarguello


People also ask

How do you mock React a component in Jest?

To mock a React component, the most straightforward approach is to use the jest. mock function. You mock the file that exports the component and replace it with a custom implementation. Since a component is basically a function, the mock should also return a function.

Which of the given method from Jest are used to test React component?

test. js extension as when the tests are run using the npm test command, React automatically checks for all the file names with a . test extension and runs the tests.


2 Answers

The official Writing Tests doc from Redux recommends this approach:

But sometimes you want to test just the rendering of the component, without a Redux store.

In order to be able to test the...component itself without having to deal with the decorator, we recommend you to also export the undecorated component

In other words...export NavBar as a named export so you can access it in your tests.

Then you can test it directly as a simple UI component that just renders based on the props you give it.

like image 176
Brian Adams Avatar answered Oct 19 '22 09:10

Brian Adams


I created a helper function to wrap my components with redux.

import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import initialState from '../store/initialState';

const mockStore = (state = initialState) => configureMockStore()(state);

export const testableComponent = (component, state) =>
  (<Provider store={mockStore(state)}>{component}</Provider>);

And then you can call it just like this, passing your state

testableComponent(<YourComponent />, {yourUpdatedMockedState})
like image 42
AlexZvl Avatar answered Oct 19 '22 09:10

AlexZvl