testing and fixes to middleware matching
This commit is contained in:
294
router.test.ts
Normal file
294
router.test.ts
Normal file
@@ -0,0 +1,294 @@
|
||||
// deno-lint-ignore-file require-await
|
||||
import { assertEquals } from "@std/assert";
|
||||
import { beforeEach, describe, it } from "@std/testing/bdd";
|
||||
import Router from "./router.ts";
|
||||
|
||||
describe("Router", () => {
|
||||
let router: Router;
|
||||
|
||||
beforeEach(() => {
|
||||
router = new Router();
|
||||
});
|
||||
|
||||
describe("Basic Routing", () => {
|
||||
it("should handle basic GET request", async () => {
|
||||
router.route("/test")
|
||||
.get(async () => new Response("test response"));
|
||||
|
||||
const req = new Request("http://localhost/test", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
const res = await router.handle(req);
|
||||
assertEquals(res.status, 200);
|
||||
assertEquals(await res.text(), "test response");
|
||||
});
|
||||
|
||||
it("should return 404 for non-existent route", async () => {
|
||||
const req = new Request("http://localhost/nonexistent", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
const res = await router.handle(req);
|
||||
assertEquals(res.status, 404);
|
||||
});
|
||||
|
||||
it("should return 405 for unsupported method", async () => {
|
||||
router.route("/test")
|
||||
.get(async () => new Response("test"));
|
||||
|
||||
const req = new Request("http://localhost/test", {
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
const res = await router.handle(req);
|
||||
assertEquals(res.status, 405);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Route Parameters", () => {
|
||||
it("should handle route parameters", async () => {
|
||||
router.route("/users/:id")
|
||||
.get(async (ctx) => new Response(ctx.params.id));
|
||||
|
||||
const req = new Request("http://localhost/users/123", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
const res = await router.handle(req);
|
||||
assertEquals(await res.text(), "123");
|
||||
});
|
||||
|
||||
it("should handle multiple route parameters", async () => {
|
||||
router.route("/users/:userId/posts/:postId")
|
||||
.get(async (ctx) => {
|
||||
return new Response(JSON.stringify(ctx.params));
|
||||
});
|
||||
|
||||
const req = new Request("http://localhost/users/123/posts/456", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
const res = await router.handle(req);
|
||||
const params = JSON.parse(await res.text());
|
||||
assertEquals(params.userId, "123");
|
||||
assertEquals(params.postId, "456");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Middleware", () => {
|
||||
it("should execute global middleware", async () => {
|
||||
let middlewareExecuted = false;
|
||||
|
||||
router.use(async (_ctx, next) => {
|
||||
middlewareExecuted = true;
|
||||
return await next();
|
||||
});
|
||||
|
||||
router.route("/test")
|
||||
.get(async () => new Response("test"));
|
||||
|
||||
const req = new Request("http://localhost/test", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
await router.handle(req);
|
||||
assertEquals(middlewareExecuted, true);
|
||||
});
|
||||
|
||||
it("should execute path-specific middleware", async () => {
|
||||
let middlewareExecuted = false;
|
||||
|
||||
router.use("/test", async (_ctx, next) => {
|
||||
middlewareExecuted = true;
|
||||
console.log('middlware happened')
|
||||
return await next();
|
||||
});
|
||||
|
||||
router.route("/test")
|
||||
.get(async () => new Response("test"));
|
||||
|
||||
const req = new Request("http://localhost/test", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
await router.handle(req);
|
||||
assertEquals(middlewareExecuted, true);
|
||||
});
|
||||
|
||||
it("should handle middleware parameters", async () => {
|
||||
const capturedParams: Record<string, string | undefined> = {};
|
||||
|
||||
router.use("/:version/.*", async (ctx, next) => {
|
||||
capturedParams.version = ctx.params.version;
|
||||
return await next();
|
||||
});
|
||||
|
||||
router.route("/:version/test")
|
||||
.get(async () => new Response("test"));
|
||||
|
||||
const req = new Request("http://localhost/v1/test", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
await router.handle(req);
|
||||
assertEquals(capturedParams.version, "v1");
|
||||
});
|
||||
|
||||
it("should execute middleware in correct order", async () => {
|
||||
const order: number[] = [];
|
||||
|
||||
router.use(async (_ctx, next) => {
|
||||
order.push(1);
|
||||
return await next();
|
||||
});
|
||||
|
||||
router.use("/test", async (_ctx, next) => {
|
||||
order.push(2);
|
||||
return await next();
|
||||
});
|
||||
|
||||
router.route("/test")
|
||||
.get(async () => {
|
||||
order.push(3);
|
||||
return new Response("test");
|
||||
});
|
||||
|
||||
const req = new Request("http://localhost/test", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
await router.handle(req);
|
||||
assertEquals(order, [1, 2, 3]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Nested Routers", () => {
|
||||
it("should handle nested routes", async () => {
|
||||
const apiRouter = new Router();
|
||||
apiRouter.route("/test")
|
||||
.get(async () => new Response("api test"));
|
||||
|
||||
router.use("/api", apiRouter);
|
||||
|
||||
const req = new Request("http://localhost/api/test", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
const res = await router.handle(req);
|
||||
assertEquals(await res.text(), "api test");
|
||||
});
|
||||
|
||||
it("should handle nested routes with parameters", async () => {
|
||||
const apiRouter = new Router();
|
||||
apiRouter.route("/users/:id")
|
||||
.get(async (ctx) => new Response(ctx.params.id));
|
||||
|
||||
router.use("/api/:version", apiRouter);
|
||||
|
||||
const req = new Request("http://localhost/api/v1/users/123", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
const res = await router.handle(req);
|
||||
assertEquals(await res.text(), "123");
|
||||
});
|
||||
|
||||
it("should handle nested middleware", async () => {
|
||||
const apiRouter = new Router();
|
||||
let middlewareExecuted = false;
|
||||
|
||||
apiRouter.use(async (_ctx, next) => {
|
||||
middlewareExecuted = true;
|
||||
return await next();
|
||||
});
|
||||
|
||||
apiRouter.route("/test")
|
||||
.get(async () => new Response("test"));
|
||||
|
||||
router.use("/api", apiRouter);
|
||||
|
||||
const req = new Request("http://localhost/api/test", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
await router.handle(req);
|
||||
assertEquals(middlewareExecuted, true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Context State", () => {
|
||||
it("should maintain state across middleware chain", async () => {
|
||||
router.use(async (ctx, next) => {
|
||||
ctx.state.test = "value";
|
||||
return await next();
|
||||
});
|
||||
|
||||
router.route("/test")
|
||||
.get(async (ctx) => {
|
||||
return new Response(ctx.state.test as string);
|
||||
});
|
||||
|
||||
const req = new Request("http://localhost/test", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
const res = await router.handle(req);
|
||||
assertEquals(await res.text(), "value");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Error Handling", () => {
|
||||
it("should handle errors in handlers", async () => {
|
||||
router.route("/error")
|
||||
.get(async () => {
|
||||
throw new Error("Test error");
|
||||
});
|
||||
|
||||
const req = new Request("http://localhost/error", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
const res = await router.handle(req);
|
||||
assertEquals(res.status, 500);
|
||||
assertEquals(await res.text(), "Internal Server Error");
|
||||
});
|
||||
|
||||
it("should handle errors in middleware", async () => {
|
||||
router.use(async () => {
|
||||
throw new Error("Middleware error");
|
||||
});
|
||||
|
||||
router.route("/test")
|
||||
.get(async () => new Response("test"));
|
||||
|
||||
const req = new Request("http://localhost/test", {
|
||||
method: "GET",
|
||||
});
|
||||
|
||||
const res = await router.handle(req);
|
||||
assertEquals(res.status, 500);
|
||||
});
|
||||
});
|
||||
|
||||
describe("HTTP Methods", () => {
|
||||
const methods = ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"];
|
||||
|
||||
methods.forEach(method => {
|
||||
it(`should handle ${method} requests`, async () => {
|
||||
const route = router.route("/test");
|
||||
route[method.toLowerCase() as keyof typeof route](
|
||||
async () => new Response(method)
|
||||
);
|
||||
|
||||
const req = new Request("http://localhost/test", {
|
||||
method: method,
|
||||
});
|
||||
|
||||
const res = await router.handle(req);
|
||||
assertEquals(res.status, 200);
|
||||
assertEquals(await res.text(), method);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user