You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
4.2 KiB
TypeScript

import {
afterAll,
afterEach,
beforeAll,
beforeEach,
describe,
expect,
it,
} from "bun:test";
import Caprover, { Application } from "./Caprover";
import { TestApp } from "../domain/testing/TestApp";
import server, {
CAPROVER_TEST_DOMAIN,
CAPROVER_TEST_PASSWORD,
} from "./mocks/caproverServer";
import appsFixtures from "./mocks/apps.fixtures.json";
describe("Caprover", () => {
describe("Application", () => {
const anAppDefinition = appsFixtures[0];
it("should create an application from definition", () => {
const app = Application.createFromDefinition(anAppDefinition);
expect(app.name).toBe("adminer");
});
describe("docker image", () => {
it("should return the docker image name of the current version", () => {
const app = Application.createFromDefinition(anAppDefinition);
expect(app.dockerImage).toEqual({
name: "adminer",
tag: "4.8.1",
hubUrl: "https://hub.docker.com/_/adminer",
});
});
it("should parse names with organization namespace", () => {
const app = Application.createFromDefinition({
...anAppDefinition,
deployedVersion: 0,
versions: [
{
...anAppDefinition.versions[0],
deployedImageName: "vaultwarden/server:1.30.0-alpine",
},
],
});
expect(app.dockerImage).toEqual({
name: "vaultwarden/server",
tag: "1.30.0-alpine",
hubUrl: "https://hub.docker.com/r/vaultwarden/server",
});
});
it("should not parse custom built images", () => {
const app = Application.createFromDefinition({
...anAppDefinition,
deployedVersion: 0,
versions: [
{
...anAppDefinition.versions[0],
deployedImageName:
"registry.example.org:996/captain/img-captain-nextcloud-cron:4",
},
],
});
expect(app.dockerImage).toBeUndefined();
});
});
});
describe("Initialization", () => {
it("should throw an error when no domain is provided", () => {
expect(() => new Caprover(new TestApp().eventStore, "")).toThrowError(
"Missing domain or password"
);
});
it("should throw an error when no password is provided", () => {
expect(
() => new Caprover(new TestApp().eventStore, CAPROVER_TEST_DOMAIN)
).toThrowError("Missing domain or password");
});
});
describe("API interactions", () => {
let app: TestApp, caprover: Caprover;
beforeAll(() => server.listen());
beforeEach(() => {
app = new TestApp();
caprover = new Caprover(
app.eventStore,
CAPROVER_TEST_DOMAIN,
CAPROVER_TEST_PASSWORD
);
});
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
describe("getApps", () => {
it("should return the list of applications", async () => {
const apps = await caprover.getApps();
expect(apps).toBeArrayOfSize(3);
expect(apps[0]).toBeInstanceOf(Application);
expect(apps[0].name).toBe("adminer");
expect(apps[1].name).toBe("mysql");
expect(apps[2].name).toBe("redis");
});
});
describe("updateApplication", () => {
it("should update the application with the provided version and emit an event upon success", async () => {
await caprover.updateApplication("adminer", "adminer:4.2.0");
const apps = await caprover.getApps();
expect(apps[0].imageName).toBe("adminer:4.2.0");
const events = app.eventStore.getAllEvents();
expect(events).toBeArrayOfSize(1);
expect(events[0]).toMatchObject({
type: "ApplicationUpdateStarted",
payload: { id: "adminer", newVersion: "adminer:4.2.0" },
});
});
it("should throw an error when the application does not exist and not emit any event", async () => {
await expect(
caprover.updateApplication("unknown", "adminer:4.2.0")
).rejects.toThrowError(/Failed to update application unknown/);
const events = app.eventStore.getAllEvents();
expect(events).toBeArrayOfSize(0);
});
});
});
});