diff --git a/test/unit/node/proxy.test.ts b/test/unit/node/proxy.test.ts index febc8a6d..b40819cc 100644 --- a/test/unit/node/proxy.test.ts +++ b/test/unit/node/proxy.test.ts @@ -1,5 +1,9 @@ import bodyParser from "body-parser" import * as express from "express" +import * as nodeFetch from "node-fetch" +import * as http from "http" +import { HttpCode } from "../../../src/common/http" +import { proxy } from "../../../src/node/proxy" import * as httpserver from "../../utils/httpserver" import * as integration from "../../utils/integration" @@ -102,4 +106,107 @@ describe("proxy", () => { expect(resp.status).toBe(200) expect(await resp.json()).toBe("coder is the best") }) + + it("should handle bad requests", async () => { + e.use(bodyParser.json({ strict: false })) + e.post("/wsup", (req, res) => { + res.json(req.body) + }) + codeServer = await integration.setup(["--auth=none"], "") + const resp = await codeServer.fetch(proxyPath, { + method: "post", + body: "coder is the best", + headers: { + "Content-Type": "application/json", + }, + }) + expect(resp.status).toBe(400) + expect(resp.statusText).toMatch("Bad Request") + }) + + it("should handle invalid routes", async () => { + e.post("/wsup", (req, res) => { + res.json(req.body) + }) + codeServer = await integration.setup(["--auth=none"], "") + const resp = await codeServer.fetch(`${proxyPath}/hello`) + expect(resp.status).toBe(404) + expect(resp.statusText).toMatch("Not Found") + }) + + it("should handle errors", async () => { + e.use(bodyParser.json({ strict: false })) + e.post("/wsup", (req, res) => { + throw new Error("BROKEN") + }) + codeServer = await integration.setup(["--auth=none"], "") + const resp = await codeServer.fetch(proxyPath, { + method: "post", + body: JSON.stringify("coder is the best"), + headers: { + "Content-Type": "application/json", + }, + }) + expect(resp.status).toBe(500) + expect(resp.statusText).toMatch("Internal Server Error") + }) +}) + +// NOTE@jsjoeio +// Both this test suite and the one above it are very similar +// The main difference is this one uses http and node-fetch +// and specifically tests the proxy in isolation vs. using +// the httpserver abstraction we've built. +// +// Leaving this as a separate test suite for now because +// we may consider refactoring the httpserver abstraction +// in the future. +// +// If you're writing a test specifically for code in +// src/node/proxy.ts, you should probably add it to +// this test suite. +describe("proxy (standalone)", () => { + const PORT = 9003 + const PROXY_PORT = 8003 + const URL = `http://localhost:${PORT}` + const PROXY_URL = `http://localhost:${PROXY_PORT}` + let testServer: http.Server + let proxyTarget: http.Server + + beforeEach(async () => { + // Define server and a proxy server + testServer = http.createServer((req, res) => { + proxy.web(req, res, { + target: PROXY_URL, + }) + }) + + proxyTarget = http.createServer((req, res) => { + res.writeHead(200, { "Content-Type": "text/plain" }) + res.end() + }) + + // Start both servers + await proxyTarget.listen(PROXY_PORT) + await testServer.listen(PORT) + }) + + afterEach(async () => { + await testServer.close() + await proxyTarget.close() + }) + + it("should return a 500 when proxy target errors ", async () => { + // Close the proxy target so that proxy errors + await proxyTarget.close() + const errorResp = await nodeFetch.default(`${URL}/error`) + expect(errorResp.status).toBe(HttpCode.ServerError) + expect(errorResp.statusText).toBe("Internal Server Error") + }) + + it("should proxy correctly", async () => { + const resp = await nodeFetch.default(`${URL}/route`) + expect(resp.status).toBe(200) + expect(resp.statusText).toBe("OK") + }) })