Skip to content

Commit 54c6d95

Browse files
Bill Leoutsakoscursoragent
authored andcommitted
fix(e2e): derive usage from entitled coverage
Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 96fd2a8 commit 54c6d95

3 files changed

Lines changed: 69 additions & 52 deletions

File tree

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import type { ResolvedScenario, ScenarioSubscription } from './scenario'
2+
3+
export function isEntitledSubscription(subscription: ScenarioSubscription): boolean {
4+
return subscription.status === 'active' || subscription.status === 'past_due'
5+
}
6+
7+
export function sameBillingReference(
8+
left: ScenarioSubscription,
9+
right: ScenarioSubscription
10+
): boolean {
11+
return billingReferenceIdentity(left) === billingReferenceIdentity(right)
12+
}
13+
14+
export function initialSubscriptionStatus(
15+
scenario: ResolvedScenario,
16+
definition: ScenarioSubscription
17+
): 'active' | 'past_due' | 'canceled' {
18+
if (definition.status !== 'lapsed') return definition.status
19+
const hasEntitledReplacement = scenario.definition.subscriptions.some(
20+
(candidate) =>
21+
candidate.key !== definition.key &&
22+
isEntitledSubscription(candidate) &&
23+
sameBillingReference(candidate, definition)
24+
)
25+
return hasEntitledReplacement ? 'canceled' : 'active'
26+
}
27+
28+
export function expectedUsageLimit(scenario: ResolvedScenario, userKey: string): string | null {
29+
const organizationKeys = new Set(
30+
scenario.definition.organizationMemberships
31+
.filter((membership) => membership.userKey === userKey)
32+
.map((membership) => membership.organizationKey)
33+
)
34+
const hasEntitledOrganizationSubscription = scenario.definition.subscriptions.some(
35+
(candidate) =>
36+
candidate.billingReference.kind === 'organization' &&
37+
organizationKeys.has(candidate.billingReference.organizationKey) &&
38+
isEntitledSubscription(candidate)
39+
)
40+
if (hasEntitledOrganizationSubscription) return null
41+
42+
const personalSubscription = scenario.definition.subscriptions.find(
43+
(candidate) =>
44+
candidate.billingReference.kind === 'user' &&
45+
candidate.billingReference.userKey === userKey &&
46+
isEntitledSubscription(candidate)
47+
)
48+
if (personalSubscription?.plan.startsWith('pro_')) {
49+
return String(Number(personalSubscription.plan.split('_')[1]) / 200)
50+
}
51+
return '5'
52+
}
53+
54+
function billingReferenceIdentity(subscription: ScenarioSubscription): string {
55+
return subscription.billingReference.kind === 'user'
56+
? `user/${subscription.billingReference.userKey}`
57+
: `organization/${subscription.billingReference.organizationKey}`
58+
}

apps/sim/e2e/foundation/scenario-validation.spec.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
type ScenarioOrganizationMembership,
88
type ScenarioWorkspaceGrant,
99
} from '../fixtures/scenario'
10+
import { expectedUsageLimit } from '../fixtures/scenario-billing'
1011
import {
1112
ScenarioValidationError,
1213
validateScenario,
@@ -254,7 +255,15 @@ test.describe('pure scenario validation', () => {
254255
: persona
255256
)
256257

257-
expect(() => validateScenario(scenario)).not.toThrow()
258+
const resolved = validateScenario(scenario)
259+
if (lapsed.billingReference.kind !== 'organization') {
260+
throw new Error('Expected an organization subscription')
261+
}
262+
const ownerUserKey = resolved.organizationsByKey.get(
263+
lapsed.billingReference.organizationKey
264+
)?.ownerUserKey
265+
if (!ownerUserKey) throw new Error('Expected an organization owner')
266+
expect(expectedUsageLimit(resolved, ownerUserKey)).toBeNull()
258267
})
259268

260269
test('rejects permission groups without active Enterprise organization/workspace scope', () => {

apps/sim/e2e/scripts/seed-world.ts

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import {
4040
import { createWorkspace, grantWorkspacePermission } from '../fixtures/factories/workspaces'
4141
import { E2eHttpClient } from '../fixtures/http-client'
4242
import type { ResolvedScenario, ScenarioSubscription } from '../fixtures/scenario'
43+
import { expectedUsageLimit, initialSubscriptionStatus } from '../fixtures/scenario-billing'
4344
import { validateScenario, validateScenarioSet } from '../fixtures/validate-scenario'
4445
import { createSettingsPersonaScenarios } from '../settings/personas'
4546
import { writeSyntheticSecretCanary } from '../support/leak-canary'
@@ -729,57 +730,6 @@ function resolveBillingReference(world: E2EWorld, subscription: ScenarioSubscrip
729730
).id
730731
}
731732

732-
function initialSubscriptionStatus(
733-
scenario: ResolvedScenario,
734-
definition: ScenarioSubscription
735-
): 'active' | 'past_due' | 'canceled' {
736-
if (definition.status !== 'lapsed') return definition.status
737-
const hasEntitledReplacement = scenario.definition.subscriptions.some(
738-
(candidate) =>
739-
candidate.key !== definition.key &&
740-
(candidate.status === 'active' || candidate.status === 'past_due') &&
741-
sameBillingReference(candidate, definition)
742-
)
743-
return hasEntitledReplacement ? 'canceled' : 'active'
744-
}
745-
746-
function sameBillingReference(left: ScenarioSubscription, right: ScenarioSubscription): boolean {
747-
const identity = (subscription: ScenarioSubscription): string =>
748-
subscription.billingReference.kind === 'user'
749-
? `user/${subscription.billingReference.userKey}`
750-
: `organization/${subscription.billingReference.organizationKey}`
751-
return identity(left) === identity(right)
752-
}
753-
754-
function expectedUsageLimit(scenario: ResolvedScenario, userKey: string): string | null {
755-
const membership = scenario.definition.organizationMemberships.find(
756-
(candidate) => candidate.userKey === userKey
757-
)
758-
if (membership) {
759-
const organizationSubscription = scenario.definition.subscriptions.find(
760-
(candidate) =>
761-
candidate.billingReference.kind === 'organization' &&
762-
candidate.billingReference.organizationKey === membership.organizationKey
763-
)
764-
if (
765-
organizationSubscription?.status === 'active' ||
766-
organizationSubscription?.status === 'past_due'
767-
) {
768-
return null
769-
}
770-
}
771-
const personalSubscription = scenario.definition.subscriptions.find(
772-
(candidate) =>
773-
candidate.billingReference.kind === 'user' &&
774-
candidate.billingReference.userKey === userKey &&
775-
(candidate.status === 'active' || candidate.status === 'past_due')
776-
)
777-
if (personalSubscription?.plan.startsWith('pro_')) {
778-
return String(Number(personalSubscription.plan.split('_')[1]) / 200)
779-
}
780-
return '5'
781-
}
782-
783733
function matchesEnterpriseMetadata(
784734
metadata: unknown,
785735
definition: ScenarioSubscription,

0 commit comments

Comments
 (0)