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

TypeError: myFile?.slice(...).arrayBuffer is not a function #2273

Closed
4 tasks done
corneliusroemer opened this issue Sep 10, 2024 · 24 comments
Closed
4 tasks done

TypeError: myFile?.slice(...).arrayBuffer is not a function #2273

corneliusroemer opened this issue Sep 10, 2024 · 24 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

@corneliusroemer
Copy link

Prerequisites

Environment check

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

Node.js version

22.8

Reproduction repository

loculus-project/loculus@c813cd9

Reproduction steps

gh repo clone https://github.com/loculus-project/loculus/pull/2755/commits/c813cd965449e820c9ac52ae183645a1301c2ebb
cd website
nvm use
npm ci
npm run test-fast

Current behavior

Getting error:

TypeError: myFile?.slice(...).arrayBuffer is not a function
 ❯ Timeout._onTimeout src/components/Submission/DataUploadForm.tsx:186:18
    184|             myFile
    185|                 ?.slice(0, 1)
    186|                 .arrayBuffer()
       |                  ^
    187|                 .catch(() => {
    188|                     setMyFile(null);
 ❯ listOnTimeout node:internal/timers:594:17
 ❯ processTimers node:internal/timers:529:7

 FAIL  src/components/Submission/SubmissionForm.spec.tsx > SubmitForm > should unexpected error with proper error message
TestingLibraryElementError: Unable to find an element with the text: (text) => text.includes(receivedUnexpectedMessageFromBackend). This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

Expected behavior

No error when doing patch update from 2.4.1 to 2.4.4

@corneliusroemer corneliusroemer added bug Something isn't working needs:triage Issues that have not been investigated yet. scope:node Related to MSW running in Node labels Sep 10, 2024
@ddolcimascolo
Copy link

Hi everyone,

I also have all tests broken but with a different error, adding here for simplicity but I'm OK to open a new issue if you want. I'm upgrading from 4.2.2 to 4.2.4 and I'm using Vitest as my test runner.

Stacktrace:

TypeError: unusable
❯ Request.clone node:internal/deps/undici/undici:5434:17
❯ XMLHttpRequestController.respondWith node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts:299:29
❯ Object.onResponse node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts:70:24
❯ handleResponse node_modules/@mswjs/interceptors/src/utils/handleRequest.ts:55:21
❯ handleRequest node_modules/@mswjs/interceptors/src/utils/handleRequest.ts:207:12
❯ runNextTicks node:internal/process/task_queues:60:5
❯ processTimers node:internal/timers:511:9
❯ XMLHttpRequestController.xhrRequestController.onRequest node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts:64:34

Thanks,
David

@jpreis
Copy link

jpreis commented Sep 10, 2024

We encounter the same issue as @ddolcimascolo after upgrading from 2.4.2 to 2.4.2 (we're also using Vitest).

Edit: Fix versions, thanks @corneliusroemer :)

@kettanaito
Copy link
Member

@ddolcimascolo, this one looks related to mswjs/interceptors#630.

@corneliusroemer
Copy link
Author

I'm upgrading from 4.2.2 to 4.2.4 and I'm using Vitest as my test runner.

I think you all mean 2.4.2 not 4.2.2 🙃

@ddolcimascolo
Copy link

I'm upgrading from 4.2.2 to 4.2.4 and I'm using Vitest as my test runner.

I think you all mean 2.4.2 not 4.2.2 🙃

Indeed 😅

@frodeaa
Copy link

frodeaa commented Sep 10, 2024

Seems to also break the Request type

TypeError: Cannot read properties of undefined (reading 'push')
             request.headers.set("Authorization", `Bearer ${accessToken}`);

The headers on the request object have changed from a Headers object where set is supported to an Map object

@kettanaito
Copy link
Member

None of these errors look MSW related (at least directly). I highly recommend you check your Node.js versions because MSW in no shape or form influences how Request/Response/Headers function.

@frodeaa
Copy link

frodeaa commented Sep 10, 2024

None of these errors look MSW related (at least directly). I highly recommend you check your Node.js versions because MSW in no shape or form influences how Request/Response/Headers function.

Tested v2.4.3, no issue, the upgrade from v2.4.3 to v2.4.4 break the previous behaviour

@frodeaa
Copy link

frodeaa commented Sep 10, 2024

Using resolution to downgrade the transitive dependency on "@mswjs/interceptors@^0.35.0 to v0.33.0 fixes the issue, so it seems to be an issue cause by changed done in v0.34.0

@jgarplind
Copy link

None of these errors look MSW related (at least directly). I highly recommend you check your Node.js versions because MSW in no shape or form influences how Request/Response/Headers function.

Tested v2.4.3, no issue, the upgrade from v2.4.3 to v2.4.4 break the previous behaviour

By bisecting I arrived at the same msw version causing us test errors when running vitest, though, like other users, we are seeing a different error. Partial stack trace:

⎯⎯⎯⎯ Unhandled Rejection ⎯⎯⎯⎯⎯
TypeError: unusable
❯ Request.clone node:internal/deps/undici/undici:6232:17
...
XMLHttpRequestController.xhrRequestController.onRequest ../node_modules/.pnpm/@mswjs+interceptors@0.35.1/node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts:64:34

@greysteil
Copy link
Contributor

greysteil commented Sep 11, 2024

Seeing the same issue as @ddolcimascolo on 2.4.4. Also using vitest:

TypeError: unusable
 ❯ Request.clone node:internal/deps/undici/undici:9651:17
 ❯ XMLHttpRequestController.respondWith node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts:299:29
 ❯ Object.onResponse node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts:70:24
 ❯ handleResponse node_modules/@mswjs/interceptors/src/utils/handleRequest.ts:55:21
 ❯ handleRequest node_modules/@mswjs/interceptors/src/utils/handleRequest.ts:207:12
 ❯ XMLHttpRequestController.xhrRequestController.onRequest node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts:64:34

Downgrading @mswjs/interceptors to 0.33.3 works for us, too, suggesting mswjs/interceptors#630 might be the underlying issue.

@dominikbulaj
Copy link

I had the same issue using Vitest after upgrading MSW from 2.2.0 to 2.4.5 (and 2.4.4). It works correctly in 2.4.3, though...

Vitest caught 1 unhandled error during the test run.
This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Unhandled Rejection ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
TypeError: unusable
 ❯ Request.clone node:internal/deps/undici/undici:5434:17
 ❯ XMLHttpRequestController.respondWith node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts:299:29
 ❯ Object.onResponse node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts:70:24
 ❯ handleResponse node_modules/@mswjs/interceptors/src/utils/handleRequest.ts:55:21
 ❯ handleRequest node_modules/@mswjs/interceptors/src/utils/handleRequest.ts:207:12
 ❯ processTicksAndRejections node:internal/process/task_queues:95:5
 ❯ runNextTicks node:internal/process/task_queues:64:3
 ❯ listOnTimeout node:internal/timers:540:9
 ❯ processTimers node:internal/timers:514:7
 ❯ XMLHttpRequestController.xhrRequestController.onRequest node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestProxy.ts:64:34

corneliusroemer added a commit to loculus-project/loculus that referenced this issue Sep 12, 2024
…t not interceptors) (#2766)

* deps(website): update headlessui and add jsdom polyfill

see:
- tailwindlabs/headlessui#3473
- tailwindlabs/headlessui#3469

* Update msw, pinning transitive dep msw interceptors to 0.33.3 for the time being

see:
- mswjs/msw#2273
@kettanaito
Copy link
Member

The TypeError: unusable error is being fixed in mswjs/interceptors#632.

@kettanaito
Copy link
Member

Just released https://github.com/mswjs/msw/releases/tag/v2.4.6. Can someone please update and let me know if this issue is resolved? Thanks.

@ddolcimascolo
Copy link

Yep. Renovate will pick it up for our repo later today, I'll report back here

@ddolcimascolo
Copy link

@kettanaito I can confirm that this specific issue is resolved in v2.4.6

I have two failing tests, though, where the response body looks undefined . I'll check these and open an issue if I can confirm the problem is in msw.

Thanks for the great work !

David

@ddolcimascolo
Copy link

The failing tests were on my side. Thanks again !

@greysteil
Copy link
Contributor

All fixed for me too - thanks @kettanaito! ❤️

@kettanaito
Copy link
Member

Awesome! Thanks for a swift confirmation.

Would love to hear whether that also fixed the myFile?.slice() issue. That one doesn't seem to be related to MSW, but perhaps some transitive issue? If @corneliusroemer has a moment to verify, I'd be grateful.

@corneliusroemer
Copy link
Author

corneliusroemer commented Sep 14, 2024

@kettanaito the issue with myFile?.slice() is related to msw interceptors - if I pin it to 0.33.3 then I can upgrade msw to 2.4.6 - but if I just bump msw without pinning the issue continues to exist

@kettanaito kettanaito changed the title Patch upgrade from 2.4.1 to 2.4.4 breaks tests with TypeError: myFile?.slice(...).arrayBuffer is not a function TypeError: myFile?.slice(...).arrayBuffer is not a function Sep 15, 2024
@kettanaito kettanaito changed the title TypeError: myFile?.slice(...).arrayBuffer is not a function TypeError: myFile?.slice(...).arrayBuffer is not a function Sep 15, 2024
@kettanaito
Copy link
Member

kettanaito commented Sep 15, 2024

Update

Sharing some info I found on this issue below.

Root cause

The issue is introduced in mswjs/interceptors#613, caused by calculating the total request body size here. Reading the FormData request body hangs forever here. The request is being cloned correctly (fixed in https://github.com/mswjs/interceptors/releases/tag/v0.35.3; I'm testing against the upstream).

In fact, I cannot read the intercepted POST http://backend.dummy/testOrganism/submit request's body at all.

I still don't understand how that causes Blob.prototype.arrayBuffer to be undefined, but I suspect that's related to your tested code. Since it never receives a mocked 500 response, that error scenario has a file that's somehow invalid, perhaps? You'd know better.

Behavior change

Since we are now correctly calculating the XMLHttpRequest total body size to support upload events, your request body is being read internally during that test (previously, it wasn't). @corneliusroemer, can you please tell me more about what's the form data in that failing test case? Is there a chance it's invalid/missing? That would cause request.arrayBuffer() to malfunction, I expect.

If I try to read await metadataFile.text() as a part of submitAndExpectErrorMessageContains, the content reading methods are all undefined there. I understand the issue manifests with the MSW update, but let's verify that the test files are indeed correct.

Likely irrelevant observations

Importing from vitest.setup.ts in a test file is not a good idea:

// website/src/components/Submission/SubmissionForm.spec.tsx
import { mockRequest, testAccessToken, testConfig, testGroups, testOrganism } from '../../../vitest.setup.ts';

This itself can cause some issues. I recommend you refactor this, moving the reused things away into a standalone module.

@kettanaito
Copy link
Member

kettanaito commented Sep 15, 2024

File/Blob reading methods are undefined even if I don't enable MSW:

- beforeAll(() => testServer.listen({ onUnhandledRequest: 'error' }));
+// beforeAll(() => testServer.listen({ onUnhandledRequest: 'error' }));

+console.log('demo:', new File(['content'], 'foo.txt', { type: 'text/plain' }).text());
TypeError: (intermediate value).text is not a function

This strongly suggests that the issue only surfaces through the library, but isn't caused by it. MSW/Interceptors don't establish any side effects before you start them (call .listen()). The broken File instance is likely coming from elsewhere.

Update

I can confirm that the File class you are using in tests is not Node's File. That's likely caused by you relying on JSDOM.

// your tests
import { File as NativeFile } from 'node:buffer';

console.log(new File(['content'], 'foo.txt', { type: 'text/plain' }) instanceof NativeFile);
// false!
// node repl
const { File: NativeFile } = require('node:buffer')
new File(['content'], 'foo.txt', { type: 'text/plain' }) instanceof NativeFile
true

If I switch your tests to happy-dom instead of jsdom, your broken test scenario is fixed:

 ✓ src/components/Submission/SubmissionForm.spec.tsx (6)
   ✓ SubmitForm (6)
     ↓ should handle file upload and server response [skipped]
     ↓ should answer with feedback that a file is missing [skipped]
     ↓ should be able to open change date modal [skipped]
     ✓ should unexpected error with proper error message
     ↓ should handle unprocessable entity error with proper error message [skipped]
     ↓ should allow submission only after agreeing to terms of INSDC submission [skipped]
const vitestConfig = defineVitestConfig({
    test: {
        globals: true,
-       environment: 'jsdom',
+       environment: 'happy-dom',
        setupFiles: ['./vitest.setup.ts'],
        include: ['./src/**/*.spec.ts', './src/**/*.spec.tsx'],
    },
});

What this means is that sometime during the test run, JSDOM decides not to implement File methods anymore. There's nothing we can or should do about this on MSW's side. As I've suspected, this surfaces through MSW but is not related to it.

I am closing this as Jest/JSDOM-related issue, which we are not addressing. You can learn more about MSW's stance on Jest/JSDOM support.

Solution

Test browser code in the browser. If you can't, use happy-dom.

@corneliusroemer
Copy link
Author

Thanks @kettanaito for the thorough investigation and apologies for reporting something that was only indirectly broken by msw with root cause being our wrong usage of some libraries.

@kettanaito
Copy link
Member

No worries! Appreciate your understanding on this one. It wasn't as obvious as other jsdom issues. Happy to add it to my cursed chest of browser-like environments' quirks.

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

8 participants