170 lines
5.9 KiB
TypeScript
170 lines
5.9 KiB
TypeScript
/**
|
|
* Transition Config Error Tests (Attach V2)
|
|
*
|
|
* Tests for validation errors when using transition configs incorrectly.
|
|
*
|
|
* Key behaviors:
|
|
* - reset_after_trial_end is not allowed on allocated features (continuous_use)
|
|
* - Allocated features don't have next_reset_at, so the config is meaningless
|
|
*/
|
|
|
|
import { test } from "bun:test";
|
|
import { TestFeature } from "@tests/setup/v2Features";
|
|
import { expectAutumnError } from "@tests/utils/expectUtils/expectErrUtils";
|
|
import { items } from "@tests/utils/fixtures/items";
|
|
import { products } from "@tests/utils/fixtures/products";
|
|
import { initScenario, s } from "@tests/utils/testInitUtils/initScenario";
|
|
import chalk from "chalk";
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
// TEST 1: reset_after_trial_end on allocated feature (free)
|
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Scenario:
|
|
* - Product has freeAllocatedWorkflows (continuous_use feature with no price)
|
|
* - Customer tries to attach with reset_after_trial_end: true for workflows
|
|
*
|
|
* Expected Result:
|
|
* - Error thrown: reset_after_trial_end is not supported for allocated features
|
|
*
|
|
* Why:
|
|
* - Allocated features (continuous_use) don't have next_reset_at
|
|
* - They represent things like seats/workflows that don't reset on billing cycles
|
|
* - reset_after_trial_end would be meaningless for these features
|
|
*/
|
|
test.concurrent(`${chalk.yellowBright("transition-config-errors 1: reset_after_trial_end on allocated feature (free)")}`, async () => {
|
|
const customerId = "trans-config-err-allocated-free";
|
|
|
|
const pro = products.pro({
|
|
id: "pro-allocated-workflows",
|
|
items: [items.freeAllocatedWorkflows({ includedUsage: 5 })],
|
|
});
|
|
|
|
const { autumnV1 } = await initScenario({
|
|
customerId,
|
|
setup: [
|
|
s.customer({ paymentMethod: "success" }),
|
|
s.products({ list: [pro] }),
|
|
],
|
|
actions: [],
|
|
});
|
|
|
|
// Attempt to attach with reset_after_trial_end on allocated feature should fail
|
|
await expectAutumnError({
|
|
func: async () => {
|
|
await autumnV1.billing.attach({
|
|
customer_id: customerId,
|
|
product_id: pro.id,
|
|
options: [
|
|
{
|
|
feature_id: TestFeature.Workflows,
|
|
quantity: 5,
|
|
},
|
|
],
|
|
transition_rules: {
|
|
reset_after_trial_end: [TestFeature.Workflows],
|
|
},
|
|
});
|
|
},
|
|
});
|
|
});
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
// TEST 2: reset_after_trial_end on allocated feature (paid)
|
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Scenario:
|
|
* - Product has allocatedUsers (continuous_use feature with prorated pricing)
|
|
* - Customer tries to attach with reset_after_trial_end: true for users
|
|
*
|
|
* Expected Result:
|
|
* - Error thrown: reset_after_trial_end is not supported for allocated features
|
|
*/
|
|
test.concurrent(`${chalk.yellowBright("transition-config-errors 2: reset_after_trial_end on allocated feature (paid)")}`, async () => {
|
|
const customerId = "trans-config-err-allocated-paid";
|
|
|
|
const pro = products.pro({
|
|
id: "pro-allocated-users",
|
|
items: [items.allocatedUsers({ includedUsage: 0 })],
|
|
});
|
|
|
|
const { autumnV1 } = await initScenario({
|
|
customerId,
|
|
setup: [
|
|
s.customer({ paymentMethod: "success" }),
|
|
s.products({ list: [pro] }),
|
|
],
|
|
actions: [],
|
|
});
|
|
|
|
// Attempt to attach with reset_after_trial_end on allocated feature should fail
|
|
await expectAutumnError({
|
|
func: async () => {
|
|
await autumnV1.billing.attach({
|
|
customer_id: customerId,
|
|
product_id: pro.id,
|
|
options: [
|
|
{
|
|
feature_id: TestFeature.Users,
|
|
quantity: 5,
|
|
},
|
|
],
|
|
transition_rules: {
|
|
reset_after_trial_end: [TestFeature.Users],
|
|
},
|
|
});
|
|
},
|
|
});
|
|
});
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
// TEST 3: feature options for non-existent feature
|
|
// ═══════════════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Scenario:
|
|
* - Product has allocatedUsers feature
|
|
* - Customer tries to attach with options for a feature that doesn't exist on the product
|
|
*
|
|
* Expected Result:
|
|
* - Error thrown: feature_id in options doesn't match any feature on the product
|
|
*/
|
|
test.concurrent(`${chalk.yellowBright("transition-config-errors 3: feature options for non-existent feature")}`, async () => {
|
|
const customerId = "trans-config-err-nonexistent-feature";
|
|
|
|
const pro = products.pro({
|
|
id: "pro-users-only",
|
|
items: [items.allocatedUsers({ includedUsage: 0 })],
|
|
});
|
|
|
|
const { autumnV1 } = await initScenario({
|
|
customerId,
|
|
setup: [
|
|
s.customer({ paymentMethod: "success" }),
|
|
s.products({ list: [pro] }),
|
|
],
|
|
actions: [],
|
|
});
|
|
|
|
// Attempt to attach with options for a feature that doesn't exist on the product
|
|
await expectAutumnError({
|
|
func: async () => {
|
|
await autumnV1.billing.attach({
|
|
customer_id: customerId,
|
|
product_id: pro.id,
|
|
options: [
|
|
{
|
|
feature_id: "random-nonexistent-feature",
|
|
quantity: 5,
|
|
},
|
|
],
|
|
transition_rules: {
|
|
reset_after_trial_end: ["random-nonexistent-feature"],
|
|
},
|
|
});
|
|
},
|
|
});
|
|
});
|