expo / vector-icons

https://icons.expo.fyi
MIT License
647 stars 114 forks source link

jest failed with @expo/vector-icons #188

Open farhan-ibrahim opened 2 years ago

farhan-ibrahim commented 2 years ago

I have a component containing @expo/vector-icons that's working but failed in jest. The test is succeed when commented out the icon

Error messages

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

TestComponent.tsx

import React from "react";
import { Ionicons } from "@expo/vector-icons"
import { View } from "react-native"

const TestComponent = () => {
    return(
        <View>
           <Ionicons />
        </View>
    )
}

export default TestComponent

TestComponent.test.tsx

import React from 'react';
import TestComponent from '../../components/TestComponent';
import { render } from '@testing-library/react-native';

describe('test TestComponent component', () => {
  it('renders correctly', () => {
    const tree = render(<TestComponent />);
    expect(tree).toMatchSnapshot();
  });
});

package.json

"@expo/vector-icons": "^12.0.5",
"expo": "^42.0.0",
"react": "16.13.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-42.0.0.tar.gz",
"@testing-library/react-native": "^7.1.0",
ssarnot commented 2 years ago

Try this mock, before all your describes and tests:

jest.mock("@expo/vector-icons", () => ({
  Ionicons: "",
}));
colin1227 commented 9 months ago

Try this mock, before all your describes and tests:

jest.mock("@expo/vector-icons", () => ({
  Ionicons: "",
}));

This solved my issue, I experienced a similar issue when running unit tests seeing the following error:

TypeError: Cannot read properties of null (reading 'uri')

in my case <Feather /> was throwing an error and was fixed by adding this mock.

hbiede commented 8 months ago

We solve this with the following:

package.json:

...
      "\\.(eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/jest/fileMock.js",
      "\\.(jpg|jpeg|png|gif)$": "<rootDir>/jest/imageMock.js",
...

<rootDir>/jest/fileMock.js

// Used to mock non-image files in Jest tests that can sometimes fail to be read correctly by Jest's internal mappings
module.exports = 'test-file-stub';

<rootDir>/jest/imageMock.js

// Used to mock image files in Jest tests that can sometimes fail to be read correctly by Jest's internal mappings
module.exports = {
  default: {
    uri: 'mock.png',
  },
};
vaibhavs2 commented 3 months ago

Try this mock, before all your describes and tests:

jest.mock("@expo/vector-icons", () => ({
  Ionicons: "",
}));

@ssarnot is it fair to ask how "" will be rendered at the time of testing, and how the layout will be created by react-native-testing-library? Well, I am wondering how the below snippet will get parsed by RNTL, wouldn't the layout will get disturbed? After mocking by some string, will "aaaa" get at the left side? assuming the mock will not occupy the same area as the real one.

     <View style={{flexDirection:'row', backgroundColor:"red"}}>
          <SomeIcon style={{marginEnd:40}}/>
          <Text>aaaa</Text>
     </View>

Well, is it worth considering the case when we do unit testing?