expo / vector-icons

https://icons.expo.fyi
MIT License
650 stars 113 forks source link

Jest with @expo/vector-icons cause async error? #143

Open timeturnback opened 3 years ago

timeturnback commented 3 years ago

This is my component . I use jest to test it as simple as possible . but got the error when it go to the Ionicons component . createIconSet .

    const HeaderBackButton = ({ navigation, color }) => {
      return (
        <TouchableOpacity
          style={styles.buttonContainer}
          onPress={
            navigation.getParam("overrideBack") || (() => navigation.goBack())
          }
        >
          <Ionicons
            name={"ios-arrow-back"}
            size={32}
            color={color || Colors.greenSilverTree}
          />
        </TouchableOpacity>
      );
    };

I run jest test with it

    describe("HeaderBackButton", () => {
      test("HeaderBackButton renders correctly", () => {
        const navigation = {
          getParam: () => {
            return true;
          }
        };
        const tree = renderer
          .create(<HeaderBackButton navigation={navigation} color={"#123123"} />)
          .toJSON();
        expect(tree).toMatchSnapshot();
      });
    });

And I got this error :

      Cannot log after tests are done. Did you forget to wait for something async in your test?
        Attempted to log "The above error occurred in the <Icon> component:
            in Icon (at createIconSet.js:38)
            in Icon (at HeaderBackButton.js:14)
            in View (created by View)
            in View (at createAnimatedComponent.js:151)
            in AnimatedComponent (at TouchableOpacity.js:308)
            in TouchableOpacity (at HeaderBackButton.js:8)
            in HeaderBackButton (at HeaderBackButton.test.js:20)

Any ideas , pls help :(

brentvatne commented 3 years ago

are you using the jest-expo preset?

MustansirZia commented 3 years ago

I had issues with Jest as well. I ended up disabling the rendering of these icons altogether in our component tests by creating a mock version for each of these icons which returned null.

Here's the mock version.

import { FunctionComponent } from 'react';

const Icon: FunctionComponent = () => {
    return null;
};

export default Icon;

Where as the actual version looked something like this.

import React, { FunctionComponent, memo } from 'react';
import {
    EvilIcons,
    AntDesign,
    Fontisto,
    FontAwesome5,
    Ionicons,
    MaterialIcons,
    MaterialCommunityIcons,
    SimpleLineIcons,
    Entypo,
} from '@expo/vector-icons';
import { Icon as VectorIcon } from '@expo/vector-icons/build/createIconSet';
import { Color } from 'domains/theme/types';
import useTheme from 'domains/theme/useTheme';

type IconFamily =
    | 'EvilIcons'
    | 'AntDesign'
    | 'Fontisto'
    | 'FontAwesome5'
    | 'Ionicons'
    | 'MaterialIcons'
    | 'MaterialCommunityIcons'
    | 'SimpleLineIcons'
    | 'Entypo';

type IconProps = {
    size?: number;
    name: string;
    family: IconFamily;
};

const Icon: FunctionComponent<IconProps> = ({ name, family, size = 32 }) => {
    let Component: VectorIcon<string, string>;
    switch (family) {
        case 'EvilIcons':
            Component = EvilIcons;
            break;
        case 'AntDesign':
            Component = AntDesign;
            break;
        case 'Fontisto':
            Component = Fontisto;
            break;
        case 'FontAwesome5':
            Component = FontAwesome5;
            break;
        case 'Ionicons':
            Component = Ionicons;
            break;
        case 'MaterialIcons':
            Component = MaterialIcons;
            break;
        case 'MaterialCommunityIcons':
            Component = MaterialCommunityIcons;
            break;
        case 'SimpleLineIcons':
            Component = SimpleLineIcons;
            break;
        case 'Entypo':
            Component = Entypo;
            break;
        default:
            Component = EvilIcons;
            break;
    }
    return <Component name={name} size={size}  />;
};

export default memo(Icon);

export type { IconFamily, IconProps };

This pattern worked well for us since we had a generic wrapper Icon over the @expo/vector-icons package and thus we were able to mock this pretty easily. I'm not sure how easy it would be for you or whether it's even feasible since you're planning to compare snapshots of your components.

Please note that I was using the jest-expo preset.

The error we saw was this. Expected font asset of type string | FontResource | Asset (number is not supported on web) instead got: null It comes from the package expo-font that is used by this package to load icons as fonts.

rchavik commented 2 years ago

I am also getting similar error. I'm already using preset jest-expo.

The issue was for a test that tries to render a component that uses react-native-paper TextInput.Icon.

I managed to workaround the Cannot log after tests are done. Did you forget to wait for something async in your test? error by mocking the following:

jest.mock('@expo/vector-icons/build/vendor/react-native-vector-icons/lib/create-icon-set.js', () => {
    return () => '';
});
d4rky-pl commented 2 years ago

I'm guessing this is similar to expo/expo#9004. This code:

import font from './vendor/react-native-vector-icons/Fonts/MaterialIcons.ttf';

returns 1 in the tests (and correct path when running in the web).

felpsio commented 1 year ago

I'm having the same problem.

My current jest config:

"jest": {
    "preset": "jest-expo",
    "setupFiles": [
      "./jest.setup.ts"
    ],
    "setupFilesAfterEnv": [
      "@testing-library/jest-native/extend-expect"
    ]
  },

jest.setup.ts:

import mockAsyncStorage from '@react-native-async-storage/async-storage/jest/async-storage-mock';

jest.mock('@react-native-async-storage/async-storage', () => mockAsyncStorage);

Right now I'm adding the following in my jest.setup.ts:

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

But would be nice to have a better solution like having jest-expo working fine with the icons

brentvatne commented 1 year ago

@felpsio - can you open up a pull request to jest-expo? https://github.com/expo/expo/blob/main/packages/jest-expo

norellanac commented 7 months ago

use:

"jest": {
     "preset": "jest-expo"
}

https://github.com/expo/expo/issues/6952#issuecomment-606872638