cimplify
Testing harness

Suites

Three pre-baked vitest suites cover the common shape contracts. Templates wire them in three lines each: when a new case lands in the SDK, every storefront inherits it on `bun update @cimplify/sdk`.

createBrandSuite

Validates lib/brand.ts against BrandSchema. Catches missing fields, placeholder copy, malformed contact info, and seed/businessId mismatch.

__tests__/brand.test.ts
import { createBrandSuite } from "@cimplify/sdk/testing/suite";
import { brand } from "../lib/brand";

createBrandSuite({ brand });

Cases registered:

  • conforms to the Cimplify brand contract
  • declares a known mock seed
  • has no placeholder copy left in (lorem ipsum, todo, fixme, "your store", …)
  • uses the bus_ businessId convention
  • zod-parses cleanly with full issue paths

createCartFlowSuite

Boots the in-process mock and exercises the full cart lifecycle with shape assertions on every response. Catches SDK ↔ mock contract drift, missing fields, dropped variant payloads.

__tests__/cart-flow.test.ts
import { createCartFlowSuite } from "@cimplify/sdk/testing/suite";
import { brand } from "../lib/brand";

createCartFlowSuite({ seed: brand.mock.seed, businessId: brand.mock.businessId });

Cases registered:

  • starts with an empty cart matching the canonical shape
  • adds the first product, persists it, returns a shape-valid cart
  • dedupes by line_key when the same product is added twice
  • removes items and zeroes the subtotal
  • (when businessId is supplied) returns the brand's businessId on cart responses

createContractSuite

Exercises the schemas against actual mock traffic. Catches outbound payloads dropping required fields and inbound responses missing fields the storefront depends on.

__tests__/contract.test.ts
import { createContractSuite } from "@cimplify/sdk/testing/suite";
import { brand } from "../lib/brand";

createContractSuite({ seed: brand.mock.seed });

Cases registered:

  • AddItemPayloadSchema accepts a minimal valid body
  • AddItemPayloadSchema rejects negative quantity
  • AddItemPayloadSchema rejects empty item_id
  • cart line items returned by the mock match CartItemSchema
  • CheckoutResponse from the mock includes bill_token and order_id

The extend hook

Append your own cases inside the same describe block. createBrandSuite hands you vitest's it; the cart and contract suites also hand you a getHandle() getter for the live TestClientHandle.

Extending the brand suite
import { createBrandSuite } from "@cimplify/sdk/testing/suite";
import { brand } from "../lib/brand";
import { expect } from "vitest";

createBrandSuite({
  brand,
  extend: (it) => {
    it("ships in our merchant's currency", () => {
      expect(brand.currency).toBe("GHS");
    });
  },
});
Extending the cart-flow suite
import { createCartFlowSuite } from "@cimplify/sdk/testing/suite";
import { brand } from "../lib/brand";
import { expect } from "vitest";

createCartFlowSuite({
  seed: brand.mock.seed,
  businessId: brand.mock.businessId,
  extend: ({ getHandle, it }) => {
    it("every product priced in GHS", async () => {
      const list = await getHandle().client.catalogue.getProducts();
      if (!list.ok) throw list.error;
      for (const p of list.value.items ?? []) {
        expect(p.currency).toBe("GHS");
      }
    });
  },
});

Suite options

SuiteRequiredOptional
createBrandSuitebrandlabel, extend
createCartFlowSuitenoneseed, businessId, label, extend, all CreateAppOptions (frozenAt, rngSeed, …)
createContractSuitenoneseed, label, extend, all CreateAppOptions

Next

  • Test client createTestClient for custom flows

  • Schemas The shape contract behind every suite

On this page