test(api): assert the export body's brand, not which realm built its Blob
`expect(x).toBeInstanceOf(Blob)` asks which realm constructed the body, not
whether there is one. Under jsdom the ambient `Blob` is jsdom's class, while
`Response.blob()` hands back node's own on Node 22 and jsdom's on Node 24 — so
both assertions passed locally and failed on the server gate, for a reason that
says nothing about the code under test. `.text()` is the mirror image: jsdom's
Blob does not implement it, so reading the bytes back is green on 22 and red on
24.
Both now assert the brand (`[object Blob]`, agreed by both realms) plus size and
type. Mutation-checked in node:22-bookworm: dropping `{ raw: true }` from
`debugExport` still turns the test red, so the repaired assertion still catches
the defect it was written for.
core.test.ts also stops building its Response from a jsdom `Blob`: on Node 22
undici does not recognise it as a body and stringifies it, so the fixture's body
was the 13 bytes of "[object Blob]" rather than the zip header. A string body is
what the sibling test already used.
This commit is contained in:
@@ -221,7 +221,7 @@ describe("req — a file, not a parsed answer", () => {
|
||||
// A zip. Without the `raw` branch this falls into `r.json()`, throws on the first byte, and the
|
||||
// download dies as an opaque failure — which no lane would see, because the only consumer test
|
||||
// mocks the api method wholesale.
|
||||
const zip = new Response(new Blob(["PK"]), {
|
||||
const zip = new Response("PK", {
|
||||
status: 200,
|
||||
headers: {
|
||||
"content-type": "application/zip",
|
||||
@@ -234,7 +234,16 @@ describe("req — a file, not a parsed answer", () => {
|
||||
|
||||
expect(r).toBe(zip);
|
||||
expect(r.headers.get("content-disposition")).toContain("siftlode-debug-260919.zip");
|
||||
expect(await r.blob()).toBeInstanceOf(Blob); // the body is still there to be read
|
||||
// NOT `toBeInstanceOf(Blob)`: that asserts which realm built the body, not that there is one.
|
||||
// Under jsdom the ambient `Blob` is jsdom's class, while `Response.blob()` hands back node's own
|
||||
// on Node 22 and jsdom's on Node 24 — so the same assertion passed here and failed on the server
|
||||
// gate (measured 2026-09-20). Nor `.text()`, for the mirror-image reason: jsdom's Blob has no
|
||||
// such method, so reading the bytes back is green on 22 and red on 24. The brand and the size
|
||||
// are the two things both realms agree on, and they are what this test means.
|
||||
const body = await r.blob();
|
||||
expect(Object.prototype.toString.call(body)).toBe("[object Blob]");
|
||||
expect(body.size).toBe(4); // the body is still there to be read, all four of its bytes
|
||||
expect(body.type).toBe("application/zip");
|
||||
});
|
||||
|
||||
it("still refuses before the body is touched, so a refusal is shown and not saved", async () => {
|
||||
|
||||
@@ -42,7 +42,10 @@ describe("debugExport", () => {
|
||||
|
||||
expect(out.name).toBe("siftlode-debug-20260919-1402-abc123.zip");
|
||||
// The body is read as bytes, not parsed: `r.json()` on a zip would throw on its first one.
|
||||
expect(out.blob).toBeInstanceOf(Blob);
|
||||
// Brand, not `toBeInstanceOf(Blob)` — that asks which realm built the body: under jsdom the
|
||||
// ambient `Blob` is jsdom's class, while `Response.blob()` returns node's own on Node 22 and
|
||||
// jsdom's on Node 24, so the instance check passed locally and failed on the server gate.
|
||||
expect(Object.prototype.toString.call(out.blob)).toBe("[object Blob]");
|
||||
expect(out.blob.size).toBe(4);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user