UNPKG

@halsp/http

Version:

支持 Halsp HTTP 请求

287 lines (270 loc) 5.67 kB
import { Context, Middleware, Startup } from "@halsp/core"; import { getReasonPhrase } from "../../src"; const normalMethod = [ { method: "ok", code: 200, }, { method: "accepted", code: 202, }, { method: "partialContent", code: 206, }, { method: "badRequest", code: 400, error: true, }, { method: "unauthorized", code: 401, error: true, }, { method: "forbidden", code: 403, error: true, }, { method: "notFound", code: 404, error: true, }, { method: "methodNotAllowed", code: 405, error: true, }, { method: "notAcceptable", code: 406, error: true, }, { method: "requestTimeout", code: 408, error: true, }, { method: "conflict", code: 409, error: true, }, { method: "gone", code: 410, error: true, }, { method: "preconditionFailed", code: 412, error: true, }, { method: "requestTooLong", code: 413, error: true, }, { method: "unsupportedMediaType", code: 415, error: true, }, { method: "imATeapot", code: 418, error: true, }, { method: "misdirected", code: 421, error: true, }, { method: "unprocessableEntity", code: 422, error: true, }, { method: "unprocessableEntity", code: 422, error: true, }, { method: "internalServerError", code: 500, error: true, }, { method: "notImplemented", code: 501, error: true, }, { method: "badGateway", code: 502, error: true, }, { method: "serviceUnavailable", code: 503, error: true, }, { method: "gatewayTimeout", code: 504, error: true, }, { method: "httpVersionNotSupported", code: 505, error: true, }, ]; async function testBody(body?: unknown) { for (let i = 0; i < normalMethod.length; i++) { const methodItem = normalMethod[i]; const res = await new Startup() .useHttp() .use(async (ctx) => { ctx.res[methodItem.method](body); }) ["invoke"](); expect(res.status).toBe(methodItem.code); if (methodItem.error && methodItem.method.endsWith("Msg")) { expect(res.body).toEqual({ message: body ?? getReasonPhrase(methodItem.code), status: methodItem.code, }); } else { expect(res.body).toBe(body); } } } test(`test handler func without body`, async () => { await testBody(); }); test(`test handler func with body`, async () => { await testBody("body"); }); test(`error message`, async () => { { const res = await new Startup() .useHttp() .use(async (ctx) => { ctx.res.badRequestMsg("err"); }) ["invoke"](); expect(res.status).toBe(400); expect(res.body).toEqual({ message: "err", status: 400, }); } }); test(`http result created`, async () => { { const res = await new Startup() .useHttp() .use(async (ctx) => { ctx.res.created("loca"); }) ["invoke"](); expect(res.status).toBe(201); expect(res.getHeader("location")).toBe("loca"); } { const res = await new Startup() .useHttp() .use(async (ctx) => { ctx.res.created("loca", "body"); }) ["invoke"](); expect(res.status).toBe(201); expect(res.body).toBe("body"); expect(res.getHeader("location")).toBe("loca"); } }); test(`http result noContent`, async () => { const res = await new Startup() .useHttp() .use(async (ctx) => { ctx.res.noContent(); }) ["invoke"](); expect(res.status).toBe(204); expect(res.body).toBe(undefined); }); const msgMethods = normalMethod .filter((method) => method.error == true) .map((m) => { const obj = Object.assign({}, m); obj.method = obj.method + "Msg"; return obj; }); for (let i = 0; i < msgMethods.length; i++) { const methodItem = msgMethods[i]; const errorMsgTest = `error message ${methodItem.method}`; class Md extends Middleware { async invoke(): Promise<void> { new Startup().useHttp(); (this as any)[methodItem.method]( this.existMsg ? { message: errorMsgTest, } : undefined, ); } constructor(private existMsg: boolean) { super(); (this as any).init(new Context(), 0); } } { const md = new Md(true); md.invoke(); test(errorMsgTest, async () => { const result = md.ctx.res; expect(result.status).toBe(methodItem.code); expect((result.body as any).message).toBe(errorMsgTest); }); } { const md = new Md(false); md.invoke(); test(errorMsgTest, async () => { const result = md.ctx.res; expect(result.status).toBe(methodItem.code); expect((result.body as any).message).toBe( getReasonPhrase(methodItem.code), ); }); } } const redirectCodes = [301, 302, 303, 307, 308, undefined]; const location = "/test"; for (let i = 0; i < redirectCodes.length; i++) { const code = redirectCodes[i] as 301 | 302 | 303 | 307 | 308 | undefined; test(`${code} redirect`, async () => { const md = new RedirectMd(code, location); await md.invoke(); expect(md.ctx.res.status).toBe(code || 302); expect(md.ctx.res.getHeader("location")).toBe(location); }); } class RedirectMd extends Middleware { constructor( readonly code: number | undefined, readonly location: string, ) { super(); (this as any).init(new Context(), 0); } async invoke(): Promise<void> { this.redirect(this.location, this.code); } }