alepha
Version:
Easy-to-use modern TypeScript framework for building many kind of applications.
80 lines (65 loc) • 2.4 kB
text/typescript
import { Alepha, z } from "alepha";
import { describe, it } from "vitest";
import { $action, ServerProvider } from "../index.ts";
class TestApp {
badResponse = $action({
schema: {
response: z.object({
name: z.text(),
age: z.integer(),
}),
},
handler: () =>
({
// missing required `age` → response codec.encode will throw
name: "John",
secretToken: "leaked-token-xyz",
}) as any,
});
}
describe("ServerRouterProvider - response serialization error", () => {
describe("in production mode", () => {
it("should not leak validation details or response payload in 500 response", async ({
expect,
}) => {
const alepha = Alepha.create({
env: {
NODE_ENV: "production",
SERVER_PORT: 0,
APP_SECRET: "test-secret",
},
}).with(TestApp);
await alepha.start();
const hostname = alepha.inject(ServerProvider).hostname;
const response = await fetch(`${hostname}/api/badResponse`);
const json = await response.json();
expect(response.status).toBe(500);
expect(json.error).toBe("InternalServerError");
expect(json.message).toBe("Internal Server Error");
// payload from the handler must not leak through the error
const dump = JSON.stringify(json);
expect(dump).not.toContain("leaked-token-xyz");
expect(dump).not.toContain("secretToken");
await alepha.stop();
});
});
describe("in development mode", () => {
it("should include explicit validation details in 500 response", async ({
expect,
}) => {
const alepha = Alepha.create().with(TestApp);
await alepha.start();
const hostname = alepha.inject(ServerProvider).hostname;
const response = await fetch(`${hostname}/api/badResponse`);
const json = await response.json();
expect(response.status).toBe(500);
expect(json.error).toBe("InternalServerError");
// dev mode must surface enough context to debug the schema mismatch
expect(json.message).not.toBe("Internal Server Error");
expect(json.message.toLowerCase()).toMatch(/age|required|expected/);
// even in dev, the raw handler payload (potential secrets) must not be echoed
expect(json.message).not.toContain("leaked-token-xyz");
await alepha.stop();
});
});
});