How to mock a single state variable in a context provider with jest?

Viewed 1077

I am using jest and react-testing-library to write tests for my react application. In the application, I have a context provider that contains the state across most of the application. In my tests, I need to mock one state variable in context provider and leave one alone, but I'm not sure how to do this.

AppContext.tsx

const empty = (): void => {};

export const emptyApi: ApiList = {
    setStep: empty,
    callUsers: empty,
}

export const defaultState: StateList = {
    userList = [],
    step = 0,
}

const AppContext = createContext<ContextProps>({ api: emptyApi, state: defaultState });

export const AppContextProvider: React.FC<Props> = props => {
    const [stepNum, setStepNum] = React.useState(0);
    const [users, setUsers] = useState<User[]>([]);

    const api: ApiList = {
        setStep: setStepNum,
        callUsers: callUsers,
    }

    const state: Statelist = {
        userList: users,
        step: stepNum,
    }

    const callUsers = () => {
        const usersResponse = ... // call users api - invoked somewhere else in application
        setUsers(userResponse);
    }
    return <AppContext.Provider value={{ api, state}}>{children}</AppContext.Provider>;
}

export default AppContext

In _app.tsx

import { AppContextProvider } from '../src/context/AppContext';
import { AppProps } from 'next/app';
import { NextPage } from 'next';

const app: NextPage<AppProps> = props => {
    const { Component, pageProps } = props;
    return (
        <React.Fragment>
            <AppContextProvider>
                <Component {...pageProps}
            </AppContextProvider>
        </React.Fragment>
    )
}
export default app

the component that uses AppContext progress.tsx

import AppContext from './context/AppContext';

const progress: React.FC<Props> = props => {
    const { state: appState, api: appApi } = useContext(AppContext);
    const { userList, step } = appState;
    const { setStep } = appApi;


    return (
        <div>
            <Name />
            {step > 0 && <Date /> }
            {step > 1 && <UserStep list={userList} /> }
            {step > 2 && <Address />
        </div>
   
    )
    
}

export default progress

users is data that comes in from an API which I would like to mock. This data is shown in progress.tsx. stepNum controls the display of subcomponents in progress.tsx. It is incremented after a step is completed, once incremented, the next step will show.

In my test, I have tried the following for rendering - progress.test.tsx

import progress from './progress'
import AppContext, { emptyApi, defaultState } from './context/AppContext'
import { render } from "@testing-library/react"

describe('progress', () => ({
    const api = emptyApi;
    const state = defaultState;
    it('should go through the steps', () => ({
        state.usersList = {...}
        render(
            <AppContext.Provider value={{api, state}}>
                <progress />
            </AppContext.Provider>
        )

        // interact with screen... 
        // expect(...)
    })
})

However, when I set up the context provider like that in the test, I can set the userList to whatever I want, but it'll also override the setStep state hook so in the component, it won't update the state. Is it possible to mock only the users variable inside of AppContext with jest, but leave users hook alone?

0 Answers
Related