@@ -388,7 +388,7 @@ describe('useAssignTeamMembersRole', () => {
388388 } ) ;
389389
390390 await act ( async ( ) => {
391- result . current . mutate ( { data : { scope : 'lib:123' , users : [ 'jdoe' ] , role : 'author' } } ) ;
391+ result . current . mutate ( { data : { scopes : [ 'lib:123' ] , users : [ 'jdoe' ] , role : 'author' } } ) ;
392392 } ) ;
393393
394394 await waitFor ( ( ) => expect ( result . current . isSuccess ) . toBe ( true ) ) ;
@@ -407,7 +407,7 @@ describe('useAssignTeamMembersRole', () => {
407407 } ) ;
408408
409409 await act ( async ( ) => {
410- result . current . mutate ( { data : { scope : 'lib:123' , users : [ 'jdoe' ] , role : 'author' } } ) ;
410+ result . current . mutate ( { data : { scopes : [ 'lib:123' ] , users : [ 'jdoe' ] , role : 'author' } } ) ;
411411 } ) ;
412412
413413 await waitFor ( ( ) => expect ( result . current . isError ) . toBe ( true ) ) ;
@@ -465,6 +465,128 @@ describe('useValidateUsers', () => {
465465 } ) ;
466466} ) ;
467467
468+ describe ( 'useScopes' , ( ) => {
469+ beforeEach ( ( ) => {
470+ jest . clearAllMocks ( ) ;
471+ } ) ;
472+
473+ const makeScopesResponse = ( next : string | null = null ) => ( {
474+ results : [ {
475+ externalKey : 'lib:testorg:testlib' ,
476+ displayName : 'Test Library' ,
477+ org : { id : 1 , name : 'Test Org' , slug : 'testorg' } ,
478+ } ] ,
479+ count : 1 ,
480+ next,
481+ previous : null ,
482+ } ) ;
483+
484+ it ( 'returns pages data on success' , async ( ) => {
485+ getAuthenticatedHttpClient . mockReturnValue ( {
486+ get : jest . fn ( ) . mockResolvedValue ( { data : makeScopesResponse ( ) } ) ,
487+ } ) ;
488+
489+ const { result } = renderHook ( ( ) => useScopes ( { } ) , { wrapper : createWrapper ( ) } ) ;
490+
491+ await waitFor ( ( ) => expect ( result . current . isSuccess ) . toBe ( true ) ) ;
492+
493+ expect ( result . current . data ?. pages ) . toHaveLength ( 1 ) ;
494+ expect ( result . current . data ?. pages [ 0 ] . results ) . toHaveLength ( 1 ) ;
495+ } ) ;
496+
497+ it ( 'hasNextPage is false when next is null' , async ( ) => {
498+ getAuthenticatedHttpClient . mockReturnValue ( {
499+ get : jest . fn ( ) . mockResolvedValue ( { data : makeScopesResponse ( null ) } ) ,
500+ } ) ;
501+
502+ const { result } = renderHook ( ( ) => useScopes ( { } ) , { wrapper : createWrapper ( ) } ) ;
503+
504+ await waitFor ( ( ) => expect ( result . current . isSuccess ) . toBe ( true ) ) ;
505+ expect ( result . current . hasNextPage ) . toBe ( false ) ;
506+ } ) ;
507+
508+ it ( 'hasNextPage is true when next URL has page param' , async ( ) => {
509+ getAuthenticatedHttpClient . mockReturnValue ( {
510+ get : jest . fn ( ) . mockResolvedValue ( {
511+ data : makeScopesResponse ( 'http://localhost:8000/api/authz/v1/scopes/?page=2' ) ,
512+ } ) ,
513+ } ) ;
514+
515+ const { result } = renderHook ( ( ) => useScopes ( { } ) , { wrapper : createWrapper ( ) } ) ;
516+
517+ await waitFor ( ( ) => expect ( result . current . isSuccess ) . toBe ( true ) ) ;
518+ expect ( result . current . hasNextPage ) . toBe ( true ) ;
519+ } ) ;
520+
521+ it ( 'hasNextPage is false when next URL has no page param' , async ( ) => {
522+ getAuthenticatedHttpClient . mockReturnValue ( {
523+ get : jest . fn ( ) . mockResolvedValue ( {
524+ data : makeScopesResponse ( 'http://localhost:8000/api/authz/v1/scopes/' ) ,
525+ } ) ,
526+ } ) ;
527+
528+ const { result } = renderHook ( ( ) => useScopes ( { } ) , { wrapper : createWrapper ( ) } ) ;
529+
530+ await waitFor ( ( ) => expect ( result . current . isSuccess ) . toBe ( true ) ) ;
531+ expect ( result . current . hasNextPage ) . toBe ( false ) ;
532+ } ) ;
533+
534+ it ( 'hasNextPage is false when next is an invalid URL' , async ( ) => {
535+ getAuthenticatedHttpClient . mockReturnValue ( {
536+ get : jest . fn ( ) . mockResolvedValue ( {
537+ data : makeScopesResponse ( 'not-a-valid-url' ) ,
538+ } ) ,
539+ } ) ;
540+
541+ const { result } = renderHook ( ( ) => useScopes ( { } ) , { wrapper : createWrapper ( ) } ) ;
542+
543+ await waitFor ( ( ) => expect ( result . current . isSuccess ) . toBe ( true ) ) ;
544+ expect ( result . current . hasNextPage ) . toBe ( false ) ;
545+ } ) ;
546+
547+ it ( 'handles error when API call fails' , async ( ) => {
548+ getAuthenticatedHttpClient . mockReturnValue ( {
549+ get : jest . fn ( ) . mockRejectedValue ( new Error ( 'Network error' ) ) ,
550+ } ) ;
551+
552+ const { result } = renderHook ( ( ) => useScopes ( { } ) , { wrapper : createWrapper ( ) } ) ;
553+
554+ await waitFor ( ( ) => expect ( result . current . isError ) . toBe ( true ) ) ;
555+ expect ( result . current . error ) . toBeDefined ( ) ;
556+ } ) ;
557+ } ) ;
558+
559+ describe ( 'useOrgs' , ( ) => {
560+ beforeEach ( ( ) => {
561+ jest . clearAllMocks ( ) ;
562+ } ) ;
563+
564+ const mockOrgs = [ {
565+ id : 1 , name : 'Org One' , shortName : 'org1' , description : '' , logo : null , active : true ,
566+ } ] ;
567+
568+ it ( 'returns organizations on success' , async ( ) => {
569+ getAuthenticatedHttpClient . mockReturnValue ( {
570+ get : jest . fn ( ) . mockResolvedValue ( { data : { results : mockOrgs } } ) ,
571+ } ) ;
572+
573+ const { result } = renderHook ( ( ) => useOrgs ( ) , { wrapper : createWrapper ( ) } ) ;
574+
575+ await waitFor ( ( ) => expect ( result . current . isSuccess ) . toBe ( true ) ) ;
576+ expect ( result . current . data ?. results ) . toEqual ( mockOrgs ) ;
577+ } ) ;
578+
579+ it ( 'handles error when API fails' , async ( ) => {
580+ getAuthenticatedHttpClient . mockReturnValue ( {
581+ get : jest . fn ( ) . mockRejectedValue ( new Error ( 'Failed' ) ) ,
582+ } ) ;
583+
584+ const { result } = renderHook ( ( ) => useOrgs ( ) , { wrapper : createWrapper ( ) } ) ;
585+
586+ await waitFor ( ( ) => expect ( result . current . isError ) . toBe ( true ) ) ;
587+ } ) ;
588+ } ) ;
589+
468590describe ( 'useRevokeUserRoles' , ( ) => {
469591 beforeEach ( ( ) => {
470592 jest . clearAllMocks ( ) ;
@@ -663,9 +785,9 @@ describe('useScopes', () => {
663785 it ( 'fetches and returns scopes' , async ( ) => {
664786 const { result } = renderHook ( ( ) => useScopes ( ) , { wrapper : createWrapper ( ) } ) ;
665787 await waitFor ( ( ) => {
666- expect ( result . current . data ?. results ) . toHaveLength ( 2 ) ;
667- expect ( result . current . data ?. results [ 0 ] . displayName ) . toBe ( 'Open edX Demo Course' ) ;
668- expect ( result . current . data ?. count ) . toBe ( 2 ) ;
788+ expect ( result . current . data ?. pages [ 0 ] . results ) . toHaveLength ( 2 ) ;
789+ expect ( result . current . data ?. pages [ 0 ] . results [ 0 ] . displayName ) . toBe ( 'Open edX Demo Course' ) ;
790+ expect ( result . current . data ?. pages [ 0 ] . count ) . toBe ( 2 ) ;
669791 } ) ;
670792 } ) ;
671793
@@ -679,8 +801,8 @@ describe('useScopes', () => {
679801 } ) ;
680802 const { result } = renderHook ( ( ) => useScopes ( ) , { wrapper : createWrapper ( ) } ) ;
681803 await waitFor ( ( ) => {
682- expect ( result . current . data ?. results ) . toEqual ( [ ] ) ;
683- expect ( result . current . data ?. count ) . toBe ( 0 ) ;
804+ expect ( result . current . data ?. pages [ 0 ] . results ) . toEqual ( [ ] ) ;
805+ expect ( result . current . data ?. pages [ 0 ] . count ) . toBe ( 0 ) ;
684806 } ) ;
685807 } ) ;
686808} ) ;
0 commit comments