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

Axios call with data doesn't match predicate with same path in 2.x #1929

Closed
4 tasks done
jc-samcart opened this issue Dec 14, 2023 · 7 comments
Closed
4 tasks done

Axios call with data doesn't match predicate with same path in 2.x #1929

jc-samcart opened this issue Dec 14, 2023 · 7 comments
Labels
bug Something isn't working needs:triage Issues that have not been investigated yet. scope:node Related to MSW running in Node

Comments

@jc-samcart
Copy link

Prerequisites

Environment check

  • I'm using the latest msw version
  • I'm using Node.js version 18 or higher

Node.js version

v20.9.0

Reproduction repository

https://github.com/jc-samcart/msw-example

Reproduction steps

yarn test

Current behavior

I have created a handler for posting to the bananas endpoint. When I make calls to this endpoint with axios, it only is captured if I don't provide any data to the post via axios. If data is provided, I receive AxiosError: Network Error

    http.post('https://localhost:2345/bananas', ({ request, params, cookies }) => {
        return HttpResponse.json({age: 7})
    }),

This post request works:

await axios.post('bananas');

This post throws an error:

await axios.post('bananas', {age});

Expected behavior

I would expect both axios post calls to match the handler. This did work in 1.x and I only encountered this error when upgrading to 2.x

@jc-samcart jc-samcart added bug Something isn't working needs:triage Issues that have not been investigated yet. scope:node Related to MSW running in Node labels Dec 14, 2023
@zigsong
Copy link

zigsong commented Jan 2, 2024

I have the exact same problem 🙁

@ilyaulyanov
Copy link

Hi @jc-samcart, wondering if you were able to find a workaround for this issue? I am experiencing it as well

@jc-samcart
Copy link
Author

Hi @jc-samcart, wondering if you were able to find a workaround for this issue? I am experiencing it as well

@ilyaulyanov Not yet. I assumed I was doing something wrong rather than it being a code issue, so I've just been putting off upgrading.

@kettanaito
Copy link
Member

I suspect this is the same problem as #1931. Jest -> JSDOM -> core-js -> cannot call structuredClone on ReadableStream (a polyfill's problem). Will post more once I look into this...

@kettanaito
Copy link
Member

Root cause

So if we dive deeper into what causes the response error, we can find this:

error: ReferenceError: structuredClone is not defined
          at cloneBody (/msw-example/node_modules/undici/lib/fetch/body.js:277:21)
          at cloneRequest (/msw-example/node_modules/undici/lib/fetch/request.js:807:23)
          at Request.clone (/msw-example/node_modules/undici/lib/fetch/request.js:717:27)
          at HttpHandler.<anonymous> (/msw-example/node_modules/msw/lib/core/handlers/RequestHandler.js:116:43)

Somewhere along the line, the XMLHttpRequest interceptor has called .errorWith(). That happened because resolving the request has thrown an error (which you can see above). The interceptor treats any runtime errors as network errors since that what would happen if the server had that runtime error.

Granted, I think we should improve this behavior only in Node.js. I don't yet know how, since I don't want to dive back into guessing whether this was an intended exception thrown in the handler or an unexpected exception. But printing that original error would be nice. Perhaps we should store it in error.cause, given Axios and others can actually preserve that (I suspect not).

Based on the error, the structuredClone function that undici@6 uses to clone ReadableStream request/response bodies is missing in your test environment. This is really a shame because that's a standard function globally available in the browser and Node.js. Since you are using Jest+JSDOM, you don't get it.

Solution

There is no solution to this. Node.js doesn't export the structuredClone implementation as it references the internal binding written in C straight away (doesn't have a JavaScript counterpart). You cannot require it and so you cannot polyfill it yourself in jest.polyfills.ts as you do with other things thats JSDOM robs you off.

I recommend migrating to Vitest. Vitest respects your test environment and preserves Node.js globals even if using JSDOM. You are quite blocked by the obsolete tooling that at this point, so migrating to modern tooling is the way to go.

@kettanaito
Copy link
Member

Regarding forwarding the original error, it's like I suspected: your request client will control whether that error is forwarded at all. For example, Axios uses XHR when it runs in JSDOM, and erroring an XMLHttpRequest doesn't accept any error as an argument (see this). Since using XHR is Axios' choice, you see how request client you are using controls how much information you get in case of errors.

@jc-samcart
Copy link
Author

@kettanaito Appreciate your time looking at this. Just went through the process of updating to vitest using this nifty script and then the msw codemods. Everything is working as expected. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs:triage Issues that have not been investigated yet. scope:node Related to MSW running in Node
Projects
None yet
Development

No branches or pull requests

4 participants