Skip to content
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

How to test FlashMessage and show message using the react native testing library #165

Open
Lois-Varghese opened this issue Jun 16, 2021 · 5 comments

Comments

@Lois-Varghese
Copy link

Lois-Varghese commented Jun 16, 2021

"@testing-library/react-native": "^7.2.0",

import React, {useEffect} from 'react';
import RNBootSplash from 'react-native-bootsplash';
import {StatusBar} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {SafeAreaProvider} from 'react-native-safe-area-context';
import FlashMessage from 'react-native-flash-message';
import Navigation from '@navigation/navigation';
import theme from '@config/themes';
import {Provider} from 'react-redux';
import Store from '@src/redux/store';

export default function App() {
  useEffect(() => {
    RNBootSplash.hide({fade: true});
    StatusBar.setHidden(true);
  }, []);

  const textStyle = {
    fontFamily: theme.fonts[0],
    fontSize: 16,
  };

  return (
    <Provider store={Store}>
      <NavigationContainer>
        <SafeAreaProvider>
          <Navigation />
        </SafeAreaProvider>
      </NavigationContainer>
      <FlashMessage position="bottom" animated={true} titleStyle={textStyle} />
    </Provider>
  );
}

In the snapshot test I get Flash Message as an invalid element

@lucasferreira
Copy link
Owner

Hi @Lois-Varghese

I never had the opportunity to do that on my own, but some people relate in other issues:

#147
#113

I guess that you need to do something with testID prop.

@Lois-Varghese
Copy link
Author

Hi @lucasferreira

I solved my issue by mocking the showMessage and other functions I was using from the library, using Jest and I also had to mock FlashMessage component from react-native-flash-message library and then my tests were passing. I wrote the tests using testing-library/react-native.

@moiseshilario
Copy link

moiseshilario commented Jul 15, 2021

Just for reference how to make a basic mock, that worked for me:

jest.mock('react-native-flash-message', () => ({
  hideMessage: () => jest.fn(),
  showMessage: () => jest.fn(),
  __esModule: true,
  default: jest.fn().mockReturnValue(() => <></>),
}));

@rodrigodiasf1984
Copy link

Hello @lucasferreira can you please reopen this issue? I'm facing the same problem, I've got the two functions inside the showMessage that inst covered:

this is my jest.setup:

jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');

jest.mock('@react-native-community/netinfo', () => mockRNCNetInfo);
jest.mock('rn-swipe-button', () => 'SwipeButton');
jest.mock('@react-native-async-storage/async-storage', () =>
  require('@react-native-async-storage/async-storage/jest/async-storage-mock'),
);

jest.mock('aws-amplify');

jest.mock('react-native-maps', () => {
  const { View } = require('react-native');
  const MockMapView = props => {
    return <View>{props.children}</View>;
  };
  const MockMarker = props => {
    return <View>{props.children}</View>;
  };
  return {
    __esModule: true,
    default: MockMapView,
    Marker: MockMarker,
  };
});

jest.mock('react-native-flash-message', () => ({
  hideMessage: () => jest.fn(),
  showMessage: () => jest.fn(),
  __esModule: true,
  default: jest.fn().mockReturnValue(() => <></>),
}));

this is my component:

import React, { useCallback, useEffect, useState } from 'react';
import { CustomToastProps } from '../../@types';
import { showMessage } from 'react-native-flash-message';
import { CheckCircle, Info, WarningCircle } from 'phosphor-react-native';
import { theme } from '../../../tailwind.config';
import { ThemeConfig } from 'tailwindcss/types/config';
import { View } from 'react-native';

export const CustomToast = ({
  description,
  setIsToastOpen,
  title,
  type,
}: CustomToastProps) => {
  const { toast_colors, colors } = theme?.extend as ThemeConfig;

  const handleToastStatus = useCallback(() => {
    switch (type) {
      case 'success':
        return {
          icon: (
            <View testID="success-icon">
              <CheckCircle
                size={25}
                color={colors['text_black']}
                weight="bold"
                style={{ marginRight: 10 }}
              />
            </View>
          ),
          borderColor: toast_colors['border_success'],
          backgroundColor: toast_colors['background_success'],
        };
      case 'danger':
        return {
          icon: (
            <View testID="warning-icon">
              <WarningCircle
                size={25}
                color={colors['text_black']}
                weight="bold"
                style={{ marginRight: 10 }}
              />
            </View>
          ),
          borderColor: toast_colors['border_danger'],
          backgroundColor: toast_colors['background_danger'],
        };
      case 'info':
        return {
          icon: (
            <View testID="info-icon">
              <Info
                size={25}
                color={colors['text_black']}
                weight="bold"
                style={{ marginRight: 10 }}
              />
            </View>
          ),
          borderColor: toast_colors['border_info'],
          backgroundColor: toast_colors['background_info'],
        };
    }
  }, [type]);

  useEffect(() => {
    const showToast = () => {
      showMessage({
        message: title,
        description: description,
        icon: 'auto',
        style: {
          alignSelf: 'center',
          marginBottom: 80,
          width: '94%',
          borderRadius: 5,
          borderLeftWidth: 5,
          borderLeftColor: handleToastStatus()?.borderColor,
          backgroundColor: handleToastStatus()?.backgroundColor,
          alignItems: 'center',
        },
        color: colors['text_black'],
        renderFlashMessageIcon: () => handleToastStatus()?.icon ?? null,
        onHide: () => setIsToastOpen(false),
      });
    };
    showToast();
  }, []);

  return <View testID="custom-toast" />;
};

this is my test file:

import { render } from '@testing-library/react-native';
import { CustomToast } from '..';

describe('CustomToast', () => {
  const setIsToastOpen = jest.fn();

  it('should render the component with type success', async () => {
    const { container } = render(
      <CustomToast
        setIsToastOpen={setIsToastOpen}
        title="Test toast"
        description=""
        type="success"
      />,
    );
    expect(container).toBeDefined();
  });

  it('should render the component with type danger', () => {
    const { container } = render(
      <CustomToast
        setIsToastOpen={setIsToastOpen}
        title="Test toast"
        description=""
        type="danger"
      />,
    );

    expect(container).toBeDefined();
  });

  it('should render the component with type info', () => {
    const { container } = render(
      <CustomToast
        setIsToastOpen={setIsToastOpen}
        title="Test toast"
        description=""
        type="info"
      />,
    );
    expect(container).toBeDefined();
  });
});

this is the result of the running tests:

image

I've tried to do a spyOn but I'm getting this error:
image

import { render, waitFor } from '@testing-library/react-native';
import { CustomToast } from '..';
import { showMessage } from 'react-native-flash-message';
import flashMessage from 'react-native-flash-message';

const renderFlashMessageIcon = jest.fn();
const onHide = jest.fn();

const mockShowMessage = jest.spyOn(flashMessage, 'showMessage');

describe('CustomToast', () => {
  const setIsToastOpen = jest.fn();

  jest.mock('react-native-flash-message', () => {
    return {
      showMessage: () => ({
        renderFlashMessageIcon: () => jest.fn(),
        onHide: () => jest.fn(),
      }),
    };
  });

  it('should render the component with type success', async () => {
    const { container } = render(
      <CustomToast
        setIsToastOpen={setIsToastOpen}
        title="Test toast"
        description=""
        type="success"
      />,
    );
    expect(mockShowMessage).toHaveBeenCalled();

    expect(container).toBeDefined();
  });

  it('should render the component with type danger', () => {
    const { container } = render(
      <CustomToast
        setIsToastOpen={setIsToastOpen}
        title="Test toast"
        description=""
        type="danger"
      />,
    );

    expect(container).toBeDefined();
  });

  it('should render the component with type info', () => {
    const { container } = render(
      <CustomToast
        setIsToastOpen={setIsToastOpen}
        title="Test toast"
        description=""
        type="info"
      />,
    );

    expect(container).toBeDefined();
  });
});

@Lois-Varghese @moiseshilario any idea how to do it? Thanks

@lucasferreira lucasferreira reopened this Feb 23, 2023
@lucasferreira
Copy link
Owner

Reopened @rodrigodiasf1984,

But I can't help too much here, never done this jest kind of tests in RN.

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

4 participants