Files
bun.sh/test/js/web/fetch/fetch-args.test.ts
2024-09-03 21:32:52 -07:00

240 lines
6.1 KiB
TypeScript

import { TCPSocketListener } from "bun";
import { afterAll, beforeAll, describe, expect, mock, spyOn, test } from "bun:test";
let server;
let requestCount = 0;
beforeAll(async () => {
server = Bun.serve({
port: 0,
fetch(request) {
requestCount++;
return new Response(undefined, { headers: request.headers });
},
});
});
afterAll(() => {
server!.stop(true);
});
test("fetch(request subclass with headers)", async () => {
class MyRequest extends Request {
constructor(input: RequestInfo, init?: RequestInit) {
super(input, init);
this.headers.set("hello", "world");
}
}
const myRequest = new MyRequest(server!.url + "/");
const { headers } = await fetch(myRequest);
expect(headers.get("hello")).toBe("world");
});
test("fetch(RequestInit, headers)", async () => {
const myRequest = {
headers: {
"hello": "world",
},
url: server!.url,
};
const { headers } = await fetch(myRequest, {
headers: {
"hello": "world2",
},
});
expect(headers.get("hello")).toBe("world2");
});
test("fetch(url, RequestSubclass)", async () => {
class MyRequest extends Request {
constructor(input: RequestInfo, init?: RequestInit) {
super(input, init);
this.headers.set("hello", "world");
}
}
const myRequest = new MyRequest(server!.url);
const { headers } = await fetch(server.url, myRequest);
expect(headers.get("hello")).toBe("world");
});
test("fetch({toString throwing}, {headers} isn't accessed)", async () => {
const obj = {
headers: null,
};
const mocked = spyOn(obj, "headers");
const str = {
toString: mock(() => {
throw new Error("bad2");
}),
};
expect(async () => await fetch(str, obj)).toThrow("bad2");
expect(mocked).not.toHaveBeenCalled();
expect(str.toString).toHaveBeenCalledTimes(1);
});
test("fetch(RequestSubclass, undefined)", async () => {
class MyRequest extends Request {
constructor(input: RequestInfo, init?: RequestInit) {
super(input, init);
this.headers.set("hello", "world");
}
}
const myRequest = new MyRequest(server!.url);
const { headers } = await fetch(myRequest, undefined);
expect(headers.get("hello")).toBe("world");
});
describe("does not send a request when", () => {
let requestCount = 0;
let server: TCPSocketListener | undefined;
let url: string;
beforeAll(async () => {
server = Bun.listen({
port: 0,
hostname: "127.0.0.1",
socket: {
open(socket) {
requestCount++;
socket.terminate();
},
data(socket, data) {
socket.terminate();
},
},
});
});
afterAll(() => {
server!.stop(true);
url = "http://" + server!.hostname + ":" + server!.port;
});
test("Invalid headers", async () => {
const prevCount = requestCount;
expect(
async () =>
await fetch(url, {
headers: {
"😀smile ": "😀",
},
}),
).toThrow();
// Give it a chance to possibly send the request.
await Bun.sleep(2);
expect(requestCount).toBe(prevCount);
});
test("Invalid url", async () => {
const prevCount = requestCount;
expect(async () => await fetch("😀")).toThrow();
// Give it a chance to possibly send the request.
await Bun.sleep(2);
expect(requestCount).toBe(prevCount);
});
test("Invalid redirect", async () => {
const prevCount = requestCount;
expect(async () => await fetch(url, { redirect: "😀" })).toThrow();
// Give it a chance to possibly send the request.
await Bun.sleep(2);
expect(requestCount).toBe(prevCount);
});
test("proxy and unix", async () => {
const prevCount = requestCount;
expect(async () => await fetch(url, { proxy: url, unix: "/tmp/abc.sock" })).toThrow();
// Give it a chance to possibly send the request.
await Bun.sleep(2);
expect(requestCount).toBe(prevCount);
});
test("Invalid ca in tls", async () => {
const prevCount = requestCount;
expect(async () => await fetch(url, { tls: { ca: 123 } })).toThrow();
// Give it a chance to possibly send the request.
await Bun.sleep(2);
expect(requestCount).toBe(prevCount);
});
const propertyNamesToThrow = [
"body",
"decompression",
"headers",
"keepalive",
"method",
"proxy",
"redirect",
"signal",
"timeout",
"tls",
"unix",
"verbose",
];
test(`ReadableStream body throws`, async () => {
const prevCount = requestCount;
expect(
async () =>
await fetch(url, {
body: async function* () {
throw new Error("boom");
},
}),
).toThrow();
// Give it a chance to possibly send the request.
await Bun.sleep(2);
expect(requestCount).toBe(prevCount);
});
for (const propertyName of propertyNamesToThrow) {
test(`get "${propertyName}" throws (url, 1st arg)`, async () => {
const prevCount = requestCount;
expect(
async () =>
await fetch(url, {
get [propertyName]() {
throw new Error("boom");
},
}),
).toThrow();
// Give it a chance to possibly send the request.
await Bun.sleep(2);
expect(requestCount).toBe(prevCount);
});
test(`get "${propertyName}" throws (1st arg)`, async () => {
const prevCount = requestCount;
expect(
async () =>
await fetch({
url,
get [propertyName]() {
throw new Error("boom");
},
}),
).toThrow();
// Give it a chance to possibly send the request.
await Bun.sleep(2);
expect(requestCount).toBe(prevCount);
});
test(`get "${propertyName}" throws (Request object, 1st arg)`, async () => {
const prevCount = requestCount;
expect(
async () =>
await fetch(new Request(url), {
get [propertyName]() {
throw new Error("boom");
},
}),
).toThrow();
// Give it a chance to possibly send the request.
await Bun.sleep(2);
expect(requestCount).toBe(prevCount);
});
}
});