@@ -442,6 +442,103 @@ describe("AuthDebugger", () => {
442
442
} ) ;
443
443
} ) ;
444
444
445
+ describe ( "Client Registration behavior" , ( ) => {
446
+ it ( "uses preregistered (static) client information without calling DCR" , async ( ) => {
447
+ const preregClientInfo = {
448
+ client_id : "static_client_id" ,
449
+ client_secret : "static_client_secret" ,
450
+ redirect_uris : [ "http://localhost:3000/oauth/callback/debug" ] ,
451
+ } ;
452
+
453
+ // Return preregistered client info for the server-specific key
454
+ sessionStorageMock . getItem . mockImplementation ( ( key ) => {
455
+ if (
456
+ key ===
457
+ `[${ defaultProps . serverUrl } ] ${ SESSION_KEYS . PREREGISTERED_CLIENT_INFORMATION } `
458
+ ) {
459
+ return JSON . stringify ( preregClientInfo ) ;
460
+ }
461
+ return null ;
462
+ } ) ;
463
+
464
+ const updateAuthState = jest . fn ( ) ;
465
+
466
+ await act ( async ( ) => {
467
+ renderAuthDebugger ( {
468
+ updateAuthState,
469
+ authState : {
470
+ ...defaultAuthState ,
471
+ isInitiatingAuth : false ,
472
+ oauthStep : "client_registration" ,
473
+ oauthMetadata : mockOAuthMetadata as unknown as OAuthMetadata ,
474
+ } ,
475
+ } ) ;
476
+ } ) ;
477
+
478
+ // Proceed from client_registration → authorization_redirect
479
+ await act ( async ( ) => {
480
+ fireEvent . click ( screen . getByText ( "Continue" ) ) ;
481
+ } ) ;
482
+
483
+ // Should NOT attempt dynamic client registration
484
+ expect ( mockRegisterClient ) . not . toHaveBeenCalled ( ) ;
485
+
486
+ // Should advance with the preregistered client info
487
+ expect ( updateAuthState ) . toHaveBeenCalledWith (
488
+ expect . objectContaining ( {
489
+ oauthClientInfo : expect . objectContaining ( {
490
+ client_id : "static_client_id" ,
491
+ } ) ,
492
+ oauthStep : "authorization_redirect" ,
493
+ } ) ,
494
+ ) ;
495
+ } ) ;
496
+
497
+ it ( "falls back to DCR when no static client information is available" , async ( ) => {
498
+ // No preregistered or dynamic client info present in session storage
499
+ sessionStorageMock . getItem . mockImplementation ( ( ) => null ) ;
500
+
501
+ // DCR returns a new client
502
+ mockRegisterClient . mockResolvedValueOnce ( mockOAuthClientInfo ) ;
503
+
504
+ const updateAuthState = jest . fn ( ) ;
505
+
506
+ await act ( async ( ) => {
507
+ renderAuthDebugger ( {
508
+ updateAuthState,
509
+ authState : {
510
+ ...defaultAuthState ,
511
+ isInitiatingAuth : false ,
512
+ oauthStep : "client_registration" ,
513
+ oauthMetadata : mockOAuthMetadata as unknown as OAuthMetadata ,
514
+ } ,
515
+ } ) ;
516
+ } ) ;
517
+
518
+ await act ( async ( ) => {
519
+ fireEvent . click ( screen . getByText ( "Continue" ) ) ;
520
+ } ) ;
521
+
522
+ expect ( mockRegisterClient ) . toHaveBeenCalledTimes ( 1 ) ;
523
+
524
+ // Should save and advance with the DCR client info
525
+ expect ( updateAuthState ) . toHaveBeenCalledWith (
526
+ expect . objectContaining ( {
527
+ oauthClientInfo : expect . objectContaining ( {
528
+ client_id : "test_client_id" ,
529
+ } ) ,
530
+ oauthStep : "authorization_redirect" ,
531
+ } ) ,
532
+ ) ;
533
+
534
+ // Verify the dynamically registered client info was persisted
535
+ expect ( sessionStorage . setItem ) . toHaveBeenCalledWith (
536
+ `[${ defaultProps . serverUrl } ] ${ SESSION_KEYS . CLIENT_INFORMATION } ` ,
537
+ expect . any ( String ) ,
538
+ ) ;
539
+ } ) ;
540
+ } ) ;
541
+
445
542
describe ( "OAuth State Persistence" , ( ) => {
446
543
it ( "should store auth state to sessionStorage before redirect in Quick OAuth Flow" , async ( ) => {
447
544
const updateAuthState = jest . fn ( ) ;
0 commit comments