Testing
Testing utilities for unit and integration tests with in-memory SDK instances and fixtures.
createTestSDK()
Create an in-memory SDK instance for unit tests. No server or network needed.
__tests__/contacts.test.ts
import { createTestSDK } from "@reopt-ai/brandapp-sdk/testing";
import { describe, it, expect, afterAll } from "vitest";
describe("Contact CRUD", () => {
const { sdk, devServer } = await createTestSDK({
schema: {
entities: {
contacts: {
name: "contacts",
attributes: {
name: { label: "Name", dataType: "string", isRequired: true },
email: { label: "Email", dataType: "email", isRequired: true },
},
},
},
},
});
afterAll(async () => {
await devServer.close();
});
it("should create a contact", async () => {
const entities = await sdk.eav.entities.list();
const contacts = entities[0];
const record = await sdk.eav.records.create(contacts.id, {
values: { name: "Jane", email: "jane@test.com" },
});
expect(record.id).toBeDefined();
expect(record.values.name).toBe("Jane");
});
});createTestServer()
Start a real HTTP test server for integration tests.
__tests__/integration.test.ts
import { createTestServer } from "@reopt-ai/brandapp-sdk/testing";
import { createReoptSDK } from "@reopt-ai/brandapp-sdk";
import { afterAll } from "vitest";
// Start a test server on a random port
const { devServer, url, sdkConfig } = await createTestServer({
schema: { /* ... */ },
});
// Build the SDK from the ready-made config (clientId/secret/brandappId + baseUrl).
// You could also wire your own: createReoptSDK({ ...sdkConfig, debug: true }).
const sdk = createReoptSDK(sdkConfig);
// `url` is also exposed if you need to point a fetch/other client at the server.
console.log("Test server:", url);
// Clean up after tests
afterAll(async () => {
await devServer.close();
});createFixture()
Create typed test data fixtures that can be seeded into test SDKs.
__tests__/fixtures.ts
import { createTestSDK, createFixture } from "@reopt-ai/brandapp-sdk/testing";
// createFixture takes factory functions — each returns a { values } record and
// accepts optional overrides. This keeps repeated test data DRY.
const fixture = createFixture({
contact: (overrides) => ({
values: {
name: "Default Name",
email: "default@test.com",
status: "active",
...overrides,
},
}),
product: (overrides) => ({
values: { title: "Widget", price: "29.99", sku: "WDG-001", ...overrides },
}),
});
// Default values
const defaultContact = fixture.contact();
// Override specific fields
const alice = fixture.contact({ name: "Alice", email: "alice@test.com" });
// Seed via the dev server (keyed by entity name) — not sdk.seed()
const { devServer } = await createTestSDK({ schema: { /* ... */ } });
await devServer.seed({
contacts: [defaultContact, alice, fixture.contact({ name: "Bob", status: "inactive" })],
});
// Each factory result is { values: Record<string, unknown> }
type ContactSeed = ReturnType<typeof fixture.contact>;
// { values: { name: string; email: string; status: string } }