{"version":3,"sources":["../../src/playwright/setup.ts","../../src/playwright/setupClerkTestingToken.ts","../../src/playwright/helpers.ts"],"sourcesContent":["import type { ClerkSetupOptions } from '../common';\nimport { fetchEnvVars } from '../common';\n\n/**\n * Sets up Clerk for testing by fetching the testing token from the Clerk Backend API.\n *\n * @param options.publishableKey - The publishable key for your Clerk dev instance.\n * @param options.frontendApiUrl - The frontend API URL for your Clerk dev instance, without the protocol. It overrides the Frontend API URL parsed from the publishable key.\n * @param options.debug - Enable debug logs.\n * @returns A promise that resolves when Clerk is set up.\n *\n * @throws An error if the publishable key or the secret key is not provided.\n * @throws An error if the secret key is from a production instance.\n * @throws An error if the testing token cannot be fetched from the Clerk Backend API.\n */\nexport const clerkSetup = async (options?: ClerkSetupOptions) => {\n  const { CLERK_FAPI, CLERK_TESTING_TOKEN } = await fetchEnvVars(options);\n  process.env.CLERK_FAPI = CLERK_FAPI;\n  process.env.CLERK_TESTING_TOKEN = CLERK_TESTING_TOKEN;\n};\n","import type { Page } from '@playwright/test';\n\nimport type { SetupClerkTestingTokenOptions } from '../common';\nimport { ERROR_MISSING_FRONTEND_API_URL, TESTING_TOKEN_PARAM } from '../common';\n\ntype SetupClerkTestingTokenParams = {\n  page: Page;\n  options?: SetupClerkTestingTokenOptions;\n};\n\n/**\n * Bypasses bot protection by appending the testing token in the Frontend API requests.\n *\n * @param params.page - The Playwright page object.\n * @param params.options.frontendApiUrl - The frontend API URL for your Clerk dev instance, without the protocol.\n * @returns A promise that resolves when the bot protection bypass is set up.\n * @throws An error if the Frontend API URL is not provided.\n * @example\n * import { setupClerkTestingToken } from '@clerk/testing/playwright';\n *\n * test('should bypass bot protection', async ({ page }) => {\n *    await setupClerkTestingToken({ page });\n *    await page.goto('https://your-app.com');\n *    // Continue with your test...\n *  });\n */\nexport const setupClerkTestingToken = async ({ page, options }: SetupClerkTestingTokenParams) => {\n  const fapiUrl = options?.frontendApiUrl || process.env.CLERK_FAPI;\n  if (!fapiUrl) {\n    throw new Error(ERROR_MISSING_FRONTEND_API_URL);\n  }\n  const apiUrl = `https://${fapiUrl}/v1/**/*`;\n\n  await page.route(apiUrl, async route => {\n    const originalUrl = new URL(route.request().url());\n    const testingToken = process.env.CLERK_TESTING_TOKEN;\n\n    if (testingToken) {\n      originalUrl.searchParams.set(TESTING_TOKEN_PARAM, testingToken);\n    }\n\n    try {\n      const response = await route.fetch({\n        url: originalUrl.toString(),\n      });\n\n      const json = await response.json();\n\n      // Override captcha_bypass in /v1/client\n      if (json?.response?.captcha_bypass === false) {\n        json.response.captcha_bypass = true;\n      }\n\n      // Override captcha_bypass in piggybacking\n      if (json?.client?.captcha_bypass === false) {\n        json.client.captcha_bypass = true;\n      }\n\n      await route.fulfill({\n        response,\n        json,\n      });\n    } catch {\n      await route\n        .continue({\n          url: originalUrl.toString(),\n        })\n        .catch(console.error);\n    }\n  });\n};\n","import type { Clerk, SignOutOptions } from '@clerk/types';\nimport type { Page } from '@playwright/test';\n\nimport type { ClerkSignInParams, SetupClerkTestingTokenOptions } from '../common';\nimport { signInHelper } from '../common';\nimport { setupClerkTestingToken } from './setupClerkTestingToken';\n\ndeclare global {\n  interface Window {\n    Clerk: Clerk;\n  }\n}\n\ntype PlaywrightClerkLoadedParams = {\n  page: Page;\n};\n\ntype ClerkHelperParams = {\n  /**\n   * Signs in a user using Clerk. This helper supports only password, phone_code and email_code first factor strategies.\n   * Multi-factor is not supported.\n   * This helper is using the `setupClerkTestingToken` internally.\n   * It is required to call `page.goto` before calling this helper, and navigate to a not protected page that loads Clerk.\n   *\n   * If the strategy is password, the helper will sign in the user using the provided password and identifier.\n   * If the strategy is phone_code, you are required to have a user with a test phone number as an identifier (e.g. +15555550100).\n   * If the strategy is email_code, you are required to have a user with a test email as an identifier (e.g. your_email+clerk_test@example.com).\n   *\n   * @param opts.signInParams.strategy - The sign in strategy. Supported strategies are 'password', 'phone_code' and 'email_code'.\n   * @param opts.signInParams.identifier - The user's identifier. Could be a username, a phone number or an email.\n   * @param opts.signInParams.password - The user's password. Required only if the strategy is 'password'.\n   * @param opts.page - The Playwright page object.\n   * @param opts.setupClerkTestingTokenOptions - The options for the `setupClerkTestingToken` function. Optional.\n   *\n   * @example\n   * import { clerk } from \"@clerk/testing/playwright\";\n   *\n   *  test(\"sign in\", async ({ page }) => {\n   *     await page.goto(\"/\");\n   *     await clerk.signIn({\n   *       page,\n   *       signInParams: { strategy: 'phone_code', identifier: '+15555550100' },\n   *     });\n   *     await page.goto(\"/protected\");\n   *   });\n   */\n  signIn: (opts: PlaywrightClerkSignInParams) => Promise<void>;\n  /**\n   * Signs out the current user using Clerk.\n   * It is required to call `page.goto` before calling this helper, and navigate to a page that loads Clerk.\n   * @param opts.signOutOptions - A SignOutOptions object.\n   * @param opts.page - The Playwright page object.\n   *\n   * @example\n   * import { clerk } from \"@clerk/testing/playwright\";\n   *\n   *  test(\"sign out\", async ({ page }) => {\n   *     await page.goto(\"/\");\n   *     await clerk.signIn({\n   *       page,\n   *       signInParams: { strategy: 'phone_code', identifier: '+15555550100' },\n   *     });\n   *     await page.goto(\"/protected\");\n   *     await clerk.signOut({ page });\n   *     await page.goto(\"/protected\");\n   *     // should redirect to sign in page\n   *   });\n   */\n  signOut: (opts: PlaywrightClerkSignOutParams) => Promise<void>;\n  /**\n   * Asserts that Clerk has been loaded.\n   * It is required to call `page.goto` before calling this helper, and navigate to a page that loads Clerk.\n   *\n   * @param opts.page - The Playwright page object.\n   */\n  loaded: (opts: PlaywrightClerkLoadedParams) => Promise<void>;\n};\n\nconst loaded = async ({ page }: PlaywrightClerkLoadedParams) => {\n  await page.waitForFunction(() => window.Clerk !== undefined);\n  await page.waitForFunction(() => window.Clerk.loaded);\n};\n\ntype PlaywrightClerkSignInParams = {\n  page: Page;\n  signInParams: ClerkSignInParams;\n  setupClerkTestingTokenOptions?: SetupClerkTestingTokenOptions;\n};\n\nconst signIn = async ({ page, signInParams, setupClerkTestingTokenOptions }: PlaywrightClerkSignInParams) => {\n  await setupClerkTestingToken({ page, options: setupClerkTestingTokenOptions });\n  await loaded({ page });\n\n  await page.evaluate(signInHelper, { signInParams });\n};\n\ntype PlaywrightClerkSignOutParams = {\n  page: Page;\n  signOutOptions?: SignOutOptions;\n};\n\nconst signOut = async ({ page, signOutOptions }: PlaywrightClerkSignOutParams) => {\n  await loaded({ page });\n\n  await page.evaluate(async options => {\n    await window.Clerk.signOut(options);\n  }, signOutOptions);\n};\n\nexport const clerk: ClerkHelperParams = {\n  signIn,\n  signOut,\n  loaded,\n};\n"],"mappings":"+DAeO,IAAMA,EAAa,MAAOC,GAAgC,CAC/D,GAAM,CAAE,WAAAC,EAAY,oBAAAC,CAAoB,EAAI,MAAMC,EAAaH,CAAO,EACtE,QAAQ,IAAI,WAAaC,EACzB,QAAQ,IAAI,oBAAsBC,CACpC,ECOO,IAAME,EAAyB,MAAO,CAAE,KAAAC,EAAM,QAAAC,CAAQ,IAAoC,CAC/F,IAAMC,EAAUD,GAAS,gBAAkB,QAAQ,IAAI,WACvD,GAAI,CAACC,EACH,MAAM,IAAI,MAAMC,CAA8B,EAEhD,IAAMC,EAAS,WAAWF,CAAO,WAEjC,MAAMF,EAAK,MAAMI,EAAQ,MAAMC,GAAS,CACtC,IAAMC,EAAc,IAAI,IAAID,EAAM,QAAQ,EAAE,IAAI,CAAC,EAC3CE,EAAe,QAAQ,IAAI,oBAE7BA,GACFD,EAAY,aAAa,IAAIE,EAAqBD,CAAY,EAGhE,GAAI,CACF,IAAME,EAAW,MAAMJ,EAAM,MAAM,CACjC,IAAKC,EAAY,SAAS,CAC5B,CAAC,EAEKI,EAAO,MAAMD,EAAS,KAAK,EAG7BC,GAAM,UAAU,iBAAmB,KACrCA,EAAK,SAAS,eAAiB,IAI7BA,GAAM,QAAQ,iBAAmB,KACnCA,EAAK,OAAO,eAAiB,IAG/B,MAAML,EAAM,QAAQ,CAClB,SAAAI,EACA,KAAAC,CACF,CAAC,CACH,MAAQ,CACN,MAAML,EACH,SAAS,CACR,IAAKC,EAAY,SAAS,CAC5B,CAAC,EACA,MAAM,QAAQ,KAAK,CACxB,CACF,CAAC,CACH,ECQA,IAAMK,EAAS,MAAO,CAAE,KAAAC,CAAK,IAAmC,CAC9D,MAAMA,EAAK,gBAAgB,IAAM,OAAO,QAAU,MAAS,EAC3D,MAAMA,EAAK,gBAAgB,IAAM,OAAO,MAAM,MAAM,CACtD,EAQMC,EAAS,MAAO,CAAE,KAAAD,EAAM,aAAAE,EAAc,8BAAAC,CAA8B,IAAmC,CAC3G,MAAMC,EAAuB,CAAE,KAAAJ,EAAM,QAASG,CAA8B,CAAC,EAC7E,MAAMJ,EAAO,CAAE,KAAAC,CAAK,CAAC,EAErB,MAAMA,EAAK,SAASK,EAAc,CAAE,aAAAH,CAAa,CAAC,CACpD,EAOMI,EAAU,MAAO,CAAE,KAAAN,EAAM,eAAAO,CAAe,IAAoC,CAChF,MAAMR,EAAO,CAAE,KAAAC,CAAK,CAAC,EAErB,MAAMA,EAAK,SAAS,MAAMQ,GAAW,CACnC,MAAM,OAAO,MAAM,QAAQA,CAAO,CACpC,EAAGD,CAAc,CACnB,EAEaE,EAA2B,CACtC,OAAAR,EACA,QAAAK,EACA,OAAAP,CACF","names":["clerkSetup","options","CLERK_FAPI","CLERK_TESTING_TOKEN","fetchEnvVars","setupClerkTestingToken","page","options","fapiUrl","ERROR_MISSING_FRONTEND_API_URL","apiUrl","route","originalUrl","testingToken","TESTING_TOKEN_PARAM","response","json","loaded","page","signIn","signInParams","setupClerkTestingTokenOptions","setupClerkTestingToken","signInHelper","signOut","signOutOptions","options","clerk"]}