Search code examples
reactjsunit-testingcypressstubbinguse-reducer

how to stub react-redux useReducer hook - using cypress


could someone please help me understand how to stub useReducer from react-redux? This code looks like it should work, but it just doesnt (stub never intercepts the useReducer function).

import React from 'react';
import { mount } from '@cypress/react';
import * as ReactReduxModule from 'react-redux';
const { Provider } = ReactReduxModule;

import { Button } from './button';
import { store } from './store';
import * as SomethingModule from './something';

describe('<Button />', () => {
  it('uses stubbed things', () => {
    cy.stub(ReactReduxModule, 'useSelector')
      .as('useSelector')
      .returns({ moo: 'woof' });
    cy.stub(SomethingModule, 'something').as('something').returns('scary!!');

    cy.get('@something').should('not.have.been.called'); 
    cy.get('@useSelector').should('not.have.been.called'); 

    mount(
      <Provider store={store}>
        <Button />
      </Provider>,
    );
    // cy.contains('moo: woof scary').should('exist');
    cy.get('@something').should('have.been.called'); // passes
    cy.get('@useSelector').should('have.been.called'); // fails! :(
  });
});

the "something" stub does indeed trigger and intercept the import, but the useSelector stub does not. :( help the component in question is SUPER simple too:

import React from 'react';
import { useSelector } from 'react-redux';

import { something } from './something';
import { StoreState } from './store';

export const Button = ({}) => {
  const { moo } = useSelector((store: StoreState) => {
    return { moo: store.moo };
  });
  return (
    <button>
      moo: {moo} {something()}
    </button>
  );
};

Solution

  • Incase anyone else ever ends up in this thread, I eventually managed to do all this (with the help of a plugin and some babel config changes).

    I just added this little plugin into my babel build: https://github.com/asapach/babel-plugin-rewire-exports which allows you to rewire most* imports contained inside a module file (presuming ur working inside an esmodule codebase).

    I've got some demo code here: https://github.com/glomotion/stripped-down-next-rewire-ts/blob/tryout/rewire-exports/src/components/Moo/Moo.cy.test.jsx

    * note: To mock npm components is a little trickier, unless the component in question is an esmodule, in which case you configure babel to parse it, and ur good to go!