Component Testing suggestion
# i-need-help
i
I would like to use Cypress component testing instead of Jest & React Testing Library. So far, I have a little struggle since my component will use dispatch & useSelector for Redux, and i18 to support multiple language. For example, there is one of my button component, I will take userInfo & targetCompanyId from Redux store, how could I mock them ?
Copy code
export default ({
    label,
    feature,
    featureDetail,
    size = 'medium',
} => {
    const { t, i18n } = useTranslation();

    const userInfo:(userInfoProps|null) = useAppSelector(({ root }) => root.userInfo);

    const targetCompanyId:string = useAppSelector(({ root }) => root.targetCompanyId);

  const openAirtableLink = () =>{
    //formUrl will use userInfo & targetCompanyId to build url
    window.open(formUrl, '_blank');
  }

    return (
        <Button 
            className="account-upgrade-button"
            size={size}
            label={label || t(`general.btn_upgradeAccount`)}
            color={standardColor.secondary}
            iconImageSize={16}
            iconUrl="./circled-up-2.png"
            onButtonClick={openAirtableLink}
        />
    );
};
I don't know how to mock a variable, function or hook with cypress, there are only few resource for cypress component testing. Or maybe I should correct my word, what's the boundary for e2e & component testing in cypress? should I really need it or just always do e2e testing?
w
> what's the boundary for e2e & component testing in cypress? We often think of it at the router level - if a component test would need to mock the router and will navigate to a bunch of pages, it is probably better as an end-to-end test. Generally component testing is easiest when testing components that are pretty well isolated from the other parts of the app. Something like mocking a store is a grey area - some people may say that's too much, but for me that's the whole point of a store, to be a source of truth components can look to. So for me it's OK to mock the store in component tests.
> I will take userInfo & targetCompanyId from Redux store, how could I mock them ? You can probably find an example here that is close to what you want: https://github.com/muratkeremozcan/cypress-react-component-test-examples I am on the road so can't look through in detail but I bet @magnificent-finland-58048 can tell you more!
I talk about it in the book CCTDD https://muratkerem.gitbook.io/cctdd/ch18-suspense-errboundary-concurrency#heroes-component

https://cdn.discordapp.com/attachments/1110102483193319455/1110681255596523630/image.png

In the book I advocate two things test everything you can at CT level, when you cannot test anymore, move up and use e2e that routing and state management is a good border between CT and e2e but since then I've run into real life cases where the component takes everything from the path, and that we can test plenty for routing with custom wrappers. the idea is from react-router, this is how they test their library themselves we use it at work, people love it

https://www.youtube.com/watch?v=jYaDpuPQW9M

here are some more real life custom mount examples assume
configureStore
is the mega redux store of the app we can import it and reuse it in the component tests, and we can also customize it
Copy code
typescript
Cypress.Commands.add('mount', mount)

const wrappedMount = (
  WrappedComponent: React.ReactNode,
  theme: ThemeName = 'merchants',
  options = {},
): Cypress.Chainable<MountReturn> => {
  const wrapped = (
    <BrowserRouter>
      <ThemeProvider theme={getThemeByName(theme)}>
        <GlobalStyles />
        {WrappedComponent}
      </ThemeProvider>
    </BrowserRouter>
  )
  return cy.mount(wrapped, options)
}
Cypress.Commands.add('wrappedMount', wrappedMount)

const storeWrappedMount = (
  WrappedComponent: React.ReactNode,
  preLoadedState: DeepPartial<RootState> = {},
  theme: ThemeName = 'merchants',
  options = {},
): Cypress.Chainable<MountReturn> => {
  const wrapped = (
    <BrowserRouter>
      <ThemeProvider theme={getThemeByName(theme)}>
        <GlobalStyles />
        <Provider store={configureStore(preLoadedState)}>{WrappedComponent}</Provider>
      </ThemeProvider>
    </BrowserRouter>
  )
  return cy.mount(wrapped, options)
}
Cypress.Commands.add('storeWrappedMount', storeWrappedMount)
so you have 3 tools, they are really the same tools you had in rtl custom mounts / renders - same idea in cyct vs rtl mocking the network: cy.intercept vs msw (the Kent Dodds recommended way, and for some reason we still see low level jest mocks...) low level mocks (should be rarely needed, if ever) sinon vs jest.mock --------- here's a cheat sheet for sinon & cypress I'm planning to put this in another repo and do a jest mirror https://github.com/muratkeremozcan/cypressExamples/tree/master/spy-stub-practice/cypress/e2e
i
thanks guys. 👍🏻 I will take time to try it