feat(billing): post-grant upgrade prompt variant for depleted signupGrant#4128
Conversation
…rant Add exhaustedAfterGrant store getter (free plan + balance<=0 + signup_grant ledger entry) and post-grant copy variant in BillingUpgradePromptComponent with Boost pack CTA first, upgrade Growth/Pro second. PricingCard badge already wired via plan.badge — add explicit tests to document. i18n keys added en+fr.
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (7)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds a “post-grant” upgrade prompt flow in the billing module, driven by a new Pinia getter that detects when a Free-plan org has depleted its one-shot signup grant, along with i18n strings and unit test coverage to validate the new behavior.
Changes:
- Added
exhaustedAfterGrantgetter touseBillingStoreto detect “signup grant depleted” state. - Extended
BillingUpgradePromptwith a post-grant variant UI (new copy + Boost pack CTA + secondary upgrade CTA). - Added/extended unit tests and introduced new i18n keys in
en.js/fr.js.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/modules/billing/tests/billing.upgradePrompt.component.unit.tests.js | Adds unit tests covering the new post-grant rendering/CTAs. |
| src/modules/billing/tests/billing.store.unit.tests.js | Adds unit tests for the new exhaustedAfterGrant getter guard conditions and null-safety. |
| src/modules/billing/tests/billing.pricingCard.component.unit.tests.js | Adds tests documenting existing plan.badge chip rendering behavior. |
| src/modules/billing/stores/billing.store.js | Introduces exhaustedAfterGrant getter to drive post-grant UI logic. |
| src/modules/billing/lang/fr.js | Adds French i18n strings for the post-grant variant. |
| src/modules/billing/lang/en.js | Adds English i18n strings for the post-grant variant. |
| src/modules/billing/components/billing.upgradePrompt.component.vue | Implements the post-grant variant UI and wires it to the billing store getter. |
| it('does not render badge chip when plan.badge is absent', () => { | ||
| const wrapper = mountComponent({ plan: freePlan }); | ||
| // freePlan has no badge — verify by checking the text doesn't contain any badge content | ||
| expect(wrapper.text()).not.toContain('500 compute @ signup'); | ||
| expect(wrapper.text()).not.toContain('Most Popular'); | ||
| }); |
| <!-- Post-grant variant: signup grant is depleted (Free plan, balance = 0, ledger has signup_grant entry) --> | ||
| <div v-if="exhaustedAfterGrant" class="my-4"> | ||
| <v-alert type="info" variant="tonal" prominent> | ||
| <template #text> | ||
| <p class="font-weight-bold mb-1">{{ $t('billing.upgradePrompt.postGrantTitle') }}</p> | ||
| <p>{{ $t('billing.upgradePrompt.postGrantBody') }}</p> | ||
| </template> | ||
| <template #append> | ||
| <div class="d-flex flex-column ga-2"> | ||
| <v-btn | ||
| data-test="cta-pack" | ||
| color="primary" | ||
| variant="flat" | ||
| size="small" | ||
| class="text-none" | ||
| @click="$emit('buy-pack')" | ||
| > | ||
| {{ $t('billing.upgradePrompt.postGrantBuyPack') }} | ||
| </v-btn> | ||
| <v-btn | ||
| data-test="cta-upgrade" | ||
| variant="text" | ||
| size="small" | ||
| class="text-none" | ||
| to="/pricing" | ||
| > | ||
| {{ $t('billing.upgradePrompt.postGrantUpgrade') }} | ||
| </v-btn> | ||
| </div> |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #4128 +/- ##
=======================================
Coverage 99.54% 99.54%
=======================================
Files 31 31
Lines 1089 1098 +9
Branches 302 308 +6
=======================================
+ Hits 1084 1093 +9
Misses 5 5 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Summary
exhaustedAfterGrantPinia getter to billing store: returnstruewhen plan=free,extrasBalance.balance <= 0, andextrasLedgerhas asignup_grantentry — null-safe for all edge casesBillingUpgradePromptComponentwith apost-grantvariant: when the getter istrue, renders "Your signup grant is depleted" copy with Boost pack CTA (primary) + Growth/Pro upgrade CTA (secondary text)plan.badge— added explicit tests to document the existing behavioren.js+fr.jsTest plan
billing.store.unit.tests.js: 9 new tests forexhaustedAfterGrantgetter (all 6 guard conditions + null-safety)billing.upgradePrompt.component.unit.tests.js: 7 new component tests — post-grant variant renders/doesn't render per store statebilling.pricingCard.component.unit.tests.js: 2 new tests for badge chip fromplan.badgebillingStore.subscription.plan = 'free',extrasBalance.balance = 0,extrasLedger.entries = [{ source: 'signup_grant' }]in devtools → upgrade modal shows post-grant copyPart of
N2 Free Tier Grant plan — Task 5 of 7. WS-B T1/T2/T3/T4 merged upstream (devkit Node).