Skip to content

Commit e78c73e

Browse files
authored
feat(clerk-js,types): Display trial subscriptions in profiles (#6526)
1 parent 47e7049 commit e78c73e

File tree

6 files changed

+383
-3
lines changed

6 files changed

+383
-3
lines changed

.changeset/fresh-breads-fall.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+
Display trial subscriptions in UserProfile and OrganizationProfile.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ function Card(props: CardProps) {
240240
? localizationKeys('badge__trialEndsAt', {
241241
date: subscription.periodEnd,
242242
})
243-
: localizationKeys('badge__startsAt', { date: subscription?.periodStart })
243+
: localizationKeys('badge__startsAt', { date: subscription.periodStart })
244244
}
245245
colorScheme='secondary'
246246
sx={t => ({

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

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,66 @@ describe('PricingTable - trial info', () => {
174174
expect(getByText('Subscribe')).toBeVisible();
175175
});
176176
});
177+
178+
it('shows footer notice with "starts at" when subscription is upcoming and not a free trial', async () => {
179+
const { wrapper, fixtures, props } = await createFixtures(f => {
180+
f.withUser({ email_addresses: ['test@clerk.com'] });
181+
});
182+
183+
// Provide empty props to the PricingTable context
184+
props.setProps({});
185+
186+
const nonTrialPlan = {
187+
...trialPlan,
188+
freeTrialEnabled: false,
189+
freeTrialDays: 0,
190+
};
191+
192+
fixtures.clerk.billing.getPlans.mockResolvedValue({ data: [nonTrialPlan as any], total_count: 1 });
193+
fixtures.clerk.billing.getSubscription.mockResolvedValue({
194+
id: 'sub_1',
195+
status: 'active',
196+
activeAt: new Date('2021-01-01'),
197+
createdAt: new Date('2021-01-01'),
198+
nextPayment: null,
199+
pastDueAt: null,
200+
updatedAt: null,
201+
subscriptionItems: [
202+
{
203+
id: 'si_1',
204+
plan: nonTrialPlan,
205+
createdAt: new Date('2021-01-01'),
206+
paymentSourceId: 'src_1',
207+
pastDueAt: null,
208+
canceledAt: null,
209+
periodStart: new Date('2021-02-01'),
210+
periodEnd: new Date('2021-02-15'),
211+
planPeriod: 'month' as const,
212+
status: 'upcoming' as const,
213+
isFreeTrial: false,
214+
cancel: jest.fn(),
215+
pathRoot: '',
216+
reload: jest.fn(),
217+
},
218+
],
219+
pathRoot: '',
220+
reload: jest.fn(),
221+
});
222+
223+
const { findByRole, getByText, userEvent } = render(<PricingTable />, { wrapper });
224+
225+
// Wait for the plan to appear
226+
await findByRole('heading', { name: 'Pro' });
227+
228+
// Default period is annual in mounted mode; switch to monthly to match the subscription
229+
const periodSwitch = await findByRole('switch', { name: /billed annually/i });
230+
await userEvent.click(periodSwitch);
231+
232+
await waitFor(() => {
233+
// Non-trial upcoming subscription uses badge__startsAt localization
234+
expect(getByText('Starts Feb 1, 2021')).toBeVisible();
235+
});
236+
});
177237
});
178238

179239
describe('PricingTable - plans visibility', () => {

packages/clerk-js/src/ui/components/Subscriptions/SubscriptionsList.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,9 @@ function SubscriptionRow({ subscription, length }: { subscription: CommerceSubsc
162162
>
163163
{subscription.plan.name}
164164
</Text>
165-
{length > 1 || subscription.canceledAt !== null ? <SubscriptionBadge subscription={subscription} /> : null}
165+
{subscription.isFreeTrial || length > 1 || !!subscription.canceledAt ? (
166+
<SubscriptionBadge subscription={subscription.isFreeTrial ? { status: 'free_trial' } : subscription} />
167+
) : null}
166168
</Flex>
167169

168170
{(!subscription.plan.isDefault || subscription.status === 'upcoming') && (

0 commit comments

Comments
 (0)