feat: add high-level Capsule lifecycle API

This commit is contained in:
Tasnim Kabir Sadik
2026-05-14 22:51:01 +06:00
parent 52282618bd
commit 8fb9753fde
8 changed files with 579 additions and 2 deletions

View File

@ -0,0 +1,92 @@
import { describe, expect, it } from "vitest";
import { Capsule, type CapsuleCreateOptions } from "../../src/capsule.js";
import { DEFAULT_BASE_URL } from "../../src/config.js";
const baseUrl = process.env.WRENN_BASE_URL ?? DEFAULT_BASE_URL;
const apiKey = process.env.WRENN_API_KEY;
const template = process.env.WRENN_TEST_TEMPLATE ?? "minimal";
const waitTimeoutMs = Number(process.env.WRENN_TEST_WAIT_TIMEOUT_MS ?? 120_000);
const describeWithApiKey = apiKey ? describe : describe.skip;
const clientOpts = { apiKey, baseUrl } satisfies CapsuleCreateOptions;
describeWithApiKey("Capsule live integration", () => {
it(
"creates, waits for, inspects, pings, and destroys a live capsule",
async () => {
let capsule: Capsule | undefined;
try {
capsule = await Capsule.create(template, {
...clientOpts,
timeout_sec: 60,
});
expect(capsule.id).toBeTypeOf("string");
expect(capsule.id.length).toBeGreaterThan(0);
const ready = await capsule.waitForReady({
intervalMs: 2_000,
timeoutMs: waitTimeoutMs,
});
expect(ready).toMatchObject({ id: capsule.id, status: "running" });
const connected = Capsule.connect(capsule.id, clientOpts);
const info = await connected.getInfo();
expect(info.id).toBe(capsule.id);
await expect(connected.ping()).resolves.toBeUndefined();
const metrics = await connected.getMetrics({ range: "10m" });
expect(metrics).toBeTypeOf("object");
await connected.close();
await connected[Symbol.asyncDispose]();
await Capsule.destroy(capsule.id, clientOpts);
capsule = undefined;
} finally {
if (capsule) {
await Capsule.destroy(capsule.id, clientOpts).catch(() => undefined);
}
}
},
waitTimeoutMs + 30_000,
);
it(
"pauses and resumes a live capsule through high-level methods",
async () => {
let capsule: Capsule | undefined;
try {
capsule = await Capsule.create(template, {
...clientOpts,
timeout_sec: 60,
});
await capsule.waitForReady({
intervalMs: 2_000,
timeoutMs: waitTimeoutMs,
});
const paused = await capsule.pause();
expect(paused).toMatchObject({ id: capsule.id });
expect(paused.status).toBe("paused");
const resumed = await capsule.resume({
intervalMs: 2_000,
timeoutMs: waitTimeoutMs,
wait: true,
});
expect(resumed).toMatchObject({ id: capsule.id, status: "running" });
} finally {
if (capsule) {
await Capsule.destroy(capsule.id, clientOpts).catch(() => undefined);
}
}
},
waitTimeoutMs * 2 + 30_000,
);
});