aboutsummaryrefslogtreecommitdiff
path: root/test/bun.js/FormData.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'test/bun.js/FormData.test.ts')
-rw-r--r--test/bun.js/FormData.test.ts410
1 files changed, 0 insertions, 410 deletions
diff --git a/test/bun.js/FormData.test.ts b/test/bun.js/FormData.test.ts
deleted file mode 100644
index 25c0d5d54..000000000
--- a/test/bun.js/FormData.test.ts
+++ /dev/null
@@ -1,410 +0,0 @@
-import { afterAll, beforeAll, describe, expect, it, test } from "bun:test";
-import fs, { chmodSync, unlinkSync } from "fs";
-import { mkfifo } from "mkfifo";
-import { gc, withoutAggressiveGC } from "./gc";
-
-describe("FormData", () => {
- it("should be able to append a string", () => {
- const formData = new FormData();
- formData.append("foo", "bar");
- expect(formData.get("foo")).toBe("bar");
- expect(formData.getAll("foo")[0]).toBe("bar");
- });
-
- it("should be able to append a Blob", async () => {
- const formData = new FormData();
- formData.append("foo", new Blob(["bar"]));
- expect(await formData.get("foo").text()).toBe("bar");
- expect(formData.getAll("foo")[0] instanceof Blob).toBe(true);
- });
-
- it("should be able to set a Blob", async () => {
- const formData = new FormData();
- formData.set("foo", new Blob(["bar"]));
- expect(await formData.get("foo").text()).toBe("bar");
- expect(formData.getAll("foo")[0] instanceof Blob).toBe(true);
- });
-
- it("should be able to set a string", async () => {
- const formData = new FormData();
- formData.set("foo", "bar");
- expect(formData.get("foo")).toBe("bar");
- expect(formData.getAll("foo")[0]).toBe("bar");
- });
-
- const multipartFormDataFixturesRawBody = [
- {
- name: "simple",
- body: '--foo\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbar\r\n--foo--\r\n',
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- expected: {
- foo: "bar",
- },
- },
- {
- name: "simple with trailing CRLF",
- body: '--foo\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbar\r\n--foo--\r\n\r\n',
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- expected: {
- foo: "bar",
- },
- },
- {
- name: "simple with trailing CRLF and extra CRLF",
- body: '--foo\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbar\r\n--foo--\r\n\r\n\r\n',
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- expected: {
- foo: "bar",
- },
- },
- {
- name: "advanced",
- body: '--foo\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbar\r\n--foo\r\nContent-Disposition: form-data; name="baz"\r\n\r\nqux\r\n--foo--\r\n',
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- expected: {
- foo: "bar",
- baz: "qux",
- },
- },
- {
- name: "advanced with multiple values",
- body: '--foo\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbar\r\n--foo\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbaz\r\n--foo--\r\n',
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- expected: {
- foo: ["bar", "baz"],
- },
- },
- {
- name: "advanced with multiple values and trailing CRLF",
- body: '--foo\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbar\r\n--foo\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbaz\r\n--foo--\r\n\r\n',
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- expected: {
- foo: ["bar", "baz"],
- },
- },
- {
- name: "extremely advanced",
- body: '--foo\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbar\r\n--foo\r\nContent-Disposition: form-data; name="baz"\r\n\r\nqux\r\n--foo\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbaz\r\n--foo--\r\n',
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- expected: {
- foo: ["bar", "baz"],
- baz: "qux",
- },
- },
- {
- name: "with name and filename",
- body: '--foo\r\nContent-Disposition: form-data; name="foo"; filename="bar"\r\n\r\nbaz\r\n--foo--\r\n',
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- expected: {
- foo: new Blob(["baz"]),
- },
- },
- {
- name: "with name and filename and trailing CRLF",
- body: '--foo\r\nContent-Disposition: form-data; name="foo"; filename="bar"\r\n\r\nbaz\r\n--foo--\r\n\r\n',
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- expected: {
- foo: new Blob(["baz"]),
- },
- },
- ];
-
- for (const { name, body, headers, expected: expected_ } of multipartFormDataFixturesRawBody) {
- const Class = [Response, Request] as const;
- for (const C of Class) {
- it(`should parse multipart/form-data (${name}) with ${C.name}`, async () => {
- const response = C === Response ? new Response(body, { headers }) : new Request({ headers, body });
- const formData = await response.formData();
- expect(formData instanceof FormData).toBe(true);
- const entry = {};
- const expected = Object.assign({}, expected_);
-
- for (const key of formData.keys()) {
- const values = formData.getAll(key);
- if (values.length > 1) {
- entry[key] = values;
- } else {
- entry[key] = values[0];
- if (entry[key] instanceof Blob) {
- expect(expected[key] instanceof Blob).toBe(true);
-
- entry[key] = await entry[key].text();
- expected[key] = await expected[key].text();
- } else {
- expect(typeof entry[key]).toBe(typeof expected[key]);
- expect(expected[key] instanceof Blob).toBe(false);
- }
- }
- }
-
- expect(entry).toEqual(expected);
- });
-
- it(`should roundtrip multipart/form-data (${name}) with ${C.name}`, async () => {
- const response = C === Response ? new Response(body, { headers }) : new Request({ headers, body });
- const formData = await response.formData();
- expect(formData instanceof FormData).toBe(true);
-
- const request = await new Response(formData).formData();
- expect(request instanceof FormData).toBe(true);
-
- const aKeys = Array.from(formData.keys());
- const bKeys = Array.from(request.keys());
- expect(aKeys).toEqual(bKeys);
-
- for (const key of aKeys) {
- const aValues = formData.getAll(key);
- const bValues = request.getAll(key);
- for (let i = 0; i < aValues.length; i++) {
- const a = aValues[i];
- const b = bValues[i];
- if (a instanceof Blob) {
- expect(b instanceof Blob).toBe(true);
- expect(await a.text()).toBe(await b.text());
- } else {
- expect(a).toBe(b);
- }
- }
- }
-
- // Test that it also works with Blob.
- const c = await new Blob([body], { type: headers["Content-Type"] }).formData();
- expect(c instanceof FormData).toBe(true);
- const cKeys = Array.from(c.keys());
- expect(cKeys).toEqual(bKeys);
- for (const key of cKeys) {
- const cValues = c.getAll(key);
- const bValues = request.getAll(key);
- for (let i = 0; i < cValues.length; i++) {
- const c = cValues[i];
- const b = bValues[i];
- if (c instanceof Blob) {
- expect(b instanceof Blob).toBe(true);
- expect(await c.text()).toBe(await b.text());
- } else {
- expect(c).toBe(b);
- }
- }
- }
- });
- }
- }
-
- it("should throw on missing final boundary", async () => {
- const response = new Response('-foo\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbar\r\n', {
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- });
- try {
- await response.formData();
- throw "should have thrown";
- } catch (e) {
- expect(typeof e.message).toBe("string");
- }
- });
-
- it("should throw on bad boundary", async () => {
- const response = new Response('foo\r\nContent-Disposition: form-data; name="foo"\r\n\r\nbar\r\n', {
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- });
- try {
- await response.formData();
- throw "should have thrown";
- } catch (e) {
- expect(typeof e.message).toBe("string");
- }
- });
-
- it("should throw on bad header", async () => {
- const response = new Response('foo\r\nContent-Disposition: form-data; name"foo"\r\n\r\nbar\r\n', {
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- });
- try {
- await response.formData();
- throw "should have thrown";
- } catch (e) {
- expect(typeof e.message).toBe("string");
- }
- });
-
- it("file upload on HTTP server (receive)", async () => {
- const server = Bun.serve({
- port: 0,
- development: false,
- async fetch(req) {
- const formData = await req.formData();
- return new Response(formData.get("foo"));
- },
- });
-
- const reqBody = new Request(`http://${server.hostname}:${server.port}`, {
- body: '--foo\r\nContent-Disposition: form-data; name="foo"; filename="bar"\r\n\r\nbaz\r\n--foo--\r\n\r\n',
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- method: "POST",
- });
-
- const res = await fetch(reqBody);
- const body = await res.text();
- expect(body).toBe("baz");
- server.stop(true);
- });
-
- it("file send on HTTP server (receive)", async () => {
- const server = Bun.serve({
- port: 0,
- development: false,
- async fetch(req) {
- const formData = await req.formData();
- return new Response(formData);
- },
- });
-
- const reqBody = new Request(`http://${server.hostname}:${server.port}`, {
- body: '--foo\r\nContent-Disposition: form-data; name="foo"; filename="bar"\r\n\r\nbaz\r\n--foo--\r\n\r\n',
- headers: {
- "Content-Type": "multipart/form-data; boundary=foo",
- },
- method: "POST",
- });
-
- const res = await fetch(reqBody);
- const body = await res.formData();
- expect(await (body.get("foo") as Blob).text()).toBe("baz");
- server.stop(true);
- });
-
- describe("Bun.file support", () => {
- describe("roundtrip", () => {
- const path = import.meta.dir + "/form-data-fixture.txt";
- for (const C of [Request, Response]) {
- it(`with ${C.name}`, async () => {
- await Bun.write(path, "foo!");
- const formData = new FormData();
- formData.append("foo", Bun.file(path));
- const response = C === Response ? new Response(formData) : new Request({ body: formData });
- expect(response.headers.get("content-type")?.startsWith("multipart/form-data;")).toBe(true);
-
- const formData2 = await response.formData();
- expect(formData2 instanceof FormData).toBe(true);
- expect(formData2.get("foo") instanceof Blob).toBe(true);
- expect(await (formData2.get("foo") as Blob).text()).toBe("foo!");
- });
- }
- });
-
- it("doesnt crash when file is missing", async () => {
- const formData = new FormData();
- formData.append("foo", Bun.file("missing"));
- expect(() => new Response(formData)).toThrow();
- });
- });
-
- it("Bun.inspect", () => {
- const formData = new FormData();
- formData.append("foo", "bar");
- formData.append("foo", new Blob(["bar"]));
- formData.append("bar", "baz");
- formData.append("boop", Bun.file("missing"));
- expect(Bun.inspect(formData).length > 0).toBe(true);
- });
-
- describe("URLEncoded", () => {
- test("should parse URL encoded", async () => {
- const response = new Response("foo=bar&baz=qux", {
- headers: {
- "Content-Type": "application/x-www-form-urlencoded",
- },
- });
- const formData = await response.formData();
- expect(formData instanceof FormData).toBe(true);
- expect(formData.get("foo")).toBe("bar");
- expect(formData.get("baz")).toBe("qux");
- });
-
- test("should parse URLSearchParams", async () => {
- const searchParams = new URLSearchParams("foo=bar&baz=qux");
- const response = new Response(searchParams);
- expect(response.headers.get("Content-Type")).toBe("application/x-www-form-urlencoded;charset=UTF-8");
-
- expect(searchParams instanceof URLSearchParams).toBe(true);
- expect(searchParams.get("foo")).toBe("bar");
-
- const formData = await response.formData();
- expect(formData instanceof FormData).toBe(true);
- expect(formData.get("foo")).toBe("bar");
- expect(formData.get("baz")).toBe("qux");
- });
-
- test("should parse URL encoded with charset", async () => {
- const response = new Response("foo=bar&baz=qux", {
- headers: {
- "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
- },
- });
- const formData = await response.formData();
- expect(formData instanceof FormData).toBe(true);
- expect(formData.get("foo")).toBe("bar");
- expect(formData.get("baz")).toBe("qux");
- });
-
- test("should parse URL encoded with charset and space", async () => {
- const response = new Response("foo=bar&baz=qux+quux", {
- headers: {
- "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
- },
- });
- const formData = await response.formData();
- expect(formData instanceof FormData).toBe(true);
- expect(formData.get("foo")).toBe("bar");
- expect(formData.get("baz")).toBe("qux quux");
- });
-
- test("should parse URL encoded with charset and plus", async () => {
- const response = new Response("foo=bar&baz=qux+quux", {
- headers: {
- "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
- },
- });
- const formData = await response.formData();
- expect(formData instanceof FormData).toBe(true);
- expect(formData.get("foo")).toBe("bar");
- expect(formData.get("baz")).toBe("qux quux");
- });
-
- it("should handle multiple values", async () => {
- const response = new Response("foo=bar&foo=baz", {
- headers: {
- "Content-Type": "application/x-www-form-urlencoded",
- },
- });
- const formData = await response.formData();
- expect(formData instanceof FormData).toBe(true);
- expect(formData.getAll("foo")).toEqual(["bar", "baz"]);
- });
- });
-});