UNPKG

@clerk/testing

Version:

Utilities to help you create E2E test suites for apps using Clerk

10 lines (6 loc) • 8.88 kB
"use strict";var Y=Object.create;var k=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var H=Object.getPrototypeOf,q=Object.prototype.hasOwnProperty;var X=(e,n)=>{for(var t in n)k(e,t,{get:n[t],enumerable:!0})},S=(e,n,t,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of D(n))!q.call(e,o)&&o!==t&&k(e,o,{get:()=>n[o],enumerable:!(r=G(n,o))||r.enumerable});return e};var W=(e,n,t)=>(t=e!=null?Y(H(e)):{},S(n||!e||!e.__esModule?k(t,"default",{value:e,enumerable:!0}):t,e)),J=e=>S(k({},"__esModule",{value:!0}),e);var ae={};X(ae,{clerk:()=>M,clerkSetup:()=>b,createAgentTestingTask:()=>N,setupClerkTestingToken:()=>w});module.exports=J(ae);var R=require("@clerk/backend"),V="A secretKey is required to create agent tasks. Pass it directly or set the CLERK_SECRET_KEY environment variable.";var j="Failed to create agent task: ";async function P(e){let{apiUrl:n,secretKey:t,clerkClient:r,...o}=e;if(!r&&!t)throw new Error(V);let i=r??(0,R.createClerkClient)({apiUrl:n,secretKey:t});try{return await i.agentTasks.create(o)}catch(s){throw new Error(j+(s instanceof Error?s.message:String(s)))}}var I="__clerk_testing_token";var L=require("@clerk/backend"),u=require("@clerk/shared/error"),K=require("@clerk/shared/keys"),O=W(require("dotenv")),T=5,z=1e3,Q=500,A=3e4,Z=new Set([408,429,500,502,503,504]),ee=new Set(["ECONNREFUSED","ECONNRESET","ENOTFOUND","ETIMEDOUT","EAI_AGAIN"]);function te(e){return e instanceof Error&&"code"in e&&ee.has(e.code??"")}async function re(e,n){for(let t=0;t<=T;t++)try{return await e()}catch(r){let o=(0,u.isClerkAPIResponseError)(r)&&Z.has(r.status),i=te(r);if(!o&&!i||t===T)throw r;let s=(0,u.isClerkAPIResponseError)(r)?r.status:r.code,a=z*Math.pow(2,t)+Math.random()*Q,c=(0,u.isClerkAPIResponseError)(r)&&typeof r.retryAfter=="number"?Math.min(Math.max(r.retryAfter*1e3,a),A):Math.min(a,A);console.warn(`[Retry] ${s} for ${n}, attempt ${t+1}/${T}, waiting ${Math.round(c)}ms`),await new Promise(d=>setTimeout(d,c))}throw new Error("Unreachable")}var v=async e=>{let{debug:n=!1,dotenv:t=!0,...r}=e||{},o=c=>{n&&console.log(`Clerk: ${c}`)};o("Setting up Clerk..."),t&&O.default.config({path:[".env.local",".env"]});let i=r.publishableKey||process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY||process.env.VITE_CLERK_PUBLISHABLE_KEY||process.env.CLERK_PUBLISHABLE_KEY||process.env.REACT_APP_CLERK_PUBLISHABLE_KEY||process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY,s=r.secretKey||process.env.CLERK_SECRET_KEY,a=process.env.CLERK_TESTING_TOKEN;if(!i)throw new Error("You need to set the CLERK_PUBLISHABLE_KEY environment variable.");if(!s&&!a)throw new Error("You need to set the CLERK_SECRET_KEY or the CLERK_TESTING_TOKEN environment variable.");if(s&&!a){o("Fetching testing token from Clerk Backend API...");try{let c=r?.apiUrl||process.env.CLERK_API_URL,d=(0,L.createClerkClient)({secretKey:s,apiUrl:c});a=(await re(()=>d.testingTokens.createTestingToken(),"testingTokens.createTestingToken")).token}catch(c){throw console.error("Failed to fetch testing token from Clerk API."),c}}return{CLERK_FAPI:e?.frontendApiUrl||(0,K.parsePublishableKey)(i)?.frontendApi,CLERK_TESTING_TOKEN:a}};var F="The Clerk Frontend API URL is required to bypass bot protection. Make sure the clerkSetup function is called during your global setup before setupClerkTestingToken is called.";var h=async({signInParams:e,windowObject:n})=>{try{let t=n||window;if(!t.Clerk.client)return;let r=t.Clerk.client.signIn;switch(e.strategy){case"password":{let o=await r.create(e);await t.Clerk.setActive({session:o.createdSessionId});break}case"ticket":{let o=await r.create({strategy:"ticket",ticket:e.ticket});if(o.status==="complete")await t.Clerk.setActive({session:o.createdSessionId});else throw new Error(`Sign-in with ticket failed. Status: ${o.status}`);break}case"phone_code":{if(!/^\+1\d{3}55501\d{2}$/.test(e.identifier))throw new Error(`Phone number should be a test phone number. Example: +1XXX55501XX. Learn more here: https://clerk.com/docs/testing/test-emails-and-phones#phone-numbers`);let{supportedFirstFactors:o}=await r.create({identifier:e.identifier}),i=o?.find(s=>s.strategy==="phone_code");if(i){await r.prepareFirstFactor({strategy:"phone_code",phoneNumberId:i.phoneNumberId});let s=await r.attemptFirstFactor({strategy:"phone_code",code:"424242"});if(s.status==="complete")await t.Clerk.setActive({session:s.createdSessionId});else throw new Error(`Status is ${s.status}`)}else throw new Error("phone_code is not enabled.");break}case"email_code":{if(!e.identifier.includes("+clerk_test"))throw new Error(`Email should be a test email. Any email with the +clerk_test subaddress is a test email address. Learn more here: https://clerk.com/docs/testing/test-emails-and-phones#email-addresses`);let{supportedFirstFactors:o}=await r.create({identifier:e.identifier}),i=o?.find(s=>s.strategy==="email_code");if(i){await r.prepareFirstFactor({strategy:"email_code",emailAddressId:i.emailAddressId});let s=await r.attemptFirstFactor({strategy:"email_code",code:"424242"});if(s.status==="complete")await t.Clerk.setActive({session:s.createdSessionId});else throw new Error(`Status is ${s.status}`)}else throw new Error("email_code is not enabled.");break}default:throw new Error(`Unsupported strategy: ${e.strategy}`)}}catch(t){throw new Error(`Clerk: Failed to sign in: ${t?.message}`)}};var b=async e=>{let{CLERK_FAPI:n,CLERK_TESTING_TOKEN:t}=await v(e);process.env.CLERK_FAPI=n,process.env.CLERK_TESTING_TOKEN=t};function N(e){return P({...e,apiUrl:e.apiUrl||process.env.CLERK_API_URL,secretKey:e.secretKey||process.env.CLERK_SECRET_KEY})}var _=new WeakSet,se=new Set([429,502,503,504]),g=3,U=500,x=250,w=async({context:e,options:n,page:t})=>{let r=e??t?.context();if(!r)throw new Error("Either context or page must be provided to setup testing token");if(_.has(r)){process.env.CLERK_TESTING_DEBUG&&console.log("[Clerk Testing] Route handler already registered for this context, skipping duplicate setup");return}let o=n?.frontendApiUrl||process.env.CLERK_FAPI;if(!o)throw new Error(F);let i=o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),s=new RegExp(`^https://${i}/v1/.*?(\\?.*)?$`);_.add(r);try{await r.route(s,async a=>{let c=new URL(a.request().url()),d=process.env.CLERK_TESTING_TOKEN;d&&c.searchParams.set(I,d);let C=c.toString();for(let l=0;l<=g;l++)try{let p=await a.fetch({url:C}),m=p.status();if(se.has(m)){if(l<g){let y=U*Math.pow(2,l)+Math.random()*x;process.env.CLERK_TESTING_DEBUG&&console.log(`[Clerk Testing] FAPI returned ${m}, retrying (attempt ${l+1}/${g}, delay ${Math.round(y)}ms): ${a.request().url()}`),await new Promise(B=>setTimeout(B,y));continue}console.warn(`[Clerk Testing] FAPI request failed with status ${m} after ${g+1} attempts: ${a.request().url()}`),await a.fulfill({response:p});return}let E=await p.json();E?.response?.captcha_bypass===!1&&(E.response.captcha_bypass=!0),E?.client?.captcha_bypass===!1&&(E.client.captcha_bypass=!0),await a.fulfill({response:p,json:E});return}catch(p){if(l<g){let m=U*Math.pow(2,l)+Math.random()*x;process.env.CLERK_TESTING_DEBUG&&console.log(`[Clerk Testing] FAPI request error, retrying (attempt ${l+1}/${g}, delay ${Math.round(m)}ms): ${a.request().url()}`,p),await new Promise(E=>setTimeout(E,m));continue}console.warn(`[Clerk Testing] FAPI request failed after ${g+1} attempts: ${a.request().url()}`,p),await a.continue({url:C}).catch(console.error);return}})}catch(a){throw _.delete(r),a}};var $=require("@clerk/backend");var f=async({page:e})=>{await e.waitForFunction(()=>window.Clerk!==void 0),await e.waitForFunction(()=>window.Clerk.loaded)},ne=async e=>{let n=e.page.context();if(!n)throw new Error("Page context is not available. Make sure the page is properly initialized.");if(await w({context:n,options:"setupClerkTestingTokenOptions"in e?e.setupClerkTestingTokenOptions:void 0}),await f({page:e.page}),"emailAddress"in e){let{emailAddress:t,page:r}=e,o=process.env.CLERK_SECRET_KEY;if(!o)throw new Error("CLERK_SECRET_KEY environment variable is required for email-based sign-in");let i=(0,$.createClerkClient)({secretKey:o});try{let s=await i.users.getUserList({emailAddress:[t]});if(!s.data||s.data.length===0)throw new Error(`No user found with email: ${t}`);let a=s.data[0],c=await i.signInTokens.createSignInToken({userId:a.id,expiresInSeconds:300});await r.evaluate(h,{signInParams:{strategy:"ticket",ticket:c.token}}),await r.waitForFunction(()=>window.Clerk?.user!==null)}catch(s){throw new Error(`Failed to sign in with email ${t}: ${s?.message}`)}}else{let{page:t,signInParams:r}=e;await t.evaluate(h,{signInParams:r})}},oe=async({page:e,signOutOptions:n})=>{await f({page:e}),await e.evaluate(async t=>{await window.Clerk.signOut(t)},n)},M={signIn:ne,signOut:oe,loaded:f};0&&(module.exports={clerk,clerkSetup,createAgentTestingTask,setupClerkTestingToken}); //# sourceMappingURL=index.js.map