Testing#

Buntok provides app.request() for testing routes without binding a real port. It dispatches requests directly through the router, making tests fast and deterministic.

app.request()#

Dispatch a request without starting a server. Returns a standard Response object.

typescript
import { Buntok } from "@buntok/core";

const app = new Buntok();

app.get("/users", async (ctx) => {
  return ctx.json([{ id: 1, name: "Alice" }]);
});

app.post("/users", async (ctx) => {
  const body = await ctx.body();
  return ctx.json({ created: true, ...body }, 201);
});

// GET request
const res = await app.request("/users");
const data = await res.json();
// data === [{ id: 1, name: "Alice" }]

// POST request with body
const res2 = await app.request("/users", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "Bob" }),
});
console.log(res2.status); // 201
ParameterTypeDescription
inputstring | URL | RequestThe request path or URL
init?RequestInitMethod, headers, body, etc.

Unit Testing Example#

typescript
import { describe, it, expect } from "bun:test";
import { Buntok } from "@buntok/core";
import { NotFoundError } from "@buntok/core";

function createTestApp() {
  const app = new Buntok();

  app.get("/health", (ctx) => {
    return ctx.json({ status: "ok" });
  });

  app.get("/users/:id", async (ctx) => {
    const id = ctx.params.id;
    if (id === "999") {
      throw new NotFoundError("User not found");
    }
    return ctx.json({ id, name: "Alice" });
  });

  return app;
}

describe("API Routes", () => {
  it("GET /health returns ok", async () => {
    const app = createTestApp();
    const res = await app.request("/health");
    const body = await res.json();

    expect(res.status).toBe(200);
    expect(body.status).toBe("ok");
  });

  it("GET /users/:id returns user", async () => {
    const app = createTestApp();
    const res = await app.request("/users/1");
    const body = await res.json();

    expect(res.status).toBe(200);
    expect(body.name).toBe("Alice");
  });

  it("GET /users/:id returns 404 for unknown", async () => {
    const app = createTestApp();
    const res = await app.request("/users/999");

    expect(res.status).toBe(404);
  });
});
Info
app.request() processes requests through the full middleware stack, so you can test auth, validation, and error handling just like real HTTP requests.

Testing with Middleware#

typescript
const app = new Buntok();

app.use(requireAuth(process.env.JWT_SECRET!));

app.get("/protected", (ctx) => {
  return ctx.json({ user: ctx.user });
});

// Without token → 401
const res1 = await app.request("/protected");
expect(res1.status).toBe(401);

// With valid token → 200
const token = await signToken({ id: 1, role: "admin" });
const res2 = await app.request("/protected", {
  headers: { Authorization: `Bearer ${token}` },
});
expect(res2.status).toBe(200);