aboutsummaryrefslogtreecommitdiff
path: root/test/js/web/fetch
diff options
context:
space:
mode:
authorGravatar Dylan Conway <dylan.conway567@gmail.com> 2023-10-17 14:10:25 -0700
committerGravatar Dylan Conway <dylan.conway567@gmail.com> 2023-10-17 14:10:25 -0700
commit7458b969c5d9971e89d187b687e1924e78da427e (patch)
treeee3dbf95c728cf407bf49a27826b541e9264a8bd /test/js/web/fetch
parentd4a2c29131ec154f5e4db897d4deedab2002cbc4 (diff)
parente91436e5248d947b50f90b4a7402690be8a41f39 (diff)
downloadbun-7458b969c5d9971e89d187b687e1924e78da427e.tar.gz
bun-7458b969c5d9971e89d187b687e1924e78da427e.tar.zst
bun-7458b969c5d9971e89d187b687e1924e78da427e.zip
Merge branch 'main' into postinstall_3
Diffstat (limited to 'test/js/web/fetch')
-rw-r--r--test/js/web/fetch/blob.test.ts29
-rw-r--r--test/js/web/fetch/body-stream.test.ts29
-rw-r--r--test/js/web/fetch/fetch.stream.test.ts143
-rw-r--r--test/js/web/fetch/fetch.test.ts425
-rw-r--r--test/js/web/fetch/response.test.ts32
5 files changed, 656 insertions, 2 deletions
diff --git a/test/js/web/fetch/blob.test.ts b/test/js/web/fetch/blob.test.ts
index ba44f8c1b..ea8d86a7a 100644
--- a/test/js/web/fetch/blob.test.ts
+++ b/test/js/web/fetch/blob.test.ts
@@ -1,6 +1,6 @@
import { test, expect } from "bun:test";
-test("Blob.slice", () => {
+test("Blob.slice", async () => {
const blob = new Blob(["Bun", "Foo"]);
const b1 = blob.slice(0, 3, "Text/HTML");
expect(b1 instanceof Blob).toBeTruthy();
@@ -26,6 +26,33 @@ test("Blob.slice", () => {
expect(blob.slice(null, "-123").size).toBe(6);
expect(blob.slice(0, 10).size).toBe(blob.size);
expect(blob.slice("text/plain;charset=utf-8").type).toBe("text/plain;charset=utf-8");
+
+ // test Blob.slice().slice(), issue#6252
+ expect(await blob.slice(0, 4).slice(0, 3).text()).toBe("Bun");
+ expect(await blob.slice(0, 4).slice(1, 3).text()).toBe("un");
+ expect(await blob.slice(1, 4).slice(0, 3).text()).toBe("unF");
+ expect(await blob.slice(1, 4).slice(1, 3).text()).toBe("nF");
+ expect(await blob.slice(1, 4).slice(2, 3).text()).toBe("F");
+ expect(await blob.slice(1, 4).slice(3, 3).text()).toBe("");
+ expect(await blob.slice(1, 4).slice(4, 3).text()).toBe("");
+ // test negative start
+ expect(await blob.slice(1, 4).slice(-1, 3).text()).toBe("F");
+ expect(await blob.slice(1, 4).slice(-2, 3).text()).toBe("nF");
+ expect(await blob.slice(1, 4).slice(-3, 3).text()).toBe("unF");
+ expect(await blob.slice(1, 4).slice(-4, 3).text()).toBe("unF");
+ expect(await blob.slice(1, 4).slice(-5, 3).text()).toBe("unF");
+ expect(await blob.slice(-1, 4).slice(-1, 3).text()).toBe("");
+ expect(await blob.slice(-2, 4).slice(-1, 3).text()).toBe("");
+ expect(await blob.slice(-3, 4).slice(-1, 3).text()).toBe("F");
+ expect(await blob.slice(-4, 4).slice(-1, 3).text()).toBe("F");
+ expect(await blob.slice(-5, 4).slice(-1, 3).text()).toBe("F");
+ expect(await blob.slice(-5, 4).slice(-2, 3).text()).toBe("nF");
+ expect(await blob.slice(-5, 4).slice(-3, 3).text()).toBe("unF");
+ expect(await blob.slice(-5, 4).slice(-4, 3).text()).toBe("unF");
+ expect(await blob.slice(-4, 4).slice(-3, 3).text()).toBe("nF");
+ expect(await blob.slice(-5, 4).slice(-4, 3).text()).toBe("unF");
+ expect(await blob.slice(-3, 4).slice(-2, 3).text()).toBe("F");
+ expect(await blob.slice(-blob.size, 4).slice(-blob.size, 3).text()).toBe("Bun");
});
test("new Blob", () => {
diff --git a/test/js/web/fetch/body-stream.test.ts b/test/js/web/fetch/body-stream.test.ts
index 8e2baf92a..8f7675528 100644
--- a/test/js/web/fetch/body-stream.test.ts
+++ b/test/js/web/fetch/body-stream.test.ts
@@ -13,6 +13,35 @@ var port = 0;
];
const useRequestObjectValues = [true, false];
+ test("Should not crash when not returning a promise when stream is in progress", async () => {
+ var called = false;
+ await runInServer(
+ {
+ async fetch() {
+ var stream = new ReadableStream({
+ type: "direct",
+ pull(controller) {
+ controller.write("hey");
+ setTimeout(() => {
+ controller.end();
+ }, 100);
+ },
+ });
+
+ return new Response(stream);
+ },
+ },
+ async url => {
+ called = true;
+ expect(await fetch(url).then(res => res.text())).toContain(
+ "Welcome to Bun! To get started, return a Response object.",
+ );
+ },
+ );
+
+ expect(called).toBe(true);
+ });
+
for (let RequestPrototypeMixin of BodyMixin) {
for (let useRequestObject of useRequestObjectValues) {
describe(`Request.prototoype.${RequestPrototypeMixin.name}() ${
diff --git a/test/js/web/fetch/fetch.stream.test.ts b/test/js/web/fetch/fetch.stream.test.ts
index 98271ee79..cc518e397 100644
--- a/test/js/web/fetch/fetch.stream.test.ts
+++ b/test/js/web/fetch/fetch.stream.test.ts
@@ -28,6 +28,142 @@ const smallText = Buffer.from("Hello".repeat(16));
const empty = Buffer.alloc(0);
describe("fetch() with streaming", () => {
+ it(`should be able to fail properly when reading from readable stream`, async () => {
+ let server: Server | null = null;
+ try {
+ server = Bun.serve({
+ port: 0,
+ async fetch(req) {
+ return new Response(
+ new ReadableStream({
+ async start(controller) {
+ controller.enqueue("Hello, World!");
+ await Bun.sleep(1000);
+ controller.enqueue("Hello, World!");
+ controller.close();
+ },
+ }),
+ {
+ status: 200,
+ headers: {
+ "Content-Type": "text/plain",
+ },
+ },
+ );
+ },
+ });
+
+ const server_url = `http://${server.hostname}:${server.port}`;
+ try {
+ const res = await fetch(server_url, { signal: AbortSignal.timeout(20) });
+ const reader = res.body?.getReader();
+ while (true) {
+ const { done } = await reader?.read();
+ if (done) break;
+ }
+ expect(true).toBe("unreachable");
+ } catch (err: any) {
+ if (err.name !== "TimeoutError") throw err;
+ expect(err.message).toBe("The operation timed out.");
+ }
+ } finally {
+ server?.stop();
+ }
+ });
+
+ it(`should be locked after start buffering`, async () => {
+ let server: Server | null = null;
+ try {
+ server = Bun.serve({
+ port: 0,
+ fetch(req) {
+ return new Response(
+ new ReadableStream({
+ async start(controller) {
+ controller.enqueue("Hello, World!");
+ await Bun.sleep(10);
+ controller.enqueue("Hello, World!");
+ await Bun.sleep(10);
+ controller.enqueue("Hello, World!");
+ await Bun.sleep(10);
+ controller.enqueue("Hello, World!");
+ await Bun.sleep(10);
+ controller.close();
+ },
+ }),
+ {
+ status: 200,
+ headers: {
+ "Content-Type": "text/plain",
+ },
+ },
+ );
+ },
+ });
+
+ const server_url = `http://${server.hostname}:${server.port}`;
+ const res = await fetch(server_url);
+ try {
+ const promise = res.text(); // start buffering
+ res.body?.getReader(); // get a reader
+ const result = await promise; // should throw the right error
+ expect(result).toBe("unreachable");
+ } catch (err: any) {
+ if (err.name !== "TypeError") throw err;
+ expect(err.message).toBe("ReadableStream is locked");
+ }
+ } finally {
+ server?.stop();
+ }
+ });
+
+ it(`should be locked after start buffering when calling getReader`, async () => {
+ let server: Server | null = null;
+ try {
+ server = Bun.serve({
+ port: 0,
+ fetch(req) {
+ return new Response(
+ new ReadableStream({
+ async start(controller) {
+ controller.enqueue("Hello, World!");
+ await Bun.sleep(10);
+ controller.enqueue("Hello, World!");
+ await Bun.sleep(10);
+ controller.enqueue("Hello, World!");
+ await Bun.sleep(10);
+ controller.enqueue("Hello, World!");
+ await Bun.sleep(10);
+ controller.close();
+ },
+ }),
+ {
+ status: 200,
+ headers: {
+ "Content-Type": "text/plain",
+ },
+ },
+ );
+ },
+ });
+
+ const server_url = `http://${server.hostname}:${server.port}`;
+ const res = await fetch(server_url);
+ try {
+ const body = res.body as ReadableStream<Uint8Array>;
+ const promise = res.text(); // start buffering
+ body.getReader(); // get a reader
+ const result = await promise; // should throw the right error
+ expect(result).toBe("unreachable");
+ } catch (err: any) {
+ if (err.name !== "TypeError") throw err;
+ expect(err.message).toBe("ReadableStream is locked");
+ }
+ } finally {
+ server?.stop();
+ }
+ });
+
it("can deflate with and without headers #4478", async () => {
let server: Server | null = null;
try {
@@ -77,7 +213,12 @@ describe("fetch() with streaming", () => {
.listen(0);
const address = server.address() as AddressInfo;
- const url = `http://${address.address}:${address.port}`;
+ let url;
+ if (address.family == "IPv4") {
+ url = `http://${address.address}:${address.port}`;
+ } else {
+ url = `http://[${address.address}]:${address.port}`;
+ }
async function getRequestLen(url: string) {
const response = await fetch(url);
const hasBody = response.body;
diff --git a/test/js/web/fetch/fetch.test.ts b/test/js/web/fetch/fetch.test.ts
index aa44ee76a..3ed20345b 100644
--- a/test/js/web/fetch/fetch.test.ts
+++ b/test/js/web/fetch/fetch.test.ts
@@ -3,8 +3,10 @@ import { afterAll, afterEach, beforeAll, describe, expect, it, beforeEach } from
import { chmodSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from "fs";
import { mkfifo } from "mkfifo";
import { tmpdir } from "os";
+import { gzipSync } from "zlib";
import { join } from "path";
import { gc, withoutAggressiveGC, gcTick } from "harness";
+import net from "net";
const tmp_dir = mkdtempSync(join(realpathSync(tmpdir()), "fetch.test"));
@@ -93,6 +95,30 @@ describe("fetch data urls", () => {
expect(blob.type).toBe("text/plain;charset=utf-8");
expect(blob.text()).resolves.toBe("helloworld!");
});
+ it("unstrict parsing of invalid URL characters", async () => {
+ var url = "data:application/json,{%7B%7D}";
+ var res = await fetch(url);
+ expect(res.status).toBe(200);
+ expect(res.statusText).toBe("OK");
+ expect(res.ok).toBe(true);
+
+ var blob = await res.blob();
+ expect(blob.size).toBe(4);
+ expect(blob.type).toBe("application/json;charset=utf-8");
+ expect(blob.text()).resolves.toBe("{{}}");
+ });
+ it("unstrict parsing of double percent characters", async () => {
+ var url = "data:application/json,{%%7B%7D%%}%%";
+ var res = await fetch(url);
+ expect(res.status).toBe(200);
+ expect(res.statusText).toBe("OK");
+ expect(res.ok).toBe(true);
+
+ var blob = await res.blob();
+ expect(blob.size).toBe(9);
+ expect(blob.type).toBe("application/json;charset=utf-8");
+ expect(blob.text()).resolves.toBe("{%{}%%}%%");
+ });
it("data url (invalid)", async () => {
var url = "data:Hello%2C%20World!";
expect(async () => {
@@ -321,6 +347,27 @@ describe("Headers", () => {
expect(headers.getAll("set-cookie")).toEqual(["foo=bar; Path=/; HttpOnly"]);
});
+ it("presence of content-encoding header(issue #5668)", async () => {
+ startServer({
+ fetch(req) {
+ const content = gzipSync(JSON.stringify({ message: "Hello world" }));
+ return new Response(content, {
+ status: 200,
+ headers: {
+ "content-encoding": "gzip",
+ "content-type": "application/json",
+ },
+ });
+ },
+ });
+ const result = await fetch(`http://${server.hostname}:${server.port}/`);
+ const value = result.headers.get("content-encoding");
+ const body = await result.json();
+ expect(value).toBe("gzip");
+ expect(body).toBeDefined();
+ expect(body.message).toBe("Hello world");
+ });
+
it(".getSetCookie() with array", () => {
const headers = new Headers([
["content-length", "123"],
@@ -1216,6 +1263,16 @@ describe("Request", () => {
expect(req.signal.aborted).toBe(true);
});
+ it("copies method (#6144)", () => {
+ const request = new Request("http://localhost:1337/test", {
+ method: "POST",
+ });
+ const new_req = new Request(request, {
+ body: JSON.stringify({ message: "Hello world" }),
+ });
+ expect(new_req.method).toBe("POST");
+ });
+
it("cloned signal", async () => {
gc();
const controller = new AbortController();
@@ -1391,3 +1448,371 @@ it("cloned response headers are independent after accessing", () => {
cloned.headers.set("content-type", "text/plain");
expect(response.headers.get("content-type")).toBe("text/html; charset=utf-8");
});
+
+it("should work with http 100 continue", async () => {
+ let server: net.Server | undefined;
+ try {
+ server = net.createServer(socket => {
+ socket.on("data", data => {
+ const lines = data.toString().split("\r\n");
+ for (const line of lines) {
+ if (line.length == 0) {
+ socket.write("HTTP/1.1 100 Continue\r\n\r\n");
+ socket.write("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 13\r\n\r\nHello, World!");
+ break;
+ }
+ }
+ });
+ });
+
+ const { promise: start, resolve } = Promise.withResolvers();
+ server.listen(8080, resolve);
+
+ await start;
+
+ const address = server.address() as net.AddressInfo;
+ const result = await fetch(`http://localhost:${address.port}`).then(r => r.text());
+ expect(result).toBe("Hello, World!");
+ } finally {
+ server?.close();
+ }
+});
+
+it("should work with http 100 continue on the same buffer", async () => {
+ let server: net.Server | undefined;
+ try {
+ server = net.createServer(socket => {
+ socket.on("data", data => {
+ const lines = data.toString().split("\r\n");
+ for (const line of lines) {
+ if (line.length == 0) {
+ socket.write(
+ "HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 13\r\n\r\nHello, World!",
+ );
+ break;
+ }
+ }
+ });
+ });
+
+ const { promise: start, resolve } = Promise.withResolvers();
+ server.listen(8080, resolve);
+
+ await start;
+
+ const address = server.address() as net.AddressInfo;
+ const result = await fetch(`http://localhost:${address.port}`).then(r => r.text());
+ expect(result).toBe("Hello, World!");
+ } finally {
+ server?.close();
+ }
+});
+
+describe("should strip headers", () => {
+ it("status code 303", async () => {
+ const server = Bun.serve({
+ port: 0,
+ async fetch(request: Request) {
+ if (request.url.endsWith("/redirect")) {
+ return new Response("hello", {
+ headers: {
+ ...request.headers,
+ "Location": "/redirected",
+ },
+ status: 303,
+ });
+ }
+
+ return new Response("hello", {
+ headers: request.headers,
+ });
+ },
+ });
+
+ const { headers, url, redirected } = await fetch(`http://${server.hostname}:${server.port}/redirect`, {
+ method: "POST",
+ headers: {
+ "I-Am-Here": "yes",
+ "Content-Language": "This should be stripped",
+ },
+ });
+
+ expect(headers.get("I-Am-Here")).toBe("yes");
+ expect(headers.get("Content-Language")).toBeNull();
+ expect(url).toEndWith("/redirected");
+ expect(redirected).toBe(true);
+ server.stop(true);
+ });
+
+ it("cross-origin status code 302", async () => {
+ const server1 = Bun.serve({
+ port: 0,
+ async fetch(request: Request) {
+ if (request.url.endsWith("/redirect")) {
+ return new Response("hello", {
+ headers: {
+ ...request.headers,
+ "Location": `http://${server2.hostname}:${server2.port}/redirected`,
+ },
+ status: 302,
+ });
+ }
+
+ return new Response("hello", {
+ headers: request.headers,
+ });
+ },
+ });
+
+ const server2 = Bun.serve({
+ port: 0,
+ async fetch(request: Request, server) {
+ if (request.url.endsWith("/redirect")) {
+ return new Response("hello", {
+ headers: {
+ ...request.headers,
+ "Location": `http://${server.hostname}:${server.port}/redirected`,
+ },
+ status: 302,
+ });
+ }
+
+ return new Response("hello", {
+ headers: request.headers,
+ });
+ },
+ });
+
+ const { headers, url, redirected } = await fetch(`http://${server1.hostname}:${server1.port}/redirect`, {
+ method: "GET",
+ headers: {
+ "Authorization": "yes",
+ },
+ });
+
+ expect(headers.get("Authorization")).toBeNull();
+ expect(url).toEndWith("/redirected");
+ expect(redirected).toBe(true);
+ server1.stop(true);
+ server2.stop(true);
+ });
+});
+
+it("same-origin status code 302 should not strip headers", async () => {
+ const server = Bun.serve({
+ port: 0,
+ async fetch(request: Request, server) {
+ if (request.url.endsWith("/redirect")) {
+ return new Response("hello", {
+ headers: {
+ ...request.headers,
+ "Location": `http://${server.hostname}:${server.port}/redirected`,
+ },
+ status: 302,
+ });
+ }
+
+ return new Response("hello", {
+ headers: request.headers,
+ });
+ },
+ });
+
+ const { headers, url, redirected } = await fetch(`http://${server.hostname}:${server.port}/redirect`, {
+ method: "GET",
+ headers: {
+ "Authorization": "yes",
+ },
+ });
+
+ expect(headers.get("Authorization")).toEqual("yes");
+ expect(url).toEndWith("/redirected");
+ expect(redirected).toBe(true);
+ server.stop(true);
+});
+
+describe("should handle relative location in the redirect, issue#5635", () => {
+ var server: Server;
+ beforeAll(async () => {
+ server = Bun.serve({
+ port: 0,
+ async fetch(request: Request) {
+ return new Response("Not Found", {
+ status: 404,
+ });
+ },
+ });
+ });
+ afterAll(() => {
+ server.stop(true);
+ });
+
+ it.each([
+ ["/a/b", "/c", "/c"],
+ ["/a/b", "c", "/a/c"],
+ ["/a/b", "/c/d", "/c/d"],
+ ["/a/b", "c/d", "/a/c/d"],
+ ["/a/b", "../c", "/c"],
+ ["/a/b", "../c/d", "/c/d"],
+ ["/a/b", "../../../c", "/c"],
+ // slash
+ ["/a/b/", "/c", "/c"],
+ ["/a/b/", "c", "/a/b/c"],
+ ["/a/b/", "/c/d", "/c/d"],
+ ["/a/b/", "c/d", "/a/b/c/d"],
+ ["/a/b/", "../c", "/a/c"],
+ ["/a/b/", "../c/d", "/a/c/d"],
+ ["/a/b/", "../../../c", "/c"],
+ ])("('%s', '%s')", async (pathname, location, expected) => {
+ server.reload({
+ async fetch(request: Request) {
+ const url = new URL(request.url);
+ if (url.pathname == pathname) {
+ return new Response("redirecting", {
+ headers: {
+ "Location": location,
+ },
+ status: 302,
+ });
+ } else if (url.pathname == expected) {
+ return new Response("Fine.");
+ }
+ return new Response("Not Found", {
+ status: 404,
+ });
+ },
+ });
+
+ const resp = await fetch(`http://${server.hostname}:${server.port}${pathname}`);
+ expect(resp.redirected).toBe(true);
+ expect(new URL(resp.url).pathname).toStrictEqual(expected);
+ expect(resp.status).toBe(200);
+ expect(await resp.text()).toBe("Fine.");
+ });
+});
+
+it("should throw RedirectURLTooLong when location is too long", async () => {
+ const server = Bun.serve({
+ port: 0,
+ async fetch(request: Request) {
+ gc();
+ const url = new URL(request.url);
+ if (url.pathname == "/redirect") {
+ return new Response("redirecting", {
+ headers: {
+ "Location": "B".repeat(8193),
+ },
+ status: 302,
+ });
+ }
+ return new Response("Not Found", {
+ status: 404,
+ });
+ },
+ });
+
+ let err = undefined;
+ try {
+ gc();
+ const resp = await fetch(`http://${server.hostname}:${server.port}/redirect`);
+ } catch (error) {
+ gc();
+ err = error;
+ }
+ expect(err).not.toBeUndefined();
+ expect(err).toBeInstanceOf(Error);
+ expect(err.code).toStrictEqual("RedirectURLTooLong");
+ server.stop(true);
+});
+
+it("304 not modified with missing content-length does not cause a request timeout", async () => {
+ const server = await Bun.listen({
+ socket: {
+ open(socket) {
+ socket.write("HTTP/1.1 304 Not Modified\r\n\r\n");
+ socket.flush();
+ setTimeout(() => {
+ socket.end();
+ }, 9999).unref();
+ },
+ data() {},
+ close() {},
+ },
+ port: 0,
+ hostname: "localhost",
+ });
+
+ const response = await fetch(`http://${server.hostname}:${server.port}/`);
+ expect(response.status).toBe(304);
+ expect(await response.arrayBuffer()).toHaveLength(0);
+ server.stop(true);
+});
+
+it("304 not modified with missing content-length and connection close does not cause a request timeout", async () => {
+ const server = await Bun.listen({
+ socket: {
+ open(socket) {
+ socket.write("HTTP/1.1 304 Not Modified\r\nConnection: close\r\n\r\n");
+ socket.flush();
+ setTimeout(() => {
+ socket.end();
+ }, 9999).unref();
+ },
+ data() {},
+ close() {},
+ },
+ port: 0,
+ hostname: "localhost",
+ });
+
+ const response = await fetch(`http://${server.hostname}:${server.port}/`);
+ expect(response.status).toBe(304);
+ expect(await response.arrayBuffer()).toHaveLength(0);
+ server.stop(true);
+});
+
+it("304 not modified with content-length 0 and connection close does not cause a request timeout", async () => {
+ const server = await Bun.listen({
+ socket: {
+ open(socket) {
+ socket.write("HTTP/1.1 304 Not Modified\r\nConnection: close\r\nContent-Length: 0\r\n\r\n");
+ socket.flush();
+ setTimeout(() => {
+ socket.end();
+ }, 9999).unref();
+ },
+ data() {},
+ close() {},
+ },
+ port: 0,
+ hostname: "localhost",
+ });
+
+ const response = await fetch(`http://${server.hostname}:${server.port}/`);
+ expect(response.status).toBe(304);
+ expect(await response.arrayBuffer()).toHaveLength(0);
+ server.stop(true);
+});
+
+it("304 not modified with 0 content-length does not cause a request timeout", async () => {
+ const server = await Bun.listen({
+ socket: {
+ open(socket) {
+ socket.write("HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n");
+ socket.flush();
+ setTimeout(() => {
+ socket.end();
+ }, 9999).unref();
+ },
+ data() {},
+ close() {},
+ },
+ port: 0,
+ hostname: "localhost",
+ });
+
+ const response = await fetch(`http://${server.hostname}:${server.port}/`);
+ expect(response.status).toBe(304);
+ expect(await response.arrayBuffer()).toHaveLength(0);
+ server.stop(true);
+});
diff --git a/test/js/web/fetch/response.test.ts b/test/js/web/fetch/response.test.ts
new file mode 100644
index 000000000..ddfcd70f7
--- /dev/null
+++ b/test/js/web/fetch/response.test.ts
@@ -0,0 +1,32 @@
+import { describe, test, expect } from "bun:test";
+
+test("zero args returns an otherwise empty 200 response", () => {
+ const response = new Response();
+ expect(response.status).toBe(200);
+ expect(response.statusText).toBe("");
+});
+
+test("1-arg form returns a 200 response", () => {
+ const response = new Response("body text");
+
+ expect(response.status).toBe(200);
+ expect(response.statusText).toBe("");
+});
+
+describe("2-arg form", () => {
+ test("can fill in status/statusText, and it works", () => {
+ const response = new Response("body text", {
+ status: 202,
+ statusText: "Accepted.",
+ });
+
+ expect(response.status).toBe(202);
+ expect(response.statusText).toBe("Accepted.");
+ });
+ test('empty object continues to return 200/""', () => {
+ const response = new Response("body text", {});
+
+ expect(response.status).toBe(200);
+ expect(response.statusText).toBe("");
+ });
+});