@clerk/testing
Version:
Utilities to help you create E2E test suites for apps using Clerk
1 lines • 53 kB
Source Map (JSON)
{"version":3,"sources":["../../../src/playwright/unstable/page-objects/common.ts","../../../src/playwright/unstable/page-objects/apiKeys.ts","../../../src/playwright/unstable/page-objects/app.ts","../../../src/playwright/unstable/page-objects/checkout.ts","../../../src/playwright/unstable/page-objects/clerk.ts","../../../src/playwright/unstable/page-objects/expect.ts","../../../src/playwright/unstable/page-objects/impersonation.ts","../../../src/playwright/unstable/page-objects/keylessPopover.ts","../../../src/playwright/unstable/page-objects/organizationSwitcher.ts","../../../src/playwright/unstable/page-objects/pricingTable.ts","../../../src/playwright/unstable/page-objects/sessionTask.ts","../../../src/playwright/unstable/page-objects/signIn.ts","../../../src/playwright/unstable/page-objects/signUp.ts","../../../src/playwright/unstable/page-objects/subscriptionDetails.ts","../../../src/playwright/unstable/page-objects/testingToken.ts","../../../src/playwright/unstable/page-objects/userButton.ts","../../../src/playwright/unstable/page-objects/userProfile.ts","../../../src/playwright/unstable/page-objects/userVerification.ts","../../../src/playwright/unstable/page-objects/waitlist.ts","../../../src/playwright/unstable/page-objects/index.ts"],"sourcesContent":["import type { EnhancedPage } from './app';\n\nexport const common = ({ page }: { page: EnhancedPage }) => {\n const self = {\n continue: () => {\n return page.getByRole('button', { name: 'Continue', exact: true }).click();\n },\n setEmailAddress: (val: string) => {\n return self.getEmailAddressInput().fill(val);\n },\n setPassword: (val: string) => {\n return self.getPasswordInput().fill(val);\n },\n setPasswordConfirmation: (val: string) => {\n return page.locator('input[name=confirmPassword]').fill(val);\n },\n enterOtpCode: async (code: string) => {\n await page.getByRole('textbox', { name: /digit 1/i }).click();\n // We've got a delay here to ensure the prepare call is triggered before the OTP is auto-submitted.\n await page.keyboard.type(code, { delay: 100 });\n },\n enterTestOtpCode: async () => {\n return self.enterOtpCode('424242');\n },\n // It's recommended to use .fill instead of .type\n // @see https://playwright.dev/docs/api/class-keyboard#keyboard-type\n fillTestOtpCode: async (name: string) => {\n return page.getByRole('textbox', { name: name }).fill('424242');\n },\n getIdentifierInput: () => {\n return page.locator('input[name=identifier]');\n },\n getEmailAddressInput: () => {\n return page.locator('input[name=emailAddress]');\n },\n getPhoneNumberInput: () => {\n return page.locator('input[name=phoneNumber]');\n },\n getUsernameInput: () => {\n return page.locator('input[name=username]');\n },\n getPasswordInput: () => {\n return page.locator('input[name=password]');\n },\n getLegalAccepted: () => {\n return page.locator('input[name=legalAccepted]');\n },\n getFirstNameInput: () => {\n return page.locator('input[name=firstName]');\n },\n getLastNameInput: () => {\n return page.locator('input[name=lastName]');\n },\n waitForSession: async () => {\n return page.waitForFunction(() => {\n return !!window.Clerk?.session;\n });\n },\n };\n\n return self;\n};\n","import type { EnhancedPage } from './app';\nimport { common } from './common';\n\nexport const createAPIKeysComponentPageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n\n const expirationOptions = {\n never: 'Never',\n '1d': '1 Day',\n '7d': '7 Days',\n '30d': '30 Days',\n '60d': '60 Days',\n '90d': '90 Days',\n '180d': '180 Days',\n '1y': '1 Year',\n } as const;\n\n const self = {\n ...common(testArgs),\n waitForMounted: () => {\n return page.waitForSelector('.cl-apiKeys-root', { state: 'attached' });\n },\n clickAddButton: () => {\n return page.getByText(/Add new key/i).click();\n },\n waitForFormOpened: () => {\n return page.waitForSelector('.cl-apiKeysCreateForm', { state: 'attached' });\n },\n waitForFormClosed: () => {\n return page.waitForSelector('.cl-apiKeysCreateForm', { state: 'detached' });\n },\n waitForRevokeModalOpened: () => {\n return page.waitForSelector('.cl-apiKeysRevokeModal', { state: 'attached' });\n },\n waitForRevokeModalClosed: () => {\n return page.waitForSelector('.cl-apiKeysRevokeModal', { state: 'detached' });\n },\n typeName: (value: string) => {\n return page.getByLabel(/Secret key name/i).fill(value);\n },\n typeDescription: (value: string) => {\n return page.getByLabel(/Description/i).fill(value);\n },\n selectExpiration: async (value?: keyof typeof expirationOptions) => {\n await page.getByRole('button', { name: /Select date/i }).click();\n return page.getByText(expirationOptions[value ?? 'never'], { exact: true }).click();\n },\n clickSaveButton: () => {\n return page.getByText(/Create key/i).click();\n },\n typeRevokeConfirmation: (value: string) => {\n return page.getByLabel(/Type \"Revoke\" to confirm/i).fill(value);\n },\n clickConfirmRevokeButton: () => {\n return page.getByText(/Revoke key/i).click();\n },\n };\n return self;\n};\n","import type { Page } from '@playwright/test';\n\nimport { setupClerkTestingToken } from '../../setupClerkTestingToken';\n\nexport type EnhancedPage = ReturnType<typeof createAppPageObject>;\nexport const createAppPageObject = (testArgs: { page: Page; useTestingToken?: boolean }, app: { baseURL?: string }) => {\n const { page, useTestingToken = true } = testArgs;\n const appPage = Object.create(page) as Page;\n const helpers = {\n goToAppHome: async () => {\n if (!app.baseURL) {\n throw new Error(\n 'Attempted to call method requiring baseURL, but baseURL was not provided to createPageObjects.',\n );\n }\n\n try {\n if (useTestingToken) {\n await setupClerkTestingToken({ page });\n }\n\n await page.goto(app.baseURL);\n } catch {\n // do not fail the test if interstitial is returned (401)\n }\n },\n goToRelative: async (\n path: string,\n opts: { waitUntil?: any; searchParams?: URLSearchParams; timeout?: number } = {},\n ) => {\n if (!app.baseURL) {\n throw new Error(\n 'Attempted to call method requiring baseURL, but baseURL was not provided to createPageObjects.',\n );\n }\n let url: URL;\n\n try {\n // When testing applications using real domains we want to manually navigate to the domain first\n // and not follow serverUrl (localhost) by default, as this is usually proxied\n if (page.url().includes('about:blank')) {\n url = new URL(path, app.baseURL);\n } else {\n url = new URL(path, page.url());\n }\n } catch {\n // However, in most tests we don't need to manually navigate to the domain\n // as the test is using a localhost app directly\n // This handles the case where the page is at about:blank\n // and instead it uses the serverUrl\n url = new URL(path, app.baseURL);\n }\n\n if (opts.searchParams) {\n url.search = opts.searchParams.toString();\n }\n\n if (useTestingToken) {\n await setupClerkTestingToken({ page });\n }\n\n return page.goto(url.toString(), { timeout: opts.timeout ?? 20000, waitUntil: opts.waitUntil });\n },\n waitForClerkJsLoaded: async () => {\n return page.waitForFunction(() => {\n return window.Clerk?.loaded;\n });\n },\n signOut: async () => {\n return page.waitForFunction(() => {\n return window.Clerk?.signOut({});\n });\n },\n waitForClerkComponentMounted: async () => {\n return page.waitForSelector('.cl-rootBox', { state: 'attached' });\n },\n waitForAppUrl: async (relativePath: string) => {\n if (!app.baseURL) {\n throw new Error(\n 'Attempted to call method requiring baseURL, but baseURL was not provided to createPageObjects.',\n );\n }\n return page.waitForURL(new URL(relativePath, app.baseURL).toString());\n },\n /**\n * Get the cookies for the URL the page is currently at.\n * Suffixed cookies can be accessed by using the wildcard character `*` at the end of the cookie name,\n * eg `get('__session')` and `get('__session_*')`.\n */\n cookies: async () => {\n const array = await page.context().cookies();\n const map = array.reduce((acc, cookie) => {\n // If a suffixed cookie is found, we usually don't care about the suffix itself\n // Instead, simply replace the suffix with _* so we can easily read it\n // TODO: deal with collisions if neede\n // TODO: might be too much magic here\n // Maybe extract this into a different helper?\n if (cookie.name.match(/^(__.*_)(.{8})$/)) {\n acc.set(cookie.name.replace(/^(__.*_)(.{8})$/, '$1*'), cookie);\n } else {\n acc.set(cookie.name, cookie);\n }\n return acc;\n }, new Map<string, (typeof array)[number]>());\n return Object.assign(map, { raw: () => array });\n },\n };\n return Object.assign(appPage, helpers);\n};\n","import type { EnhancedPage } from './app';\nimport { common } from './common';\n\nexport const createCheckoutPageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n const self = {\n ...common(testArgs),\n waitForMounted: (selector = '.cl-checkout-root') => {\n return page.waitForSelector(selector, { state: 'attached' });\n },\n closeDrawer: () => {\n return page.locator('.cl-drawerClose').click();\n },\n fillTestCard: async () => {\n await self.fillCard({\n number: '4242424242424242',\n expiration: '1234',\n cvc: '123',\n country: 'United States',\n zip: '12345',\n });\n },\n fillCard: async (card: { number: string; expiration: string; cvc: string; country: string; zip: string }) => {\n const frame = page.frameLocator('iframe[src*=\"elements-inner-payment\"]');\n await frame.getByLabel('Card number').fill(card.number);\n await frame.getByLabel('Expiration date').fill(card.expiration);\n await frame.getByLabel('Security code').fill(card.cvc);\n await frame.getByLabel('Country').selectOption(card.country);\n await frame.getByLabel('ZIP code').fill(card.zip);\n },\n waitForStripeElements: async ({ state = 'visible' }: { state?: 'visible' | 'hidden' } = {}) => {\n return page.frameLocator('iframe[src*=\"elements-inner-payment\"]').getByLabel('Card number').waitFor({ state });\n },\n clickPayOrSubscribe: async () => {\n await self.root.getByRole('button', { name: /subscribe|pay\\s\\$/i }).click();\n },\n waitForSubscribeButton: async () => {\n await self.root.getByRole('button', { name: /^subscribe$/i }).waitFor({ state: 'visible' });\n },\n confirmAndContinue: async () => {\n await self.root.getByRole('button', { name: /^continue$/i }).click();\n },\n clickAddPaymentMethod: async () => {\n await self.root.getByRole('radio', { name: 'Add payment method' }).click();\n },\n clickPaymentMethods: async () => {\n await self.root.getByRole('radio', { name: 'Payment Methods' }).click();\n },\n root: page.locator('.cl-checkout-root'),\n };\n return self;\n};\n","import type { EnhancedPage } from './app';\n\nexport const createClerkPageObject = ({ page }: { page: EnhancedPage }) => {\n return {\n toBeLoaded: async () => {\n return page.waitForFunction(() => {\n return !!window.Clerk?.loaded;\n });\n },\n getClientSideActor: () => {\n return page.evaluate(() => {\n return window.Clerk?.session?.actor;\n });\n },\n toBeLoading: async () => {\n return page.waitForFunction(() => {\n return window.Clerk?.status === 'loading';\n });\n },\n toBeReady: async () => {\n return page.waitForFunction(() => {\n return window.Clerk?.status === 'ready';\n });\n },\n toBeDegraded: async () => {\n return page.waitForFunction(() => {\n return window.Clerk?.status === 'degraded';\n });\n },\n getClientSideUser: () => {\n return page.evaluate(() => {\n return window.Clerk?.user;\n });\n },\n };\n};\n","import type { Response } from '@playwright/test';\nimport { expect } from '@playwright/test';\n\nimport type { EnhancedPage } from './app';\n\nexport const createExpectPageObject = ({ page }: { page: EnhancedPage }) => {\n return {\n toBeHandshake: async (res: Response) => {\n // Travel the redirect chain until we find the handshake header\n // TODO: Loop through the redirects until we find a handshake header, or timeout trying\n const redirect = await res.request().redirectedFrom()?.redirectedFrom()?.response();\n expect(redirect?.status()).toBe(307);\n expect(redirect?.headers()['x-clerk-auth-status']).toContain('handshake');\n },\n toBeSignedOut: (args?: { timeOut: number }) => {\n return page.waitForFunction(\n () => {\n return !window.Clerk?.user;\n },\n null,\n { timeout: args?.timeOut },\n );\n },\n toBeSignedIn: async () => {\n return page.waitForFunction(() => {\n return !!window.Clerk?.user;\n });\n },\n toBeSignedInAsActor: async () => {\n return page.waitForFunction(() => {\n return !!window.Clerk?.session?.actor;\n });\n },\n toHaveResolvedTask: async () => {\n return page.waitForFunction(() => {\n return !window.Clerk?.session?.currentTask;\n });\n },\n };\n};\n","import type { EnhancedPage } from './app';\n\nexport const createImpersonationPageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n const self = {\n waitForMounted: (selector = '.cl-impersonationFab') => {\n return page.waitForSelector(selector, { state: 'attached' });\n },\n getSignOutLink: () => {\n return page.locator('.cl-impersonationFab').getByText('Sign out');\n },\n };\n return self;\n};\n","import type { EnhancedPage } from './app';\n\nexport const createKeylessPopoverPageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n // TODO: Is this the ID we really want ?\n const elementId = '#--clerk-keyless-prompt-button';\n const self = {\n waitForMounted: () => page.waitForSelector(elementId, { state: 'attached' }),\n waitForUnmounted: () => page.waitForSelector(elementId, { state: 'detached' }),\n isExpanded: () =>\n page\n .locator(elementId)\n .getAttribute('aria-expanded')\n .then(val => val === 'true'),\n toggle: () => page.locator(elementId).click(),\n\n promptsToClaim: () => {\n return page.getByRole('link', { name: /^claim application$/i });\n },\n promptToUseClaimedKeys: () => {\n return page.getByRole('link', { name: /^get api keys$/i });\n },\n promptToDismiss: () => {\n return page.getByRole('button', { name: /^dismiss$/i });\n },\n };\n return self;\n};\n","import { expect } from '@playwright/test';\n\nimport type { EnhancedPage } from './app';\nimport { common } from './common';\n\nexport const createOrganizationSwitcherComponentPageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n\n const self = {\n ...common(testArgs),\n goTo: async (relativePath = '/switcher') => {\n await page.goToRelative(relativePath);\n return self.waitForMounted();\n },\n waitForMounted: () => {\n return page.waitForSelector('.cl-organizationSwitcher-root', { state: 'attached' });\n },\n expectNoOrganizationSelected: () => {\n return expect(page.getByText(/No organization selected/i)).toBeVisible();\n },\n expectPersonalAccount: () => {\n return expect(page.getByText(/personal account/i)).toBeVisible();\n },\n toggleTrigger: () => {\n return page.locator('.cl-organizationSwitcherTrigger').click();\n },\n waitForAnOrganizationToSelected: () => {\n return page.waitForSelector('.cl-userPreviewMainIdentifier__personalWorkspace', { state: 'detached' });\n },\n };\n\n return self;\n};\n","import type { EnhancedPage } from './app';\nimport { common } from './common';\n\ntype BillingPeriod = 'monthly' | 'annually';\n\nexport const createPricingTablePageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n\n const locators = {\n toggle: (planSlug: string) => page.locator(`.cl-pricingTableCard__${planSlug} .cl-pricingTableCardPeriodToggle`),\n indicator: (planSlug: string) => page.locator(`.cl-pricingTableCard__${planSlug} .cl-switchIndicator`),\n badge: (planSlug: string) => page.locator(`.cl-pricingTableCard__${planSlug} .cl-badge`),\n footer: (planSlug: string) => page.locator(`.cl-pricingTableCard__${planSlug} .cl-pricingTableCardFooter`),\n };\n\n const ensurePricingPeriod = async (planSlug: string, period: BillingPeriod): Promise<void> => {\n async function waitForAttribute(selector: string, attribute: string, value: string, timeout = 5000) {\n return page\n .waitForFunction(\n ({ sel, attr, val }) => {\n const element = document.querySelector(sel);\n return element?.getAttribute(attr) === val;\n },\n { sel: selector, attr: attribute, val: value },\n { timeout },\n )\n .then(() => {\n return true;\n })\n .catch(() => {\n return false;\n });\n }\n\n const isAnnually = await waitForAttribute(\n `.cl-pricingTableCard__${planSlug} .cl-switchIndicator`,\n 'data-checked',\n 'true',\n 500,\n );\n\n if (isAnnually && period === 'monthly') {\n await locators.toggle(planSlug).click();\n }\n\n if (!isAnnually && period === 'annually') {\n await locators.toggle(planSlug).click();\n }\n };\n\n const self = {\n ...common(testArgs),\n waitForMounted: (selector = '.cl-pricingTable-root') => {\n return page.waitForSelector(selector, { state: 'attached' });\n },\n clickResubscribe: async () => {\n await page.getByText('Re-subscribe').click();\n },\n waitToBeActive: async ({ planSlug }: { planSlug: string }) => {\n return locators.badge(planSlug).getByText('Active').waitFor({ state: 'visible' });\n },\n getPlanCardCTA: ({ planSlug }: { planSlug: string }) => {\n return locators.footer(planSlug).getByRole('button', {\n name: /get|switch|subscribe/i,\n });\n },\n startCheckout: async ({\n planSlug,\n shouldSwitch,\n period,\n }: {\n planSlug: string;\n shouldSwitch?: boolean;\n period?: BillingPeriod;\n }) => {\n const targetButtonName =\n shouldSwitch === true ? 'Switch to this plan' : shouldSwitch === false ? /subscribe/i : /get|switch|subscribe/i;\n\n if (period) {\n await ensurePricingPeriod(planSlug, period);\n }\n\n await locators\n .footer(planSlug)\n .getByRole('button', {\n name: targetButtonName,\n })\n .click();\n },\n };\n return self;\n};\n","import { expect } from '@playwright/test';\n\nimport type { EnhancedPage } from './app';\nimport { common } from './common';\n\nexport const createSessionTaskComponentPageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n\n const self = {\n ...common(testArgs),\n resolveForceOrganizationSelectionTask: async (fakeOrganization: { name: string; slug: string }) => {\n const createOrganizationButton = page.getByRole('button', { name: /create new organization/i });\n\n await expect(createOrganizationButton).toBeVisible();\n\n await page.locator('input[name=name]').fill(fakeOrganization.name);\n await page.locator('input[name=slug]').fill(fakeOrganization.slug);\n\n await createOrganizationButton.click();\n },\n };\n\n return self;\n};\n","import { expect } from '@playwright/test';\n\nimport type { EnhancedPage } from './app';\nimport { common } from './common';\n\nexport const createSignInComponentPageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n const self = {\n ...common(testArgs),\n goTo: async (opts?: { searchParams?: URLSearchParams; headlessSelector?: string; timeout?: number }) => {\n const navRes = await page.goToRelative('/sign-in', opts);\n\n if (typeof opts?.headlessSelector !== 'undefined') {\n await self.waitForMounted(opts.headlessSelector);\n } else {\n await self.waitForMounted();\n }\n return navRes;\n },\n waitForMounted: (selector = '.cl-signIn-root') => {\n return page.waitForSelector(selector, { state: 'attached' });\n },\n waitForModal: (state?: 'open' | 'closed') => {\n return page.waitForSelector('.cl-modalContent:has(.cl-signIn-root)', {\n state: state === 'closed' ? 'detached' : 'attached',\n });\n },\n setIdentifier: (val: string) => {\n return self.getIdentifierInput().fill(val);\n },\n setInstantPassword: async (val: string) => {\n const passField = self.getPasswordInput();\n await expect(passField).toBeVisible();\n await passField.fill(val, { force: true });\n },\n usePhoneNumberIdentifier: () => {\n return page.getByRole('link', { name: /^use phone/i });\n },\n useEmailIdentifier: () => {\n return page.getByRole('link', { name: /^use email/i });\n },\n useUsernameIdentifier: () => {\n return page.getByRole('link', { name: /^username$/i });\n },\n getForgotPassword: () => {\n return page.getByRole('link', { name: /forgot password/i });\n },\n getGoToSignUp: () => {\n return page.getByRole('link', { name: /sign up/i });\n },\n getResetPassword: () => {\n return page.getByRole('button', { name: /(reset password|reset your password)/i });\n },\n getUseAnotherMethodLink: () => {\n return page.getByRole('link', { name: /use another method/i });\n },\n getAltMethodsEmailCodeButton: () => {\n return page.getByRole('button', { name: /email code to/i });\n },\n getAltMethodsEmailLinkButton: () => {\n return page.getByRole('button', { name: /email link to/i });\n },\n signInWithOauth: (provider: string) => {\n return page.getByRole('button', { name: new RegExp(`continue with ${provider}`, 'gi') });\n },\n signInWithEmailAndInstantPassword: async ({\n email,\n password,\n waitForSession = true,\n }: {\n email: string;\n password: string;\n waitForSession?: boolean;\n }) => {\n const identifierField = self.getIdentifierInput();\n await expect(identifierField).toBeVisible();\n\n await identifierField.fill(email);\n await self.setInstantPassword(password);\n await self.continue();\n\n if (waitForSession) {\n await self.waitForSession();\n }\n },\n };\n return self;\n};\n","import type { EnhancedPage } from './app';\nimport { common } from './common';\n\ntype SignUpFormInputs = {\n email?: string;\n password?: string;\n firstName?: string;\n lastName?: string;\n username?: string;\n phoneNumber?: string;\n legalAccepted?: boolean;\n};\n\nexport const createSignUpComponentPageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n\n const self = {\n ...common(testArgs),\n goTo: async (opts?: { searchParams?: URLSearchParams; headlessSelector?: string }) => {\n await page.goToRelative('/sign-up', { searchParams: opts?.searchParams });\n\n if (typeof opts?.headlessSelector !== 'undefined') {\n return self.waitForMounted(opts.headlessSelector);\n }\n return self.waitForMounted();\n },\n waitForMounted: (selector = '.cl-signUp-root') => {\n return page.waitForSelector(selector, { state: 'attached' });\n },\n waitForModal: (state?: 'open' | 'closed') => {\n return page.waitForSelector('.cl-modalContent:has(.cl-signUp-root)', {\n state: state === 'closed' ? 'detached' : 'attached',\n });\n },\n signUpWithOauth: (provider: string) => {\n return page.getByRole('button', { name: new RegExp(`continue with ${provider}`, 'gi') });\n },\n signUp: async (opts: SignUpFormInputs) => {\n if (opts.firstName) {\n await self.getFirstNameInput().fill(opts.firstName);\n }\n\n if (opts.lastName) {\n await self.getLastNameInput().fill(opts.lastName);\n }\n\n if (opts.email) {\n await self.getEmailAddressInput().fill(opts.email);\n }\n\n if (opts.username) {\n await self.getUsernameInput().fill(opts.username);\n }\n\n if (opts.phoneNumber) {\n await self.getPhoneNumberInput().fill(opts.phoneNumber);\n }\n\n if (opts.password) {\n await self.getPasswordInput().fill(opts.password);\n }\n\n if (opts.legalAccepted) {\n await self.getLegalAccepted().check();\n }\n\n await self.continue();\n },\n signUpWithEmailAndPassword: async (opts: Pick<SignUpFormInputs, 'email' | 'password'>) => {\n await self.signUp({ email: opts.email, password: opts.password });\n },\n waitForEmailVerificationScreen: async () => {\n await page.waitForURL(/verify/);\n await page.getByRole('heading', { name: /Verify your email/i }).waitFor();\n },\n };\n\n return self;\n};\n","import type { EnhancedPage } from './app';\nimport { common } from './common';\n\nexport const createSubscriptionDetailsPageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n const self = {\n ...common(testArgs),\n waitForMounted: (selector = '.cl-subscriptionDetails-root') => {\n return page.waitForSelector(selector, { state: 'attached' });\n },\n waitForUnmounted: () => {\n return self.root.locator('.cl-drawerRoot').waitFor({ state: 'detached' });\n },\n closeDrawer: () => {\n return self.root.locator('.cl-drawerClose').click();\n },\n root: page.locator('.cl-subscriptionDetails-root'),\n };\n return self;\n};\n","import { setupClerkTestingToken } from '../../setupClerkTestingToken';\nimport type { EnhancedPage } from './app';\n\nexport const createTestingTokenPageObject = ({ page }: { page: EnhancedPage }) => {\n return {\n setup: async () => setupClerkTestingToken({ page }),\n };\n};\n","import { expect } from '@playwright/test';\n\nimport type { EnhancedPage } from './app';\n\nexport const createUserButtonPageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n\n const self = {\n waitForMounted: () => {\n return page.waitForSelector('.cl-userButtonTrigger', { state: 'attached' });\n },\n toggleTrigger: () => {\n return page.locator('.cl-userButtonTrigger').click();\n },\n waitForPopover: () => {\n return page.waitForSelector('.cl-userButtonPopoverCard', { state: 'visible' });\n },\n waitForPopoverClosed: () => {\n return page.waitForSelector('.cl-userButtonPopoverCard', { state: 'detached' });\n },\n toHaveVisibleMenuItems: async (menuItems: string | RegExp | Array<string | RegExp>) => {\n if (typeof menuItems === 'string' || menuItems instanceof RegExp) {\n menuItems = [menuItems];\n }\n for (const menuItem of menuItems) {\n await expect(page.getByRole('menuitem', { name: menuItem })).toBeVisible();\n }\n },\n triggerSignOut: () => {\n return page.getByRole('menuitem', { name: /Sign out$/i }).click();\n },\n triggerManageAccount: () => {\n return page.getByRole('menuitem', { name: /Manage account/i }).click();\n },\n switchAccount: (emailAddress: string) => {\n return page.getByText(emailAddress).click();\n },\n };\n\n return self;\n};\n","import type { EnhancedPage } from './app';\nimport { common } from './common';\n\nexport type Sections = 'profile' | 'emailAddresses' | 'username' | 'phoneNumbers' | 'danger';\n\nexport const createUserProfileComponentPageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n const self = {\n ...common(testArgs),\n goTo: async (opts?: { searchParams: URLSearchParams }) => {\n await page.goToRelative('/user', opts);\n return self.waitForMounted();\n },\n switchToSecurityTab: async () => {\n await page.getByText(/Security/i).click();\n },\n switchToBillingTab: async () => {\n await page.getByText(/Billing/i).click();\n },\n waitForMounted: () => {\n return page.waitForSelector('.cl-userProfile-root', { state: 'attached' });\n },\n clickSetUsername: () => {\n return page.getByText(/Set username/i).click();\n },\n clickToUpdateProfile: () => {\n return page.getByText(/update profile/i).click();\n },\n clickUpdateUsername: () => {\n return page.getByText(/update username/i).click();\n },\n clickSetPassword: () => {\n return page.getByText(/Set password/i).click();\n },\n waitForSectionCard: (section: Sections, opened: boolean) => {\n return page.waitForSelector(`.cl-profileSectionContent__${section} .cl-headerTitle`, {\n state: opened ? 'visible' : 'detached',\n });\n },\n waitForSectionCardOpened: (section: Sections) => {\n return self.waitForSectionCard(section, true);\n },\n waitForSectionCardClosed: (section: Sections) => {\n return self.waitForSectionCard(section, false);\n },\n typeUsername: (value: string) => {\n return self.getUsernameInput().fill(value);\n },\n typeFirstName: (value: string) => {\n return self.getFirstNameInput().fill(value);\n },\n typeLastName: (value: string) => {\n return self.getLastNameInput().fill(value);\n },\n typePhoneNumber: (value: string) => {\n return self.getPhoneNumberInput().fill(value);\n },\n clickAddEmailAddress: () => {\n return page.getByText(/add email address/i).click();\n },\n clickAddPhoneNumber: () => {\n return page.getByText(/add phone number/i).click();\n },\n typeEmailAddress: (value: string) => {\n return page.getByLabel(/Email address/i).fill(value);\n },\n waitForUserProfileModal: (state?: 'open' | 'closed') => {\n return page.waitForSelector('.cl-modalContent:has(.cl-userProfile-root)', {\n state: state === 'closed' ? 'detached' : 'attached',\n });\n },\n };\n return self;\n};\n","import type { EnhancedPage } from './app';\nimport { common } from './common';\n\nexport const createUserVerificationComponentPageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n const self = {\n ...common(testArgs),\n waitForMounted: (selector = '.cl-userVerification-root') => {\n return page.waitForSelector(selector, { state: 'attached' });\n },\n waitForClosed: (selector = '.cl-userVerification-root') => {\n return page.waitForSelector(selector, { state: 'detached' });\n },\n closeReverificationModal: () => {\n return page.getByLabel('Close modal').click();\n },\n getUseAnotherMethodLink: () => {\n return page.getByRole('link', { name: /use another method/i });\n },\n getAltMethodsEmailCodeButton: () => {\n return page.getByRole('button', { name: /email code to/i });\n },\n getAltMethodsEmailLinkButton: () => {\n return page.getByRole('button', { name: /email link to/i });\n },\n };\n return self;\n};\n","import type { EnhancedPage } from './app';\nimport { common } from './common';\n\ntype WaitlistFormInputs = {\n email: string;\n};\n\nexport const createWaitlistComponentPageObject = (testArgs: { page: EnhancedPage }) => {\n const { page } = testArgs;\n\n const self = {\n ...common(testArgs),\n goTo: async (opts?: { searchParams?: URLSearchParams; headlessSelector?: string }) => {\n await page.goToRelative('/waitlist', { searchParams: opts?.searchParams });\n\n if (typeof opts?.headlessSelector !== 'undefined') {\n return self.waitForMounted(opts.headlessSelector);\n }\n return self.waitForMounted();\n },\n waitForMounted: (selector = '.cl-waitlist-root') => {\n return page.waitForSelector(selector, { state: 'attached' });\n },\n joinWaitlist: async (opts: WaitlistFormInputs) => {\n await self.getEmailAddressInput().fill(opts.email);\n\n await self.joinWaitlistContinue();\n },\n joinWaitlistContinue: () => {\n return page.getByRole('button', { name: 'Join the waitlist', exact: true }).click();\n },\n };\n\n return self;\n};\n","import type { Page } from '@playwright/test';\n\nimport { createAPIKeysComponentPageObject } from './apiKeys';\nimport { createAppPageObject } from './app';\nimport { createCheckoutPageObject } from './checkout';\nimport { createClerkPageObject } from './clerk';\nimport { createExpectPageObject } from './expect';\nimport { createImpersonationPageObject } from './impersonation';\nimport { createKeylessPopoverPageObject } from './keylessPopover';\nimport { createOrganizationSwitcherComponentPageObject } from './organizationSwitcher';\nimport { createPricingTablePageObject } from './pricingTable';\nimport { createSessionTaskComponentPageObject } from './sessionTask';\nimport { createSignInComponentPageObject } from './signIn';\nimport { createSignUpComponentPageObject } from './signUp';\nimport { createSubscriptionDetailsPageObject } from './subscriptionDetails';\nimport { createTestingTokenPageObject } from './testingToken';\nimport { createUserButtonPageObject } from './userButton';\nimport { createUserProfileComponentPageObject } from './userProfile';\nimport { createUserVerificationComponentPageObject } from './userVerification';\nimport { createWaitlistComponentPageObject } from './waitlist';\n\nexport const createPageObjects = ({\n page,\n useTestingToken = true,\n baseURL,\n}: {\n page: Page;\n useTestingToken?: boolean;\n baseURL?: string;\n}) => {\n const app = createAppPageObject({ page, useTestingToken }, { baseURL });\n const testArgs = { page: app };\n\n return {\n page: app,\n clerk: createClerkPageObject(testArgs),\n checkout: createCheckoutPageObject(testArgs),\n expect: createExpectPageObject(testArgs),\n impersonation: createImpersonationPageObject(testArgs),\n keylessPopover: createKeylessPopoverPageObject(testArgs),\n organizationSwitcher: createOrganizationSwitcherComponentPageObject(testArgs),\n pricingTable: createPricingTablePageObject(testArgs),\n sessionTask: createSessionTaskComponentPageObject(testArgs),\n signIn: createSignInComponentPageObject(testArgs),\n signUp: createSignUpComponentPageObject(testArgs),\n testingToken: createTestingTokenPageObject(testArgs),\n userButton: createUserButtonPageObject(testArgs),\n userProfile: createUserProfileComponentPageObject(testArgs),\n userVerification: createUserVerificationComponentPageObject(testArgs),\n waitlist: createWaitlistComponentPageObject(testArgs),\n apiKeys: createAPIKeysComponentPageObject(testArgs),\n subscriptionDetails: createSubscriptionDetailsPageObject(testArgs),\n };\n};\n"],"mappings":"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