0

It's driving me crazy. How test react with mobx with useContext ? I'm trying to do with jest and enzyme, but when I try

export const HelloWorldView = observer(() => {
    const { store } = useHelloWorldController()
    const dataStore = store.datastore

    return (
        <>
            <DisplayVersion version={dataStore.versionNumber} />
        </>
    )
})

And

export const useHelloWorldController = () => React.useContext(React.createContext({
  store: store,
}));

Store is a simple mobx store

export class Store {
    @observable
    versionNumber?: string

    @action
    changeVersion(versionNumber: string){
        this.versionNumber = versionNumber
    }
}

I tried this

const store = observable({
    versionNumber: "1.2.0",
    changeVersion: jest.fn()
})

jest.mock("../HelloWorldPage", () => ({
    ...jest.requireActual("../HelloWorldPage"),
    useHelloWorldController: () => ({ 
        store: {
            datastore: store
        }
     })
}));

describe("HelloWorldView", () => {
    test("display version number", async () => {
        const wrapper = render(<HelloWorldView />);

        expect(await wrapper.queryByText("1.9.2")?.textContent).toEqual("1.9.2")  // VERSION
    })

But i'm getting

the module factory of jest.mock() is not allowed to reference any out-of-scope variables.

Already tried with doMock, but this is not working at all

skyboyer
  • 22,209
  • 7
  • 57
  • 64
Xero
  • 3,951
  • 4
  • 41
  • 73
  • 1
    Hm, your setup is confusing me a bit. Usually, I'd expect context to be exported from a module, so that the `context.Provider` component could be used to setup the context. But the way you are creating the context here, is anonymously, and it doesn't seem like there is a way to get a context provider. If the context provider was available to tests, then it would be a simple matter to pass a test value (the mock store) to the context when rendering. – Garrett Motzner Sep 15 '20 at 20:10

1 Answers1

0

I have changed how I setuped the Provider

export const helloWorldContext = React.createContext({ store: controller })
export const useHelloWorldController = () => React.useContext(helloWorldContext);

and now I can test :

import React from "react";
import { render, fireEvent, screen } from '@testing-library/react'
import { HelloWorldView } from "./HelloWorldView";
import { helloWorldContext } from "../HelloWorldPage";
import { HelloWorldController } from "../../controllers/HelloWorldController";
import { HelloWorldDI } from "../../config/HelloWorldDI";
import { HelloWorldDS } from "../../datastores/HelloWorldDS";
import { mocked } from 'ts-jest/utils';

jest.mock('../../datastores/HelloWorldDS', () => {
    return {
        HelloWorldDS: jest.fn().mockImplementation(() => {
            return {
                versionNumber: "1.2.0",
                changeVersion: jest.fn()
            };
        })
    };
});

describe("HelloWorldView", () => {
    // mock
    const HelloWorldDSMock = mocked(HelloWorldDS, true);
    beforeEach(() => {
        HelloWorldDSMock.mockClear();
    });

    test("display version number", async () => {
        // UT
        const controller = new HelloWorldController(new HelloWorldDI(), new HelloWorldDS());
        const wrapper = render(
            <helloWorldContext.Provider value={{ store: controller }}>
                <HelloWorldView />
            </helloWorldContext.Provider>
        );

        expect(await wrapper.queryByText("1.2.0")?.textContent).toEqual("1.2.0")
    })

    test("click must call changeVersion", async () => {
        // arrange
        const ds = new HelloWorldDS()
        let changeVersion = jest.spyOn(ds, 'changeVersion').mockImplementation(() => {});
        const controller = new HelloWorldController(new HelloWorldDI(), ds);

        // act
        render(
            <helloWorldContext.Provider value={{ store: controller }}>
                <HelloWorldView />
            </helloWorldContext.Provider>
        );
        fireEvent.click(screen.getByText('Upgrade button'))

        // assert
        expect(changeVersion).toHaveBeenCalledTimes(1);
        changeVersion.mockRestore();
    })
})

Special thanks to Garrett Motzner

Xero
  • 3,951
  • 4
  • 41
  • 73