Skip to content

Commit 2fa2a41

Browse files
authored
chore(e2e): Add test cases for billing buttons (#6573)
1 parent 9f0aad2 commit 2fa2a41

File tree

11 files changed

+132
-4
lines changed

11 files changed

+132
-4
lines changed

.changeset/legal-ants-flow.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+
Add class `cl-planDetails-root` to the parent div element that containes the plan details drawer.

.changeset/little-seals-hang.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/testing': patch
3+
---
4+
5+
Add `planDetails` to the page details object.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { SignedIn } from '@clerk/nextjs';
2+
import { CheckoutButton } from '@clerk/nextjs/experimental';
3+
4+
export default function Home() {
5+
return (
6+
<main>
7+
<SignedIn>
8+
<CheckoutButton
9+
planId='cplan_2wMjqdlza0hTJc4HLCoBwAiExhF'
10+
planPeriod='month'
11+
>
12+
Checkout Now
13+
</CheckoutButton>
14+
</SignedIn>
15+
</main>
16+
);
17+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { PlanDetailsButton } from '@clerk/nextjs/experimental';
2+
3+
export default function Home() {
4+
return (
5+
<main>
6+
<PlanDetailsButton planId='cplan_2wMjqdlza0hTJc4HLCoBwAiExhF'>Plan details</PlanDetailsButton>
7+
</main>
8+
);
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { SubscriptionDetailsButton } from '@clerk/nextjs/experimental';
2+
3+
export default function Home() {
4+
return (
5+
<main>
6+
<SubscriptionDetailsButton>Subscription details</SubscriptionDetailsButton>
7+
</main>
8+
);
9+
}

integration/templates/next-app-router/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"noEmit": true,
1010
"esModuleInterop": true,
1111
"module": "esnext",
12-
"moduleResolution": "node",
12+
"moduleResolution": "bundler",
1313
"resolveJsonModule": true,
1414
"isolatedModules": true,
1515
"jsx": "preserve",

integration/tests/pricing-table.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,29 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl
2828
await expect(u.po.page.getByRole('heading', { name: 'Pro' })).toBeVisible();
2929
});
3030

31+
test('renders pricing details of a specific plan', async ({ page, context }) => {
32+
if (!app.name.includes('next')) {
33+
return;
34+
}
35+
36+
const u = createTestUtils({ app, page, context });
37+
await u.po.page.goToRelative('/billing/plan-details-btn');
38+
39+
await u.po.page.getByRole('button', { name: 'Plan details' }).click();
40+
41+
await u.po.planDetails.waitForMounted();
42+
const { root } = u.po.planDetails;
43+
await expect(root.getByRole('heading', { name: 'Plus' })).toBeVisible();
44+
await expect(root.getByText('$9.99')).toBeVisible();
45+
await expect(root.getByText('This is the Plus plan!')).toBeVisible();
46+
await expect(root.getByText('Feature One')).toBeVisible();
47+
await expect(root.getByText('First feature')).toBeVisible();
48+
await expect(root.getByText('Feature Two')).toBeVisible();
49+
await expect(root.getByText('Second feature')).toBeVisible();
50+
await expect(root.getByText('Feature Three')).toBeVisible();
51+
await expect(root.getByText('Third feature')).toBeVisible();
52+
});
53+
3154
test('when signed out, clicking subscribe button navigates to sign in page', async ({ page, context }) => {
3255
const u = createTestUtils({ app, page, context });
3356
await u.po.page.goToRelative('/pricing-table');
@@ -39,6 +62,10 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl
3962
});
4063

4164
test('when signed in, clicking get started button opens checkout drawer', async ({ page, context }) => {
65+
if (!app.name.includes('next')) {
66+
return;
67+
}
68+
4269
const u = createTestUtils({ app, page, context });
4370
await u.po.signIn.goTo();
4471
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password });
@@ -64,6 +91,21 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl
6491
await expect(u.po.page.getByText('Checkout')).toBeVisible();
6592
});
6693

94+
test('when signed in, clicking checkout button open checkout drawer', async ({ page, context }) => {
95+
if (!app.name.includes('next')) {
96+
return;
97+
}
98+
const u = createTestUtils({ app, page, context });
99+
await u.po.signIn.goTo();
100+
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password });
101+
await u.po.page.goToRelative('/billing/checkout-btn');
102+
103+
await u.po.page.getByRole('button', { name: 'Checkout Now' }).click();
104+
await u.po.checkout.waitForMounted();
105+
await u.po.page.getByText(/^Checkout$/).click();
106+
await u.po.checkout.fillTestCard();
107+
});
108+
67109
test('can subscribe to a plan', async ({ page, context }) => {
68110
const u = createTestUtils({ app, page, context });
69111
await u.po.signIn.goTo();
@@ -86,6 +128,25 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl
86128
}
87129
});
88130

131+
test('Displays subscription details drawer', async ({ page, context }) => {
132+
if (!app.name.includes('next')) {
133+
return;
134+
}
135+
const u = createTestUtils({ app, page, context });
136+
await u.po.signIn.goTo();
137+
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password });
138+
await u.po.page.goToRelative('/billing/subscription-details-btn');
139+
140+
await u.po.page.getByRole('button', { name: 'Subscription details' }).click();
141+
142+
await u.po.subscriptionDetails.waitForMounted();
143+
await expect(u.po.page.getByText('Plus')).toBeVisible();
144+
await expect(u.po.page.getByText('Subscription details')).toBeVisible();
145+
await expect(u.po.page.getByText('Current billing cycle')).toBeVisible();
146+
await expect(u.po.page.getByText('Next payment on')).toBeVisible();
147+
await expect(u.po.page.getByText('Next payment amount')).toBeVisible();
148+
});
149+
89150
test('can upgrade to a new plan with saved card', async ({ page, context }) => {
90151
const u = createTestUtils({ app, page, context });
91152
await u.po.signIn.goTo();

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
Col,
2121
descriptors,
2222
Flex,
23+
Flow,
2324
Heading,
2425
localizationKeys,
2526
Span,
@@ -30,9 +31,13 @@ import {
3031

3132
export const PlanDetails = (props: __internal_PlanDetailsProps) => {
3233
return (
33-
<Drawer.Content>
34-
<PlanDetailsInternal {...props} />
35-
</Drawer.Content>
34+
<Flow.Root flow='planDetails'>
35+
<Flow.Part>
36+
<Drawer.Content>
37+
<PlanDetailsInternal {...props} />
38+
</Drawer.Content>
39+
</Flow.Part>
40+
</Flow.Root>
3641
);
3742
};
3843

packages/clerk-js/src/ui/elements/contexts/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export type FlowMetadata = {
100100
| 'apiKeys'
101101
| 'oauthConsent'
102102
| 'subscriptionDetails'
103+
| 'subscriptionDetails'
103104
| 'taskChooseOrganization';
104105
part?:
105106
| 'start'

packages/testing/src/playwright/unstable/page-objects/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { createExpectPageObject } from './expect';
88
import { createImpersonationPageObject } from './impersonation';
99
import { createKeylessPopoverPageObject } from './keylessPopover';
1010
import { createOrganizationSwitcherComponentPageObject } from './organizationSwitcher';
11+
import { createPlanDetailsPageObject } from './planDetails';
1112
import { createPricingTablePageObject } from './pricingTable';
1213
import { createSessionTaskComponentPageObject } from './sessionTask';
1314
import { createSignInComponentPageObject } from './signIn';
@@ -50,5 +51,6 @@ export const createPageObjects = ({
5051
waitlist: createWaitlistComponentPageObject(testArgs),
5152
apiKeys: createAPIKeysComponentPageObject(testArgs),
5253
subscriptionDetails: createSubscriptionDetailsPageObject(testArgs),
54+
planDetails: createPlanDetailsPageObject(testArgs),
5355
};
5456
};

0 commit comments

Comments
 (0)