refactor(api): unify /api contract across frontend, nginx, and backend
Some checks failed
CI / build-and-test (pull_request) Has been cancelled

This commit is contained in:
Anton
2026-04-08 11:59:46 +03:00
parent 9f63b190f1
commit 8eaf006906
17 changed files with 103 additions and 81 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "calendar-run-backend",
"version": "1.1.0",
"version": "1.2.0",
"private": true,
"scripts": {
"build": "tsc",

View File

@@ -12,9 +12,6 @@ export function createApp(): express.Express {
);
app.use(express.json());
app.use(healthRouter);
app.use(racesRouter);
// Тот же API под /api/* — если прокси не снимает префикс или запрос идёт напрямую на порт бэкенда с /api.
app.use("/api", healthRouter);
app.use("/api", racesRouter);

View File

@@ -5,59 +5,43 @@ import { createApp } from "../src/app";
const app = createApp();
test("GET /health returns ok", async () => {
const res = await request(app).get("/health").expect(200);
assert.equal(res.body.status, "ok");
assert.equal(typeof res.body.version, "string");
assert.ok(res.body.version.length > 0);
});
test("GET /api/health returns ok (prefix without proxy strip)", async () => {
test("GET /api/health returns ok", async () => {
const res = await request(app).get("/api/health").expect(200);
assert.equal(res.body.status, "ok");
});
test("GET /meta returns version for UI footer", async () => {
const res = await request(app).get("/meta").expect(200);
assert.equal(typeof res.body.version, "string");
assert.ok(res.body.version.length > 0);
});
test("GET /api/meta mirrors GET /meta", async () => {
test("GET /api/meta returns version for UI footer", async () => {
const res = await request(app).get("/api/meta").expect(200);
assert.equal(typeof res.body.version, "string");
assert.ok(res.body.version.length > 0);
});
test("GET /ready succeeds with mock database", async () => {
const res = await request(app).get("/ready").expect(200);
test("GET /api/ready succeeds with mock database", async () => {
const res = await request(app).get("/api/ready").expect(200);
assert.equal(res.body.status, "ready");
assert.equal(res.body.db, "connected");
});
test("GET /races rejects invalid year", async () => {
const res = await request(app).get("/races?year=bad").expect(400);
test("GET /api/races rejects invalid year", async () => {
const res = await request(app).get("/api/races?year=bad").expect(400);
assert.equal(res.body.error, "validation_error");
assert.ok(Array.isArray(res.body.details));
});
test("GET /races rejects month out of range", async () => {
const res = await request(app).get("/races?month=13").expect(400);
test("GET /api/races rejects month out of range", async () => {
const res = await request(app).get("/api/races?month=13").expect(400);
assert.equal(res.body.error, "validation_error");
});
test("GET /races accepts year and month", async () => {
const res = await request(app).get("/races?year=2026&month=5").expect(200);
assert.ok(Array.isArray(res.body));
});
test("GET /api/races mirrors GET /races", async () => {
test("GET /api/races accepts year and month", async () => {
const res = await request(app).get("/api/races?year=2026&month=5").expect(200);
assert.ok(Array.isArray(res.body));
});
test("GET /races/:id returns not_found", async () => {
const res = await request(app).get("/races/does-not-exist").expect(404);
test("GET /api/races/:id returns not_found", async () => {
const res = await request(app).get("/api/races/does-not-exist").expect(404);
assert.equal(res.body.error, "not_found");
assert.ok(Array.isArray(res.body.details));
});