Search code examples
javascriptreact-nativejestjsreact-native-navigationreact-native-ui-kitten

Testing the ui-kitten button with react native testing library


I am trying to test that the Button navigates to the right screen using react-native-testing library. I am using UI Kitten library for my components and facing the issues because of it. I am simply trying to render the Button in my test for now and getting the error: TypeError: Cannot read properties of undefined (reading 'name'). I am assuming that is the property that exists on the Icon that this button uses and I don't know how to mock / pass it. I wrapped my button in the ApplicationProvider because I was getting another error: TypeError: Cannot read properties of undefined (reading 'appearances'). Here is the code with the component I am trying to render and the test I am running:

// HomeBtn.tsx
import React from 'react';
import {Button} from '@ui-kitten/components';
import {HomeIcon} from '../shared/icons';
import styles from './Btn.style';

export const HomeBtn = ({navigation}: any) => {
  return (
    <Button
      style={styles.button}
      accessoryLeft={props => HomeIcon(props, styles.icon)}
      onPress={() => navigation.navigate('Home')}
    />
  );
};

//HomeIcon.tsx
import React from 'react';
import {Icon} from '@ui-kitten/components';

const HomeIcon = (props: any = {}, styles: any = {}) => (
  <Icon style={styles} fill="#000" name="home" {...props} />
);

export default HomeIcon;

//HomeBtn.test.tsx
import React from 'react';
import * as eva from '@eva-design/eva';
import {ApplicationProvider} from '@ui-kitten/components';
import {render} from '@testing-library/react-native';
import {HomeBtn} from '../../../components/buttons/HomeBtn';

describe('HomeBtn', () => {
  it('should navigate to the Home Screen', () => {
    const pushMock = jest.fn();
    render(
    <ApplicationProvider {...eva} theme={eva.light}>
      <HomeBtn navigation={{ push: pushMock }} />
    </ApplicationProvider>,
    );
    expect(pushMock).toBeCalledWith('Home');
  });
});


Solution

  • That's the right way to render the components if you use ui-kitten library:

    // HomeBtn.tsx
    import React from 'react';
    import {Button} from '@ui-kitten/components';
    import {HomeIcon} from '../shared/icons';
    import styles from './Btn.style';
    
    export const HomeBtn = ({navigation}: any) => {
      return (
        <Button
          style={styles.button}
          accessoryLeft={props => HomeIcon(props, styles.icon)}
          onPress={() => navigation.navigate('Home')}
        />
      );
    };
    
    //HomeIcon.tsx
    import React from 'react';
    import {Icon} from '@ui-kitten/components';
    
    const HomeIcon = (props: any = {}, styles: any = {}) => (
      <Icon style={styles} fill="#000" name="home" {...props} />
    );
    
    export default HomeIcon;
    
    //HomeBtn.test.tsx
    import React from 'react';
    import * as eva from '@eva-design/eva';
    import {RootSiblingParent} from 'react-native-root-siblings';
    import {EvaIconsPack} from '@ui-kitten/eva-icons';
    import {ApplicationProvider} from '@ui-kitten/components';
    import {render} from '@testing-library/react-native';
    import {HomeBtn} from '../../../components/buttons/HomeBtn';
    
    describe('HomeBtn', () => {
      it('should navigate to the Home Screen', () => {
        const pushMock = jest.fn();
        const {getByTestId} = render(
          <RootSiblingParent>
            <IconRegistry icons={EvaIconsPack} />
            <ApplicationProvider {...eva} theme={eva.light}>
              <HomeBtn navigation={{push: pushMock}} />
            </ApplicationProvider>
          </RootSiblingParent>,
        );
        fireEvent.press(getByTestId('homeBtn'));
        expect(pushMock).toBeCalledWith('Home');
      });
    });