Skip to content

Commit 2b18d7a

Browse files
fix(clerk-js): Correctly pass newSubscriptionRedirectUrl to checkout drawer (#5909)
1 parent 68a7b40 commit 2b18d7a

10 files changed

Lines changed: 82 additions & 11 deletions

File tree

.changeset/tangy-facts-poke.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/clerk-js': patch
3+
---
4+
5+
Fixes `newSubscriptionRedirectUrl` usage on `PricingTable`.
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
---
2-
import { PricingTable } from "@clerk/astro/components";
3-
import Layout from "../layouts/Layout.astro";
2+
import { PricingTable } from '@clerk/astro/components';
3+
import Layout from '../layouts/Layout.astro';
4+
5+
const newSubscriptionRedirectUrl = Astro.url.searchParams.get('newSubscriptionRedirectUrl');
46
---
57

6-
<Layout title="Pricing Table">
7-
<div class="w-full flex justify-center">
8-
<PricingTable />
8+
<Layout title='Pricing Table'>
9+
<div class='w-full flex justify-center'>
10+
<PricingTable newSubscriptionRedirectUrl={newSubscriptionRedirectUrl} />
911
</div>
1012
</Layout>
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { PricingTable } from '@clerk/nextjs';
22

3-
export default function PricingTablePage() {
4-
return <PricingTable />;
3+
export default async function PricingTablePage({
4+
searchParams,
5+
}: {
6+
searchParams: Promise<{ newSubscriptionRedirectUrl: string }>;
7+
}) {
8+
const newSubscriptionRedirectUrl = (await searchParams).newSubscriptionRedirectUrl;
9+
return <PricingTable newSubscriptionRedirectUrl={newSubscriptionRedirectUrl} />;
510
}
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
<template>
2-
<PricingTable />
2+
<PricingTable :newSubscriptionRedirectUrl="newSubscriptionRedirectUrl" />
33
</template>
4+
5+
<script setup>
6+
import { useRoute } from 'vue-router';
7+
8+
const route = useRoute();
9+
const newSubscriptionRedirectUrl = route.query.newSubscriptionRedirectUrl;
10+
</script>
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
<script setup lang="ts">
22
import { PricingTable } from '@clerk/vue';
3+
import { useRoute } from 'vue-router';
4+
5+
const route = useRoute();
6+
const newSubscriptionRedirectUrl = route.query.newSubscriptionRedirectUrl as string;
37
</script>
48

59
<template>
6-
<PricingTable />
10+
<PricingTable :newSubscriptionRedirectUrl="newSubscriptionRedirectUrl" />
711
</template>

integration/tests/pricing-table.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,42 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl
104104
// await expect(u.po.page.getByRole('button', { name: /resubscribe|re-subscribe/i }).first()).toBeVisible();
105105
// });
106106

107+
test.describe('redirects', () => {
108+
test('default navigates to afterSignInUrl', async ({ page, context }) => {
109+
const u = createTestUtils({ app, page, context });
110+
await u.po.signIn.goTo();
111+
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password });
112+
await u.po.page.goToRelative('/pricing-table');
113+
await u.po.pricingTable.waitForMounted();
114+
await u.po.pricingTable.startCheckout({ planSlug: 'pro' });
115+
await u.po.checkout.waitForMounted();
116+
await u.po.checkout.clickPayOrSubscribe();
117+
await expect(u.po.page.getByText('Success!')).toBeVisible();
118+
await page
119+
.locator('.cl-checkout-root')
120+
.getByRole('button', { name: /^continue$/i })
121+
.click();
122+
await u.page.waitForAppUrl('/');
123+
});
124+
125+
test('navigates to supplied newSubscriptionRedirectUrl', async ({ page, context }) => {
126+
const u = createTestUtils({ app, page, context });
127+
await u.po.signIn.goTo();
128+
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password });
129+
await u.po.page.goToRelative('/pricing-table?newSubscriptionRedirectUrl=/success');
130+
await u.po.pricingTable.waitForMounted();
131+
await u.po.pricingTable.startCheckout({ planSlug: 'plus' });
132+
await u.po.checkout.waitForMounted();
133+
await u.po.checkout.clickPayOrSubscribe();
134+
await expect(u.po.page.getByText('Success!')).toBeVisible();
135+
await page
136+
.locator('.cl-checkout-root')
137+
.getByRole('button', { name: /^continue$/i })
138+
.click();
139+
await u.page.waitForAppUrl('/success');
140+
});
141+
});
142+
107143
test.describe('in UserProfile', () => {
108144
test('renders pricing table with plans', async ({ page, context }) => {
109145
const u = createTestUtils({ app, page, context });

packages/clerk-js/bundlewatch.config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"files": [
3-
{ "path": "./dist/clerk.js", "maxSize": "594.1kB" },
3+
{ "path": "./dist/clerk.js", "maxSize": "594.2kB" },
44
{ "path": "./dist/clerk.browser.js", "maxSize": "68.3KB" },
55
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "110KB" },
66
{ "path": "./dist/clerk.headless*.js", "maxSize": "52KB" },

packages/clerk-js/src/ui/components/PricingTable/PricingTable.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ const PricingTableRoot = (props: PricingTableProps) => {
5656
planPeriod,
5757
event,
5858
appearance: props.checkoutProps?.appearance,
59+
newSubscriptionRedirectUrl: props.newSubscriptionRedirectUrl,
5960
});
6061
return;
6162
};

packages/clerk-js/src/ui/contexts/components/Plans.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ type HandleSelectPlanProps = {
137137
mode?: 'modal' | 'mounted';
138138
event?: React.MouseEvent<HTMLElement>;
139139
appearance?: Appearance;
140+
newSubscriptionRedirectUrl?: string;
140141
};
141142

142143
export const usePlansContext = () => {
@@ -318,7 +319,15 @@ export const usePlansContext = () => {
318319

319320
// handle the selection of a plan, either by opening the subscription details or checkout
320321
const handleSelectPlan = useCallback(
321-
({ plan, planPeriod, onSubscriptionChange, mode = 'mounted', event, appearance }: HandleSelectPlanProps) => {
322+
({
323+
plan,
324+
planPeriod,
325+
onSubscriptionChange,
326+
mode = 'mounted',
327+
event,
328+
appearance,
329+
newSubscriptionRedirectUrl,
330+
}: HandleSelectPlanProps) => {
322331
const subscription = activeOrUpcomingSubscription(plan);
323332

324333
const portalRoot = getClosestProfileScrollBox(mode, event);
@@ -351,6 +360,7 @@ export const usePlansContext = () => {
351360
},
352361
appearance,
353362
portalRoot,
363+
newSubscriptionRedirectUrl,
354364
});
355365
}
356366
},

packages/clerk-js/src/ui/lazyModules/MountedCheckoutDrawer.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export function MountedCheckoutDrawer({
4444
onSubscriptionComplete={checkoutDrawer.props.onSubscriptionComplete}
4545
portalRoot={checkoutDrawer.props.portalRoot}
4646
appearance={checkoutDrawer.props.appearance}
47+
newSubscriptionRedirectUrl={checkoutDrawer.props.newSubscriptionRedirectUrl}
4748
/>
4849
)}
4950
</LazyDrawerRenderer>

0 commit comments

Comments
 (0)