@@ -47,18 +47,19 @@ function createMockRoute(
4747}
4848
4949function createMockContext ( ) {
50- let routeHandler : ( ( route : Route ) => Promise < void > ) | undefined ;
50+ const registrations : { pattern : RegExp ; handler : ( route : Route ) => Promise < void > } [ ] = [ ] ;
5151
5252 const context = {
53- route : vi . fn ( ( _pattern : RegExp , handler : ( route : Route ) => Promise < void > ) => {
54- routeHandler = handler ;
53+ route : vi . fn ( ( pattern : RegExp , handler : ( route : Route ) => Promise < void > ) => {
54+ registrations . push ( { pattern , handler } ) ;
5555 return Promise . resolve ( ) ;
5656 } ) ,
5757 } as unknown as BrowserContext ;
5858
5959 return {
6060 context,
61- getRouteHandler : ( ) => routeHandler ,
61+ getRouteHandler : ( ) => registrations . at ( - 1 ) ?. handler ,
62+ getRegistrations : ( ) => registrations ,
6263 getRouteCallCount : ( ) => ( context . route as ReturnType < typeof vi . fn > ) . mock . calls . length ,
6364 } ;
6465}
@@ -157,6 +158,129 @@ describe('setupClerkTestingToken', () => {
157158
158159 expect ( getRouteCallCount ( ) ) . toBe ( 1 ) ;
159160 } ) ;
161+
162+ it ( 'no-ops on a second call with the same explicit frontendApiUrl' , async ( ) => {
163+ const { context, getRouteCallCount } = createMockContext ( ) ;
164+
165+ await setupClerkTestingToken ( { context, options : { frontendApiUrl : 'a.clerk.com' } } ) ;
166+ await setupClerkTestingToken ( { context, options : { frontendApiUrl : 'a.clerk.com' } } ) ;
167+
168+ expect ( getRouteCallCount ( ) ) . toBe ( 1 ) ;
169+ } ) ;
170+
171+ it ( 'registers an additional route for a different frontendApiUrl on the same context' , async ( ) => {
172+ const { context, getRegistrations } = createMockContext ( ) ;
173+
174+ await setupClerkTestingToken ( { context, options : { frontendApiUrl : 'a.clerk.com' } } ) ;
175+ await setupClerkTestingToken ( { context, options : { frontendApiUrl : 'b.clerk.com' } } ) ;
176+
177+ const registrations = getRegistrations ( ) ;
178+ expect ( registrations ) . toHaveLength ( 2 ) ;
179+ expect ( registrations [ 0 ] . pattern . test ( 'https://a.clerk.com/v1/client' ) ) . toBe ( true ) ;
180+ expect ( registrations [ 0 ] . pattern . test ( 'https://b.clerk.com/v1/client' ) ) . toBe ( false ) ;
181+ expect ( registrations [ 1 ] . pattern . test ( 'https://b.clerk.com/v1/client' ) ) . toBe ( true ) ;
182+ expect ( registrations [ 1 ] . pattern . test ( 'https://a.clerk.com/v1/client' ) ) . toBe ( false ) ;
183+ } ) ;
184+ } ) ;
185+
186+ describe ( 'per-instance testing tokens' , ( ) => {
187+ it ( 'uses options.testingToken string over the env var' , async ( ) => {
188+ const { context, getRouteHandler } = createMockContext ( ) ;
189+ await setupClerkTestingToken ( { context, options : { testingToken : 'option_token' } } ) ;
190+
191+ const { route } = createMockRoute ( ) ;
192+ await getRouteHandler ( ) ! ( route ) ;
193+
194+ expect ( route . fetch ) . toHaveBeenCalledWith ( {
195+ url : expect . stringContaining ( '__clerk_testing_token=option_token' ) ,
196+ } ) ;
197+ } ) ;
198+
199+ it ( 'resolves an async testing token provider' , async ( ) => {
200+ const { context, getRouteHandler } = createMockContext ( ) ;
201+ await setupClerkTestingToken ( { context, options : { testingToken : ( ) => Promise . resolve ( 'provider_token' ) } } ) ;
202+
203+ const { route } = createMockRoute ( ) ;
204+ await getRouteHandler ( ) ! ( route ) ;
205+
206+ expect ( route . fetch ) . toHaveBeenCalledWith ( {
207+ url : expect . stringContaining ( '__clerk_testing_token=provider_token' ) ,
208+ } ) ;
209+ } ) ;
210+
211+ it ( 'invokes the provider once per registration across multiple requests' , async ( ) => {
212+ const { context, getRouteHandler } = createMockContext ( ) ;
213+ const provider = vi . fn ( ( ) => Promise . resolve ( 'provider_token' ) ) ;
214+ await setupClerkTestingToken ( { context, options : { testingToken : provider } } ) ;
215+
216+ const handler = getRouteHandler ( ) ! ;
217+ await handler ( createMockRoute ( ) . route ) ;
218+ await handler ( createMockRoute ( ) . route ) ;
219+
220+ expect ( provider ) . toHaveBeenCalledTimes ( 1 ) ;
221+ } ) ;
222+
223+ it ( 'falls back to the env var and warns when the provider rejects' , async ( ) => {
224+ const warnSpy = vi . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } ) ;
225+ const { context, getRouteHandler } = createMockContext ( ) ;
226+ await setupClerkTestingToken ( {
227+ context,
228+ options : { testingToken : ( ) => Promise . reject ( new Error ( 'mint failed' ) ) } ,
229+ } ) ;
230+
231+ const { route, fulfilled } = createMockRoute ( ) ;
232+ await getRouteHandler ( ) ! ( route ) ;
233+
234+ expect ( warnSpy ) . toHaveBeenCalledWith (
235+ expect . stringContaining ( 'Failed to resolve the testing token' ) ,
236+ expect . any ( Error ) ,
237+ ) ;
238+ expect ( route . fetch ) . toHaveBeenCalledWith ( {
239+ url : expect . stringContaining ( `__clerk_testing_token=${ TESTING_TOKEN } ` ) ,
240+ } ) ;
241+ expect ( fulfilled [ 0 ] . json . response . captcha_bypass ) . toBe ( true ) ;
242+
243+ warnSpy . mockRestore ( ) ;
244+ } ) ;
245+
246+ it ( 'falls back to the env var when the provider resolves undefined' , async ( ) => {
247+ const { context, getRouteHandler } = createMockContext ( ) ;
248+ await setupClerkTestingToken ( { context, options : { testingToken : ( ) => undefined } } ) ;
249+
250+ const { route } = createMockRoute ( ) ;
251+ await getRouteHandler ( ) ! ( route ) ;
252+
253+ expect ( route . fetch ) . toHaveBeenCalledWith ( {
254+ url : expect . stringContaining ( `__clerk_testing_token=${ TESTING_TOKEN } ` ) ,
255+ } ) ;
256+ } ) ;
257+
258+ it ( 'appends each registration its own token when two instances share a context' , async ( ) => {
259+ const { context, getRegistrations } = createMockContext ( ) ;
260+
261+ await setupClerkTestingToken ( {
262+ context,
263+ options : { frontendApiUrl : 'a.clerk.com' , testingToken : 'token_a' } ,
264+ } ) ;
265+ await setupClerkTestingToken ( {
266+ context,
267+ options : { frontendApiUrl : 'b.clerk.com' , testingToken : ( ) => Promise . resolve ( 'token_b' ) } ,
268+ } ) ;
269+
270+ const [ first , second ] = getRegistrations ( ) ;
271+
272+ const routeA = createMockRoute ( { url : 'https://a.clerk.com/v1/client' } ) ;
273+ await first . handler ( routeA . route ) ;
274+ expect ( routeA . route . fetch ) . toHaveBeenCalledWith ( {
275+ url : expect . stringContaining ( '__clerk_testing_token=token_a' ) ,
276+ } ) ;
277+
278+ const routeB = createMockRoute ( { url : 'https://b.clerk.com/v1/client' } ) ;
279+ await second . handler ( routeB . route ) ;
280+ expect ( routeB . route . fetch ) . toHaveBeenCalledWith ( {
281+ url : expect . stringContaining ( '__clerk_testing_token=token_b' ) ,
282+ } ) ;
283+ } ) ;
160284 } ) ;
161285
162286 describe ( 'route handler' , ( ) => {
0 commit comments