import { describe, it, expect, beforeAll, afterAll } from "vitest"; import { buildApp } from "../src/app.js"; import { loadConfig } from "../src/config.js"; import type { FastifyInstance } from "fastify"; describe("fleet api", () => { let app: FastifyInstance; let authHeader: { authorization: string }; beforeAll(async () => { app = await buildApp({ config: { ...loadConfig(), staticDir: null, authRequired: false }, memory: true, }); const login = await app.inject({ method: "POST", url: "/api/v1/auth/login", payload: { username: "admin", password: "admin" }, }); expect(login.statusCode).toBe(200); const token = login.json().token as string; authHeader = { authorization: `Bearer ${token}` }; }); afterAll(async () => { await app.close(); }); it("lists seeded locations", async () => { const res = await app.inject({ method: "GET", url: "/api/v1/locations", headers: authHeader, }); expect(res.statusCode).toBe(200); const body = res.json(); expect(body.length).toBeGreaterThanOrEqual(5); expect(body.some((l: { code: string }) => l.code === "msk")).toBe(true); }); it("creates zone, node, alias and exports bind", async () => { const zoneRes = await app.inject({ method: "POST", url: "/api/v1/zones", headers: authHeader, payload: { name: "rtnt.top" }, }); expect(zoneRes.statusCode).toBe(200); const zone = zoneRes.json(); const locs = ( await app.inject({ method: "GET", url: "/api/v1/locations", headers: authHeader, }) ).json(); const msk = locs.find((l: { code: string }) => l.code === "msk"); const nodeRes = await app.inject({ method: "POST", url: "/api/v1/nodes", headers: authHeader, payload: { zoneId: zone.id, locationId: msk.id, role: "hub", indexNum: 1, ipv4: "94.142.140.141", }, }); expect(nodeRes.statusCode).toBe(200); const node = nodeRes.json(); expect(node.hostname).toBe("msk-hub01.rtnt.top"); const aliasRes = await app.inject({ method: "POST", url: "/api/v1/aliases", headers: authHeader, payload: { zoneId: zone.id, name: "msk.rtnt.top", purpose: "geo", mode: "primary", targetNodeId: node.id, }, }); expect(aliasRes.statusCode).toBe(200); const bind = await app.inject({ method: "GET", url: `/api/v1/zones/${zone.id}/export/bind`, headers: authHeader, }); expect(bind.statusCode).toBe(200); expect(bind.json().content).toContain("msk-hub01.rtnt.top"); expect(bind.json().content).toContain("msk.rtnt.top"); const stats = await app.inject({ method: "GET", url: "/api/v1/dashboard/stats", headers: authHeader, }); expect(stats.statusCode).toBe(200); expect(stats.json().nodes).toBe(1); expect(stats.json().aliases).toBe(1); const topo = await app.inject({ method: "GET", url: "/api/v1/topology", headers: authHeader, }); expect(topo.statusCode).toBe(200); expect(topo.json().nodes).toHaveLength(1); const preview = await app.inject({ method: "GET", url: `/api/v1/naming/preview?${new URLSearchParams({ zoneId: zone.id, locationId: msk.id, role: "gw", indexNum: "2", ipv4: "198.51.100.10", ipv6: "2001:db8::10", nodeId: node.id, })}`, headers: authHeader, }); expect(preview.statusCode).toBe(200); const body = preview.json() as { hostname: string; records: Array<{ type: string; name: string; content: string }>; }; expect(body.hostname).toBe("msk-gw02.rtnt.top"); expect(body.records).toEqual( expect.arrayContaining([ expect.objectContaining({ type: "A", name: "msk-gw02.rtnt.top", content: "198.51.100.10", }), expect.objectContaining({ type: "AAAA", name: "msk-gw02.rtnt.top", content: "2001:db8::10", }), expect.objectContaining({ type: "CNAME", name: "msk.rtnt.top", content: "msk-gw02.rtnt.top", }), ]), ); }); });