JSDOM environement: blob is not typeof Blob
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
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- [X] The provided reproduction is a minimal reproducible example of the bug.