Is your feature request related to a problem? Please describe.
I am currently building a httpClient for a browser-based app. I am using msw (it is awesome!) to cover edge-cases like network failures with tests on network level. The client basically wraps axios.
I was looking forward to response.networkError() that was added in https://github.com/mswjs/msw/pull/253 because I needed a way to simulate a network problem (like being offline).
I am using networkError(someCustomMessage) in the response resolver. I am asserting that the error caught by axios states my custom message. Instead I am seeing the following error
{
"message": "Request aborted",
"code": "ECONNABORTED"
"stack": "Error: Request aborted
at createError (D:\dev\kraken\core\node_modules\axios\lib\core\createError.js:16:15)
at XMLHttpRequestOverride.handleAbort [as onabort] (D:\dev\kraken\core\node_modules\axios\lib\adapters\xhr.js:73:14)
at XMLHttpRequestOverride.trigger (D:\dev\kraken\core\node_modules\node-request-interceptor\lib\XMLHttpRequest\XMLHttpRequest\createXMLHttpRequestOverride.js:100:92)
at XMLHttpRequestOverride.abort (D:\dev\kraken\core\node_modules\node-request-interceptor\lib\XMLHttpRequest\XMLHttpRequest\createXMLHttpRequestOverride.js:252:22)
at D:\dev\kraken\core\node_modules\node-request-interceptor\lib\XMLHttpRequest\XMLHttpRequest\createXMLHttpRequestOverride.js:182:27";
"//": "..more stuff I stripped from the error"
}
My error handling logic goes on and treats the error as timeout error, which was not my intention.
Describe the solution you'd like
I would like to augment the simulation of network errors in a way that axios treats the error as network error (error.message === 'Network Error', see https://github.com/axios/axios/issues/383).
I would therefore like to add respective tests to https://github.com/mswjs/msw/tree/master/test/msw-api/res.
Additional context
Hey, @s-pic. Thanks for the feedback and for reaching out!
Please, could you create a reproduction repo for this? Ideally, with a failed state and an expected state (may be without MSW for now). We'd be happy to help you with this.
Hey @kettanaito thanks for looking into this. I used the examples repo, and in there the rest-react example to reproduce the case in a simplified manner: https://github.com/s-pic/examples.
Here are some instructions to set up and inspect my changes:
git clone https://github.com/s-pic/examplescd examples/rest-react/git checkout reproduce_axios_network_error # that is where I workedyarn install && yarn startapiServiceyarn run test:unit --watchAll=false (otherwise the already commited tests are skipped) and inspect the following jest error log:FAIL src/test/apiService.test.js
● apiService › fetchJson › handles a network error
expect(received).toEqual(expected) // deep equality
Expected: "Network Error"
Received: "Request aborted"
35 |
36 | // ASSERT: make sure actual return equals asserted return
> 37 | expect(error.message).toEqual(axiosErrorMessage)
| ^
38 | })
39 | })
40 | });
at Object.<anonymous> (src/test/apiService.test.js:37:35)
PASS src/LoginForm.test.js
Test Suites: 1 failed, 1 passed, 2 total
Tests: 1 failed, 2 passed, 3 total
Snapshots: 0 total
Time: 3.62s, estimated 7s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
I figured I should maybe provide some more background:
What I am trying to do is to prepare an axios-based client by writing all kinds of tests for it -- until it is safe to integrate it in the app. I know that using Jest to run tests against axios in a Node environment is not a 100% valid aproach: The client will be used in the browser, but the xhr- and the http- adapter differ in some parts (e.g. regarding timeout handling). But since cypress tests and headless browser tests are not an option at the moment, I kinda have to live with this inaccuracy. Anyways, my goal is to catch all kinds of errors that can occur during a request, detect their nature as good as possible and handle them accordingly.
Hey there, has the provided information been sufficient? Please let me know if I can help to clarify the problem.
Hey, @s-pic. Thanks for providing those clarifications, they are tremendously useful. I'll look into them once I have a minute. Thank you for the patience.
The issue happens because the mocked network error is handled differently in a browser and NodeJS. In a browser it's being caught and handled as a special message type sent to the Service Worker:
In NodeJS, however, there is no such handling, as any thrown exception is handled on the node-request-interceptor library (the library that powers requests interception and mocking in NodeJS). That library handles any exception, including an emulated network error, according to how it should be treated in a regular request.
Here's how an exception is handled in NRI:
I'm investigating a few possibilities whether this can be changed. Will keep you updated.
It seems that the order of emitted events in XMLHttpRequest override was incorrect:
- abort
- error
+ error
+ abort
Once ordered as error then abort, you receive the given network error message in the axios, and the test passes. The fix is issued in https://github.com/mswjs/node-request-interceptor/pull/54, awaits CI and update in MSW.
The fix is published in [email protected]. MSW update to be issued.
This is great @kettanaito !
I wanted to test if the fix makes the test in in the reproduction repo pass, but I am having trouble overriding the transitive dependency. I will test this as soon as I can and get back to you here,
Even if I pin down the transitive dependency of node-request-interceptor to 0.5.1 (by using the resolutions field), I still see the same ouput in the failing test.
See https://github.com/s-pic/examples/commit/1ed266a95c5c05c0bd1a5d53f3652b6094ddae0b in the reproduction repo.
Am I missing something here?
@kettanaito You wrote
MSW update to be issued.
I figured that would just include updating the dependency to node-request-interceptor.
This issue was resolved in [email protected]. Could you please update and let us know if it's fixed for you? Thanks.
Yip, that fixed it 😅
Thanks.