Files
cfw-autumn/server/tests/TEST_GUIDE.md
John Yeo 6f21ec4a07 wip
2026-01-07 10:25:01 +00:00

4.4 KiB

Test Writing Guide

Quick Start

Use initTestScenario for the fastest test setup:

import { test } from "bun:test";
import { TestFeature } from "@tests/setup/v2Features.js";
import { items } from "@tests/utils/fixtures/items.js";
import { products } from "@tests/utils/fixtures/products.js";
import { initTestScenario } from "@tests/utils/testInitUtils/initTestScenario.js";

test.concurrent("my test", async () => {
  const messagesItem = items.monthlyMessages({ includedUsage: 500 });

  const free = products.base({ items: [messagesItem] });

  const { customerId, autumnV1 } = await initTestScenario({
    customerId: "my-unique-test-id",
    products: [free],
    attachProducts: [free.id],  // Pass original IDs - auto-prefixed
    customerOptions: {
      withTestClock: true,
      attachPm: "success",
    },
  });

  // Your test logic here
  await autumnV1.track({
    customer_id: customerId,
    feature_id: TestFeature.Messages,
    value: 100,
  });
});

Fixtures

Item Fixtures (@tests/utils/fixtures/items)

Pre-configured product items for common feature types:

import { items } from "@tests/utils/fixtures/items.js";
Item Description Default
items.dashboard() Boolean feature (on/off) -
items.monthlyMessages({ includedUsage }) Resets monthly 100
items.monthlyWords({ includedUsage }) Resets monthly 100
items.monthlyCredits({ includedUsage }) Resets monthly 100
items.unlimitedMessages() No usage cap -
items.lifetimeMessages({ includedUsage }) Never resets 100
items.prepaidMessages({ includedUsage }) Buy upfront ($10/unit) 0
items.consumableMessages({ includedUsage }) Pay-per-use ($0.10/unit) 0
items.allocatedUsers({ includedUsage }) Prorated seats ($10/seat) 0

Product Fixtures (@tests/utils/fixtures/products)

import { products } from "@tests/utils/fixtures/products.js";
Product Description
products.base({ items, id?, isDefault? }) No base price, id defaults to "base", isDefault defaults to false

Example:

// Simple product
const free = products.base({ items: [items.monthlyMessages()] });

// With custom ID
const addon = products.base({ 
  id: "messages-addon", 
  items: [items.prepaidMessages()] 
});

// As default product
const defaultProd = products.base({ 
  items: [items.dashboard()], 
  isDefault: true 
});

Test Scenario Initialization

initTestScenario

Combines customer creation, product creation, and attachment into one call.

import { initTestScenario } from "@tests/utils/testInitUtils/initTestScenario.js";

const { customerId, products, autumnV1, autumnV2, testClockId, customer, ctx } = 
  await initTestScenario({
    customerId: "unique-test-id",      // Used as customer ID AND product prefix
    products: [free, addon],           // Products to create
    attachProducts: [free.id],         // Original IDs (auto-prefixed with customerId_)
    customerOptions: {
      withTestClock: true,             // Default: true
      attachPm: "success",             // "success" | "fail" | "authenticate"
      withDefault: false,              // Default: false
      customerData: { fingerprint },   // Optional customer data
    },
  });

Important: Product IDs are prefixed with customerId_ for test isolation.

  • You pass: attachProducts: ["base"]
  • Actual product ID becomes: "my-test-id_base"

Legacy Patterns

Customer Initialization (Direct)

For cases where initTestScenario doesn't fit:

import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js";

await initCustomerV3({
  ctx,
  customerId,
  customerData: { fingerprint: "test" },
  withTestClock: true,
  withDefault: true,  // Attach default product on creation
  attachPm: "success",
});

Product Initialization (Direct)

import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js";

await initProductsV0({
  ctx,
  products: [free, pro],
  prefix: customerId,  // Prefix product IDs for isolation
});

Running Tests

Run specific test block

Place cursor inside a test.concurrent() or describe() block and press Cmd+T.

Rerun last test

Cmd+Shift+P → "Rerun Last Task"

Run entire file

bun test path/to/file.test.ts