1+ import { Auth0Client } from '@auth0/auth0-spa-js' ;
12import { act , renderHook , waitFor } from '@testing-library/react' ;
23import React from 'react' ;
34import { Auth0ContextInterface , initialContext } from '../src/auth0-context' ;
45import useAuth0 from '../src/use-auth0' ;
56import { createWrapper } from './helpers' ;
67
8+ const mockClient = jest . mocked ( new Auth0Client ( { clientId : '' , domain : '' } ) ) ;
9+
710describe ( 'useAuth0' , ( ) => {
11+ let wrapper : ReturnType < typeof createWrapper > ;
12+
13+ const TEST_AUDIENCE = 'test-audience' ;
14+ const TEST_SCOPE = 'read:data' ;
15+ const TEST_USER = { name : '__test_user__' } ;
16+ const AUDIENCE_1 = 'audience1' ;
17+ const SCOPE_1 = 'scope1' ;
18+ const AUDIENCE_2 = 'audience2' ;
19+ const SCOPE_2 = 'scope2' ;
20+
21+ beforeEach ( ( ) => {
22+ jest . clearAllMocks ( ) ;
23+
24+ mockClient . getUser . mockResolvedValue ( TEST_USER ) ;
25+ mockClient . isAuthenticated . mockResolvedValue ( true ) ;
26+ mockClient . isAuthorized . mockResolvedValue ( true ) ;
27+
28+ wrapper = createWrapper ( ) ;
29+ } ) ;
30+
31+ const expectAuthenticatedState = async (
32+ result : { current : Auth0ContextInterface } ,
33+ isAuthenticated = true
34+ ) => {
35+ await waitFor ( ( ) => {
36+ expect ( result . current . isAuthenticated ) . toBe ( isAuthenticated ) ;
37+ expect ( result . current . isLoading ) . toBe ( false ) ;
38+ } ) ;
39+ } ;
40+
841 it ( 'should provide the auth context' , async ( ) => {
9- const wrapper = createWrapper ( ) ;
1042 const {
11- result : { current }
43+ result : { current } ,
1244 } = renderHook ( ( ) => useAuth0 ( ) , { wrapper } ) ;
1345 await waitFor ( ( ) => {
1446 expect ( current ) . toBeDefined ( ) ;
@@ -26,10 +58,10 @@ describe('useAuth0', () => {
2658
2759 it ( 'should throw when context is not associated with provider' , async ( ) => {
2860 const context = React . createContext < Auth0ContextInterface > ( initialContext ) ;
29- const wrapper = createWrapper ( { context } ) ;
61+ const customWrapper = createWrapper ( { context } ) ;
3062 const {
3163 result : { current } ,
32- } = renderHook ( ( ) => useAuth0 ( ) , { wrapper } ) ;
64+ } = renderHook ( ( ) => useAuth0 ( ) , { wrapper : customWrapper } ) ;
3365 await act ( async ( ) => {
3466 expect ( current . loginWithRedirect ) . toThrowError (
3567 'You forgot to wrap your component in <Auth0Provider>.'
@@ -39,13 +71,110 @@ describe('useAuth0', () => {
3971
4072 it ( 'should accept custom auth context' , async ( ) => {
4173 const context = React . createContext < Auth0ContextInterface > ( initialContext ) ;
42- const wrapper = createWrapper ( { context } ) ;
74+ const customWrapper = createWrapper ( { context } ) ;
4375 const {
4476 result : { current } ,
45- } = renderHook ( ( ) => useAuth0 ( context ) , { wrapper } ) ;
77+ } = renderHook ( ( ) => useAuth0 ( context ) , { wrapper : customWrapper } ) ;
4678 await waitFor ( ( ) => {
4779 expect ( current ) . toBeDefined ( ) ;
4880 expect ( current . loginWithRedirect ) . not . toThrowError ( ) ;
4981 } ) ;
5082 } ) ;
83+
84+ it ( 'should handle audience and scope options' , async ( ) => {
85+ const { result } = renderHook (
86+ ( ) => useAuth0 ( undefined , { audience : TEST_AUDIENCE , scope : TEST_SCOPE } ) ,
87+ { wrapper }
88+ ) ;
89+
90+ await expectAuthenticatedState ( result ) ;
91+
92+ expect ( mockClient . isAuthorized ) . toHaveBeenCalledWith ( {
93+ audience : TEST_AUDIENCE ,
94+ scope : TEST_SCOPE ,
95+ } ) ;
96+ } ) ;
97+
98+ it ( 'should set isAuthenticated to false when isAuthorized returns false' , async ( ) => {
99+ mockClient . isAuthorized . mockResolvedValue ( false ) ;
100+
101+ const { result } = renderHook (
102+ ( ) => useAuth0 ( undefined , { audience : TEST_AUDIENCE , scope : TEST_SCOPE } ) ,
103+ { wrapper }
104+ ) ;
105+
106+ await expectAuthenticatedState ( result , false ) ;
107+
108+ expect ( mockClient . isAuthorized ) . toHaveBeenCalledWith ( {
109+ audience : TEST_AUDIENCE ,
110+ scope : TEST_SCOPE ,
111+ } ) ;
112+ } ) ;
113+
114+ it ( 'should not call isAuthorized when user is not authenticated' , async ( ) => {
115+ mockClient . getUser . mockResolvedValue ( undefined ) ;
116+ mockClient . isAuthenticated . mockResolvedValue ( false ) ;
117+
118+ const { result } = renderHook (
119+ ( ) => useAuth0 ( undefined , { audience : TEST_AUDIENCE , scope : TEST_SCOPE } ) ,
120+ { wrapper }
121+ ) ;
122+
123+ await expectAuthenticatedState ( result , false ) ;
124+
125+ expect ( mockClient . isAuthorized ) . not . toHaveBeenCalled ( ) ;
126+ } ) ;
127+
128+ it ( 'should not call isAuthorized when no audience or scope provided' , async ( ) => {
129+ const { result } = renderHook ( ( ) => useAuth0 ( ) , { wrapper } ) ;
130+
131+ await expectAuthenticatedState ( result ) ;
132+
133+ expect ( mockClient . isAuthorized ) . not . toHaveBeenCalled ( ) ;
134+ } ) ;
135+
136+ it ( 'should show loading state during auth check' , async ( ) => {
137+ mockClient . isAuthorized . mockImplementation (
138+ ( ) => new Promise ( ( resolve ) => setTimeout ( ( ) => resolve ( true ) , 100 ) )
139+ ) ;
140+
141+ const { result } = renderHook (
142+ ( ) => useAuth0 ( undefined , { audience : TEST_AUDIENCE } ) ,
143+ { wrapper }
144+ ) ;
145+
146+ expect ( result . current . isLoading ) . toBe ( true ) ;
147+
148+ await expectAuthenticatedState ( result ) ;
149+ } ) ;
150+
151+ it ( 'should re-check authorization when dependencies change' , async ( ) => {
152+ const { result, rerender } = renderHook (
153+ ( { audience, scope } ) => useAuth0 ( undefined , { audience, scope } ) ,
154+ {
155+ wrapper,
156+ initialProps : { audience : AUDIENCE_1 , scope : SCOPE_1 } ,
157+ }
158+ ) ;
159+
160+ await waitFor ( ( ) => {
161+ expect ( result . current . isLoading ) . toBe ( false ) ;
162+ } ) ;
163+
164+ expect ( mockClient . isAuthorized ) . toHaveBeenCalledWith ( {
165+ audience : AUDIENCE_1 ,
166+ scope : SCOPE_1 ,
167+ } ) ;
168+
169+ rerender ( { audience : AUDIENCE_2 , scope : SCOPE_2 } ) ;
170+
171+ await waitFor ( ( ) => {
172+ expect ( mockClient . isAuthorized ) . toHaveBeenCalledWith ( {
173+ audience : AUDIENCE_2 ,
174+ scope : SCOPE_2 ,
175+ } ) ;
176+ } ) ;
177+
178+ expect ( mockClient . isAuthorized ) . toHaveBeenCalledTimes ( 2 ) ;
179+ } ) ;
51180} ) ;
0 commit comments