Files
bun.sh/test/js/third_party/body-parser/express-body-parser-test.test.ts

147 lines
4.2 KiB
TypeScript

// @ts-nocheck
// can't use @types/express or @types/body-parser because they
// depend on @types/node which conflicts with bun-types
import { json } from "body-parser";
import { expect, test } from "bun:test";
import express, { Application, Request, Response } from "express";
import net from "net";
// Express uses iconv-lite
test("iconv works", () => {
var iconv = require("iconv-lite");
// Convert from an encoded buffer to a js string.
var str = iconv.decode(Buffer.from([0x68, 0x65, 0x6c, 0x6c, 0x6f]), "win1251");
// Convert from a js string to an encoded buffer.
var buf = iconv.encode("Sample input string", "win1251");
expect(str).toBe("hello");
expect(iconv.decode(buf, "win1251")).toBe("Sample input string");
// Check if encoding is supported
expect(iconv.encodingExists("us-ascii")).toBe(true);
});
// https://github.com/oven-sh/bun/issues/1913
test("httpServer", async () => {
// Constants
const PORT = 8412;
// App handlers
const app: Application = express();
const httpServer = require("http").createServer(app);
app.on("error", err => {
console.error(err);
});
app.use(json());
let closeCount = 0;
let responseCloseCount = 0;
var reached = false;
// This throws a TypeError since it uses body-parser.json
app.post("/ping", (request: Request, response: Response) => {
request.on("close", () => {
if (closeCount++ === 1) {
throw new Error("request Close called multiple times");
}
});
response.on("close", () => {
if (responseCloseCount++ === 1) {
throw new Error("response Close called multiple times");
}
});
expect(request.body).toEqual({ hello: "world" });
expect(request.query).toStrictEqual({
hello: "123",
hi: "",
});
reached = true;
response.status(200).send("POST - pong");
httpServer.close();
});
httpServer.listen(PORT);
const resp = await fetch(`http://localhost:${PORT}/ping?hello=123&hi`, {
method: "POST",
body: JSON.stringify({ hello: "world" }),
headers: {
"Content-Type": "application/json",
},
});
expect(await resp.text()).toBe("POST - pong");
expect(resp.status).toBe(200);
expect(reached).toBe(true);
});
test("GET with body-parser", async () => {
const app = express();
app.use(express.json());
app.get("/", (req, res) => {
expect(req.body).toEqual({ "name": "John Doe", "email": "john.doe@example.com" });
req.res.send("Hello World!");
});
function doGet(hostname, port) {
const { promise, resolve, reject } = Promise.withResolvers();
const socket = net.createConnection(port, hostname);
const payload = Buffer.from(JSON.stringify({ "name": "John Doe", "email": "john.doe@example.com" }));
socket.write(`GET / HTTP/1.1\r\n`);
socket.write(`Host: ${hostname}\r\n`);
socket.write(`Content-Length: ${payload.byteLength}\r\n`);
socket.write(`Content-Type: application/json\r\n`);
socket.write(`Connection: close\r\n`);
socket.write(`\r\n`);
socket.write(payload);
const body = [];
socket.on("data", data => {
body.push(data);
});
socket.on("end", () => {
const response = Buffer.concat(body).toString();
const parts = response.split("\r\n\r\n");
const headers = parts[0]
?.trim()
?.split("\r\n")
?.reduce((acc, line, index) => {
if (index === 0) {
acc["status"] = Number(line.split(" ")[1]);
} else {
const [key, value] = line.split(": ");
acc[key?.toLowerCase()] = value;
}
return acc;
}, {});
resolve({ headers, body: parts[1] });
socket.end();
});
socket.on("error", reject);
return promise;
}
const { promise: listening, resolve, reject } = Promise.withResolvers();
const server = app.listen(0, async (...args) => {
const [err, hostname, port] = args;
if (err) {
reject(err);
return;
}
resolve({ hostname, port });
});
try {
const { hostname, port } = await listening;
const { headers, body } = await doGet(hostname, port);
expect(headers["status"]).toBe(200);
expect(headers["content-length"]).toBe("12");
expect(body).toBe("Hello World!");
} finally {
server.close();
}
});