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: CapsuleCreateOptions = { baseUrl }; if (apiKey) clientOpts.apiKey = apiKey; 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, ); it( "destroys an owned live capsule when async disposed", async () => { let capsuleId: string | undefined; try { const capsule = await Capsule.create(template, { ...clientOpts, timeout_sec: 60, }); capsuleId = capsule.id; await capsule.waitForReady({ intervalMs: 2_000, timeoutMs: waitTimeoutMs, }); await capsule[Symbol.asyncDispose](); await expect( Capsule.connect(capsuleId, clientOpts).getInfo(), ).resolves.toMatchObject({ id: capsuleId, status: "stopped" }); capsuleId = undefined; } finally { if (capsuleId) { await Capsule.destroy(capsuleId, clientOpts).catch(() => undefined); } } }, waitTimeoutMs + 30_000, ); });