[web] Add cancel-loss-messaging split test (#36363)

* [web] Add cancel-loss-messaging split test

Populate the cancel confirmation step with plan-specific losses when the
cancel-loss-messaging split test is enabled: "Are you sure you want to
cancel?" heading, the subscription end date, and a card listing what the
user loses moving to the Free plan (compile timeout, AI, collaborators,
history), with the lost benefit struck through next to its Free-plan
replacement.

Shown only to non-trial Student/Standard/Pro individual subscribers with
no other retention offer (trial extension or downgrade upsell) — those
keep the existing confirmation.

Copy matches the mockups in the ticket. No new analytics events; the
existing subscription-page-cancel-button-click / subscription-cancelled
funnel is used.

Part of #35765

* [web] Consolidate ActiveSubscription stories, add cancel confirmation story

Replace the 13 fixture-per-story exports with a single Dashboard story
driven by controls (subscription fixture select, flexible licensing,
cancel-loss-messaging variant), using the CSF factories pattern. Add a
CancelConfirmation story that renders the cancel confirmation step
directly so the cancel-loss-messaging variant can be previewed without
clicking through, with a Professional fixture available to see the Pro
loss rows.

* [web] Use withSplitTests for the ActiveSubscription stories

Register cancel-loss-messaging in defaultSplitTestsArgTypes and drive the
stories' variant from the shared withSplitTests decorator (radio control,
SplitTestContext provided from args) instead of hand-rolled meta tags and
SplitTestProvider. Generalize withSplitTests' typing so it composes with
CSF factories (preview.meta) as well as legacy meta objects.

* [web] Fix Storybook indexing of the ActiveSubscription stories

Storybook's static CSF indexer requires preview.meta() to receive an
object literal, so spread withSplitTests' argTypes/decorators into the
meta literal instead of wrapping the whole config in the helper call.

* [web] Compose ActiveSubscription stories from orthogonal controls

- Wrap the stories in #subscription-dashboard-root so the dashboard's
  scoped styles (e.g. the cancel-loss strikethrough) apply in Storybook
- Replace the single fixture dropdown with independent controls (group,
  plan, period, currency, trial, status, pending plan change, add-ons,
  coupons, pending license change), building the subscription from the
  fixtures' base + patches
- Guard impossible mixes with argTypes `if` conditions: individual-only
  controls hide when group is on, and pendingLicenseChange only shows
  for groups

* [web] Add student plan to the ActiveSubscription story controls

The cancel-loss-messaging variant has student-specific rows (AI
Assistant / 10 collaborators), so the plan control needs a student
option. Groups have no student plans, so for group subscriptions the
student choice maps to the Standard group fixture.

* [web] Provide ol-plans in the ActiveSubscription stories

The cancel confirmation's downgrade branch (monthly Standard is
isEligibleForDowngradeUpsell) looks up paid-personal in ol-plans and
spins forever when the meta tag is missing. Provide ol-plans and
ol-groupPlans from the fixtures, matching the test render helper.

GitOrigin-RevId: e8491c8d39ed059e42ea3442e8d70c3ef304b009
This commit is contained in:
Antoine Clausse
2026-09-17 11:52:02 +00:00
committed by Copybot
parent dac6254831
commit 1daed4efe4
7 changed files with 312 additions and 0 deletions
+12
View File
@@ -154,6 +154,8 @@
"ai_assist_unavailable": "AI features are now included in every paid plan. See the <0>pricing page</0> for what each plan includes.",
"ai_assistance": "AI assistance",
"ai_assistant": "AI Assistant",
"ai_assistant_and_higher_ai_allowance": "AI Assistant and higher AI allowance",
"ai_assistant_and_max_ai_allowance": "AI Assistant and max AI allowance",
"ai_assistant_disabled": "AI Assistant disabled",
"ai_assistant_explanation": "A LaTeX-fluent AI Assistant built into your editor.",
"ai_can_make_mistakes": "AI can make mistakes. Review fixes before you apply them.",
@@ -228,6 +230,7 @@
"are_you_affiliated_with_an_institution": "Are you affiliated with an institution?",
"are_you_getting_an_undefined_control_sequence_error": "Are you getting an Undefined Control Sequence error? If you are, make sure you’ve loaded the graphicx package—<0>\\usepackage{graphicx}</0>—in the preamble (first section of code) in your document. <1>Learn more</1>",
"are_you_still_at": "Are you still at <0>__institutionName__</0>?",
"are_you_sure_you_want_to_cancel": "Are you sure you want to cancel?",
"are_you_sure_you_want_to_cancel_add_on": "Are you sure you want to cancel the <strong>__addOnName__</strong> add-on?",
"article": "Article",
"articles": "Articles",
@@ -272,6 +275,7 @@
"basic_ai_allowance_tooltip": "5 AI uses per day across available AI tools.",
"basic_compile_time": "Basic compile time",
"basic_compile_timeout": "Basic compile timeout",
"basic_compile_timeout_for_small_projects": "Basic compile timeout (for small projects)",
"basic_compile_timeout_on_fast_servers": "Basic compile timeout on fast servers",
"been_offline_changes_saved_in_browser": "You’ve been offline for a while. Your changes are saved in the browser.",
"before_you_use_error_assistant": "Before you use Error Assist",
@@ -329,6 +333,7 @@
"cancel_personal_subscription_first": "You already have an individual subscription, would you like us to cancel this first before joining the group licence?",
"cancel_subscription": "Cancel subscription",
"cancel_your_subscription": "Cancel your subscription",
"cancelling_will_end_your_subscription_on": "Cancelling will end your subscription on __terminationDate__.",
"cannot_invite_non_user": "Can’t send invite. Recipient must already have an __appName__ account",
"cannot_invite_self": "Can’t send invite to yourself",
"cannot_verify_user_not_robot": "Sorry, we could not verify that you are not a robot. Please check that Google reCAPTCHA is not being blocked by an ad blocker or firewall.",
@@ -993,6 +998,7 @@
"from_your_project": "From your project",
"full_doc_history": "Full document history",
"full_document_history": "Full document <0>history</0>",
"full_project_history": "Full project history",
"full_width": "Full width",
"future_payments": "Future payments",
"gallery": "Gallery",
@@ -1153,6 +1159,7 @@
"hide_outline": "Hide File outline",
"higher_ai_allowance": "Higher AI allowance",
"history": "History",
"history_24_hours_only": "24 hours history only",
"history_add_label": "Add label",
"history_are_you_sure_delete_label": "Are you sure you want to delete the following label",
"history_compare_from_this_version": "Compare from this version",
@@ -1376,6 +1383,7 @@
"kb_suggestions_enquiry": "Have you checked our <0>__kbLink__</0>?",
"keep_current_plan": "Keep my current plan",
"keep_personal_projects_separate": "Keep personal projects separate",
"keep_subscription": "Keep subscription",
"keep_your_account_safe": "Keep your account safe",
"keep_your_account_safe_add_another_email": "Keep your account safe and make sure you don’t lose access to it by adding another email address.",
"keep_your_email_updated": "Keep your email updated so that you don’t lose access to your account and data.",
@@ -1703,6 +1711,7 @@
"no": "Norwegian",
"no_actions": "No actions",
"no_add_on_purchase_while_paused": "You need to unpause or cancel your existing subscription to buy an add-on.",
"no_ai_assistant": "No AI Assistant",
"no_articles_matching_your_tags": "There are no articles matching your tags",
"no_audit_logs_found": "No audit logs found",
"no_borders": "No borders",
@@ -1929,6 +1938,7 @@
"pl": "Polish",
"plan": "Plan",
"plan_24x_basic_compile_timeout": "24x Basic compile timeout",
"plan_24x_longer_compile_timeout": "24x longer compile timeout",
"plan_tooltip": "You’re on the __plan__ plan. Click to find out how to make the most of your Overleaf premium features.",
"planned_maintenance": "Planned Maintenance",
"plans_and_pricing": "Plans and Pricing",
@@ -2461,6 +2471,7 @@
"skip_welcome_animation": "Skip animation and continue",
"slash_month": "/month",
"slash_year": "/year",
"small_ai_allowance_no_assistant": "Small AI allowance (no Assistant)",
"solutions": "Solutions",
"some_dois_could_not_be_resolved": "Some or all DOIs could not be resolved.",
"something_not_right": "Something’s not right",
@@ -3209,6 +3220,7 @@
"you_unpaused_your_subscription": "You unpaused your subscription.",
"you_will_be_able_to_contact_us_any_time_to_share_your_feedback": "<0>You will be able to contact us</0> any time to share your feedback",
"you_will_be_able_to_reassign_subscription": "You will be able to reassign their subscription membership to another person in your organization",
"youll_be_moved_to_the_free_plan": "You’ll be moved to the Free plan",
"youll_get_best_results_in_visual_but_can_be_used_in_source": "You’ll get the best results from using this tool in the <0>Visual Editor</0>, although you can still use it to insert tables in the <1>Code Editor</1>. Once you’ve selected the number of rows and columns you need, the table will appear in your document and you can double click in a cell to add contents to it.",
"youll_need_to_ask_the_github_repository_owner": "You’ll need to ask the GitHub repository owner (<0>__repoOwnerEmail__</0>) to reconnect the project.",
"youll_no_longer_need_to_remember_credentials": "You’ll no longer need to remember a separate email address and password. Instead, you will use single-sign on to login to Overleaf. <0>Read more about SSO</0>.",