182 lines
5.6 KiB
TypeScript
182 lines
5.6 KiB
TypeScript
import { beforeAll, describe, expect, test } from "bun:test";
|
|
import {
|
|
ApiVersion,
|
|
AppEnv,
|
|
type CheckResponseV1,
|
|
SuccessCode,
|
|
} from "@autumn/shared";
|
|
import { TestFeature } from "@tests/setup/v2Features.js";
|
|
import ctx from "@tests/utils/testInitUtils/createTestContext.js";
|
|
import chalk from "chalk";
|
|
import { AutumnInt } from "@/external/autumn/autumnCli.js";
|
|
import { OrgService } from "@/internal/orgs/OrgService.js";
|
|
import { generatePublishableKey } from "@/utils/encryptUtils.js";
|
|
import { constructFeatureItem } from "@/utils/scriptUtils/constructItem.js";
|
|
import { constructProduct } from "@/utils/scriptUtils/createTestProducts.js";
|
|
import { initCustomerV3 } from "@/utils/scriptUtils/testUtils/initCustomerV3.js";
|
|
import { initProductsV0 } from "@/utils/scriptUtils/testUtils/initProductsV0.js";
|
|
import { timeout } from "../../../utils/genUtils.js";
|
|
|
|
const messagesFeature = constructFeatureItem({
|
|
featureId: TestFeature.Messages,
|
|
includedUsage: 1000,
|
|
});
|
|
|
|
const freeProd = constructProduct({
|
|
type: "free",
|
|
isDefault: false,
|
|
items: [messagesFeature],
|
|
});
|
|
|
|
const testCase = "check8";
|
|
const customerId = "check8";
|
|
|
|
describe(`${chalk.yellowBright("check8: test public key & send_event")}`, () => {
|
|
const autumnV1: AutumnInt = new AutumnInt({ version: ApiVersion.V1_2 });
|
|
let autumnPublic: AutumnInt;
|
|
|
|
beforeAll(async () => {
|
|
await initCustomerV3({
|
|
ctx,
|
|
customerId,
|
|
withTestClock: false,
|
|
});
|
|
|
|
await initProductsV0({
|
|
ctx,
|
|
products: [freeProd],
|
|
prefix: testCase,
|
|
});
|
|
|
|
await autumnV1.attach({
|
|
customer_id: customerId,
|
|
product_id: freeProd.id,
|
|
});
|
|
|
|
// Ensure test_pkey is set on the org (needed for public key tests)
|
|
if (!ctx.org.test_pkey) {
|
|
const testPkey = generatePublishableKey(AppEnv.Sandbox);
|
|
await OrgService.update({
|
|
db: ctx.db,
|
|
orgId: ctx.org.id,
|
|
updates: {
|
|
test_pkey: testPkey,
|
|
},
|
|
});
|
|
// Update the context org object
|
|
ctx.org.test_pkey = testPkey;
|
|
}
|
|
|
|
if (!ctx.org.test_pkey.startsWith("am_pk")) {
|
|
throw new Error(
|
|
`test_pkey "${ctx.org.test_pkey}" does not start with "am_pk". Expected format: am_pk_test_...`,
|
|
);
|
|
}
|
|
|
|
// Initialize Autumn client with public key
|
|
autumnPublic = new AutumnInt({
|
|
version: ApiVersion.V1_2,
|
|
secretKey: ctx.org.test_pkey,
|
|
});
|
|
});
|
|
|
|
test("should work with public key for /check endpoint", async () => {
|
|
const res = (await autumnPublic.check({
|
|
customer_id: customerId,
|
|
feature_id: TestFeature.Messages,
|
|
required_balance: 100,
|
|
})) as unknown as CheckResponseV1;
|
|
|
|
expect(res).toMatchObject({
|
|
allowed: true,
|
|
customer_id: customerId,
|
|
feature_id: TestFeature.Messages,
|
|
balance: 1000,
|
|
required_balance: 100,
|
|
code: SuccessCode.FeatureFound,
|
|
usage: 0,
|
|
included_usage: 1000,
|
|
overage_allowed: false,
|
|
});
|
|
|
|
expect(res.next_reset_at).toBeDefined();
|
|
});
|
|
|
|
test("should not track usage when send_event: true with public key", async () => {
|
|
// Get current balance before
|
|
const customerBefore: any = await autumnV1.customers.get(customerId);
|
|
const balanceBefore = customerBefore.features[TestFeature.Messages].balance;
|
|
const usedBefore = customerBefore.features[TestFeature.Messages].used;
|
|
|
|
// Call check with public key and send_event: true
|
|
// This should succeed but NOT send events (silently skipped)
|
|
const checkRes = (await autumnPublic.check({
|
|
customer_id: customerId,
|
|
feature_id: TestFeature.Messages,
|
|
required_balance: 50,
|
|
send_event: true,
|
|
})) as unknown as CheckResponseV1;
|
|
|
|
expect(checkRes.allowed).toBe(true);
|
|
|
|
// Wait for potential event processing
|
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
|
|
// Get customer and verify balance stayed the same
|
|
const customerAfter: any = await autumnV1.customers.get(customerId);
|
|
const balanceAfter = customerAfter.features[TestFeature.Messages].balance;
|
|
|
|
expect(balanceAfter).toBe(balanceBefore);
|
|
expect(customerAfter.features[TestFeature.Messages].used).toBe(usedBefore);
|
|
});
|
|
|
|
test("should track usage when send_event: true with secret key", async () => {
|
|
// Call check with send_event: true
|
|
const checkRes = (await autumnV1.check({
|
|
customer_id: customerId,
|
|
feature_id: TestFeature.Messages,
|
|
required_balance: 150,
|
|
send_event: true,
|
|
})) as unknown as CheckResponseV1;
|
|
|
|
expect(checkRes.allowed).toBe(true);
|
|
expect(checkRes.balance).toBe(1000);
|
|
|
|
// Wait for event to be processed
|
|
await timeout(2000);
|
|
|
|
// Get customer and verify balance decreased
|
|
const customer: any = await autumnV1.customers.get(customerId);
|
|
const balanceAfter = customer.features[TestFeature.Messages].balance;
|
|
|
|
expect(balanceAfter).toBe(850); // 1000 - 150
|
|
expect(customer.features[TestFeature.Messages].usage).toBe(150);
|
|
});
|
|
|
|
test("should not track usage when send_event: true but insufficient balance", async () => {
|
|
// Get current balance first
|
|
const customerBefore: any = await autumnV1.customers.get(customerId);
|
|
const balanceBefore = customerBefore.features[TestFeature.Messages].balance;
|
|
|
|
// Call check with required_balance > current balance
|
|
const checkRes = (await autumnV1.check({
|
|
customer_id: customerId,
|
|
feature_id: TestFeature.Messages,
|
|
required_balance: 900, // More than available (850)
|
|
send_event: true,
|
|
})) as unknown as CheckResponseV1;
|
|
|
|
expect(checkRes.allowed).toBe(false);
|
|
|
|
// Wait for potential event processing
|
|
await timeout(2000);
|
|
|
|
// Get customer and verify balance stayed the same
|
|
const customerAfter: any = await autumnV1.customers.get(customerId);
|
|
const balanceAfter = customerAfter.features[TestFeature.Messages].balance;
|
|
|
|
expect(balanceAfter).toBe(balanceBefore);
|
|
expect(customerAfter.features[TestFeature.Messages].usage).toBe(150); // Same as before
|
|
});
|
|
});
|