vitest icon indicating copy to clipboard operation
vitest copied to clipboard

JSDOM environement: blob is not typeof Blob

Open aaronklinker-st opened this issue 3 years ago • 0 comments

Describe the bug

When using node 18, there appears to be two instances of the Blob class when running tests inside a JSDOM environment.

This is very similar to a previous issue, #1703.

Reproduction

Here's a minimal repo that reproduces the error: https://github.com/aaronklinker-st/vitest-blob-issue

When running the following test:

/**
 * @vitest-environment jsdom
 */
import { JSDOM } from "jsdom";
import { expect, test } from "vitest";

function stringToDataUrl(str, BlobClass) {
  return new Promise((res) => {
    const blob = new BlobClass([str], { type: "plain/text" });
    const reader = new FileReader();
    reader.onload = (e) => res(e.target.result);
    reader.readAsDataURL(blob);
  });
}

test("Fails", async () => {
  const actual = await stringToDataUrl("hello world", Blob);
  expect(actual).toEqual("data:plain/text;base64,aGVsbG8gd29ybGQ=");
});

test("Passes", async () => {
  const dom = new JSDOM();
  const actual = await stringToDataUrl("hello world", dom.window.Blob);
  expect(actual).toEqual("data:plain/text;base64,aGVsbG8gd29ybGQ=");
});

It fails when using the global Blob, but works when specifying a JSDOM's Blob class instead.

Here's the test output:

$ npm test run


> test
> vitest run


 RUN  v0.23.4 /Users/aklinker1/Development/Temp Repos/vitest-blob-error

 ❯ example.test.js (2)
   × Fails
   ✓ Passes

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL  example.test.js > Fails
TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'.
 ❯ exports.convert node_modules/jsdom/lib/jsdom/living/generated/Blob.js:22:9
 ❯ FileReader.readAsDataURL node_modules/jsdom/lib/jsdom/living/generated/FileReader.js:197:23
 ❯ example.test.js:12:12
     10|     const reader = new FileReader();
     11|     reader.onload = (e) => res(e.target.result);
     12|     reader.readAsDataURL(blob);
       |            ^
     13|   });
     14| }
 ❯ stringToDataUrl example.test.js:8:10
 ❯ example.test.js:17:24

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: {
  "__defineGetter__": "Function<__defineGetter__>",
  "__defineSetter__": "Function<__defineSetter__>",
  "__lookupGetter__": "Function<__lookupGetter__>",
  "__lookupSetter__": "Function<__lookupSetter__>",
  "__proto__": null,
  "hasOwnProperty": "Function<hasOwnProperty>",
  "isPrototypeOf": "Function<isPrototypeOf>",
  "propertyIsEnumerable": "Function<propertyIsEnumerable>",
  "toLocaleString": "Function<toLocaleString>",
  "valueOf": "Function<valueOf>",
}


⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯

Test Files  1 failed (1)
     Tests  1 failed | 1 passed (2)
  Start at  10:04:34
  Duration  1.31s (transform 356ms, setup 0ms, collect 19ms, tests 12ms)

As you can see, this is quite the confusing error message since blob is definitely an instance of the Blob class, meaning there are two Blob classes available, but only one is accepted by the readAsDataURL method.

This passes in Node 16, likely because node 18 added it's own Blob global, similar to #1703's ArrayBuffer

System Info

System:
    OS: macOS 12.6
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 10.21 GB / 32.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.9.0 - ~/.nvm/versions/node/v18.9.0/bin/node
    npm: 8.19.1 - ~/.nvm/versions/node/v18.9.0/bin/npm
  Browsers:
    Chrome: 105.0.5195.125
    Firefox: 103.0.1
    Firefox Developer Edition: 106.0
    Safari: 16.0
  npmPackages:
    vitest: ^0.23.4 => 0.23.4

Used Package Manager

npm

Validations

aaronklinker-st avatar Sep 23 '22 15:09 aaronklinker-st