problematic tests regarding Node.js built-in `fetch`
flevi29 opened this issue · comments
Newer versions of Node.js (LTS 20.10.0, Maintenance 18.19.0) have built-in fetch
, so the cross-fetch
polyfill has no effect. This means the built-in fetch
is used, but this presents a problem with the tests that are run:
So far I identified two reoccurring errors:
● Test on abortable search › Search key: search on index multiple times, and abort only one request
expect(received).toHaveProperty(path, value)
Expected path: "message"
Expected value: "The user aborted a request."
Received value: "This operation was aborted"
1002 |
1003 | searchPromise.catch((error: any) => {
> 1004 | expect(error).toHaveProperty('message', 'The user aborted a request.')
| ^
1005 | })
1006 | })
1007 |
at tests/search.test.ts:1004:21
● Tests on url construction › Test createDump route
expect(received).rejects.toHaveProperty(path, value)
Expected path: "message"
Expected value: "request to http://127.0.0.1:7701/trailing/dumps failed, reason: connect ECONNREFUSED 127.0.0.1:7701"
Received value: "fetch failed"
60 | const strippedHost = trailing ? host.slice(0, -1) : host
61 |
> 62 | await expect(client.createDump()).rejects.toHaveProperty(
| ^
63 | 'message',
64 | `request to ${strippedHost}/${route} failed, reason: connect ECONNREFUSED ${BAD_HOST.replace(
65 | 'http://',
at Object.toHaveProperty (node_modules/expect/build/index.js:218:22)
at tests/dump.test.ts:62:47
at tests/dump.test.ts:8:71
at Object.<anonymous>.__awaiter (tests/dump.test.ts:4:12)
at Object.<anonymous> (tests/dump.test.ts:57:44)
The problem is that network and other errors aren't really standardized in fetch
.
There are two potential paths we can take to address this problem:
- Test for both built-in
fetch
andnode-fetch
- Simply switch to and require >= maintenance versions of Node.js, which has built-in
fetch
support, so we only need to test that
related: #1610
About the network error test, the code that we're testing here is flawed. As I said, it's not entirely standardized, so this doesn't work well across browsers and runtimes.
https://github.com/meilisearch/meilisearch-js/blob/main/src/errors/meilisearch-communication-error.ts this probably only works well for node-fetch
.
On built-in Node.js fetch
most relevant details of the error are behind the property cause
, and they might differ in other ways.
In Firefox's version of fetch
I get the following error:
Also fetch
doesn't only throw because of ECONNREFUSED or whatever: https://developer.mozilla.org/en-US/docs/Web/API/fetch#exceptions
This code needs to be rewritten, should open separate issue just on this.
While the tests are passing now because of #1622, it is still relevant, because we're messing with non-standard properties of fetch
errors, which means on any other implementation than what cross-fetch
provides, they won't work as expected (basically most maintained browsers and newer runtimes with builtin fetch
).
Okay, so while experimenting with builtin fetch
, found another error:
expect header not supported
But because we're messing with the error object, it turns into the following:
I assumed the test runner is at fault, but no, it's just that the way health check is done and the error object is messed with takes away all the relevant information as to why this fails.
The gist of it is that builtin fetch
actually checks if a provided header is valid and supported.
This Expect
is an invalid unsupported header.
Okay, so the problem is that builtin undici
fetch
knows about this header, and this header is a special reserved header, which would require fetch
, I presume, to work in a specific way, that it doesn't support.
The solution is to pass a random truly custom header, like 'Hello-There!': 'General Kenobi'
. That way it works.