0
votes

I am using this to store state in a React app(hooks based) instead of redux.

import React, { createContext, useContext, useReducer } from "react";

//Prepares the datalayer
export const StateContext = createContext()


//Wrap our app and provide the data layer
export const StateProvider = ({ reducer, initialState, children }) => (
    <StateContext.Provider value={useReducer(reducer, initialState)}>
        {children}
    </StateContext.Provider>
)

//Pull information from the data layer
export const useStateValue = () => useContext(StateContext)
//Accepts a context object (the value returned from React.createContext) and returns the current context value, as given by the nearest context provider for the given context.

I am using above as:

import React,{useState} from 'react'
import { useHistory } from 'react-router-dom';
import { useStateValue } from '../../store/StateProvider';
function Header() {
    const [{ basket, user }, dispatch] = useStateValue();

    const logout = () => {
        dispatch({
            type:'DELETE_USER'
        })
        history.replace('/')
    }

    return (
        <>
            <button className="btn-logout" onClick={ logout } tabIndex="0">
                { user ? ('Logout') : '' }
            </button>
        </>
    )
}

export default Header

When I run 'npm test'

This error is shown:


        TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))

       5 | function Header() {
       6 |     let history = useHistory();
    >  7 |     const [{ basket, user }, dispatch] = useStateValue();
         |                                          ^
       8 | 
       9 |     const logout = () => {
      10 |         dispatch({

      at Header (src/components/header/Header.js:7:42)
      at renderWithHooks (node_modules/react-dom/cjs/react-dom.development.js:14985:18)
      at mountIndeterminateComponent (node_modules/react-dom/cjs/react-dom.development.js:17811:13)
      at beginWork (node_modules/react-dom/cjs/react-dom.development.js:19049:16)
      at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:3945:14)
      at HTMLUnknownElement.callTheUserObjectsOperation (node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
      at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:318:25)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
      at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
      at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
      at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:3994:16)
      at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:4056:31)
      at beginWork$1 (node_modules/react-dom/cjs/react-dom.development.js:23964:7)
      at performUnitOfWork (node_modules/react-dom/cjs/react-dom.development.js:22779:12)
      at workLoopSync (node_modules/react-dom/cjs/react-dom.development.js:22707:5)
      at renderRootSync (node_modules/react-dom/cjs/react-dom.development.js:22670:7)
      at performSyncWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:22293:18)
      at scheduleUpdateOnFiber (node_modules/react-dom/cjs/react-dom.development.js:21881:7)
      at updateContainer (node_modules/react-dom/cjs/react-dom.development.js:25482:3)
      at node_modules/react-dom/cjs/react-dom.development.js:26021:7
      at unbatchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:22431:12)
      at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:26020:5)
      at Object.render (node_modules/react-dom/cjs/react-dom.development.js:26103:10)
      at node_modules/@testing-library/react/dist/pure.js:99:25
      at batchedUpdates$1 (node_modules/react-dom/cjs/react-dom.development.js:22380:12)
      at act (node_modules/react-dom/cjs/react-dom-test-utils.development.js:1042:14)
      at render (node_modules/@testing-library/react/dist/pure.js:95:26)
      at Object.<anonymous> (src/components/header/Header.test.js:30:5)

console.error Error: Uncaught [TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))] at reportException (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jsdom\lib\jsdom\living\helpers\runtime-script-errors.js:62:24) at innerInvokeEventListeners (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:333:9) at invokeEventListeners (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:274:3) at HTMLUnknownElementImpl._dispatch (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:221:9) at HTMLUnknownElementImpl.dispatchEvent (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:94:17) at HTMLUnknownElement.dispatchEvent (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jsdom\lib\jsdom\living\generated\EventTarget.js:231:34) at Object.invokeGuardedCallbackDev (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:3994:16) at invokeGuardedCallback (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:4056:31) at beginWork$1 (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:23964:7) at performUnitOfWork (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:22779:12) TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator)) at Header (C:\Users\Shubh\Desktop\react-star-wars\src\components\header\Header.js:7:42) at renderWithHooks (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:14985:18) at mountIndeterminateComponent (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:17811:13) at beginWork (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:19049:16) at HTMLUnknownElement.callCallback (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:3945:14) at HTMLUnknownElement.callTheUserObjectsOperation (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jsdom\lib\jsdom\living\generated\EventListener.js:26:30) at innerInvokeEventListeners (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:318:25) at invokeEventListeners (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:274:3) at HTMLUnknownElementImpl._dispatch (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:221:9) at HTMLUnknownElementImpl.dispatchEvent (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:94:17) at HTMLUnknownElement.dispatchEvent (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jsdom\lib\jsdom\living\generated\EventTarget.js:231:34) at Object.invokeGuardedCallbackDev (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:3994:16) at invokeGuardedCallback (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:4056:31) at beginWork$1 (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:23964:7) at performUnitOfWork (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:22779:12) at workLoopSync (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:22707:5) at renderRootSync (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:22670:7) at performSyncWorkOnRoot (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:22293:18) at scheduleUpdateOnFiber (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:21881:7) at updateContainer (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:25482:3) at C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:26021:7 at unbatchedUpdates (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:22431:12) at legacyRenderSubtreeIntoContainer (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:26020:5) at Object.render (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:26103:10) at C:\Users\Shubh\Desktop\react-star-wars\node_modules@testing-library\react\dist\pure.js:99:25 at batchedUpdates$1 (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom.development.js:22380:12) at act (C:\Users\Shubh\Desktop\react-star-wars\node_modules\react-dom\cjs\react-dom-test-utils.development.js:1042:14) at render (C:\Users\Shubh\Desktop\react-star-wars\node_modules@testing-library\react\dist\pure.js:95:26) at Object. (C:\Users\Shubh\Desktop\react-star-wars\src\components\header\Header.test.js:30:5) at Promise.then.completed (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jest-circus\build\utils.js:276:28) at new Promise () at callAsyncCircusFn (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jest-circus\build\utils.js:216:10) at _callCircusTest (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jest-circus\build\run.js:212:40) at processTicksAndRejections (internal/process/task_queues.js:97:5) at _runTest (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jest-circus\build\run.js:149:3) at _runTestsForDescribeBlock (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jest-circus\build\run.js:63:9) at _runTestsForDescribeBlock (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jest-circus\build\run.js:57:9) at run (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jest-circus\build\run.js:25:3) at runAndTransformResultsToJestFormat (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jest-circus\build\legacy-code-todo-rewrite\jestAdapterInit.js:176:21) at jestAdapter (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jest-circus\build\legacy-code-todo-rewrite\jestAdapter.js:109:19) at runTestInternal (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jest-runner\build\runTest.js:380:16) at runTest (C:\Users\Shubh\Desktop\react-star-wars\node_modules\jest-runner\build\runTest.js:472:34)

  at VirtualConsole.<anonymous> (node_modules/jsdom/lib/jsdom/virtual-console.js:29:45)
  at reportException (node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:28)
  at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:333:9)
  at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
  at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
  at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)

console.error The above error occurred in the component:

    at Header (C:\Users\Shubh\Desktop\react-star-wars\src\components\header\Header.js:6:19)

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.

  at logCapturedError (node_modules/react-dom/cjs/react-dom.development.js:20085:23)
  at update.callback (node_modules/react-dom/cjs/react-dom.development.js:20118:5)
  at callCallback (node_modules/react-dom/cjs/react-dom.development.js:12318:12)
  at commitUpdateQueue (node_modules/react-dom/cjs/react-dom.development.js:12339:9)
  at commitLifeCycles (node_modules/react-dom/cjs/react-dom.development.js:20736:11)
  at commitLayoutEffects (node_modules/react-dom/cjs/react-dom.development.js:23426:7)
  at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:3945:14)

Test Suites: 1 failed, 1 total Tests: 1 failed, 1 total

enter image description here

1
I don't think you can just pass the useReducer hook in as your context value like that... call it before returning your provider, and then pass in what you want the state value to be. It might also be better to define some specific values and functions you want to pass down to the rest of the app, rather than just handing everything from useReducer down. If you just pass everything down you're bleeding an implementation detail about how your state context works, which the rest of the app shouldn't really know about. For example I'd put your logout function in the provider and pass it downJames

1 Answers

0
votes

You can accomplish what you are trying to do with Manual Mocks.

It might look like this:

import Header from './Header';

jest.mock('state/provider/path/location', () => {
    return {
        // stuff I want to come from my module
    }
});

describe('Header', () => {
    it('does what I want it to do', () => {
        // my cool test!
    })
});

Very Important

The path that you pass to jest.mock is the relative path from the current test file to the file you are trying to mock. This took me far too long to figure out.

A quick personal note on React architecture

Try not to use context or redux if you can avoid it. It's better to intelligently pass props or pass components as props instead.