From caa32ba9eca6c5419f3060497500380e3d1d4323 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Wed, 30 Apr 2025 15:19:31 +0300 Subject: [PATCH 01/18] feat(vue,nuxt): Add __experimental_PricingTable --- integration/presets/longRunningApps.ts | 8 ++++++-- .../templates/nuxt-node/pages/pricing-table.vue | 7 +++++++ integration/templates/vue-vite/src/router.ts | 11 +++++++++++ .../vue-vite/src/views/PricingTable.vue | 7 +++++++ integration/tests/pricing-table.test.ts | 2 +- package.json | 2 +- packages/nuxt/src/module.ts | 1 + packages/nuxt/src/runtime/components/index.ts | 1 + packages/vue/src/components/index.ts | 1 + .../components/ui-components/PircingTable.vue | 17 +++++++++++++++++ 10 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 integration/templates/nuxt-node/pages/pricing-table.vue create mode 100644 integration/templates/vue-vite/src/views/PricingTable.vue create mode 100644 packages/vue/src/components/ui-components/PircingTable.vue diff --git a/integration/presets/longRunningApps.ts b/integration/presets/longRunningApps.ts index f9e863ca42d..d7b1ca72121 100644 --- a/integration/presets/longRunningApps.ts +++ b/integration/presets/longRunningApps.ts @@ -42,8 +42,12 @@ export const createLongRunningApps = () => { config: next.appRouter, env: envs.withSessionTasks, }, - { id: 'next.appRouter.withBillingStaging', config: next.appRouter, env: envs.withBillingStaging }, - { id: 'next.appRouter.withBilling', config: next.appRouter, env: envs.withBilling }, + { id: 'withBillingStaging.next.appRouter', config: next.appRouter, env: envs.withBillingStaging }, + { id: 'withBilling.next.appRouter', config: next.appRouter, env: envs.withBilling }, + { id: 'withBillingStaging.vue.vite', config: vue.vite, env: envs.withBillingStaging }, + { id: 'withBilling.vue.vite', config: vue.vite, env: envs.withBilling }, + { id: 'withBillingStaging.nuxt.node', config: nuxt.node, env: envs.withBillingStaging }, + { id: 'withBilling.nuxt.node', config: nuxt.node, env: envs.withBilling }, { id: 'next.appRouter.withLegalConsent', config: next.appRouter, diff --git a/integration/templates/nuxt-node/pages/pricing-table.vue b/integration/templates/nuxt-node/pages/pricing-table.vue new file mode 100644 index 00000000000..36b1399677e --- /dev/null +++ b/integration/templates/nuxt-node/pages/pricing-table.vue @@ -0,0 +1,7 @@ + + + diff --git a/integration/templates/vue-vite/src/router.ts b/integration/templates/vue-vite/src/router.ts index db90e9a319a..c598b2b0bff 100644 --- a/integration/templates/vue-vite/src/router.ts +++ b/integration/templates/vue-vite/src/router.ts @@ -36,6 +36,17 @@ const routes = [ path: '/custom-pages/organization-profile', component: () => import('./views/custom-pages/OrganizationProfile.vue'), }, + { + name: 'PricingTable', + path: '/pricing-table', + component: () => import('./views/PricingTable.vue'), + }, + // This was added for billing tests + { + name: 'User', + path: '/user', + component: () => import('./views/Profile.vue'), + }, ]; const router = createRouter({ diff --git a/integration/templates/vue-vite/src/views/PricingTable.vue b/integration/templates/vue-vite/src/views/PricingTable.vue new file mode 100644 index 00000000000..de480f35db3 --- /dev/null +++ b/integration/templates/vue-vite/src/views/PricingTable.vue @@ -0,0 +1,7 @@ + + + diff --git a/integration/tests/pricing-table.test.ts b/integration/tests/pricing-table.test.ts index 12fdf508b7c..e7ef74e7b34 100644 --- a/integration/tests/pricing-table.test.ts +++ b/integration/tests/pricing-table.test.ts @@ -56,7 +56,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl await frame.getByLabel('Card number').fill('4242424242424242'); await frame.getByLabel('Expiration date').fill('1234'); await frame.getByLabel('Security code').fill('123'); - await frame.getByLabel('ZIP code').fill('12345'); + // await frame.getByLabel('ZIP code').fill('12345'); await u.po.page.getByRole('button', { name: 'Pay $' }).click(); await expect(u.po.page.getByText('Payment was successful!')).toBeVisible(); diff --git a/package.json b/package.json index 434bded6a01..7acf88a5831 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "test:integration:ap-flows": "pnpm test:integration:base --grep @ap-flows", "test:integration:astro": "E2E_APP_ID=astro.* pnpm test:integration:base --grep @astro", "test:integration:base": "pnpm playwright test --config integration/playwright.config.ts", - "test:integration:billing": "E2E_APP_ID=next.appRouter.withBilling pnpm test:integration:base --grep @billing", + "test:integration:billing": "E2E_APP_ID=withBilling* pnpm test:integration:base --grep @billing", "test:integration:cleanup": "pnpm playwright test --config integration/playwright.cleanup.config.ts", "test:integration:deployment:nextjs": "pnpm playwright test --config integration/playwright.deployments.config.ts", "test:integration:elements": "E2E_APP_ID=elements.* pnpm test:integration:base --grep @elements", diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index ad9ad12aa38..7b96a11648a 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -162,6 +162,7 @@ export default defineNuxtModule({ 'SignedIn', 'SignedOut', 'Waitlist', + '__experimental_PricingTable', ]; components.forEach(component => { void addComponent({ diff --git a/packages/nuxt/src/runtime/components/index.ts b/packages/nuxt/src/runtime/components/index.ts index 12d0e860a8c..ed28a1bf2f4 100644 --- a/packages/nuxt/src/runtime/components/index.ts +++ b/packages/nuxt/src/runtime/components/index.ts @@ -27,4 +27,5 @@ export { SignUpButton, SignOutButton, SignInWithMetamaskButton, + __experimental_PricingTable, } from '@clerk/vue'; diff --git a/packages/vue/src/components/index.ts b/packages/vue/src/components/index.ts index 0d0d7740c84..e479a0af801 100644 --- a/packages/vue/src/components/index.ts +++ b/packages/vue/src/components/index.ts @@ -4,6 +4,7 @@ export { default as GoogleOneTap } from './ui-components/GoogleOneTap.vue'; export { default as Waitlist } from './ui-components/Waitlist.vue'; export { default as CreateOrganization } from './ui-components/CreateOrganization.vue'; export { default as OrganizationList } from './ui-components/OrganizationList.vue'; +export { default as __experimental_PricingTable } from './ui-components/PircingTable.vue'; export { UserProfile } from './ui-components/UserProfile'; export { OrganizationProfile } from './ui-components/OrganizationProfile'; export { OrganizationSwitcher } from './ui-components/OrganizationSwitcher'; diff --git a/packages/vue/src/components/ui-components/PircingTable.vue b/packages/vue/src/components/ui-components/PircingTable.vue new file mode 100644 index 00000000000..339dc0c2642 --- /dev/null +++ b/packages/vue/src/components/ui-components/PircingTable.vue @@ -0,0 +1,17 @@ + + + From d5d0e9b81d82b8efc821b9f63360ce5ef9cbd7c3 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Wed, 30 Apr 2025 15:21:29 +0300 Subject: [PATCH 02/18] chore(repo): Add changeset --- .changeset/twelve-ideas-exist.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/twelve-ideas-exist.md diff --git a/.changeset/twelve-ideas-exist.md b/.changeset/twelve-ideas-exist.md new file mode 100644 index 00000000000..02500990e85 --- /dev/null +++ b/.changeset/twelve-ideas-exist.md @@ -0,0 +1,6 @@ +--- +'@clerk/nuxt': minor +'@clerk/vue': minor +--- + +Introduce <\_\_experimental_PricingTable/> From aa533e9bcfb0502d4d3ae2e28fe473053e5b9447 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Wed, 30 Apr 2025 16:05:14 +0300 Subject: [PATCH 03/18] wip --- integration/presets/longRunningApps.ts | 2 +- integration/templates/nuxt-node/pages/pricing-table.vue | 5 +++-- integration/templates/vue-vite/src/views/PricingTable.vue | 4 ++-- packages/nuxt/src/module.ts | 2 +- packages/nuxt/src/runtime/components/index.ts | 2 +- packages/vue/src/components/index.ts | 2 +- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/integration/presets/longRunningApps.ts b/integration/presets/longRunningApps.ts index d7b1ca72121..03f7925f887 100644 --- a/integration/presets/longRunningApps.ts +++ b/integration/presets/longRunningApps.ts @@ -46,7 +46,7 @@ export const createLongRunningApps = () => { { id: 'withBilling.next.appRouter', config: next.appRouter, env: envs.withBilling }, { id: 'withBillingStaging.vue.vite', config: vue.vite, env: envs.withBillingStaging }, { id: 'withBilling.vue.vite', config: vue.vite, env: envs.withBilling }, - { id: 'withBillingStaging.nuxt.node', config: nuxt.node, env: envs.withBillingStaging }, + // { id: 'withBillingStaging.nuxt.node', config: nuxt.node, env: envs.withBillingStaging }, { id: 'withBilling.nuxt.node', config: nuxt.node, env: envs.withBilling }, { id: 'next.appRouter.withLegalConsent', diff --git a/integration/templates/nuxt-node/pages/pricing-table.vue b/integration/templates/nuxt-node/pages/pricing-table.vue index 36b1399677e..9ded1469fb4 100644 --- a/integration/templates/nuxt-node/pages/pricing-table.vue +++ b/integration/templates/nuxt-node/pages/pricing-table.vue @@ -1,7 +1,8 @@ diff --git a/integration/templates/vue-vite/src/views/PricingTable.vue b/integration/templates/vue-vite/src/views/PricingTable.vue index de480f35db3..e19a70cf5dc 100644 --- a/integration/templates/vue-vite/src/views/PricingTable.vue +++ b/integration/templates/vue-vite/src/views/PricingTable.vue @@ -1,7 +1,7 @@ diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index 7b96a11648a..31fa70e9219 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -162,7 +162,7 @@ export default defineNuxtModule({ 'SignedIn', 'SignedOut', 'Waitlist', - '__experimental_PricingTable', + 'Experimental_PricingTable', ]; components.forEach(component => { void addComponent({ diff --git a/packages/nuxt/src/runtime/components/index.ts b/packages/nuxt/src/runtime/components/index.ts index ed28a1bf2f4..c4a85af6e95 100644 --- a/packages/nuxt/src/runtime/components/index.ts +++ b/packages/nuxt/src/runtime/components/index.ts @@ -27,5 +27,5 @@ export { SignUpButton, SignOutButton, SignInWithMetamaskButton, - __experimental_PricingTable, + Experimental_PricingTable, } from '@clerk/vue'; diff --git a/packages/vue/src/components/index.ts b/packages/vue/src/components/index.ts index e479a0af801..f90eeb9ab43 100644 --- a/packages/vue/src/components/index.ts +++ b/packages/vue/src/components/index.ts @@ -4,7 +4,7 @@ export { default as GoogleOneTap } from './ui-components/GoogleOneTap.vue'; export { default as Waitlist } from './ui-components/Waitlist.vue'; export { default as CreateOrganization } from './ui-components/CreateOrganization.vue'; export { default as OrganizationList } from './ui-components/OrganizationList.vue'; -export { default as __experimental_PricingTable } from './ui-components/PircingTable.vue'; +export { default as Experimental_PricingTable } from './ui-components/PircingTable.vue'; export { UserProfile } from './ui-components/UserProfile'; export { OrganizationProfile } from './ui-components/OrganizationProfile'; export { OrganizationSwitcher } from './ui-components/OrganizationSwitcher'; From 2697aa2b441af3c604ae9d5407c1f1554ac3e5cc Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Wed, 30 Apr 2025 17:44:48 +0300 Subject: [PATCH 04/18] fix(vue): Fix filename typo --- packages/vue/src/components/index.ts | 2 +- .../ui-components/{PircingTable.vue => PricingTable.vue} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/vue/src/components/ui-components/{PircingTable.vue => PricingTable.vue} (100%) diff --git a/packages/vue/src/components/index.ts b/packages/vue/src/components/index.ts index f90eeb9ab43..cbdf6b3330c 100644 --- a/packages/vue/src/components/index.ts +++ b/packages/vue/src/components/index.ts @@ -4,7 +4,7 @@ export { default as GoogleOneTap } from './ui-components/GoogleOneTap.vue'; export { default as Waitlist } from './ui-components/Waitlist.vue'; export { default as CreateOrganization } from './ui-components/CreateOrganization.vue'; export { default as OrganizationList } from './ui-components/OrganizationList.vue'; -export { default as Experimental_PricingTable } from './ui-components/PircingTable.vue'; +export { default as Experimental_PricingTable } from './ui-components/PricingTable.vue'; export { UserProfile } from './ui-components/UserProfile'; export { OrganizationProfile } from './ui-components/OrganizationProfile'; export { OrganizationSwitcher } from './ui-components/OrganizationSwitcher'; diff --git a/packages/vue/src/components/ui-components/PircingTable.vue b/packages/vue/src/components/ui-components/PricingTable.vue similarity index 100% rename from packages/vue/src/components/ui-components/PircingTable.vue rename to packages/vue/src/components/ui-components/PricingTable.vue From c5df32bf74d43b4b91e1495e5993cea16ab367e0 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Wed, 30 Apr 2025 18:00:23 +0300 Subject: [PATCH 05/18] fix(e2e): Comment out Nuxt test for now --- integration/presets/longRunningApps.ts | 2 +- integration/templates/nuxt-node/pages/pricing-table.vue | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/integration/presets/longRunningApps.ts b/integration/presets/longRunningApps.ts index 03f7925f887..8b48e960265 100644 --- a/integration/presets/longRunningApps.ts +++ b/integration/presets/longRunningApps.ts @@ -47,7 +47,7 @@ export const createLongRunningApps = () => { { id: 'withBillingStaging.vue.vite', config: vue.vite, env: envs.withBillingStaging }, { id: 'withBilling.vue.vite', config: vue.vite, env: envs.withBilling }, // { id: 'withBillingStaging.nuxt.node', config: nuxt.node, env: envs.withBillingStaging }, - { id: 'withBilling.nuxt.node', config: nuxt.node, env: envs.withBilling }, + // { id: 'withBilling.nuxt.node', config: nuxt.node, env: envs.withBilling }, { id: 'next.appRouter.withLegalConsent', config: next.appRouter, diff --git a/integration/templates/nuxt-node/pages/pricing-table.vue b/integration/templates/nuxt-node/pages/pricing-table.vue index 9ded1469fb4..fe47efe5853 100644 --- a/integration/templates/nuxt-node/pages/pricing-table.vue +++ b/integration/templates/nuxt-node/pages/pricing-table.vue @@ -1,8 +1,3 @@ - - From b23bc5862687a3847abc6df64be68efe6e3de23e Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Wed, 30 Apr 2025 18:13:39 +0300 Subject: [PATCH 06/18] fix(vue,nuxt,e2e): Change compoonent to --- integration/templates/nuxt-node/pages/pricing-table.vue | 2 +- integration/templates/vue-vite/src/views/PricingTable.vue | 4 ++-- integration/tests/pricing-table.test.ts | 1 + packages/nuxt/src/module.ts | 2 +- packages/nuxt/src/runtime/components/index.ts | 2 +- packages/vue/src/components/index.ts | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/integration/templates/nuxt-node/pages/pricing-table.vue b/integration/templates/nuxt-node/pages/pricing-table.vue index fe47efe5853..e119727a0bd 100644 --- a/integration/templates/nuxt-node/pages/pricing-table.vue +++ b/integration/templates/nuxt-node/pages/pricing-table.vue @@ -1,3 +1,3 @@ diff --git a/integration/templates/vue-vite/src/views/PricingTable.vue b/integration/templates/vue-vite/src/views/PricingTable.vue index e19a70cf5dc..780e4f421d6 100644 --- a/integration/templates/vue-vite/src/views/PricingTable.vue +++ b/integration/templates/vue-vite/src/views/PricingTable.vue @@ -1,7 +1,7 @@ diff --git a/integration/tests/pricing-table.test.ts b/integration/tests/pricing-table.test.ts index e7ef74e7b34..e1a8f638060 100644 --- a/integration/tests/pricing-table.test.ts +++ b/integration/tests/pricing-table.test.ts @@ -23,6 +23,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl test('renders pricing table with plans', async ({ page, context }) => { const u = createTestUtils({ app, page, context }); await u.po.page.goToRelative('/pricing-table'); + await u.po.page.waitForURL(/pricing-table/); await expect(u.po.page.getByRole('heading', { name: 'Pro' })).toBeVisible(); }); diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index 31fa70e9219..96d3f0fd67e 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -162,7 +162,7 @@ export default defineNuxtModule({ 'SignedIn', 'SignedOut', 'Waitlist', - 'Experimental_PricingTable', + 'experimental_PricingTable', ]; components.forEach(component => { void addComponent({ diff --git a/packages/nuxt/src/runtime/components/index.ts b/packages/nuxt/src/runtime/components/index.ts index c4a85af6e95..db7d8caa513 100644 --- a/packages/nuxt/src/runtime/components/index.ts +++ b/packages/nuxt/src/runtime/components/index.ts @@ -27,5 +27,5 @@ export { SignUpButton, SignOutButton, SignInWithMetamaskButton, - Experimental_PricingTable, + experimental_PricingTable, } from '@clerk/vue'; diff --git a/packages/vue/src/components/index.ts b/packages/vue/src/components/index.ts index cbdf6b3330c..f9af337103a 100644 --- a/packages/vue/src/components/index.ts +++ b/packages/vue/src/components/index.ts @@ -4,7 +4,7 @@ export { default as GoogleOneTap } from './ui-components/GoogleOneTap.vue'; export { default as Waitlist } from './ui-components/Waitlist.vue'; export { default as CreateOrganization } from './ui-components/CreateOrganization.vue'; export { default as OrganizationList } from './ui-components/OrganizationList.vue'; -export { default as Experimental_PricingTable } from './ui-components/PricingTable.vue'; +export { default as experimental_PricingTable } from './ui-components/PricingTable.vue'; export { UserProfile } from './ui-components/UserProfile'; export { OrganizationProfile } from './ui-components/OrganizationProfile'; export { OrganizationSwitcher } from './ui-components/OrganizationSwitcher'; From 54e891102be9cae9537437cdf25f4fc585d632a5 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Wed, 30 Apr 2025 18:15:16 +0300 Subject: [PATCH 07/18] Update .changeset/twelve-ideas-exist.md --- .changeset/twelve-ideas-exist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/twelve-ideas-exist.md b/.changeset/twelve-ideas-exist.md index 02500990e85..7dbfb601d4e 100644 --- a/.changeset/twelve-ideas-exist.md +++ b/.changeset/twelve-ideas-exist.md @@ -3,4 +3,4 @@ '@clerk/vue': minor --- -Introduce <\_\_experimental_PricingTable/> +Introducing From e32974ec4ce1fcb4f1c02f602db98391d7dd15b2 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Wed, 30 Apr 2025 18:24:34 +0300 Subject: [PATCH 08/18] Update .changeset/twelve-ideas-exist.md --- .changeset/twelve-ideas-exist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/twelve-ideas-exist.md b/.changeset/twelve-ideas-exist.md index 7dbfb601d4e..e62484fd21a 100644 --- a/.changeset/twelve-ideas-exist.md +++ b/.changeset/twelve-ideas-exist.md @@ -3,4 +3,4 @@ '@clerk/vue': minor --- -Introducing +Introducing `` From 7cd840416ae1e98f7c60a0faacdcec3982b8de8c Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Wed, 30 Apr 2025 19:21:45 +0300 Subject: [PATCH 09/18] fix(e2e): Enhance E2E reliability --- integration/testUtils/index.ts | 3 +-- integration/tests/pricing-table.test.ts | 16 ++++++++++------ .../playwright/unstable/page-objects/commerce.ts | 16 ++++++++++++++++ .../playwright/unstable/page-objects/common.ts | 3 +++ .../playwright/unstable/page-objects/index.ts | 2 ++ 5 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 packages/testing/src/playwright/unstable/page-objects/commerce.ts diff --git a/integration/testUtils/index.ts b/integration/testUtils/index.ts index a02fec69200..09dde2d7660 100644 --- a/integration/testUtils/index.ts +++ b/integration/testUtils/index.ts @@ -1,12 +1,11 @@ import { createClerkClient as backendCreateClerkClient } from '@clerk/backend'; -import { createPageObjects, createAppPageObject, type EnhancedPage } from '@clerk/testing/playwright/unstable'; +import { createAppPageObject, createPageObjects, type EnhancedPage } from '@clerk/testing/playwright/unstable'; import type { Browser, BrowserContext, Page } from '@playwright/test'; import type { Application } from '../models/application'; import { createEmailService } from './emailService'; import { createInvitationService } from './invitationsService'; import { createOrganizationsService } from './organizationsService'; - import type { FakeOrganization, FakeUser } from './usersService'; import { createUserService } from './usersService'; diff --git a/integration/tests/pricing-table.test.ts b/integration/tests/pricing-table.test.ts index e1a8f638060..8c53a4cf4dd 100644 --- a/integration/tests/pricing-table.test.ts +++ b/integration/tests/pricing-table.test.ts @@ -22,14 +22,13 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl test('renders pricing table with plans', async ({ page, context }) => { const u = createTestUtils({ app, page, context }); - await u.po.page.goToRelative('/pricing-table'); - await u.po.page.waitForURL(/pricing-table/); + await u.po.commerce.goToPricingTable(); await expect(u.po.page.getByRole('heading', { name: 'Pro' })).toBeVisible(); }); test('when signed out, clicking get started button navigates to sign in page', async ({ page, context }) => { const u = createTestUtils({ app, page, context }); - await u.po.page.goToRelative('/pricing-table'); + await u.po.commerce.goToPricingTable(); await u.po.page.getByText('Get started').first().click(); await u.po.signIn.waitForMounted(); await expect(u.po.page.getByText('Checkout')).toBeHidden(); @@ -39,8 +38,9 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl const u = createTestUtils({ app, page, context }); await u.po.signIn.goTo(); await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); - await u.po.page.goToRelative('/pricing-table'); + await u.po.commerce.goToPricingTable(); await u.po.page.getByText('Get started').first().click(); + await u.po.commerce.waitForDrawerMounted(); await expect(u.po.page.getByText('Checkout')).toBeVisible(); }); @@ -48,10 +48,12 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl const u = createTestUtils({ app, page, context }); await u.po.signIn.goTo(); await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); - await u.po.page.goToRelative('/pricing-table'); + await u.po.commerce.goToPricingTable(); // We have two plans, so subscribe to the first one await u.po.page.getByText('Get started').first().click(); + await u.po.commerce.waitForDrawerMounted(); + // Stripe uses multiple iframes, so we need to find the correct one const frame = u.po.page.frameLocator('iframe[src*="elements-inner-payment"]'); await frame.getByLabel('Card number').fill('4242424242424242'); @@ -60,6 +62,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl // await frame.getByLabel('ZIP code').fill('12345'); await u.po.page.getByRole('button', { name: 'Pay $' }).click(); + await u.po.page.locator('.cl-checkoutSuccessTitle').waitFor({ state: 'visible' }); await expect(u.po.page.getByText('Payment was successful!')).toBeVisible(); }); @@ -67,8 +70,9 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl const u = createTestUtils({ app, page, context }); await u.po.signIn.goTo(); await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); - await u.po.page.goToRelative('/pricing-table'); + await u.po.commerce.goToPricingTable(); await u.po.page.getByText('Manage subscription').click(); + await u.po.commerce.waitForDrawerMounted(); await u.po.page.getByRole('button', { name: 'Cancel subscription' }).click(); await u.po.page.getByRole('alertdialog').getByRole('button', { name: 'Cancel subscription' }).click(); await expect(u.po.page.getByRole('button', { name: 'Re-subscribe' }).first()).toBeVisible(); diff --git a/packages/testing/src/playwright/unstable/page-objects/commerce.ts b/packages/testing/src/playwright/unstable/page-objects/commerce.ts new file mode 100644 index 00000000000..91709741593 --- /dev/null +++ b/packages/testing/src/playwright/unstable/page-objects/commerce.ts @@ -0,0 +1,16 @@ +import type { EnhancedPage } from './app'; +import { common } from './common'; + +export const createCommerceComponentPageObject = (testArgs: { page: EnhancedPage }) => { + const { page } = testArgs; + + const self = { + ...common(testArgs), + goToPricingTable: async (opts?: { searchParams?: URLSearchParams; headlessSelector?: string }) => { + await page.goToRelative('/pricing-table', { searchParams: opts?.searchParams }); + return await page.waitForURL(/pricing-table/); + }, + }; + + return self; +}; diff --git a/packages/testing/src/playwright/unstable/page-objects/common.ts b/packages/testing/src/playwright/unstable/page-objects/common.ts index 618a0957db4..737fd3ddd95 100644 --- a/packages/testing/src/playwright/unstable/page-objects/common.ts +++ b/packages/testing/src/playwright/unstable/page-objects/common.ts @@ -51,6 +51,9 @@ export const common = ({ page }: { page: EnhancedPage }) => { getLastNameInput: () => { return page.locator('input[name=lastName]'); }, + waitForDrawerMounted: () => { + return page.locator('.cl-drawerContent').waitFor({ state: 'attached' }); + }, }; return self; diff --git a/packages/testing/src/playwright/unstable/page-objects/index.ts b/packages/testing/src/playwright/unstable/page-objects/index.ts index 484b3075db0..1155ea81c67 100644 --- a/packages/testing/src/playwright/unstable/page-objects/index.ts +++ b/packages/testing/src/playwright/unstable/page-objects/index.ts @@ -2,6 +2,7 @@ import type { Page } from '@playwright/test'; import { createAppPageObject } from './app'; import { createClerkPageObject } from './clerk'; +import { createCommerceComponentPageObject } from './commerce'; import { createExpectPageObject } from './expect'; import { createImpersonationPageObject } from './impersonation'; import { createKeylessPopoverPageObject } from './keylessPopover'; @@ -42,5 +43,6 @@ export const createPageObjects = ({ userProfile: createUserProfileComponentPageObject(testArgs), userVerification: createUserVerificationComponentPageObject(testArgs), waitlist: createWaitlistComponentPageObject(testArgs), + commerce: createCommerceComponentPageObject(testArgs), }; }; From d67726ce370cffca228bc8c0cfdd3842ef9d3de1 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Wed, 30 Apr 2025 19:43:45 +0300 Subject: [PATCH 10/18] chore(e2e): Change commerce to billing --- .../unstable/page-objects/{commerce.ts => billing.ts} | 2 +- .../testing/src/playwright/unstable/page-objects/index.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename packages/testing/src/playwright/unstable/page-objects/{commerce.ts => billing.ts} (82%) diff --git a/packages/testing/src/playwright/unstable/page-objects/commerce.ts b/packages/testing/src/playwright/unstable/page-objects/billing.ts similarity index 82% rename from packages/testing/src/playwright/unstable/page-objects/commerce.ts rename to packages/testing/src/playwright/unstable/page-objects/billing.ts index 91709741593..f020211b1db 100644 --- a/packages/testing/src/playwright/unstable/page-objects/commerce.ts +++ b/packages/testing/src/playwright/unstable/page-objects/billing.ts @@ -1,7 +1,7 @@ import type { EnhancedPage } from './app'; import { common } from './common'; -export const createCommerceComponentPageObject = (testArgs: { page: EnhancedPage }) => { +export const createBillingComponentPageObject = (testArgs: { page: EnhancedPage }) => { const { page } = testArgs; const self = { diff --git a/packages/testing/src/playwright/unstable/page-objects/index.ts b/packages/testing/src/playwright/unstable/page-objects/index.ts index 1155ea81c67..e5f2c354b85 100644 --- a/packages/testing/src/playwright/unstable/page-objects/index.ts +++ b/packages/testing/src/playwright/unstable/page-objects/index.ts @@ -1,8 +1,8 @@ import type { Page } from '@playwright/test'; import { createAppPageObject } from './app'; +import { createBillingComponentPageObject } from './billing'; import { createClerkPageObject } from './clerk'; -import { createCommerceComponentPageObject } from './commerce'; import { createExpectPageObject } from './expect'; import { createImpersonationPageObject } from './impersonation'; import { createKeylessPopoverPageObject } from './keylessPopover'; @@ -43,6 +43,6 @@ export const createPageObjects = ({ userProfile: createUserProfileComponentPageObject(testArgs), userVerification: createUserVerificationComponentPageObject(testArgs), waitlist: createWaitlistComponentPageObject(testArgs), - commerce: createCommerceComponentPageObject(testArgs), + billing: createBillingComponentPageObject(testArgs), }; }; From 0dc21ba138da700bbbc9273969e5969007ed8b7d Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Wed, 30 Apr 2025 20:09:51 +0300 Subject: [PATCH 11/18] test(e2e): Fix tests --- integration/tests/pricing-table.test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/integration/tests/pricing-table.test.ts b/integration/tests/pricing-table.test.ts index 8c53a4cf4dd..cf640ac0ff7 100644 --- a/integration/tests/pricing-table.test.ts +++ b/integration/tests/pricing-table.test.ts @@ -22,13 +22,13 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl test('renders pricing table with plans', async ({ page, context }) => { const u = createTestUtils({ app, page, context }); - await u.po.commerce.goToPricingTable(); + await u.po.billing.goToPricingTable(); await expect(u.po.page.getByRole('heading', { name: 'Pro' })).toBeVisible(); }); test('when signed out, clicking get started button navigates to sign in page', async ({ page, context }) => { const u = createTestUtils({ app, page, context }); - await u.po.commerce.goToPricingTable(); + await u.po.billing.goToPricingTable(); await u.po.page.getByText('Get started').first().click(); await u.po.signIn.waitForMounted(); await expect(u.po.page.getByText('Checkout')).toBeHidden(); @@ -38,9 +38,9 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl const u = createTestUtils({ app, page, context }); await u.po.signIn.goTo(); await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); - await u.po.commerce.goToPricingTable(); + await u.po.billing.goToPricingTable(); await u.po.page.getByText('Get started').first().click(); - await u.po.commerce.waitForDrawerMounted(); + await u.po.billing.waitForDrawerMounted(); await expect(u.po.page.getByText('Checkout')).toBeVisible(); }); @@ -48,11 +48,11 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl const u = createTestUtils({ app, page, context }); await u.po.signIn.goTo(); await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); - await u.po.commerce.goToPricingTable(); + await u.po.billing.goToPricingTable(); // We have two plans, so subscribe to the first one await u.po.page.getByText('Get started').first().click(); - await u.po.commerce.waitForDrawerMounted(); + await u.po.billing.waitForDrawerMounted(); // Stripe uses multiple iframes, so we need to find the correct one const frame = u.po.page.frameLocator('iframe[src*="elements-inner-payment"]'); @@ -70,9 +70,9 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl const u = createTestUtils({ app, page, context }); await u.po.signIn.goTo(); await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); - await u.po.commerce.goToPricingTable(); + await u.po.billing.goToPricingTable(); await u.po.page.getByText('Manage subscription').click(); - await u.po.commerce.waitForDrawerMounted(); + await u.po.billing.waitForDrawerMounted(); await u.po.page.getByRole('button', { name: 'Cancel subscription' }).click(); await u.po.page.getByRole('alertdialog').getByRole('button', { name: 'Cancel subscription' }).click(); await expect(u.po.page.getByRole('button', { name: 'Re-subscribe' }).first()).toBeVisible(); From bda7bb4fdf14d15d86eee1d009c880ea3babe5b1 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Fri, 2 May 2025 07:48:44 +0300 Subject: [PATCH 12/18] test(e2e): Update tests --- integration/tests/pricing-table.test.ts | 27 ++++++++++++------- .../unstable/page-objects/billing.ts | 16 ----------- .../playwright/unstable/page-objects/index.ts | 2 -- 3 files changed, 18 insertions(+), 27 deletions(-) delete mode 100644 packages/testing/src/playwright/unstable/page-objects/billing.ts diff --git a/integration/tests/pricing-table.test.ts b/integration/tests/pricing-table.test.ts index cf640ac0ff7..9f5c14af36a 100644 --- a/integration/tests/pricing-table.test.ts +++ b/integration/tests/pricing-table.test.ts @@ -22,13 +22,18 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl test('renders pricing table with plans', async ({ page, context }) => { const u = createTestUtils({ app, page, context }); - await u.po.billing.goToPricingTable(); + await u.po.page.goToRelative('/pricing-table'); + + await u.po.page.locator('.cl-pricingTable-root').waitFor({ state: 'attached' }); + await expect(u.po.page.getByRole('heading', { name: 'Pro' })).toBeVisible(); }); test('when signed out, clicking get started button navigates to sign in page', async ({ page, context }) => { const u = createTestUtils({ app, page, context }); - await u.po.billing.goToPricingTable(); + await u.po.page.goToRelative('/pricing-table'); + await u.po.page.locator('.cl-pricingTable-root').waitFor({ state: 'attached' }); + await u.po.page.getByText('Get started').first().click(); await u.po.signIn.waitForMounted(); await expect(u.po.page.getByText('Checkout')).toBeHidden(); @@ -38,21 +43,23 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl const u = createTestUtils({ app, page, context }); await u.po.signIn.goTo(); await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); - await u.po.billing.goToPricingTable(); + await u.po.page.goToRelative('/pricing-table'); + await u.po.page.locator('.cl-pricingTable-root').waitFor({ state: 'attached' }); await u.po.page.getByText('Get started').first().click(); - await u.po.billing.waitForDrawerMounted(); - await expect(u.po.page.getByText('Checkout')).toBeVisible(); + await u.po.page.locator('.cl-checkout-root').waitFor({ state: 'attached' }); + await expect(u.po.page.getByText(/Checkout/i)).toBeVisible(); }); test('can subscribe to a plan', async ({ page, context }) => { const u = createTestUtils({ app, page, context }); await u.po.signIn.goTo(); await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); - await u.po.billing.goToPricingTable(); + await u.po.page.goToRelative('/pricing-table'); + await u.po.page.locator('.cl-pricingTable-root').waitFor({ state: 'attached' }); // We have two plans, so subscribe to the first one await u.po.page.getByText('Get started').first().click(); - await u.po.billing.waitForDrawerMounted(); + await u.po.page.locator('.cl-checkout-root').waitFor({ state: 'attached' }); // Stripe uses multiple iframes, so we need to find the correct one const frame = u.po.page.frameLocator('iframe[src*="elements-inner-payment"]'); @@ -70,9 +77,11 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl const u = createTestUtils({ app, page, context }); await u.po.signIn.goTo(); await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password }); - await u.po.billing.goToPricingTable(); + await u.po.page.goToRelative('/pricing-table'); + await u.po.page.locator('.cl-pricingTable-root').waitFor({ state: 'attached' }); + await u.po.page.getByText('Manage subscription').click(); - await u.po.billing.waitForDrawerMounted(); + await u.po.page.getByRole('button', { name: 'Cancel subscription' }).click(); await u.po.page.getByRole('alertdialog').getByRole('button', { name: 'Cancel subscription' }).click(); await expect(u.po.page.getByRole('button', { name: 'Re-subscribe' }).first()).toBeVisible(); diff --git a/packages/testing/src/playwright/unstable/page-objects/billing.ts b/packages/testing/src/playwright/unstable/page-objects/billing.ts deleted file mode 100644 index f020211b1db..00000000000 --- a/packages/testing/src/playwright/unstable/page-objects/billing.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { EnhancedPage } from './app'; -import { common } from './common'; - -export const createBillingComponentPageObject = (testArgs: { page: EnhancedPage }) => { - const { page } = testArgs; - - const self = { - ...common(testArgs), - goToPricingTable: async (opts?: { searchParams?: URLSearchParams; headlessSelector?: string }) => { - await page.goToRelative('/pricing-table', { searchParams: opts?.searchParams }); - return await page.waitForURL(/pricing-table/); - }, - }; - - return self; -}; diff --git a/packages/testing/src/playwright/unstable/page-objects/index.ts b/packages/testing/src/playwright/unstable/page-objects/index.ts index e5f2c354b85..484b3075db0 100644 --- a/packages/testing/src/playwright/unstable/page-objects/index.ts +++ b/packages/testing/src/playwright/unstable/page-objects/index.ts @@ -1,7 +1,6 @@ import type { Page } from '@playwright/test'; import { createAppPageObject } from './app'; -import { createBillingComponentPageObject } from './billing'; import { createClerkPageObject } from './clerk'; import { createExpectPageObject } from './expect'; import { createImpersonationPageObject } from './impersonation'; @@ -43,6 +42,5 @@ export const createPageObjects = ({ userProfile: createUserProfileComponentPageObject(testArgs), userVerification: createUserVerificationComponentPageObject(testArgs), waitlist: createWaitlistComponentPageObject(testArgs), - billing: createBillingComponentPageObject(testArgs), }; }; From 03b992dac8f6102d1a265ecd0c0813300013e582 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Fri, 2 May 2025 07:51:20 +0300 Subject: [PATCH 13/18] lint fixes --- packages/testing/src/playwright/unstable/page-objects/common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/testing/src/playwright/unstable/page-objects/common.ts b/packages/testing/src/playwright/unstable/page-objects/common.ts index 54712c21ae6..6d4c1e57b8e 100644 --- a/packages/testing/src/playwright/unstable/page-objects/common.ts +++ b/packages/testing/src/playwright/unstable/page-objects/common.ts @@ -58,7 +58,7 @@ export const common = ({ page }: { page: EnhancedPage }) => { }, waitForDrawerMounted: () => { return page.locator('.cl-drawerContent').waitFor({ state: 'attached' }); - } + }, }; return self; From 14e8b18185582f6a13425a885acdaa0acc49876c Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Fri, 2 May 2025 08:09:27 +0300 Subject: [PATCH 14/18] ci test --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7acf88a5831..5a3fd24fd69 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "test:integration:ap-flows": "pnpm test:integration:base --grep @ap-flows", "test:integration:astro": "E2E_APP_ID=astro.* pnpm test:integration:base --grep @astro", "test:integration:base": "pnpm playwright test --config integration/playwright.config.ts", - "test:integration:billing": "E2E_APP_ID=withBilling* pnpm test:integration:base --grep @billing", + "test:integration:billing": "E2E_APP_ID=withBilling.vue.vite pnpm test:integration:base --grep @billing", "test:integration:cleanup": "pnpm playwright test --config integration/playwright.cleanup.config.ts", "test:integration:deployment:nextjs": "pnpm playwright test --config integration/playwright.deployments.config.ts", "test:integration:elements": "E2E_APP_ID=elements.* pnpm test:integration:base --grep @elements", From 66345aee210c0151cf026209928d2b39bacce485 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Fri, 2 May 2025 08:31:11 +0300 Subject: [PATCH 15/18] update tests --- integration/tests/pricing-table.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/integration/tests/pricing-table.test.ts b/integration/tests/pricing-table.test.ts index 9f5c14af36a..e75a1729194 100644 --- a/integration/tests/pricing-table.test.ts +++ b/integration/tests/pricing-table.test.ts @@ -69,7 +69,6 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl // await frame.getByLabel('ZIP code').fill('12345'); await u.po.page.getByRole('button', { name: 'Pay $' }).click(); - await u.po.page.locator('.cl-checkoutSuccessTitle').waitFor({ state: 'visible' }); await expect(u.po.page.getByText('Payment was successful!')).toBeVisible(); }); From aaa7dcb573f22cb34fde08e2aa75b843f9c522a3 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Fri, 2 May 2025 08:37:06 +0300 Subject: [PATCH 16/18] update tests --- integration/tests/pricing-table.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/tests/pricing-table.test.ts b/integration/tests/pricing-table.test.ts index e75a1729194..3d203aa37cb 100644 --- a/integration/tests/pricing-table.test.ts +++ b/integration/tests/pricing-table.test.ts @@ -66,7 +66,7 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withBilling] })('pricing tabl await frame.getByLabel('Card number').fill('4242424242424242'); await frame.getByLabel('Expiration date').fill('1234'); await frame.getByLabel('Security code').fill('123'); - // await frame.getByLabel('ZIP code').fill('12345'); + await frame.getByLabel('ZIP code').fill('12345'); await u.po.page.getByRole('button', { name: 'Pay $' }).click(); await expect(u.po.page.getByText('Payment was successful!')).toBeVisible(); From 5d04533e63a0ca39b3ca2841931f2ec2a6e0409a Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Fri, 2 May 2025 08:42:50 +0300 Subject: [PATCH 17/18] update tests --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5a3fd24fd69..0a459374786 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "test:integration:ap-flows": "pnpm test:integration:base --grep @ap-flows", "test:integration:astro": "E2E_APP_ID=astro.* pnpm test:integration:base --grep @astro", "test:integration:base": "pnpm playwright test --config integration/playwright.config.ts", - "test:integration:billing": "E2E_APP_ID=withBilling.vue.vite pnpm test:integration:base --grep @billing", + "test:integration:billing": "E2E_APP_ID=withBilling.* pnpm test:integration:base --grep @billing", "test:integration:cleanup": "pnpm playwright test --config integration/playwright.cleanup.config.ts", "test:integration:deployment:nextjs": "pnpm playwright test --config integration/playwright.deployments.config.ts", "test:integration:elements": "E2E_APP_ID=elements.* pnpm test:integration:base --grep @elements", From 1eca099a5be65f7b7a51843cc09a11cb94927924 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Fri, 2 May 2025 08:57:31 +0300 Subject: [PATCH 18/18] update tests --- .../testing/src/playwright/unstable/page-objects/common.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/testing/src/playwright/unstable/page-objects/common.ts b/packages/testing/src/playwright/unstable/page-objects/common.ts index 6d4c1e57b8e..af562c94b8b 100644 --- a/packages/testing/src/playwright/unstable/page-objects/common.ts +++ b/packages/testing/src/playwright/unstable/page-objects/common.ts @@ -56,9 +56,6 @@ export const common = ({ page }: { page: EnhancedPage }) => { return !!window.Clerk?.session; }); }, - waitForDrawerMounted: () => { - return page.locator('.cl-drawerContent').waitFor({ state: 'attached' }); - }, }; return self;