local-ai-platform/src/server.test.ts
Brandon Wolfgang 66dc2b2065 feat: implement Phase 1 API foundation and testing
- Configure the Node.js test runner with tsx
- Add endpoint tests for health, readiness, and echo request validation
- Cover input length boundaries, invalid message types, unknown routes, and unexpected errors
- Extract the Fastify app factory to support isolated testing without starting the server
- Add centralized error handling and consistent 404 responses
- Guard server startup to prevent listeners from opening when the module is imported
2026-10-21 21:32:40 -05:00

140 lines
3.2 KiB
TypeScript

import assert from "node:assert";
import { after, describe, it } from "node:test";
import { buildApp } from "./server.js";
import { setServers } from "node:dns";
describe("API endpoints", () => {
const app = buildApp();
after(async () => {
await app.close();
});
it("GET /health returns 200 and status ok", async () => {
const response = await app.inject({
method: "GET",
url: "/health",
});
assert.equal(response.statusCode, 200);
assert.deepEqual(response.json(), {
status: "ok",
});
});
it("GET /ready returns 200 and dependency status", async () => {
const response = await app.inject({
method: "GET",
url: "/ready",
});
assert.equal(response.statusCode, 200);
assert.deepEqual(response.json(), {
status: "ready",
dependencies: {
ollama: "not-integrated",
},
});
});
it("POST /echo returns the validated message", async () => {
const response = await app.inject({
method: "POST",
url: "/echo",
payload: {
message: "Hello, world!",
},
});
assert.equal(response.statusCode, 200);
assert.deepEqual(response.json(), {
message: "Hello, world!",
});
});
it("POST /echo accepts a 500-character message", async () => {
const message = "a".repeat(500);
const response = await app.inject({
method: "POST",
url: "/echo",
payload: { message },
});
assert.equal(response.statusCode, 200);
assert.deepEqual(response.json(), { message });
});
it("POST /echo rejects an empty message", async () => {
const response = await app.inject({
method: "POST",
url: "/echo",
payload: {
message: "",
},
});
assert.equal(response.statusCode, 400);
assert.deepEqual(response.json(), {
error: "Invalid request body",
});
});
it("POST /echo rejects a message longer than 500 characters", async () => {
const message = "a".repeat(501);
const response = await app.inject({
method: "POST",
url: "/echo",
payload: { message },
});
assert.equal(response.statusCode, 400);
assert.deepEqual(response.json(), {
error: "Invalid request body",
});
});
it("POST /echo rejects a non-string message", async () => {
const message = "a".repeat(501);
const response = await app.inject({
method: "POST",
url: "/echo",
payload: {
message: 123,
},
});
assert.equal(response.statusCode, 400);
assert.deepEqual(response.json(), {
error: "Invalid request body",
});
});
it("returns 404 for an unknown endpoint", async () => {
const response = await app.inject({
method: "GET",
url: "/does-not-exist",
});
assert.equal(response.statusCode, 404);
assert.deepEqual(response.json(), {
error: "Not Found",
});
});
it("returns a generic 500 response for unexpected error", async () => {
const response = await app.inject({
method: "GET",
url: "/test-error",
});
assert.equal(response.statusCode, 500);
assert.deepEqual(response.json(), {
error: "Internal Server Error",
});
assert.equal(response.body.includes("Sensitive internal detail"), false);
});
});