faceyspacey/redux-first-router-link

Errors when testing with Jest

reidblomquist opened this issue · 5 comments

Hi! First of all would like to say love RFR and all the work you've done!

This isn't so much an issue as a question of "how do I". Currently working to move our framework into jest/enzyme testing and running into an issue thrown by testing components with a component:

FAIL  src/routes/About/__tests__/About.test.js
  ● Console

    console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2053
      The above error occurred in the <Link> component:
          in Link (created by Connect(Link))
          in Connect(Link) (created by _About)
          in div (created by _About)
          in div (created by _About)
          in _About (created by glamorous(_About))
          in glamorous(_About) (created by Connect(glamorous(_About)))
          in Connect(glamorous(_About))
          in ThemeProvider
          in Provider

      Consider adding an error boundary to your tree to customize error handling behavior.
      You can learn more about error boundaries at https://fb.me/react-error-boundaries.

  ● >>>A B O U T --- Snapshot › +++ capturing Snapshot of Component when user has groups

    TypeError: _selectLocationState is not a function

      at selectLocationState (node_modules/redux-first-router/dist/connectRoutes.js:551:10)
      at Link (node_modules/redux-first-router-link/dist/Link.js:68:60)
      at mountIndeterminateComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:4356:15)
      at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:4557:16)
      at performUnitOfWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6529:16)
      at workLoop (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6638:28)
      at HTMLUnknownElement.callCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2210:14)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:219:27)
      at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:126:9)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:36:27)
      at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:61:35)
      at Object.invokeGuardedCallbackDev (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2249:16)
      at invokeGuardedCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2106:29)
      at performWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6756:7)
      at scheduleUpdateImpl (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7141:19)
      at scheduleUpdate (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7080:12)
      at scheduleTopLevelUpdate (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7351:5)
      at Object.updateContainer (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7381:7)
      at create (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8186:18)
      at Object.<anonymous> (src/routes/About/__tests__/About.test.js:20:12)
          at new Promise (<anonymous>)
          at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:188:7)

Wondering what the best way might be to make these functions rfrl needs to render correctly into my redux-mock-store so all these functions are available to my test suites.

Any help would be greatly appreciated!

Cheers,
Reid

Glad you like it.

Basically, you need the redux store always there, OR you need to create some mocks. Since you're not actually testing the functionality of <Link /> (or you would have Redux and RFR provided), the easiest thing may simply be to mock the entire Link component and, for example if you're using Jest, snapshot the correct props you're passing to it.

Hmm - good thoughts thank you @faceyspacey ! For now I went ahead and poked at your createLink helper and parsed out a bit of a sparse way to create a store with the context and state RFR/RFRL need to do their thing. I may switch over to mocking RFRL components - but this seems like an easy way to ensure my thunks are actually protecting routes etc right in my snapshots. Here's where I landed:

global.createMockStore = (initState, loc) => {
  const history = createHistory({
    initialEntries: [loc || '/'],
    initialIndex: 0,
    keyLength: 6
  });

  const { middleware, enhancer, reducer } = connectRoutes(history, routes);

  initState = initState || {};
  const middlewares = applyMiddleware(middleware);
  const enhancers = compose(enhancer, middlewares);
  const rootReducer = (state = initState, action = {}) => ({
    location: reducer(state.location, action),
    auth: state.auth || {},
    config: state.config || {}
  });

  return createStore(rootReducer, enhancers);
};

It's a bit slapped together but seems to be working and getting my routeMap correctly and not barfing. Still on the fence about mocking vs this. Mocking might be cleaner as I wouldn't have to updateSnapshot each time my routeMap changes.

Anddd a quick mock for anyone that wants it:
(placed in __mocks__/redux-first-router-link.js which will be used by calling in your test or test setup jest.mock('redux-first-router-link')

import React from 'react';

const rfrLinkMock = ({ ...props }) => (
  <a {...props}/>
);

module.exports = rfrLinkMock;

solid

Updated link mock including NavLink:

import React from 'react';

const rfrLinkMock = ({ ...props }) => (
  <a {...props}/>
);

export const NavLink = rfrLinkMock;
export default rfrLinkMock;