0

Suppose I have a component that loads its content when an asynchronous call returns succesfuly:

const MyScreen = () => {
  let userData: userDataResponse;
  const [email, setEmail] = useState("");
  const [firstTime, setFirstTime] = useState(true);

  async function localGetUserData() {
    userData = await getUserData();
    setEmail(userData.email);
    setFirstTime(false);
  }

  useEffect(() => {
    localGetUserData();
  }, []);

  if (firstTime) {
    return <Text>Cargando...</Text>;
  }

  return (
    <SafeAreaView style={styles.formStyling}>

When the data is available, it sets a state variable so the real content renders

If I want to test it, I think I should mock the getUserData so the mocked function returns a mocked email, say {email: a@b.c}

What would be a good approach to achieve this?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Rafael
  • 2,413
  • 4
  • 32
  • 54
  • 1
    What underlying transport are you using? `xhr`, `fetch`, etc.? You have to mock that and return the data as you suggest. – morganney Feb 09 '23 at 02:27

1 Answers1

0

Assuming following component setup (as I cannot see whole component):

myScreenUtils.js

export const getUserData = async () => {
  return Promise.resolve('original implementation')
}

MyScreen.jsx

import { useState, useEffect } from "react";
import { getUserData } from './myScreenUtils.js'

const MyScreen = () => {
  let userData;
  const [email, setEmail] = useState("");
  const [firstTime, setFirstTime] = useState(true);

  async function localGetUserData() {
    userData = await getUserData();
    setEmail(userData.email);
    setFirstTime(false);
  }

  useEffect(() => {
    localGetUserData();
  }, []);

  if (firstTime) {
    return <div>Cargando...</div>;
  }

  return (
    <div>{email}</div>
  )
};

export default MyScreen;

You can write following tests:

import { screen, render, waitFor, waitForElementToBeRemoved } from '@testing-library/react';

import MyScreen from "../MyScreen";
import * as utils from '../myScreenUtils';

describe('MyScreen', () => {
  it('the text is displayed and then removed', async () => {
    jest.spyOn(utils, 'getUserData').mockResolvedValue({ email: 'mocked value' });
    render(<MyScreen />);

    expect(screen.getByText('Cargando...')).toBeInTheDocument();
    await waitForElementToBeRemoved(() => screen.queryByText('Cargando...'))
  })

  it('the text email is fetched and displayed', async () => {
    jest.spyOn(utils, 'getUserData').mockResolvedValue({ email: 'mocked value' });
    render(<MyScreen />);

    await waitFor(() => {
      expect(screen.getByText('mocked value')).toBeInTheDocument()
    })
  })
})
Marek Rozmus
  • 773
  • 7
  • 13