Skip to content

fix(Billing): Free trial buttons stop working after toggling yearly/monthly#7335

Merged
khvn26 merged 5 commits intomainfrom
fix/billing-trial-buttons-after-toggle
Apr 24, 2026
Merged

fix(Billing): Free trial buttons stop working after toggling yearly/monthly#7335
khvn26 merged 5 commits intomainfrom
fix/billing-trial-buttons-after-toggle

Conversation

@khvn26
Copy link
Copy Markdown
Member

@khvn26 khvn26 commented Apr 24, 2026

Thanks for submitting a PR! Please check the boxes below:

  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

Contributes to https://github.com/Flagsmith/flagsmith-private/issues/122

On the organisation Billing tab, the "14 Day Free Trial" buttons only work on first page load in Yearly mode. Toggling to Monthly — or back to Yearly — leaves the buttons inert.

Chargebee binds click handlers to [data-cb-type="checkout"] elements when Chargebee.registerAgain() scans the DOM. initChargebee was guarded by a one-shot initialised flag, so registerAgain() only ran once. The toggle in Payment.tsx remounts PaymentButton (its key is the data-cb-plan-id), and the freshly rendered buttons never get wired up.

Fix: keep the one-time work (Chargebee.init, first-promoter, checkout callbacks, plan-cookie flow) behind the initialised guard, split it out as initChargebee, and have the new exported bindChargebeeButtons call Chargebee.registerAgain() on every entry. Add yearly to the effect's dependency array so the scan re-runs after the toggle.

Also adds a new @saas E2E marker for SaaS-only tests (billing, trials, payments), wired into the staging and production E2E runs, and a dedicated e2e_billing_user seeded on a Free-plan organisation so the trial-button path under test is actually reachable.

How did you test this code?

Added frontend/e2e/tests/billing-test.pw.ts (tagged @saas). It logs in as e2e_billing_user, stubs window.Chargebee via addInitScript so registerAgain() records which data-cb-plan-id is clicked, and asserts the trial button fires a checkout in yearly → monthly → yearly order. Without the fix the second click records nothing; with the fix all three are recorded.

Ran the test manually against real Vercel deployments:

  • staging.flagsmith.com (main, unfixed) — test fails at the expected assertion. Yearly click records startup-annual-v2, toggle to monthly, click records nothing: ["startup-annual-v2"] vs expected ["startup-annual-v2", "startup-v2"]. Bug reproduced.
  • PR's Vercel staging preview (this branch, fixed) — test passes end to end: login, billing tab, toggle yearly → monthly → yearly, all three clicks recorded. 6.6s.

Manual smoke in-browser: billing tab, click "14 Day Free Trial" in yearly (opens checkout), toggle to monthly and click (opens checkout), toggle back to yearly and click (opens checkout).

Follow-up

Hooking @saas tests up to run against Vercel PR previews on every PR (not just staging/prod deploys) will come in a separate PR — it needs a workflow that waits for the Vercel preview to finish and passes its URL to the composite E2E action, which is out of scope for this bug fix.

…onthly

Chargebee's DOM-scan registration (`registerAgain`) only ran on the
first `initChargebee` call, so the `PaymentButton` instances remounted
by the yearly/monthly toggle picked up no click handler and silently
did nothing.

Call `registerAgain` on every `initChargebee` entry (one-time init
stays guarded) and re-run the effect when the toggle changes.

beep boop
@khvn26 khvn26 requested a review from a team as a code owner April 24, 2026 10:27
@khvn26 khvn26 requested review from talissoncosta and removed request for a team April 24, 2026 10:27
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization's overage spend limit has been reached.

Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.

Once credits are available, reopen this pull request to trigger a review.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
flagsmith-frontend-preview Ready Ready Preview, Comment Apr 24, 2026 11:34am
flagsmith-frontend-staging Ready Ready Preview, Comment Apr 24, 2026 11:34am
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview Apr 24, 2026 11:34am

Request Review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 24, 2026

Docker builds report

Image Build Status Security report
ghcr.io/flagsmith/flagsmith-api-test:pr-7335 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-e2e:pr-7335 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-api:pr-7335 Finished ✅ Results
ghcr.io/flagsmith/flagsmith:pr-7335 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-private-cloud:pr-7335 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-frontend:pr-7335 Finished ✅ Results

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 24, 2026

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  20.1 seconds
commit  37c8fb5
info  🔄 Run: #16313 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  54.3 seconds
commit  37c8fb5
info  🔄 Run: #16313 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  18 passed

Details

stats  18 tests across 15 suites
duration  52.1 seconds
commit  37c8fb5
info  🔄 Run: #16313 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  18 passed

Details

stats  18 tests across 15 suites
duration  59.5 seconds
commit  37c8fb5
info  🔄 Run: #16313 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  24.1 seconds
commit  239f6ad
info  🔄 Run: #16314 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  33.3 seconds
commit  239f6ad
info  🔄 Run: #16314 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  17 passed

Details

stats  17 tests across 14 suites
duration  1 minute, 3 seconds
commit  239f6ad
info  🔄 Run: #16314 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  45.7 seconds
commit  239f6ad
info  🔄 Run: #16314 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  43.9 seconds
commit  832c145
info  🔄 Run: #16316 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  50.5 seconds
commit  832c145
info  🔄 Run: #16316 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  17 passed

Details

stats  17 tests across 14 suites
duration  1 minute, 2 seconds
commit  832c145
info  🔄 Run: #16316 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  51.3 seconds
commit  832c145
info  🔄 Run: #16316 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  7.5 seconds
commit  abdc85b
info  🔄 Run: #16318 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  30 seconds
commit  abdc85b
info  🔄 Run: #16318 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  17 passed

Details

stats  17 tests across 14 suites
duration  1 minute, 2 seconds
commit  abdc85b
info  🔄 Run: #16318 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  54.6 seconds
commit  abdc85b
info  🔄 Run: #16318 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  24.7 seconds
commit  11045aa
info  🔄 Run: #16319 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  29.6 seconds
commit  11045aa
info  🔄 Run: #16319 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  17 passed

Details

stats  17 tests across 14 suites
duration  53.6 seconds
commit  11045aa
info  🔄 Run: #16319 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  46.8 seconds
commit  11045aa
info  🔄 Run: #16319 (attempt 1)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 24, 2026

Visual Regression

16 screenshots compared. See report for details.
View full report

Billing only exists on SaaS (Chargebee, trial buttons, paid plan
toggles), so the @enterprise tag was a misnomer: private-cloud builds
don't ship payments and the runtime flag-guard skipped the test there
anyway.

Introduce a @SaaS marker and wire it into the staging/production E2E
runs alongside @oss and @enterprise, so the same grep makes intent
explicit and leaves private-cloud runs free of payments-only tests.

beep boop
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.42%. Comparing base (bc6ec16) to head (11045aa).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7335   +/-   ##
=======================================
  Coverage   98.42%   98.42%           
=======================================
  Files        1393     1393           
  Lines       52304    52304           
=======================================
  Hits        51481    51481           
  Misses        823      823           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Zaimwa9
Zaimwa9 previously approved these changes Apr 24, 2026
Copy link
Copy Markdown
Contributor

@Zaimwa9 Zaimwa9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving with a NIT and a small refacto that I leave up to you.

And good call adding the E2E

Comment thread frontend/e2e/tests/billing-test.pw.ts Outdated
Comment thread frontend/web/components/modals/payment/chargebee.ts Outdated
PaymentButton only hits the Chargebee DOM-scan branch (where the bug
lives) when the organisation has no active subscription. e2e_user's
org is seeded on Enterprise with a live subscription_id for the rest
of the suite, so billing tests can't reach the buggy code path on it.

Add e2e_billing_user on its own organisation, leaving the default
Free-plan Subscription the Organisation hook creates untouched, and
switch billing-test.pw.ts to that user.

beep boop
@khvn26 khvn26 requested a review from a team as a code owner April 24, 2026 11:07
@khvn26 khvn26 requested review from emyller and removed request for a team April 24, 2026 11:07
@github-actions github-actions Bot added api Issue related to the REST API fix and removed fix labels Apr 24, 2026
…ebee

Keep initChargebee focused on the one-time init (init, checkout
callbacks, plan-cookie flow) and let the exported entry point read
as what callers are actually asking for — wire the currently rendered
Chargebee buttons.

beep boop
Copy link
Copy Markdown
Contributor

@Zaimwa9 Zaimwa9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks! 💯

Good call to separate user and orgs in the seed

@khvn26 khvn26 merged commit 1fee291 into main Apr 24, 2026
41 checks passed
@khvn26 khvn26 deleted the fix/billing-trial-buttons-after-toggle branch April 24, 2026 11:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Issue related to the REST API fix front-end Issue related to the React Front End Dashboard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants