mirror of
https://github.com/gethomepage/homepage.git
synced 2026-02-08 17:00:51 +08:00
154 lines
4.7 KiB
JavaScript
154 lines
4.7 KiB
JavaScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import createMockRes from "test-utils/create-mock-res";
|
|
|
|
const { state, DockerCtor, getDockerArguments, logger } = vi.hoisted(() => {
|
|
const state = {
|
|
docker: null,
|
|
dockerArgs: { conn: { socketPath: "/var/run/docker.sock" }, swarm: false },
|
|
};
|
|
|
|
function DockerCtor() {
|
|
return state.docker;
|
|
}
|
|
|
|
return {
|
|
state,
|
|
DockerCtor,
|
|
getDockerArguments: vi.fn(() => state.dockerArgs),
|
|
logger: { error: vi.fn() },
|
|
};
|
|
});
|
|
|
|
vi.mock("dockerode", () => ({
|
|
default: DockerCtor,
|
|
}));
|
|
|
|
vi.mock("utils/config/docker", () => ({
|
|
default: getDockerArguments,
|
|
}));
|
|
|
|
vi.mock("utils/logger", () => ({
|
|
default: () => logger,
|
|
}));
|
|
|
|
import handler from "pages/api/docker/stats/[...service]";
|
|
|
|
describe("pages/api/docker/stats/[...service]", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
state.dockerArgs = { conn: { socketPath: "/var/run/docker.sock" }, swarm: false };
|
|
state.docker = {
|
|
listContainers: vi.fn(),
|
|
getContainer: vi.fn(),
|
|
listTasks: vi.fn(),
|
|
};
|
|
});
|
|
|
|
it("returns 400 when container name/server params are missing", async () => {
|
|
const req = { query: { service: [] } };
|
|
const res = createMockRes();
|
|
|
|
await handler(req, res);
|
|
|
|
expect(res.statusCode).toBe(400);
|
|
expect(res.body).toEqual({ error: "docker query parameters are required" });
|
|
});
|
|
|
|
it("returns 500 when docker returns a non-array containers payload", async () => {
|
|
state.docker.listContainers.mockResolvedValue(Buffer.from("bad"));
|
|
|
|
const req = { query: { service: ["c", "local"] } };
|
|
const res = createMockRes();
|
|
|
|
await handler(req, res);
|
|
|
|
expect(res.statusCode).toBe(500);
|
|
expect(res.body).toEqual({ error: "query failed" });
|
|
});
|
|
|
|
it("returns stats for an existing container", async () => {
|
|
state.docker.listContainers.mockResolvedValue([{ Names: ["/myapp"], Id: "cid1" }]);
|
|
const containerStats = { cpu_stats: { cpu_usage: { total_usage: 1 } } };
|
|
state.docker.getContainer.mockReturnValue({
|
|
stats: vi.fn().mockResolvedValue(containerStats),
|
|
});
|
|
|
|
const req = { query: { service: ["myapp", "local"] } };
|
|
const res = createMockRes();
|
|
|
|
await handler(req, res);
|
|
|
|
expect(res.statusCode).toBe(200);
|
|
expect(res.body).toEqual({ stats: containerStats });
|
|
});
|
|
|
|
it("uses swarm tasks to locate a container and reports a friendly error when stats cannot be retrieved", async () => {
|
|
state.dockerArgs.swarm = true;
|
|
state.docker.listContainers.mockResolvedValue([{ Names: ["/other"], Id: "local1" }]);
|
|
state.docker.listTasks.mockResolvedValue([
|
|
{ Status: { ContainerStatus: { ContainerID: "local1" } } },
|
|
{ Status: { ContainerStatus: { ContainerID: "remote1" } } },
|
|
]);
|
|
state.docker.getContainer.mockReturnValue({
|
|
stats: vi.fn().mockRejectedValue(new Error("nope")),
|
|
});
|
|
|
|
const req = { query: { service: ["svc", "local"] } };
|
|
const res = createMockRes();
|
|
|
|
await handler(req, res);
|
|
|
|
expect(res.statusCode).toBe(200);
|
|
expect(res.body).toEqual({ error: "Unable to retrieve stats" });
|
|
});
|
|
|
|
it("returns stats for a swarm task container when present locally", async () => {
|
|
state.dockerArgs.swarm = true;
|
|
state.docker.listContainers.mockResolvedValue([{ Names: ["/other"], Id: "local1" }]);
|
|
state.docker.listTasks.mockResolvedValue([{ Status: { ContainerStatus: { ContainerID: "local1" } } }]);
|
|
|
|
const containerStats = { cpu_stats: { cpu_usage: { total_usage: 2 } } };
|
|
state.docker.getContainer.mockReturnValue({
|
|
stats: vi.fn().mockResolvedValue(containerStats),
|
|
});
|
|
|
|
const req = { query: { service: ["svc", "local"] } };
|
|
const res = createMockRes();
|
|
|
|
await handler(req, res);
|
|
|
|
expect(res.statusCode).toBe(200);
|
|
expect(res.body).toEqual({ stats: containerStats });
|
|
});
|
|
|
|
it("returns 404 when no container or swarm task is found", async () => {
|
|
state.dockerArgs.swarm = true;
|
|
state.docker.listContainers.mockResolvedValue([{ Names: ["/other"], Id: "local1" }]);
|
|
state.docker.listTasks.mockResolvedValue([]);
|
|
|
|
const req = { query: { service: ["missing", "local"] } };
|
|
const res = createMockRes();
|
|
|
|
await handler(req, res);
|
|
|
|
expect(res.statusCode).toBe(404);
|
|
expect(res.body).toEqual({ error: "not found" });
|
|
});
|
|
|
|
it("logs and returns 500 when the docker query throws", async () => {
|
|
getDockerArguments.mockImplementationOnce(() => {
|
|
throw new Error("boom");
|
|
});
|
|
|
|
const req = { query: { service: ["myapp", "local"] } };
|
|
const res = createMockRes();
|
|
|
|
await handler(req, res);
|
|
|
|
expect(res.statusCode).toBe(500);
|
|
expect(res.body).toEqual({ error: { message: "boom" } });
|
|
expect(logger.error).toHaveBeenCalled();
|
|
});
|
|
});
|