capricorn86 / happy-dom

A JavaScript implementation of a web browser without its graphical user interface
MIT License
3.42k stars 207 forks source link

API-Calls time out with vitest #476

Open elias-thok opened 2 years ago

elias-thok commented 2 years ago

Hi guys! I'm experiencing an issue in combination with vitest & useQuery. If I use happy-dom with vitest, all api-calls (going to msw) time out. If I switch vitest to jsdom, they work.

// vite.config.ts
  test: {
    globals: true,
    environment: "happy-dom",
    setupFiles: ["./src/mocks/setup.ts"],
  },

I'm using this simple test here (which doesn't use msw, to rule that out): https://react-query.tanstack.com/guides/testing#our-first-test

It works with environment: "jsdom", and times out with happy-dom. Anything I'm missing here?

Cheers!

capricorn86 commented 2 years ago

Thanks for reporting @elias-thok! :slightly_smiling_face:

Do you happen to have an example project that I can debug in available publicly? Otherwise I can try to set it up.

elias-thok commented 2 years ago

I had some time to debug & I think I can pin it down to an api-proxy for local development.

So I have an api-proxy here:

// vite.config.js
server: {
    proxy: {
      "^/api": {
        changeOrigin: true,
        target: "https://foobar.com",
      },
    },
  },
...
  test: {
    globals: true,
    environment: "jsdom",
    setupFiles: ["./src/mocks/setup.ts"],
  },

and then a query fetching from /api/stuff which turns into https://foobar.com/api/stuff for local development.

// queries.ts
export const useGetPing = () =>
  useQuery("getPing", async () => {
    const res = await axios.get(
      "/api/stuff",
      {}
    )
    return res?.data
  })

Which in the test would be called like this:

// index.test.ts
  it("should test a ping", async () => {
    const { result, waitFor } = renderHook(() => useGetPing(), { wrapper })
    await waitFor(() => result.current.isSuccess)
    expect(result.current.data).toEqual("whatever")
  })

with msw mocking the api-call like so:

// handlers.ts
...
  rest.get("/api/stuff", (req, res, ctx) => {
    return res(ctx.json("whatever"))
  }),

This weirdly works with environment jsdom but not with happy-dom. If I hardcode the full endpoint, say https://foobar.com/api/stuff into the query, it works partially.

I have a test where a user clicks on a button which shows a loading spinner & a check when done. The loading-spinner appears but the check-icon doesn't. So the query is fired but apparently doesn't finish. This also happens with hardcoded endpoint in happy-dom but works in jsdom.

Unfortunately I can't provide a sandbox since it's a private API.