Skip to content

Error from host-component-names when using jest-expo preset #1406

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
alexHewittProcter opened this issue May 7, 2023 · 3 comments
Closed

Comments

@alexHewittProcter
Copy link

Describe the bug

I have a react native app thats built using Expo so that I'm able to build for both mobile and web, I've started to write unit tests for my code and I've been using the jest-expo/univeral preset for jest, which allows my tests to be run for all platforms my app will run on (ios, android,web and node(for ssr)).

When I use RNTL's render method, it passes for both ios and android but fails for web and node with 2 different errors coming from the helpers/host-component-names.tsx file.

When I use react-test-renderer instead, all 4 tests pass with no issues, and seeing as RNTL is built ontop of this, I would have thought the result should be the same!

Expected behavior

The test should pass for all 4 platforms, exactly as it does with react-test-renderer

Steps to Reproduce

I've created a repo where I'm able to reproduce this issue, I've written a single test for a simple component called Card which has code to test both in react-test-renderer and RNTL to show the difference - here is the repo

Screenshots

Using RNTL
image

Using react-test-renderer
image

Versions

  npmPackages:
    @testing-library/react-native: ^12.1.2 => 12.1.2
    react: 18.2.0 => 18.2.0
    react-native: 0.71.7 => 0.71.7
@mdjastrzebski
Copy link
Member

TLDR: RNTL does not neither recommend nor support testing RN Web using Jest Expo. We know that users occasionally do so, but they are for nasty surprises and they are missing better tools that are available.

To explain our stance here, RNTL works using React Test Renderer, i.e. this is not a real React Native environment. RNTL runs inside Jest and has some pretty primitive simulation around how RN works, mainly in the area of event handling. At this stage we have unified environment for iOS and Android, so stuff that we simulate is neither 100% iOS compatible nor 100% Android compatible, is kinda mixed. So while you might seem to get more reassurance from running your code under iOS and Android, you probably are running it in the very same simulated environment. The only difference being that your code might pick a different xxx.ios.ts/xxx.android.ts file or provide a different Platform.OS value.

Regarding RN Web, this is an even more complex story, afaik what RN Web does, is that it renders your typical host elemetns like View and TextInput to web primitives like div and input. This is the reason why the dectectHostComponent fails with the error you mentioned, we expect Text and TextInput to be available as host components, which is not the case in RN Web. We also do develop with RN Web in mind and do not have any tests that would cover RNTL in the RN Web environment. So for this case you are in an uncharted territory. However, you can get much better support by using the original React Testing Library (without Native in the name). It provides much more robust testing environment as it uses JS Dom for simulating how real browsers behave. JS Dom provides much more realistic simulation that whatever we could possibly do with RNTL.

If the arguments about using RTL for testing RN Web do not convince you, then you might get some luck by using patch-package to provide default Text and TextInput component names under RN Web. But again highly not advised.

Regarding node environment used by Jest Expo, I am not sure what kind of environment in terms of RN it is supposed to simulate.

@mdjastrzebski mdjastrzebski closed this as not planned Won't fix, can't repro, duplicate, stale May 8, 2023
@alexHewittProcter
Copy link
Author

Thank you @mdjastrzebski for such an indepth explanation!

@davispuh
Copy link

I encountered this same issue. I solved with Jest config

setupFiles: [
    "<rootDir>/__tests__/jest-setup-web.ts",
],
moduleNameMapper": {
    "^react-native$": "react-native-web",
    "^@testing-library/react-native$": "@testing-library/react",
},

And jest-setup-web.ts

jest.mock('@testing-library/react', () => {
    const actual = jest.requireActual('@testing-library/react');
    return {
        ...actual,
        render: (...args) => {
            const result = actual.render(...args);
            result.toJSON = result.asFragment;
            return result;
        },
        fireEvent: {
            ...actual.fireEvent,
            press: actual.fireEvent.click,
        },
    };
});

This allows our existing React Native tests to work using RNTL while for Web they'll actually run with regular React Testing Library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants