Skip to content

Commit 5badea7

Browse files
author
Connor Byrne
committed
refactor(billing): drop the isActiveSubscription alias
#11464 renamed isActiveSubscription to canAccessSubscriptionFeatures because off cloud it is forced true, so the old name asserts something the value does not mean. The alias was kept for compatibility, which left both names live and the misleading one still in use across the workspace composables, settings, storybook mocks and stories. Pure rename: the alias was a direct assignment of the same computed, so every call site already read the identical value.
1 parent ca3f895 commit 5badea7

20 files changed

Lines changed: 69 additions & 63 deletions

src/composables/billing/types.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,4 @@ export interface BillingContext extends BillingState, BillingActions {
129129
isTeamPlan: ComputedRef<boolean>
130130
getMaxSeats: (tierKey: TierKey) => number
131131
canRunWorkflows: ComputedRef<boolean>
132-
/** @deprecated Use canAccessSubscriptionFeatures instead */
133-
isActiveSubscription: ComputedRef<boolean>
134132
}

src/composables/billing/useBillingContext.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,10 +376,10 @@ describe('useBillingContext', () => {
376376
await expect(topup(99.5)).rejects.toThrow()
377377
})
378378

379-
it('provides isActiveSubscription convenience computed', () => {
379+
it('provides canAccessSubscriptionFeatures convenience computed', () => {
380380
mockBillingRail.value = 'legacy_stripe'
381-
const { isActiveSubscription } = useBillingContext()
382-
expect(isActiveSubscription.value).toBe(true)
381+
const { canAccessSubscriptionFeatures } = useBillingContext()
382+
expect(canAccessSubscriptionFeatures.value).toBe(true)
383383
})
384384

385385
it('exposes requireActiveSubscription action', async () => {

src/composables/billing/useBillingContext.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,16 +147,13 @@ function useBillingContextInternal(): BillingContext {
147147
toValue(activeContext.value.canAccessSubscriptionFeatures)
148148
)
149149

150-
// Alias kept for backward compatibility; equals canAccessSubscriptionFeatures.
151-
const isActiveSubscription = canAccessSubscriptionFeatures
152-
153150
const isFreeTier = computed(() => subscription.value?.tier === 'FREE')
154151

155152
const freeTierQuota = useFreeTierQuota()
156153

157154
const canRunWorkflows = computed(
158155
() =>
159-
isActiveSubscription.value &&
156+
canAccessSubscriptionFeatures.value &&
160157
(!isFreeTier.value ||
161158
!freeTierQuota.quotaEnabled.value ||
162159
freeTierQuota.freeTierExecutionPermitted.value)
@@ -176,7 +173,7 @@ function useBillingContextInternal(): BillingContext {
176173

177174
// Plan identity, independent of subscription health: the per-credit Team plan
178175
// carries a credit stop, the retired seat-based ones a `team-` slug. Kept off
179-
// isActiveSubscription on purpose — paused and payment_failed both force
176+
// canAccessSubscriptionFeatures on purpose — paused and payment_failed both force
180177
// is_active=false, which is exactly when callers still need to know this is a
181178
// team plan.
182179
const isTeamPlan = computed(
@@ -350,9 +347,8 @@ function useBillingContextInternal(): BillingContext {
350347
occupiedSeats,
351348
isLoading,
352349
error,
353-
isActiveSubscription,
354-
canRunWorkflows,
355350
canAccessSubscriptionFeatures,
351+
canRunWorkflows,
356352
isFreeTier,
357353
isLegacyTeamPlan,
358354
isTeamPlan,

src/platform/cloud/subscription/composables/useTopUpUrlLoader.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ describe('useTopUpUrlLoader', () => {
126126

127127
it('awaits the status fetch before opening the dialog', async () => {
128128
mockRouteQuery.value = { topup: '1' }
129-
// The dialog picks top-up vs paywall from isActiveSubscription; holding
129+
// The dialog picks top-up vs paywall from canAccessSubscriptionFeatures; holding
130130
// the fetch promise open proves the loader truly awaits it (a dropped
131131
// await would open the dialog before resolveStatus runs).
132132
let resolveStatus!: () => void

src/platform/cloud/subscription/composables/useTopUpUrlLoader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export function useTopUpUrlLoader() {
5959
// resolves before the app mounts, so it is readable synchronously here.
6060
if (!permissions.value.canTopUp) return
6161

62-
// showTopUpCreditsDialog reads isActiveSubscription synchronously to pick
62+
// showTopUpCreditsDialog reads canAccessSubscriptionFeatures synchronously to pick
6363
// between the top-up dialog and the paywall; billing init on boot is
6464
// fire-and-forget, so await a status fetch to make that read reflect the
6565
// server before deciding.

src/platform/settings/composables/useSettingUI.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const env = vi.hoisted(() => {
2020
authenticatedConfigLoaded: false,
2121
partnerNodeGovernanceEnabled: false,
2222
userSecretsEnabled: false,
23-
isActiveSubscription: false,
23+
canAccessSubscriptionFeatures: false,
2424
billingType: 'legacy' as 'legacy' | 'workspace',
2525
workspaceRole: 'owner' as 'owner' | 'member'
2626
}
@@ -42,7 +42,7 @@ vi.mock('@/composables/auth/useCurrentUser', () => ({
4242

4343
vi.mock('@/composables/billing/useBillingContext', () => ({
4444
useBillingContext: () => ({
45-
canAccessSubscriptionFeatures: env.fakeRef('isActiveSubscription'),
45+
canAccessSubscriptionFeatures: env.fakeRef('canAccessSubscriptionFeatures'),
4646
type: env.fakeRef('billingType')
4747
})
4848
}))
@@ -133,7 +133,7 @@ describe('useSettingUI', () => {
133133
authenticatedConfigLoaded: false,
134134
partnerNodeGovernanceEnabled: false,
135135
userSecretsEnabled: false,
136-
isActiveSubscription: false,
136+
canAccessSubscriptionFeatures: false,
137137
billingType: 'legacy',
138138
workspaceRole: 'owner'
139139
})
@@ -214,7 +214,7 @@ describe('useSettingUI', () => {
214214
isCloud: true,
215215
isLoggedIn: true,
216216
authenticatedConfigLoaded: true,
217-
isActiveSubscription: true,
217+
canAccessSubscriptionFeatures: true,
218218
billingType: 'workspace'
219219
})
220220
window.__CONFIG__ = {
@@ -293,7 +293,7 @@ describe('useSettingUI', () => {
293293
billingControlEnabled: true,
294294
authenticatedConfigLoaded: true,
295295
partnerNodeGovernanceEnabled: true,
296-
isActiveSubscription: true
296+
canAccessSubscriptionFeatures: true
297297
})
298298
window.__CONFIG__ = {
299299
subscription_required: true

src/platform/workspace/components/SubscriptionPanelContentWorkspace.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,9 @@ vi.mock('@/platform/workspace/composables/useWorkspaceUI', () => ({
205205
})),
206206
uiConfig: computed(() => mockUiConfig.value),
207207
isInPersonalWorkspace: mockIsInPersonalWorkspace,
208-
isActiveSubscription: computed(() => mockIsActiveSubscription.value),
208+
canAccessSubscriptionFeatures: computed(
209+
() => mockIsActiveSubscription.value
210+
),
209211
isSubscriptionCancelled: mockIsSubscriptionCancelled,
210212
isTeamPlanCancelled: mockIsTeamPlanCancelled,
211213
isDeleteDisabled: mockIsDeleteDisabled,

src/platform/workspace/components/dialogs/settings/BillingStatusBanner.stories.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ function story(
8484
export const PausedOwner: Story = story(
8585
{
8686
subscription: funded,
87-
isActiveSubscription: false,
87+
canAccessSubscriptionFeatures: false,
8888
billingStatus: 'paused',
8989
subscriptionStatus: 'active'
9090
},
@@ -95,7 +95,7 @@ export const PausedOwner: Story = story(
9595
export const PausedMember: Story = story(
9696
{
9797
subscription: funded,
98-
isActiveSubscription: false,
98+
canAccessSubscriptionFeatures: false,
9999
billingStatus: 'paused',
100100
subscriptionStatus: 'active'
101101
},
@@ -109,7 +109,7 @@ export const PausedMember: Story = story(
109109
export const PaymentDeclined: Story = story(
110110
{
111111
subscription: funded,
112-
isActiveSubscription: false,
112+
canAccessSubscriptionFeatures: false,
113113
billingStatus: 'payment_failed',
114114
subscriptionStatus: 'active',
115115
renewalDate: RENEWAL_DATE
@@ -121,7 +121,7 @@ export const PaymentDeclined: Story = story(
121121
export const PaymentDeclinedNoDate: Story = story(
122122
{
123123
subscription: funded,
124-
isActiveSubscription: false,
124+
canAccessSubscriptionFeatures: false,
125125
billingStatus: 'payment_failed',
126126
subscriptionStatus: 'active'
127127
},
@@ -132,7 +132,7 @@ export const PaymentDeclinedNoDate: Story = story(
132132
export const OutOfCreditsOwner: Story = story(
133133
{
134134
subscription: exhausted,
135-
isActiveSubscription: true,
135+
canAccessSubscriptionFeatures: true,
136136
billingStatus: 'paid',
137137
subscriptionStatus: 'active',
138138
renewalDate: RENEWAL_DATE
@@ -144,7 +144,7 @@ export const OutOfCreditsOwner: Story = story(
144144
export const OutOfCreditsMember: Story = story(
145145
{
146146
subscription: exhausted,
147-
isActiveSubscription: true,
147+
canAccessSubscriptionFeatures: true,
148148
billingStatus: 'paid',
149149
subscriptionStatus: 'active',
150150
renewalDate: RENEWAL_DATE
@@ -156,7 +156,7 @@ export const OutOfCreditsMember: Story = story(
156156
export const EndingOwner: Story = story(
157157
{
158158
subscription: cancelled,
159-
isActiveSubscription: true,
159+
canAccessSubscriptionFeatures: true,
160160
billingStatus: 'paid',
161161
subscriptionStatus: 'canceled'
162162
},
@@ -166,7 +166,7 @@ export const EndingOwner: Story = story(
166166
export const EndingPromotedOwner: Story = story(
167167
{
168168
subscription: cancelled,
169-
isActiveSubscription: true,
169+
canAccessSubscriptionFeatures: true,
170170
billingStatus: 'paid',
171171
subscriptionStatus: 'canceled'
172172
},

src/platform/workspace/components/dialogs/settings/BillingStatusBanner.test.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ interface Subscription {
1919
const state = vi.hoisted(() => ({
2020
billingControlEnabled: true,
2121
v1PaymentRecovery: true,
22-
isActiveSubscription: true,
22+
canAccessSubscriptionFeatures: true,
2323
isTeamPlan: true,
2424
billingStatus: 'paid' as string | null,
2525
subscription: {
@@ -54,7 +54,9 @@ vi.mock('@/composables/useFeatureFlags', () => ({
5454

5555
vi.mock('@/composables/billing/useBillingContext', () => ({
5656
useBillingContext: () => ({
57-
isActiveSubscription: computed(() => state.isActiveSubscription),
57+
canAccessSubscriptionFeatures: computed(
58+
() => state.canAccessSubscriptionFeatures
59+
),
5860
isTeamPlan: computed(() => state.isTeamPlan),
5961
billingStatus: computed(() => state.billingStatus as BillingStatus | null),
6062
subscription: computed(() => state.subscription),
@@ -153,19 +155,19 @@ function exhausted() {
153155
// paused alongside an active subscription.
154156
function pausedState() {
155157
state.billingStatus = 'paused'
156-
state.isActiveSubscription = false
158+
state.canAccessSubscriptionFeatures = false
157159
}
158160

159161
function paymentFailedState() {
160162
state.billingStatus = 'payment_failed'
161-
state.isActiveSubscription = false
163+
state.canAccessSubscriptionFeatures = false
162164
}
163165

164166
describe('BillingStatusBanner', () => {
165167
beforeEach(() => {
166168
state.billingControlEnabled = true
167169
state.v1PaymentRecovery = true
168-
state.isActiveSubscription = true
170+
state.canAccessSubscriptionFeatures = true
169171
state.isTeamPlan = true
170172
state.billingStatus = 'paid'
171173
state.subscription = { hasFunds: true, isCancelled: false, endDate: null }
@@ -296,7 +298,7 @@ describe('BillingStatusBanner', () => {
296298
expect(screen.queryByRole('status')).not.toBeInTheDocument()
297299
unmount()
298300

299-
state.isActiveSubscription = true
301+
state.canAccessSubscriptionFeatures = true
300302
state.billingStatus = 'paid'
301303
exhausted()
302304
renderBanner()

src/platform/workspace/composables/deriveBillingBanner.test.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const funded: BillingBannerInputs = {
88
v1PaymentRecovery: true,
99
isTeamPlan: true,
1010
isLoaded: true,
11-
isActiveSubscription: true,
11+
canAccessSubscriptionFeatures: true,
1212
billingStatus: 'paid',
1313
hasFunds: true,
1414
isCancelled: false,
@@ -23,12 +23,12 @@ const funded: BillingBannerInputs = {
2323
// cannot emit, and pass no matter where the check sits.
2424
const paused: Partial<BillingBannerInputs> = {
2525
billingStatus: 'paused',
26-
isActiveSubscription: false
26+
canAccessSubscriptionFeatures: false
2727
}
2828

2929
const paymentFailed: Partial<BillingBannerInputs> = {
3030
billingStatus: 'payment_failed',
31-
isActiveSubscription: false
31+
canAccessSubscriptionFeatures: false
3232
}
3333

3434
function derive(overrides: Partial<BillingBannerInputs>) {
@@ -132,7 +132,10 @@ describe('deriveBillingBanner', () => {
132132

133133
it('shows no banner for an inactive subscription (that is a run-lock modal)', () => {
134134
expect(
135-
derive({ isActiveSubscription: false, billingStatus: 'inactive' })
135+
derive({
136+
canAccessSubscriptionFeatures: false,
137+
billingStatus: 'inactive'
138+
})
136139
).toBeNull()
137140
})
138141
})

0 commit comments

Comments
 (0)