question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

proxy failed test when using fetch with TypeError: Only absolute URLs are supported

See original GitHub issue

Describe the bug

A clear and concise description of what the bug is.

I’m using fetch to post requests in the component like this

const authActions = (store) => ({
  logIn: (state, userForm) => {
    return fetch("/api/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(userForm),
    })
      .then((response) => {
        if (!response.ok) {
          throw response;
        }
        localStorage.setItem("current_user", JSON.stringify(userForm.username));
      })
      .catch((error) => {
        console.error("Error:", error);
      });
  },

In the testing-library, I use msw to mock the post request

describe("Login", () => {
  const handlers = [
    rest.post("/api/login", (req, res, ctx) => {
      return res(
        ctx.delay(150),
        ctx.json({
          ok: true,
          msg: "",
        })
      );
    }),
  ];

  const server = setupServer(...handlers);

  beforeAll(() => server.listen());
  afterEach(() => server.resetHandlers());
  afterAll(() => server.close());

test("should render login page", () => {
    render(<Login />);
    userEvent.type(getByPlaceholderText("Username"), "valid_username");
    userEvent.type(getByPlaceholderText("Password"), "valid_password");
    userEvent.click(getByText(/Log in/i));

    await waitFor(() => {
      expect(window.localStorage.getItem("current_user")).toEqual("valid_username");
    });
  });

The problem is, the test fails with the following TypeError

    Error: TypeError: Only absolute URLs are supported
        at getNodeRequestOptions (/Users/hkoo/dom/ui/node_modules/node-fetch/lib/index.js:1327:9)
        at /Users/hkoo/dom/ui/node_modules/node-fetch/lib/index.js:1432:19
        at new Promise (<anonymous>)
        at fetch (/Users/hkoo/dom/ui/node_modules/node-fetch/lib/index.js:1429:9)
        at fetch (/Users/hkoo/dom/ui/node_modules/isomorphic-unfetch/index.js:4:34)
        at logIn (/Users/hkoo/dom/ui/src/actions/authActions.js:5:12)
        at logIn (/Users/hkoo/dom/ui/node_modules/redux-zero/react/index.js:81:34)
        at onFinish (/Users/hkoo/dom/ui/src/components/Login.js:28:5)
        at onFinish (/Users/hkoo/dom/ui/node_modules/rc-field-form/lib/Form.js:91:9)
        at /Users/hkoo/dom/ui/node_modules/rc-field-form/lib/useForm.js:836:11

But when I manually log in on the browser, it works fine without error. I use webpack to proxy the api request like this

devServer: {
    port: 3000,
    historyApiFallback: true,
    proxy: {
      "/api": {
        target: "https://my-api.com",
        changeOrigin: true,
      },
    },

Can I ask why the TypeError occurred with fetch in testing? Does testing not use HTTP://localhost:3000 as base URL? When I added absolute URL in both fetch and res.post like fetch("HTTP://localhost:3000/api/login") and rest.post(“http://localhost:3000/api/login”), the error was gone. Also, I tried using axiosinstead offetch`, the error was gone too. Is there a way to use relative path with fetch in mocking?

Environment

  • msw: 0.35.0
  • nodejs: 16.13.0
  • npm: 8.1.0
  • jest: ^27.3.1,
  • testing-library/preact: ^2.0.1,
  • preact: ^10.5.15,
  • redux-zero: ^5.1.7
  • Chrome version 96.0.4664.45 (Official Build) (x86_64)

Expected behavior

A clear and concise description of what you expected to happen.

The post response should be mocked as expected without raising error.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

4reactions
kettanaitocommented, Nov 23, 2021

Hey, @helloitsjoe. Thank you for raising this. Please see the answer to your question below.

Short answer

When testing browser-oriented code, use browser-oriented polyfills (i.e. whatwg-fetch instead of node-fetch).

Long answer

There’s no such thing as “relative URL” in Node.js: there’s nothing to be relative to. In the browser, relative URLs are resolved against the current location. If you’re testing code that makes requests to relative URLs, this likely implies you’re testing code that was written to run in a browser. Jest, along with many other unit/integration testing frameworks, runs in a Node.js process, so all Node.js restrictions still apply. Jest circumvents some of those limitations by introducing JSDOM—a browser environment polyfill for Node.js. In JSDOM, window.location is polyfilled, so that’s why you can make relative requests in Jest tests.

In the same way, window.fetch doesn’t exist in Node.js. This one, however, doesn’t exist in JSDOM either. That’s where you should pick an appropriate polyfill for fetch so whenever your tested code calls it, the poyfill is called instead.

node-fetch is indeed a fetch polyfill but it’s designed for Node.js environments (where, as you’ve learned, relative URLs are non-existent). You cannot use this particular polyfill to test browser-oriented code, because it will simply throw the exception you’re experiencing whenever given a relative URL.

Instead, there are fetch polyfills that are designed to run in either ambiguous or browser-like environments. The most prominent of those is whatwg-fetch fromGitHub. This polyfill does take relative URLs into account and will function as close as possible to the native window.fetch.

1reaction
heatherKoo07commented, Nov 21, 2021

One quick question - is this node-fetch used by msw? Or if I use fetch API in React app, does it use node-fetch? I didn’t import it -> Never mind. It came from jest-preset-preact. Browsers resolve the relative path unlike node-fetch

Read more comments on GitHub >

github_iconTop Results From Across the Web

Next.js - Error: only absolute urls are supported - Stack Overflow
It means you are trying to export data and NextJS does not support fetching data from pages/api/* directory. To avoid errors, its better...
Read more >
jest only absolute urls are supported - You.com | The AI ...
I use an environnement variable to fetch my api. It worked well in localhost but not with Heroku. I get the error: Only...
Read more >
Netlify Dev - TypeError: Only absolute URLs are supported
I'm assuming you're using that fetch statement in server-side code. Since that code is run in Lambda or Deno environment and not in...
Read more >
Build error - TypeError: Only absolute URLs are supported
Run cd test-jss-nextjs-app; Run npm run build. See this error. JSS Version: 18.0.0. Does anyone experience the same error? Who knows ...
Read more >
Receiving "only absolute urls are supported" - Shopify ...
This error comes from apollo-boost when trying to render your component server-side. It tries to fetch the /grapql page of your application ( ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found