Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JEST tests failing - fetch is not defined

I do have two Jest Test Cases which seem to fail but I dont know what is wrong. It is about Post functions and somehow it doesnt recognize it and gets the error on fetch.

Any ideas appreciated.

This is what the test outcome says:


● Testing if UI updates correctly › Testing 'updateUI' function...

    TypeError: Cannot read property 'weather' of undefined

      3 |     console.log('all data returned is:')
      4 |     console.log(data)
    > 5 |     const precip = Math.round(data.weather.precip * 10) / 10
        |                                    ^
      6 |     const postHolder = document.getElementById('all-posts')
      7 |     const newDiv = document.createElement('div');
      8 |     newDiv.classList.add('entry-holder');

      at updateUI (src/client/js/updateUI.js:5:36)
      at Object.<anonymous> (__test__/testUpdateUI.test.js:10:12)



 FAIL  __test__/testPostData.test.js
  ● Testing the posting of the data › Test 'postInput' function to make a successful post

    ReferenceError: fetch is not defined

      1 | // POST input data to server
    > 2 | const postInput = async (url = '', data = {}) => {
        |                   ^
      3 |     const response = await fetch(url, {
      4 |       method: 'POST',
      5 |       credentials: 'same-origin',

      at _callee$ (src/client/js/postData.js:2:19)
      at tryCatch (src/client/js/postData.js:10:2404)
      at Generator._invoke (src/client/js/postData.js:10:1964)
      at Generator.next (src/client/js/postData.js:10:3255)
      at asyncGeneratorStep (src/client/js/postData.js:12:103)
      at _next (src/client/js/postData.js:14:194)
      at src/client/js/postData.js:14:364
      at src/client/js/postData.js:14:97
      at postInput (src/client/js/postData.js:2:16)
      at _callee$ (__test__/testPostData.test.js:13:11)
      at tryCatch (__test__/testPostData.test.js:15:2404)
      at Generator._invoke (__test__/testPostData.test.js:15:1964)
      at Generator.next (__test__/testPostData.test.js:15:3255)
      at asyncGeneratorStep (__test__/testPostData.test.js:17:103)
      at _next (__test__/testPostData.test.js:19:194)
      at __test__/testPostData.test.js:19:364
      at Object.<anonymous> (__test__/testPostData.test.js:19:97)

And these are the functions:

// POST input data to server
const postInput = async (url = '', data = {}) => {
    const response = await fetch(url, {
      method: 'POST',
      credentials: 'same-origin',
      headers: { 'Content-Type': 'application/json', },
      body: JSON.stringify(data),
    })
    try {
      const newData = await response.json();
      console.log('newData in postInput function is:')
      console.log(newData)
      Client.updateUI(newData)
    } catch (error) {
      console.log('ERROR in POST:', error);
    }
  }
  
  export { postInput }

And the second one

// Fetches gathered data from server & updates UI with it
function updateUI(data) {
    console.log('all data returned is:')
    console.log(data)
    const precip = Math.round(data.weather.precip * 10) / 10
    const postHolder = document.getElementById('all-posts')
    const newDiv = document.createElement('div');
    newDiv.classList.add('entry-holder');
    newDiv.innerHTML =`
        <img src="${data.pix.webformatURL}" alt="destination">
        <div class="stat-holder">
            <div class="wait-time"><i>${data.geo.name}, ${Client.checkCountry(data.geo)} is ${Client.dateDiff()} days away.</i></div>
            <h3>Typical weather for then is:</h3>
            <div class="temp">High: ${data.weather.max_temp}&degC, Low: ${data.weather.min_temp}&degC</div>
            <div class="precip">With a chance for ${precip}mm of precipitation</div>
        </div>
    `;
    postHolder.appendChild(newDiv);
  }
  
  export { updateUI }
  
like image 832
Verena Avatar asked Jan 26 '26 06:01

Verena


1 Answers

Late answer, but perhaps helps someone passing by this question.

By default, jest runs tests in Node environment. Therefore, depending on your packages and configuration, fetch may not be available in your tests.

Therefore, the solution is to add fetch in the test environment.

Option 1: mock fetch

Write a mock function in a module, say mock-fetch.ts, as follows.

export function mockFetch(data: any) {
  return jest.fn().mockImplementation(() =>
    Promise.resolve({
      ok: true,
      json: () => data,
    }),
  );
}

Then in your test file, you could use it to mock fetch as follows.

import { mockFetch } from './mock-fetch';

test('postInput()', async () => {
  window.fetch = mockFetch(someJson);

  // ... your postInput or component render here
  const result = await postInput();

  // Assert your expectations
  expect(result).toEqual(someJson);
});

In this approch, you could mock fetch only where necessary. On the other hand, the mock implementation might grow complex if you want to test scenarios like network error or response not ok.

Option 2: fetch polyfill only in the test environment

Use a library like cross-fetch while running tests.

This approach is as follows:

  1. Install cross-fetch as a dev dependency.
npm i --save-dev cross-fetch
  1. Import it in jest.setup.js|ts.
import 'cross-fetch/polyfill';
  1. Configure Jest to load it before executing the tests. For example, in jest.config.js.
module.exports = {
  testEnvironment: 'jsdom',
  injectGlobals: true,
  setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
  moduleNameMapper: {
    '\\.(css|less|scss)$': 'identity-obj-proxy',
    '^@/(.*)$': '<rootDir>/src/$1',
  },
};

In this approach, you could use msw to mock API communication as recommended by testing-library.

Option 3: use a library like axios for the entire app

Use axios instead of fetch in the app.

Then mock the axios module using Jest in the test cases.

import axios from 'axios';

jest.mock('axios');

test('postInput()', async () => {
  const resp = {data: someJson};
  axios.get.mockImplementation(() => Promise.resolve(resp));

  // ... your postInput or component render here
  const result = await postInput();

  // Assert your expectations
  expect(result).toEqual(someJson);
});
like image 59
Antony Avatar answered Jan 27 '26 21:01

Antony



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!