'Testing a React context with jest and consume it in the test file

I'm now trying to test a simple React class context that is used to sets a currency to the global state. However, I didn't know how to to consume the context inside the test file using Jest.

My code is below for the context file and the test file. Please let me know if something isn't clear enough.

CurrencyContext.js

    import React, {Component, createContext} from "react"

export const CurrencyContext = createContext()

class CurrencyContextProvider extends Component {

    state = {
        selectedCurrency: 'USD'
    }
    setCurrency = (c)=>{
        this.setState({selectedCurrency: c})
    }

    render() {
        return (
            <CurrencyContext.Provider value={{...this.state, setCurrency: this.setCurrency}}>
                {this.props.children}
            </CurrencyContext.Provider>
        )
    }
}

export default CurrencyContextProvider;

CurrencyContext.test.js

    import {CurrencyContext} from "../contexts/CurrencyContext";


test("Testing Currency Context",()=>{

    // I didn't know how to consume the context in this file
    expect(3).toBe(3)
})


Solution 1:[1]

We can use these Testing Recipes to test the CurrencyContextProvider component. And we can create a test component to consume the context. I declare the renderedContext variable outside of the component to hold the context value received from the context provider so that we can assert its value in the test case.

E.g.

index.jsx:

import React, { Component, createContext } from 'react';

export const CurrencyContext = createContext();

class CurrencyContextProvider extends Component {
  state = {
    selectedCurrency: 'USD',
  };
  setCurrency = (c) => {
    this.setState({ selectedCurrency: c });
  };

  render() {
    return (
      <CurrencyContext.Provider value={{ ...this.state, setCurrency: this.setCurrency }}>
        {this.props.children}
      </CurrencyContext.Provider>
    );
  }
}

export default CurrencyContextProvider;

index.test.jsx:

import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { act } from 'react-dom/test-utils';
import CurrencyContextProvider, { CurrencyContext } from '.';

describe('70144273', () => {
  let container;
  beforeEach(() => {
    // setup a DOM element as a render target
    container = document.createElement('div');
    document.body.appendChild(container);
  });

  afterEach(() => {
    // cleanup on exiting
    unmountComponentAtNode(container);
    container.remove();
    container = undefined;
  });
  test('should pass', () => {
    let renderedContext;

    class Component extends React.PureComponent {
      static contextType = CurrencyContext;
      render() {
        renderedContext = this.context;
        return <button onClick={() => this.context.setCurrency('EUR')}>click me!</button>;
      }
    }

    act(() => {
      render(
        <CurrencyContextProvider>
          <Component />
        </CurrencyContextProvider>,
        container
      );
    });

    expect(renderedContext).toEqual({ selectedCurrency: 'USD', setCurrency: expect.any(Function) });

    const button = document.querySelector('button');
    expect(button?.innerHTML).toBe('click me!');

    act(() => {
      button?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
    });
    expect(renderedContext).toEqual({ selectedCurrency: 'EUR', setCurrency: expect.any(Function) });
  });
});

Test result:

 PASS  stackoverflow/70144273/index.test.tsx (8.839 s)
  70144273
    ? should pass (26 ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 |                   
 index.jsx |     100 |      100 |     100 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.925 s

package versions:

"jest": "^26.6.3",
"react": "^16.14.0",
"react-dom": "^16.14.0",

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1