@vitra/image-creator-test
v0.1.1
Published
Deterministic local mock of the Vitra Image Creation Platform. Offline integration testing, stripe-mock pattern.
Maintainers
Readme
@vitra/image-creator-test
Deterministic local mock of the Vitra Image Creation Platform. Stripe-mock pattern: offline, same input → same output, wire-compatible with the real server.
Use this as a dev-dep to build and test your Vitra integration before touching Vitra staging — or to run your CI without network access.
Install
npm install --save-dev @vitra/image-creator-testCLI
npx vitra-mockStarts on port 4321 (override with PORT=...). Default fixture:
| Field | Value |
|-------|-------|
| tenant slug | test-app |
| shared secret | vitra_sk_test_secret_for_local_integration_testing_only |
| allowed origins | https://app.test, http://localhost:5173 |
| initial balance | 1000 credits per user |
Point your SDK at it:
const vitra = new VitraClient({
appId: "test-app",
sharedSecret: "vitra_sk_test_secret_for_local_integration_testing_only",
baseUrl: "http://localhost:4321",
});Programmatic use (Vitest / Jest)
import { createMockServer, DEFAULT_TEST_APP } from "@vitra/image-creator-test";
import { VitraClient } from "@vitra/image-creator-node";
describe("my integration", () => {
let mock: ReturnType<typeof createMockServer>;
let baseUrl: string;
beforeAll(async () => {
mock = createMockServer();
({ url: baseUrl } = await mock.listen(0));
});
afterAll(() => mock.close());
afterEach(() => mock.reset()); // fresh state per test
it("reserves and captures", async () => {
const client = new VitraClient({
appId: "test-app",
sharedSecret: DEFAULT_TEST_APP.sharedSecret,
baseUrl,
});
// ...do your flow, then assert on mock state
expect(mock.state.reservations()).toHaveLength(1);
expect(mock.state.balance("test-app", "user-1")).toBe(990);
});
});Custom fixtures
const mock = createMockServer({
apps: [
{
slug: "translate-photo",
sharedSecret: "vitra_sk_test_abc",
allowedOrigins: ["https://app.translate.photo"],
initialBalance: 50,
},
{
slug: "cosmos",
sharedSecret: "vitra_sk_test_xyz",
allowedOrigins: ["https://cosmos.vitra.ai"],
// Simulate a user with no credits
insufficientCredits: true,
},
],
});Rotation overlap is also supported:
const mock = createMockServer({
apps: [
{
slug: "test-app",
sharedSecret: "new-current-secret",
previousSecret: "old-rotated-secret", // valid for 24h in the real server
allowedOrigins: ["https://app.test"],
},
],
});Introspection routes
Mock-only, under /_mock. Never used by production clients.
| Route | Returns |
|-------|---------|
| GET /_mock/reservations | All reservations in memory |
| GET /_mock/balance/:slug/:userId | Current balance |
| POST /_mock/reset | Reset state (keeps tenant config) |
| POST /_mock/sign | { app_id, body } → { header } for hand-rolling test requests |
Wire coverage
Implemented:
POST /api/embed/session(HMAC-verified, origin-checked)POST /api/credits/reserve(idempotent on job_id)POST /api/credits/capturePOST /api/credits/releaseGET /api/status
Not yet implemented (coming as Week 2/3 lands):
POST /api/embed/exchangeand/refresh(the iframe-side flow)POST /api/jobs(image generation)POST /assets/ingestwebhook-to-host direction
License
Apache-2.0.
