BrandApp Playground

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 } }