3.6 KiB
3.6 KiB
General Test Guide
Test Context
All tests have access to ctx which contains:
ctx.org- Test organizationctx.db- Database connectionctx.features- Organization features
Initializing Autumn Clients
Secret Key (Default)
const autumnV1 = new AutumnInt({ version: ApiVersion.V1_2 });
Public Key
const autumnPublic = new AutumnInt({
version: ApiVersion.V1_2,
secretKey: ctx.org.test_pkey!,
});
With Custom Config
const autumn = new AutumnInt({
version: ApiVersion.V1_2,
orgConfig: { include_past_due: true },
});
API Versions
ApiVersion.V0_2- Legacy v0 APIApiVersion.V1_2- Current v1 API
Common Test Patterns
Wait for Async Processing
await new Promise((resolve) => setTimeout(resolve, 2000));
Get Customer with Feature Balance
const customer: any = await autumn.customers.get(customerId);
const balance = customer.features[TestFeature.Messages].balance;
const used = customer.features[TestFeature.Messages].used;
Expect Error (Use This Instead of try-catch!)
Always use expectAutumnError instead of manual try-catch blocks:
import { expectAutumnError } from "tests/utils/expectUtils/expectErrUtils.js";
// ✅ GOOD - Use expectAutumnError
await expectAutumnError({
errCode: ErrCode.CustomerNotFound,
func: async () => {
await autumn.customers.get("invalid-id");
},
});
// ✅ GOOD - Test for duplicate idempotency key
await expectAutumnError({
errCode: ErrCode.DuplicateIdempotencyKey,
func: async () => {
await autumn.track({
customer_id: customerId,
feature_id: TestFeature.Messages,
idempotency_key: "same-key",
});
},
});
// ❌ BAD - Don't use try-catch
let errorThrown = false;
try {
await autumn.customers.get("invalid-id");
} catch (error) {
errorThrown = true;
}
expect(errorThrown).toBe(true);
Common Error Codes:
ErrCode.CustomerNotFoundErrCode.ProductNotFoundErrCode.FeatureNotFoundErrCode.InsufficientBalanceErrCode.DuplicateIdempotencyKeyErrCode.InvalidRequest
Public Key Restrictions
Public keys can only access:
GET /v1/productsPOST /v1/entitledPOST /v1/checkPOST /v1/attachGET /v1/customers/:customerId
Public keys CANNOT:
- Send events (
send_event: trueis silently ignored) - Access other endpoints
Test Organization
beforeAll- Setup (create customers, products, attach)test- Individual test cases- Use descriptive test names with
chalk.yellowBright()
Customer Initialization
Payment Methods
IMPORTANT: If your product has ANY price (overage, per-seat, usage-based, etc.), you MUST attach a payment method:
// ✅ GOOD - Product with prices requires payment method
await initCustomerV3({
ctx,
customerId,
attachPm: "success", // Required for any paid features
withTestClock: false,
});
// ❌ BAD - Product with prices but no payment method
await initCustomerV3({
ctx,
customerId,
withTestClock: false, // Missing attachPm: "success"
});
Use attachPm: "success" when:
- Product has overage pricing (arrear items)
- Product has per-seat pricing
- Product has usage-based billing
- Any feature can trigger billing
Omit attachPm only for:
- Completely free products (no prices at all)
- Tests that don't require billing
Imports
import { beforeAll, describe, expect, test } from "bun:test";
import { ApiVersion, ErrCode } from "@autumn/shared";
import chalk from "chalk";
import ctx from "tests/utils/testInitUtils/createTestContext.js";
import { AutumnInt } from "@/external/autumn/autumnCli.js";