ReactJS :: Jest Testing :: "TypeError: Cannot read property ‘then’ of undefined"

  javascript, jestjs, reactjs, testing

I am currently having some trouble compiling a test to see whether the fetch() function of my weather application is working correctly.

I have made use of the useEffect() hook to fetch the data from the OpenWeather API to store and render once the API’s URL changes.

I am new to Jest testing and have tried a couple of things, but am unfortunately not having any success. My current solution is returning the following error: "TypeError: Cannot read property ‘then’ of undefined"

Please see below my code:


// Imported hooks and react libraries.
import React, { useState, useEffect } from 'react';
// Imported stylesheet.
import './App.css';
// Imported components.
import Header from './components/Header';
import Footer from './components/Footer';
// Imported countries from i18n-iso-countries to get the iso code and return the country name in English.
import countries from 'i18n-iso-countries';
// Imported icons from Font Awesome.
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
} from '@fortawesome/free-solid-svg-icons';


function App() {
  // Setting the initial states of the app to store the response and the locations. Using the useState hook to set the data. Showing Durban as 
  // an example.
  const [apiData, setApiData] = useState({});
  const [getState, setGetState] = useState('Durban');
  const [state, setState] = useState('Durban');

  // Constructing the API URL and accessing the key via the process.env variable.
  const apiKey = process.env.REACT_APP_API_KEY;
  const apiUrl = `${state}&APPID=${apiKey}`;
  console.log (process.env.REACT_APP_API_KEY);

  // Using the useEffect hook to fetch the data from the API to store and render once the API's URL changes.
  useEffect(() => {
      .then((res) => res.json())
      .then((data) => setApiData(data));
  }, [apiUrl]);

  // Constructed an input handler to get the data once requested and to store in the getState.
  const inputHandler = (event) => {

  // Constructed a submit handler to handle the request once the search button is clicked.
  const submitHandler = () => {

  // Constructed a kelvin to celsius converter to output the temperature in celsius.
  const kelvinToCelsius = (k) => {
    return (k - 273.15).toFixed(2);

  // Constructed a miles to kilometers converter to output the temperature in kilometers.
  const milesToKilometers = (k) => {
    return (k * 3.6).toFixed(2);

  // Created a function to capitalize the first letters of each part of the countries' names.
  function capitalizeFirstLetter(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);

  // Returning the data. Included the React Bootstrap stylesheet's link and called the "Header" and "Footer" components below. I also called the
  // following from the API:

  // {[0].icon} - The icon displaying the current conditions.
  // {} - The city's name.
  // {countries.getName(, 'en', { select: 'official', })} - The country's name with the first letters capitalized.
  // {kelvinToCelsius(apiData.main.temp_min)} - The minimum temperature.
  // {kelvinToCelsius(apiData.main.temp_max)} - The maximum temperature.
  // {kelvinToCelsius(apiData.main.feels_like)} - The "feels like" temperature, taking into account the temperatures and conditions.
  // {[0].main} - The summarized condition.
  // {capitalizeFirstLetter([0].description)} - The full condition's description.
  // {apiData.main.humidity} - The humidity percentage.
  // {milesToKilometers(apiData.wind.speed)} - The wind speed.

  // Called the inputHandler (input section) and submitHandler (button) to get the current state's values and added Font Awesome icons. Also 
  // added a loading message for if the page load takes a while. Currently only shows if there is no input or upon refresh.
  return (
    <div className="App">
      <link rel="stylesheet" href=""></link>
      <Header />

      <div className="container">
        <div className="searchsection">
          <label htmlFor="location-name">Enter Location:</label>
          <button onClick={submitHandler}><FontAwesomeIcon icon={faSearchLocation} /></button>

        <div className="mt-3 mx-auto" style={{ width: '60vw' }}>
          {apiData.main ? (
            <div id="weathercontainer">
              <div id="mainweather">
                  alt="weather status icon"
                <p className="h2">{kelvinToCelsius(apiData.main.temp)}&deg;C</p>
                <h3><FontAwesomeIcon icon={faMapMarkerAlt} /> {}</h3>
                <h3>{countries.getName(, 'en', { select: 'official', })}</h3>

              <div className="temperatureconditions">
                <div id="temperature">
                  <p><FontAwesomeIcon icon={faTemperatureLow} /> {kelvinToCelsius(apiData.main.temp_min)}&deg;C</p>
                  <p><FontAwesomeIcon icon={faTemperatureHigh} /> {kelvinToCelsius(apiData.main.temp_max)}&deg;C</p>
                  <p><FontAwesomeIcon icon={faHandSparkles} /> Feels like: {kelvinToCelsius(apiData.main.feels_like)}&deg;C</p>
                <div id="conditions">
                  <p><FontAwesomeIcon icon={faCloudSunRain} /> {[0].main}: {capitalizeFirstLetter([0].description)}</p>
                  <p><FontAwesomeIcon icon={faHandHoldingWater} /> Humidity: {apiData.main.humidity}%</p>
                  <p><FontAwesomeIcon icon={faWind} /> Wind Speed: {milesToKilometers(apiData.wind.speed)} km/h</p>
          ) : (
            <h1 id="loading">Weather Bot is Loading...</h1>
      <Footer />

// Exported App to Index.js.
export default App;


import React from 'react';
import App from '../App';
import { render, screen, act } from '@testing-library/react';

global.fetch = jest.fn(() =>
        json: () =>
                value: "Durban"

describe("App", () => {
    it("loads Durban city name", async () => {
        await act(async () => render(<App />));

Does anyone mind helping?

Source: Ask Javascript Questions