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

Fetch do not work on Jest #2071

Closed
sibelius opened this issue Nov 9, 2016 · 18 comments
Closed

Fetch do not work on Jest #2071

sibelius opened this issue Nov 9, 2016 · 18 comments

Comments

@sibelius
Copy link

sibelius commented Nov 9, 2016

Do you want to request a feature or report a bug?
bug

What is the current behavior?
fetch do not make the request to the server

test example:

describe('app', () => {
  it('fetch correctly', async () => {
    const response = await fetch('http://localhost:5000/graphql')
    const data = await response.text();

    expect(data).not.toBe(null);
  });
});

This test is inside a react native project, I have a very long timeout

jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;.

I'm trying to implement integration tests using a real GraphQL backend (following the ideas of facebook/relay#1281)

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal repository on GitHub that we can npm install and npm test.

What is the expected behavior?
fetch should make the request to the server

Run Jest again with --debug and provide the full configuration it prints. Please mention your node and npm version and operating system.

jest version = 17.0.0
test framework = jasmine2
config = {
  "haste": {
    "defaultPlatform": "ios",
    "platforms": [
      "android",
      "ios"
    ],
    "providesModuleNodeModules": [
      "react",
      "react-native"
    ]
  },
  "moduleNameMapper": [
    [
      "^image![a-zA-Z0-9$_-]+$",
      "GlobalImageStub"
    ],
    [
      "^[./a-zA-Z0-9$_-]+\\.(bmp|gif|jpg|jpeg|png|psd|svg|webp)$",
      "RelativeImageStub"
    ]
  ],
  "modulePathIgnorePatterns": [
    "app/node_modules/react-native/Libraries/react-native/",
    "app/node_modules/react-native/packager/"
  ],
  "transformIgnorePatterns": [
    "node_modules/(?!react-native|tcomb-form-native|react-native-localization|@exponent/react-native-action-sheet|@exponent/ex-navigation|@exponent/react-native-touchable-native-feedback-safe|rnrf-relay-renderer|react-clone-referenced-element|react-native-looped-carousel|rn-splash-screen)"
  ],
  "setupFiles": [
    "app/node_modules/babel-polyfill/lib/index.js",
    "app/node_modules/jest-react-native/build/setup.js"
  ],
  "testEnvironment": "app/node_modules/jest-environment-node/build/index.js",
  "snapshotSerializers": [
    "app/node_modules/jest-html"
  ],
  "preset": "jest-react-native",
  "unmockedModulePathPatterns": [
    "app/node_modules/fbjs-scripts/",
    "app/node_modules/fbjs/node_modules/core-js/",
    "app/node_modules/fbjs/node_modules/promise/",
    "app/node_modules/fbjs/lib/(?!(ErrorUtils.js$|fetch.js$|fetchWithRetries.js$))",
    "app/node_modules/object-assign/",
    "app/node_modules/react/",
    "app/node_modules/react-addons-test-utils/",
    "app/node_modules/react-dom/",
    "app/node_modules/react-static-container/",
    "app/node_modules/react-relay/",
    "app/node_modules/event-target-shim",
    "app/node_modules/whatwg-fetch"
  ],
  "verbose": true,
  "moduleFileExtensions": [
    "js",
    "json",
    "es6",
    "ios.js"
  ],
  "rootDir": "app",
  "name": "-Users-sibelius-Dev-rturk-brandlovers-reactnative",
  "testRunner": "app/node_modules/jest-jasmine2/build/index.js",
  "transform": [
    [
      "^.+\\.jsx?$",
      "app/node_modules/babel-jest/build/index.js"
    ]
  ],
  "usesBabelJest": true,
  "automock": false,
  "bail": false,
  "browser": false,
  "cacheDirectory": "/var/folders/n_/30jh5m816yzg3_cftvg647j40000gn/T/jest",
  "coveragePathIgnorePatterns": [
    "/node_modules/"
  ],
  "coverageReporters": [
    "json",
    "text",
    "lcov",
    "clover"
  ],
  "expand": false,
  "globals": {},
  "mocksPattern": "__mocks__",
  "moduleDirectories": [
    "node_modules"
  ],
  "noStackTrace": false,
  "notify": false,
  "resetMocks": false,
  "resetModules": false,
  "testPathDirs": [
    "app"
  ],
  "testPathIgnorePatterns": [
    "/node_modules/"
  ],
  "testRegex": "(/__tests__/.*|\\.(test|spec))\\.jsx?$",
  "testURL": "about:blank",
  "timers": "real",
  "useStderr": false,
  "watch": false,
  "cache": true,
  "watchman": true,
  "testcheckOptions": {
    "times": 100,
    "maxSize": 200
  }
}

node 6.9.1
mac os x sierra

@atkinchris
Copy link

fetch is not available in Node, which is where Jest is running your tests. Is it an experimental browser technology.

You will need to polyfill the behaviour if you want to make actual http calls, or mock fetch to simulate network requests.

@cpojer
Copy link
Member

cpojer commented Nov 10, 2016

Exactly! Check out whatwg-fetch.

@cpojer cpojer closed this as completed Nov 10, 2016
@sibelius
Copy link
Author

@atkinchris where should I add the polyfill?

inside setupTestFrameworkScriptFile?

@sibelius
Copy link
Author

I think my problem is that react-native uses a different XMLHttpRequest

I've tried add a polyfill inside setupFiles and setupTestFrameworkScriptFile, both did not worked

I also getting this error in XMLHttpRequest if I don't unmock event-target-shim

TypeError: this.dispatchEvent is not a function

at XMLHttpRequest.setReadyState (node_modules/react-native/Libraries/Network/XMLHttpRequest.js:470:6)
at XMLHttpRequest.open (node_modules/react-native/Libraries/Network/XMLHttpRequest.js:381:6)
at node_modules/whatwg-fetch/fetch.js:415:11
at Object.<anonymous>.self.fetch (node_modules/whatwg-fetch/fetch.js:373:12)
at Object._callee$ (app/__tests__/myRelay.js:52:1)
at tryCatch (node_modules/regenerator-runtime/runtime.js:62:40)
at Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:336:22)
at Generator.prototype.(anonymous function) [as next] (node_modules/regenerator-runtime/runtime.js:95:21)
at tryCatch (node_modules/regenerator-runtime/runtime.js:62:40)
at invoke (node_modules/regenerator-runtime/runtime.js:138:20)

@sibelius
Copy link
Author

it works on setupFiles and I have to polyfill XMLHttpRequest (https://github.com/ykzts/node-xmlhttprequest)

tks

@connected-mgosbee
Copy link

connected-mgosbee commented Nov 22, 2016

@sibelius How exactly did you get it to work? I tried adding
"setupFiles": ["node_modules/w3c-xmlhttprequest/lib/index.js"]
to my package.json yet it still gives the this.dispatchEvent is not a function error

@connected-mgosbee
Copy link

connected-mgosbee commented Nov 22, 2016

Figured it out.
Added a setupJest.js file to the setupFiles section of my package.json. Then added this to setupJest.js
global.XMLHttpRequest = require('w3c-xmlhttprequest').XMLHttpRequest;

@sibelius
Copy link
Author

@connected-mgosbee I have a working example here: https://github.com/sibelius/relay-integration-test/blob/master/RelayApp/test/env.js

@dijonkitchen
Copy link

This might help too: https://github.com/jefflau/jest-fetch-mock

@mx781
Copy link

mx781 commented Aug 8, 2017

Weirdly, neither of the polyfills repacing XMLHttpResponse in the fixes above seemed to work -- I had to replace fetch entirely, by including require("isomorphic-fetch"); in the setupFiles as described above.

@whtlnv
Copy link

whtlnv commented Feb 26, 2018

I didn't really wanted to mock on a specific test and node-fetch came through brilliantly for me.

@tkrotoff
Copy link
Contributor

tkrotoff commented Jun 13, 2018

For people passing by, simplest working solution:

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

test('fetchPerson()', async () => {
  fetch = mockFetch(someJson); // or window.fetch

  const person = await fetchPerson('whatever id');
  expect(person).toEqual(someJson);

  // Make sure fetch has been called exactly once
  expect(fetch).toHaveBeenCalledTimes(1);
});

when testing this simple function:

function fetchPerson(id) {
  const response = await fetch(`${BASE_URL}/people/${id}`);
  if (!response.ok) throw new Error(response.statusText);
  const data = await response.json();
  // Some operations on data if needed...
  return person;
}

Jest configuration:

// File jest.setup.js
import 'whatwg-fetch';
// File jest.config.js
module.exports = {
  setupFiles: ['./jest.setup.js'],
};

(because Jest uses Node.js and Node.js does not come with fetch => specific to web browsers)

Real life simple example: https://github.com/tkrotoff/MarvelHeroes

@MuhammadJamaluddin
Copy link

MuhammadJamaluddin commented Apr 6, 2019

@tkrotoff Sorry, how import 'whatwg-fetch' is working? I am not familiar with this annotation. I only know about import name from 'module-name'... & is this module different from the node-fetch module?

@nelsieborja
Copy link

@tkrotoff whatwg-fetch didn't work for me, isomorphic-fetch did

@namlq93
Copy link

namlq93 commented Dec 11, 2019

@tkrotoff
Screen Shot 2019-12-11 at 16 56 07

@gblikas
Copy link

gblikas commented Feb 12, 2020

Is isomorphic-fetch not in the Jest any more?

@fabOnReact
Copy link

seems that for react-native will be solved with this pr facebook/react-native#30488

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests