SCHY-390 default initializeWithPlan to trial when available#1282
Conversation
initializeWithPlan bypasses the plan stage where the "Start X day trial" button normally lives, so customers using the documented bypass flow were landing on a paid subscription even when the plan offered a trial and the company was eligible. Adds a `startTrialIfAvailable` flag on `BypassConfig` (defaults to true) and pipes it through `CheckoutState`. The auto-init effect in `CheckoutDialog` now opts the company into trial mode when the flag is true and the selected plan is trialable. Callers can preserve the charge-immediately behavior by passing `startTrialIfAvailable: false`. Refs SCH-6507. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
isTrialable and companyCanTrial on the plan are already non-optional booleans, and the chain is part of an && expression, so the !! casts and ?? false were noise. Use the && result directly as shouldTrial. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ptions-with-no-trial-period
The legacy-string, pre-selection, and optional-planId tests are checking other concerns; switch them to toMatchObject (matching the style of the rest of the file) so adding new fields to checkoutState doesn't force edits here. The dedicated `startTrialIfAvailable configuration` block still covers the default and the explicit-false opt-out. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
🚀 Components Preview Deployed! 📍 Preview URL: https://schematic-next-example-5k2e1x2kj-schematichq.vercel.app |
…ptions-with-no-trial-period
|
🚀 Components Preview Deployed! 📍 Preview URL: https://schematic-next-example-h7hcbi4tl-schematichq.vercel.app |
| const shouldTrial = | ||
| checkoutState?.startTrialIfAvailable && | ||
| selectedPlan.isTrialable && | ||
| selectedPlan.companyCanTrial; |
There was a problem hiding this comment.
I am hesitant to put a sub-field of checkoutState in the dependencies array here.
startTrialIfAvailable is a new parameter of initializeWithPlan, and maybe we can rely on it never changing once a checkout is initiated. The initializeWithPlan function is meant to be called once.
That said, if this doesn't hurt, it's no big deal. But fewer deps is better.
There was a problem hiding this comment.
ya, i debated that a bit. not including it feels like a potential subtle bug, but I agree it'd be vv weird if that value ever changed.
want me to remove and leave an inline comment? it might trigger lint issues as well (we can suppress)
There was a problem hiding this comment.
Let's remove and suppress the lint. If we can get away with it, let's avoid another dep.
The value is set once by initializeWithPlan via SET_PLANID_BYPASS and stays stable for the dialog's lifetime, and the hasInitializedPlan ref already guards the effect to run exactly once. Listing the flag as a dep just churns the diff without changing behavior. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
🚀 Components Preview Deployed! 📍 Preview URL: https://schematic-next-example-qnei5qv2k-schematichq.vercel.app |
|
@ryanechternacht @tenub This bugfix from Ryan introduces a behavior change that is not backwards compatible. This will be a minor version bump, I think. |
) When the pre-selected plan offers a trial and the company is eligible, initializeWithPlan now starts checkout in trial mode by default to match the in-dialog "Start trial" button. Documents the new `startTrialIfAvailable` option (defaults to true, set to false to charge immediately) on the bypass config. Companion to SchematicHQ/schematic-js#1282. Refs SCH-6507. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
https://linear.app/schematic/issue/SCHY-390/trial-checkout-creates-subscriptions-with-no-trial-period
Summary
initializeWithPlanskips the plan stage where the "Start X day trial" button normally lives, so customers using the documented bypass flow landed on a paid subscription even when the plan offered a trial and the company was eligible.startTrialIfAvailableflag onBypassConfig(defaults totrue) and pipes it throughCheckoutState. The auto-init effect inCheckoutDialognow opts the company into trial mode when the flag is true and the selected plan is trialable. Callers can preserve the charge-immediately behavior by passingstartTrialIfAvailable: false.initializeWithPlanwhose pre-selected plan is trialable for the current company will now land in trial mode by default. PassstartTrialIfAvailable: falseto keep the old behavior.Refs SCH-6507.
Test plan
yarn test --runpasses (301 passed, 4 skipped, no type errors)BypassConfigand the legacy string form, plus the explicitfalseopt-outinitializeWithPlan('plan_trialable')lands in trial mode in checkoutinitializeWithPlan({ planId: 'plan_trialable', startTrialIfAvailable: false })charges immediatelyinitializeWithPlan('plan_non_trialable')charges immediately (no regression)🤖 Generated with Claude Code