Skip to content

Commit 07517bc

Browse files
test(integration): config-aware billing equivalences + plan id (closes #3609) (#3610)
* test(integration): config-aware billing equivalences + plan id assertions (#3609) - auth.integration: assert billing.equivalences against config.billing.equivalences (was hardcoded to null — broke any downstream that defines equivalences for /pricing) - billing.lifecycle.integration: derive plan ids from config.billing.plans for the starter→pro transition test (was hardcoded 'starter' — broke any downstream whose plan enum excludes starter, e.g. trawl with free/growth/pro) Tests still cover the upstream defaults (no planDefinitions → fallback to legacy 'starter'/'pro'; no equivalences → null) but no longer assume those values. Refs #3609. * fix(billing): use optional chaining on config.billing?.plans to guard against undefined * fix(billing): correct comment — upstream defaults expose plans via planDefinitions
1 parent dfee01a commit 07517bc

2 files changed

Lines changed: 20 additions & 9 deletions

File tree

modules/auth/tests/auth.integration.tests.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1542,7 +1542,7 @@ describe('Auth integration tests:', () => {
15421542
expect(result.body.data.billing).toBeDefined();
15431543
expect(typeof result.body.data.billing.enabled).toBe('boolean');
15441544
expect(typeof result.body.data.billing.meterMode).toBe('boolean');
1545-
expect(result.body.data.billing.equivalences).toBeNull();
1545+
expect(result.body.data.billing.equivalences).toEqual(config.billing?.equivalences ?? null);
15461546
});
15471547

15481548
test('should reflect billing.meterMode=true when enabled (authenticated)', async () => {

modules/billing/tests/billing.lifecycle.integration.tests.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,30 @@ describe('Billing meter lifecycle integration tests:', () => {
7070
});
7171

7272
test('plan.changed webhook updates active week quota snapshot mid-week', async () => {
73+
// Pick two distinct plan ids from the project's enum so the test runs on any downstream.
74+
// Upstream defaults expose ['free','starter','pro','enterprise'] via planDefinitions;
75+
// fallback to ['starter','pro'] only when plans array is absent or has fewer than 2 entries.
76+
const plans = Array.isArray(config.billing?.plans) && config.billing.plans.length >= 2
77+
? config.billing.plans
78+
: ['starter', 'pro'];
79+
const initialPlan = plans[0];
80+
const upgradePlan = plans[plans.length - 1];
81+
const initialVersion = `${initialPlan}-v1`;
82+
const upgradeVersion = `${upgradePlan}-v2`;
83+
7384
config.billing.planDefinitions = [
74-
{ planId: 'starter', version: 'starter-v1', meterQuota: 100, ratios: { scrap: 1 } },
75-
{ planId: 'pro', version: 'pro-v2', meterQuota: 1000, ratios: { scrap: 1 } },
85+
{ planId: initialPlan, version: initialVersion, meterQuota: 100, ratios: { scrap: 1 } },
86+
{ planId: upgradePlan, version: upgradeVersion, meterQuota: 1000, ratios: { scrap: 1 } },
7687
];
7788

7889
const organizationId = new mongoose.Types.ObjectId();
7990
const weekKey = isoWeekKey(new Date());
80-
await Organization.create({ _id: organizationId, name: 'Lifecycle Org', slug: 'lifecycle-org', plan: 'starter' });
91+
await Organization.create({ _id: organizationId, name: 'Lifecycle Org', slug: 'lifecycle-org', plan: initialPlan });
8192
await Subscription.create({
8293
organization: organizationId,
8394
stripeCustomerId: 'cus_lifecycle',
8495
stripeSubscriptionId: 'sub_lifecycle',
85-
plan: 'starter',
96+
plan: initialPlan,
8697
status: 'active',
8798
});
8899
await BillingUsage.create({
@@ -92,7 +103,7 @@ describe('Billing meter lifecycle integration tests:', () => {
92103
counters: {},
93104
meterUsed: 25,
94105
meterQuota: 100,
95-
planVersion: 'starter-v1',
106+
planVersion: initialVersion,
96107
meterBreakdown: { scrap: 25 },
97108
consumedAttributionKeys: [],
98109
});
@@ -104,20 +115,20 @@ describe('Billing meter lifecycle integration tests:', () => {
104115
current_period_end: Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60,
105116
current_period_start: Math.floor(Date.now() / 1000) - 24 * 60 * 60,
106117
cancel_at_period_end: false,
107-
items: { data: [{ price: { metadata: { planId: 'pro' } } }] },
118+
items: { data: [{ price: { metadata: { planId: upgradePlan } } }] },
108119
},
109120
{
110121
data: {
111122
previous_attributes: {
112-
items: { data: [{ price: { metadata: { planId: 'starter' } } }] },
123+
items: { data: [{ price: { metadata: { planId: initialPlan } } }] },
113124
},
114125
},
115126
},
116127
);
117128

118129
const usage = await BillingUsage.findOne({ organizationId, weekKey }).lean();
119130
expect(usage.meterQuota).toBe(1000);
120-
expect(usage.planVersion).toBe('pro-v2');
131+
expect(usage.planVersion).toBe(upgradeVersion);
121132
expect(usage.meterUsed).toBe(25);
122133
expect(usage.meterBreakdown).toEqual({ scrap: 25 });
123134
});

0 commit comments

Comments
 (0)