Skip to content

Commit 2d60388

Browse files
elucidsoftclaude
andcommitted
test: add live API smoke tests
6 tests verified against production API: - getStatus, getAccount, listJobs, listStorage, listTemplates - urlToPdf v1 sync with PDF header validation Run with: CLOUDLAYER_API_KEY=... npx tsx tests/smoke/run-smoke.ts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d8c7404 commit 2d60388

2 files changed

Lines changed: 139 additions & 0 deletions

File tree

tests/smoke/run-smoke.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { CloudLayer } from "../../src/client.js";
2+
3+
const apiKey = process.env.CLOUDLAYER_API_KEY?.trim();
4+
if (!apiKey) {
5+
console.error("Set CLOUDLAYER_API_KEY env var");
6+
process.exit(1);
7+
}
8+
9+
const client = new CloudLayer({ apiKey, apiVersion: "v2" });
10+
11+
let passed = 0;
12+
let failed = 0;
13+
14+
async function test(name: string, fn: () => Promise<void>) {
15+
try {
16+
await fn();
17+
console.log(` ✓ ${name}`);
18+
passed++;
19+
} catch (error) {
20+
console.error(` ✗ ${name}`);
21+
console.error(` ${error instanceof Error ? error.message : error}`);
22+
failed++;
23+
}
24+
}
25+
26+
console.log("\nSmoke Tests (Live API)\n");
27+
28+
await test("getStatus — API is reachable", async () => {
29+
const status = await client.getStatus();
30+
if (!status.status) throw new Error("No status field");
31+
console.log(` Status: "${status.status}"`);
32+
});
33+
34+
await test("getAccount — auth works", async () => {
35+
const account = await client.getAccount();
36+
if (!account.email) throw new Error("No email field");
37+
console.log(` Account: ${account.email} | Plan: ${account.subType} | Active: ${account.subActive}`);
38+
});
39+
40+
await test("listJobs — returns array", async () => {
41+
const jobs = await client.listJobs();
42+
if (!Array.isArray(jobs)) throw new Error("Not an array");
43+
console.log(` Jobs: ${jobs.length}`);
44+
});
45+
46+
await test("listStorage — returns array", async () => {
47+
const storages = await client.listStorage();
48+
if (!Array.isArray(storages)) throw new Error("Not an array");
49+
console.log(` Storage configs: ${storages.length}`);
50+
});
51+
52+
await test("listTemplates — public templates", async () => {
53+
const templates = await client.listTemplates();
54+
if (!Array.isArray(templates)) throw new Error("Not an array");
55+
console.log(` Public templates: ${templates.length}`);
56+
});
57+
58+
// Use v1 client for binary conversion test (v2 requires storage which may not be on the plan)
59+
const v1Client = new CloudLayer({ apiKey, apiVersion: "v1" });
60+
61+
await test("urlToPdf v1 sync — returns binary PDF", async () => {
62+
const result = await v1Client.urlToPdf({
63+
url: "https://example.com",
64+
format: "a4",
65+
});
66+
const data = result.data;
67+
if (!Buffer.isBuffer(data)) throw new Error("Expected binary buffer from v1");
68+
console.log(` PDF: ${data.length} bytes`);
69+
// Verify PDF magic bytes
70+
if (data[0] !== 0x25 || data[1] !== 0x50) throw new Error("Not a valid PDF");
71+
console.log(` Valid PDF header confirmed`);
72+
});
73+
74+
console.log(`\n${passed} passed, ${failed} failed\n`);
75+
process.exit(failed > 0 ? 1 : 0);

tests/smoke/smoke.test.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { readFileSync } from "node:fs";
2+
import { describe, expect, it } from "vitest";
3+
import { CloudLayer } from "../../src/client.js";
4+
5+
const apiKey = process.env.CLOUDLAYER_API_KEY?.trim();
6+
7+
describe.skipIf(!apiKey)("Smoke Tests (Live API)", () => {
8+
const client = new CloudLayer({
9+
apiKey: apiKey!,
10+
apiVersion: "v2",
11+
});
12+
13+
it("getStatus — API is reachable", async () => {
14+
const status = await client.getStatus();
15+
expect(status).toHaveProperty("status");
16+
console.log("Status:", JSON.stringify(status));
17+
});
18+
19+
it("getAccount — auth works", async () => {
20+
const account = await client.getAccount();
21+
expect(account).toHaveProperty("email");
22+
expect(account).toHaveProperty("uid");
23+
expect(account).toHaveProperty("subType");
24+
console.log("Account:", account.email, "| Plan:", account.subType, "| Active:", account.subActive);
25+
});
26+
27+
it("listJobs — returns array", async () => {
28+
const jobs = await client.listJobs();
29+
expect(Array.isArray(jobs)).toBe(true);
30+
console.log("Jobs count:", jobs.length);
31+
});
32+
33+
it("listStorage — returns array", async () => {
34+
const storages = await client.listStorage();
35+
expect(Array.isArray(storages)).toBe(true);
36+
console.log("Storage configs:", storages.length);
37+
});
38+
39+
it("listTemplates — public templates (no auth required)", async () => {
40+
const templates = await client.listTemplates();
41+
expect(Array.isArray(templates)).toBe(true);
42+
console.log("Public templates:", templates.length);
43+
});
44+
45+
it("urlToPdf v2 — returns Job object", async () => {
46+
const result = await client.urlToPdf({
47+
url: "https://example.com",
48+
async: false,
49+
storage: true,
50+
});
51+
const job = result.data;
52+
expect(job).toHaveProperty("id");
53+
expect(job).toHaveProperty("status");
54+
console.log("Job:", job.id, "| Status:", job.status);
55+
56+
if (job.status === "success" && job.assetUrl) {
57+
console.log("Asset URL:", job.assetUrl);
58+
const pdf = await client.downloadJobResult(job);
59+
expect(Buffer.isBuffer(pdf)).toBe(true);
60+
expect(pdf.length).toBeGreaterThan(0);
61+
console.log("Downloaded PDF:", pdf.length, "bytes");
62+
}
63+
}, 60000);
64+
});

0 commit comments

Comments
 (0)