Skip to content

Conversation

@panteliselef
Copy link
Contributor

@panteliselef panteliselef commented Jun 11, 2025

Description

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • New Features
    • Enhanced error messages for subscription plan changes, now displaying detailed plan information when a change is not allowed.
  • Bug Fixes
    • Improved reliability of the billing period toggle in the pricing table to ensure accurate selection.
  • Refactor
    • Streamlined checkout and error handling logic for clearer and more maintainable code.
  • Tests
    • Added a new test to verify that users receive a notice when attempting to switch to a disallowed plan or billing period.

@panteliselef panteliselef self-assigned this Jun 11, 2025
@changeset-bot
Copy link

changeset-bot bot commented Jun 11, 2025

🦋 Changeset detected

Latest commit: 49eaec2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 22 packages
Name Type
@clerk/testing Patch
@clerk/clerk-js Patch
@clerk/shared Patch
@clerk/types Patch
@clerk/chrome-extension Patch
@clerk/clerk-expo Patch
@clerk/agent-toolkit Patch
@clerk/astro Patch
@clerk/backend Patch
@clerk/elements Patch
@clerk/expo-passkeys Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/clerk-react Patch
@clerk/remix Patch
@clerk/tanstack-react-start Patch
@clerk/vue Patch
@clerk/localizations Patch
@clerk/themes Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Jun 11, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
clerk-js-sandbox ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 11, 2025 9:15pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 11, 2025

📝 Walkthrough

Walkthrough

The changes introduce a new test for subscription plan restrictions, refactor the pricing table page object for better modularity, and enhance error handling by including plan details in error metadata. Several UI components are updated to extract and display plan information from error objects, and related type definitions are extended to support the new error metadata structure. Additionally, plan-related state and logic are removed from the checkout page component, and the invalid plan error component is renamed and refactored to use error metadata.

Changes

Files/Paths Change Summary
integration/tests/pricing-table.test.ts Added a test verifying that users are notified when attempting to change to a restricted plan/payment period.
packages/testing/src/playwright/unstable/page-objects/pricingTable.ts Refactored pricing table page object: introduced BillingPeriod type, centralized locators, added ensurePricingPeriod helper, improved toggle logic, and cleaned up method usage.
packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx Removed all plan/plans state and logic from checkout context and loading/error handling; simplified state management.
packages/clerk-js/src/ui/components/Checkout/parts.tsx Renamed InvalidPlanError to InvalidPlanScreen; now derives plan info from error metadata using useMemo; updated rendering logic and property names.
packages/clerk-js/src/ui/components/Checkout/index.tsx Updated import and usage from InvalidPlanError to InvalidPlanScreen for the invalid plan change stage.
packages/shared/src/error.ts Added support for a plan field in error metadata; updated error parsing and serialization.
packages/types/src/api.ts Extended ClerkAPIError.meta to optionally include a plan object with formatted amount, currency, id, and name fields.
packages/types/src/json.ts Extended ClerkAPIErrorJSON.meta to optionally include a plan object with formatted amount, currency, id, and name fields.
.changeset/itchy-keys-shake.md Fixed bug in pricing table test helper to correctly match requested billing period toggle state in startCheckout.
.changeset/rotten-ghosts-build.md Documented patch update for handling invalid plan change screen using error metadata in checkout.
.changeset/sad-lines-share.md Documented patch update adding partial plan field parsing in error metadata for improved error handling.
packages/clerk-js/bundlewatch.config.json Increased max allowed bundle size for clerk.browser.js from 69.2KB to 69.3KB.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8928416 and 82e8afd.

📒 Files selected for processing (1)
  • packages/testing/src/playwright/unstable/page-objects/pricingTable.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/testing/src/playwright/unstable/page-objects/pricingTable.ts
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Build Packages
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: semgrep/ci
  • GitHub Check: Analyze (javascript-typescript)
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jun 11, 2025

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@6102

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@6102

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@6102

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@6102

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@6102

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@6102

@clerk/elements

npm i https://pkg.pr.new/@clerk/elements@6102

@clerk/clerk-expo

npm i https://pkg.pr.new/@clerk/clerk-expo@6102

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@6102

@clerk/express

npm i https://pkg.pr.new/@clerk/express@6102

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@6102

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@6102

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@6102

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@6102

@clerk/clerk-react

npm i https://pkg.pr.new/@clerk/clerk-react@6102

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@6102

@clerk/remix

npm i https://pkg.pr.new/@clerk/remix@6102

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@6102

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@6102

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@6102

@clerk/themes

npm i https://pkg.pr.new/@clerk/themes@6102

@clerk/types

npm i https://pkg.pr.new/@clerk/types@6102

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@6102

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@6102

commit: 49eaec2

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🔭 Outside diff range comments (1)
packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx (1)

92-105: 🛠️ Refactor suggestion

useMemo dependency list & error scan need tightening

  1. checkout?.status is redundant in the deps array because checkout already covers identity changes; conversely, if the same object is reused but the status mutates internally, React cannot detect it. Prefer deriving status outside the object or always replacing the object.

  2. Only errors?.[0] is inspected for invalid_plan_change, risking mis-classification (cf. comment in parts.tsx). Use errors?.some(e => e.code === invalidChangeCode) instead.

  3. useEffect(() => void startCheckout(), []) never re-fires when planId/planPeriod change. If the user toggles plans in the UI, the checkout flow will remain stale. Add them to the dependency list or document immutability.

♻️ Duplicate comments (1)
packages/shared/src/error.ts (1)

103-116: ```diff

  •  plan: error?.meta?.plan,
    
  •  ...(error?.meta?.plan ? { plan: error.meta.plan } : {}),
    
Apply to keep JSON minimal.

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>packages/shared/src/error.ts (2)</summary><blockquote>

`87-100`: **Only include `plan` in `meta` when present.**

Serialising `plan: undefined` pollutes the payload and may break strict back-end schemas. Add a conditional spread instead:

```diff
-      plan: error?.meta?.plan,
+      ...(error?.meta?.plan ? { plan: error.meta.plan } : {}),

Replicate the same pattern in errorToJSON.


273-275: Delete or fill the empty JSDoc block.

An empty comment triggers lint/docs tooling noise. Either document buildErrorThrower or remove these lines.

-/**
- *
- */
+
integration/tests/pricing-table.test.ts (1)

320-351: Make the assertion resilient to localization changes.

The test matches an exact English sentence; if copy or locales change the suite will become flaky. Consider asserting on the presence of the info Alert element or the error code instead:

await expect(
  page.locator('.cl-checkout-root [data-test-id="invalid-plan-change-alert"]'),
).toBeVisible();

(where the component exposes data-test-id).

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4118ed7 and 985bcf6.

📒 Files selected for processing (8)
  • integration/tests/pricing-table.test.ts (1 hunks)
  • packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx (3 hunks)
  • packages/clerk-js/src/ui/components/Checkout/index.tsx (2 hunks)
  • packages/clerk-js/src/ui/components/Checkout/parts.tsx (3 hunks)
  • packages/shared/src/error.ts (3 hunks)
  • packages/testing/src/playwright/unstable/page-objects/pricingTable.ts (2 hunks)
  • packages/types/src/api.ts (1 hunks)
  • packages/types/src/json.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
packages/clerk-js/src/ui/components/Checkout/index.tsx (1)
packages/clerk-js/src/ui/components/Checkout/parts.tsx (1)
  • InvalidPlanScreen (39-95)
integration/tests/pricing-table.test.ts (1)
integration/testUtils/index.ts (1)
  • createTestUtils (23-85)
packages/testing/src/playwright/unstable/page-objects/pricingTable.ts (1)
packages/clerk-js/src/ui/styledSystem/common.ts (1)
  • common (204-216)
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Build Packages
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: semgrep/ci
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
packages/clerk-js/src/ui/components/Checkout/index.tsx (2)

10-10: Remove leftover InvalidPlanError exports/imports.

InvalidPlanScreen fully replaces InvalidPlanError; make sure no code path still exports or imports the old component to avoid unused-export/tree-shaking warnings.


42-44: LGTM – new screen wired correctly.

The stage now renders InvalidPlanScreen; matches the new metadata-driven flow and keeps JSX tidy.

packages/types/src/json.ts (1)

352-358: Verify naming consistency against API contract.

All other meta fields in JSON are snake_case; the new nested fields (annual_monthly_amount_formatted, etc.) keep that style—good. Confirm the back-end really returns strings for formatted amounts (not numbers) to avoid runtime coercion.

packages/types/src/api.ts (1)

32-38: LGTM – runtime type extended.

plan is optional and mirrors the JSON interface; keeps parsing type-safe.

packages/testing/src/playwright/unstable/page-objects/pricingTable.ts (1)

20-24: Toggle-state heuristic may be inverted

data-checked === 'true' is mapped to monthly. If the design system flips the semantic (checked ⇢ annual), the helper silently sets the wrong period.
Consider reading an explicit data-period attribute or the visible price label instead of boolean state.

Comment on lines +74 to 81
title={planFromError.name}
description={planPeriod === 'annual' ? localizationKeys('commerce.billedAnnually') : undefined}
/>
<LineItems.Description
prefix={planPeriod === 'annual' ? 'x12' : undefined}
text={`${plan.currencySymbol}${planPeriod === 'month' ? plan.amountFormatted : plan.annualMonthlyAmountFormatted}`}
text={`${planFromError.currency_symbol}${planPeriod === 'month' ? planFromError.amount_formatted : planFromError.annual_monthly_amount_formatted}`}
suffix={localizationKeys('commerce.checkout.perMonth')}
/>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Missing null-guards for optional plan fields

planFromError.currency_symbol, amount_formatted, annual_monthly_amount_formatted are all optional according to the API typings.
If the backend omits any of them the component will crash during render.

Guard or provide fallbacks, e.g.

- text={`${planFromError.currency_symbol}${planPeriod === 'month' ? planFromError.amount_formatted : planFromError.annual_monthly_amount_formatted}`}
+ text={`${planFromError?.currency_symbol ?? ''}${planPeriod === 'month'
+   ? planFromError?.amount_formatted ?? '--'
+   : planFromError?.annual_monthly_amount_formatted ?? '--'}`}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
title={planFromError.name}
description={planPeriod === 'annual' ? localizationKeys('commerce.billedAnnually') : undefined}
/>
<LineItems.Description
prefix={planPeriod === 'annual' ? 'x12' : undefined}
text={`${plan.currencySymbol}${planPeriod === 'month' ? plan.amountFormatted : plan.annualMonthlyAmountFormatted}`}
text={`${planFromError.currency_symbol}${planPeriod === 'month' ? planFromError.amount_formatted : planFromError.annual_monthly_amount_formatted}`}
suffix={localizationKeys('commerce.checkout.perMonth')}
/>
title={planFromError.name}
description={planPeriod === 'annual' ? localizationKeys('commerce.billedAnnually') : undefined}
/>
<LineItems.Description
prefix={planPeriod === 'annual' ? 'x12' : undefined}
text={`${planFromError?.currency_symbol ?? ''}${planPeriod === 'month'
? planFromError?.amount_formatted ?? '--'
: planFromError?.annual_monthly_amount_formatted ?? '--'}`}
suffix={localizationKeys('commerce.checkout.perMonth')}
/>
🤖 Prompt for AI Agents
In packages/clerk-js/src/ui/components/Checkout/parts.tsx around lines 74 to 81,
the properties planFromError.currency_symbol, amount_formatted, and
annual_monthly_amount_formatted are optional and may be undefined, which can
cause the component to crash during render. Add null-guards or provide default
fallback values (such as empty strings) when accessing these fields to ensure
the component handles missing data gracefully without crashing.

@panteliselef panteliselef merged commit 48be55b into main Jun 12, 2025
37 checks passed
@panteliselef panteliselef deleted the elef/invalid-plan-change-screen-to-use-data-from-error branch June 12, 2025 09:08
wobsoriano pushed a commit that referenced this pull request Jun 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants