@@ -880,6 +880,101 @@ describe('Auth0Provider', () => {
880880 } ) ;
881881 } ) ;
882882
883+ it ( 'should provide an exchangeToken method' , async ( ) => {
884+ const tokenResponse = {
885+ access_token : '__test_access_token__' ,
886+ id_token : '__test_id_token__' ,
887+ token_type : 'Bearer' ,
888+ expires_in : 86400 ,
889+ scope : 'openid profile email' ,
890+ } ;
891+ clientMock . exchangeToken . mockResolvedValue ( tokenResponse ) ;
892+ const wrapper = createWrapper ( ) ;
893+ const { result } = renderHook (
894+ ( ) => useContext ( Auth0Context ) ,
895+ { wrapper }
896+ ) ;
897+ await waitFor ( ( ) => {
898+ expect ( result . current . exchangeToken ) . toBeInstanceOf ( Function ) ;
899+ } ) ;
900+ let response ;
901+ await act ( async ( ) => {
902+ response = await result . current . exchangeToken ( {
903+ subject_token : '__test_token__' ,
904+ subject_token_type : 'urn:test:token-type' ,
905+ scope : 'openid profile email' ,
906+ } ) ;
907+ } ) ;
908+ expect ( clientMock . exchangeToken ) . toHaveBeenCalledWith ( {
909+ subject_token : '__test_token__' ,
910+ subject_token_type : 'urn:test:token-type' ,
911+ scope : 'openid profile email' ,
912+ } ) ;
913+ expect ( response ) . toStrictEqual ( tokenResponse ) ;
914+ } ) ;
915+
916+ it ( 'should handle errors when exchanging tokens' , async ( ) => {
917+ clientMock . exchangeToken . mockRejectedValue ( new Error ( '__test_error__' ) ) ;
918+ const wrapper = createWrapper ( ) ;
919+ const { result } = renderHook (
920+ ( ) => useContext ( Auth0Context ) ,
921+ { wrapper }
922+ ) ;
923+ await waitFor ( ( ) => {
924+ expect ( result . current . exchangeToken ) . toBeInstanceOf ( Function ) ;
925+ } ) ;
926+ await act ( async ( ) => {
927+ await expect (
928+ result . current . exchangeToken ( {
929+ subject_token : '__test_token__' ,
930+ subject_token_type : 'urn:test:token-type' ,
931+ } )
932+ ) . rejects . toThrow ( '__test_error__' ) ;
933+ } ) ;
934+ expect ( clientMock . exchangeToken ) . toHaveBeenCalled ( ) ;
935+ } ) ;
936+
937+ it ( 'should update auth state after successful token exchange' , async ( ) => {
938+ const user = { name : '__test_user__' } ;
939+ const tokenResponse = {
940+ access_token : '__test_access_token__' ,
941+ id_token : '__test_id_token__' ,
942+ token_type : 'Bearer' ,
943+ expires_in : 86400 ,
944+ } ;
945+ clientMock . exchangeToken . mockResolvedValue ( tokenResponse ) ;
946+ clientMock . getUser . mockResolvedValue ( user ) ;
947+ const wrapper = createWrapper ( ) ;
948+ const { result } = renderHook (
949+ ( ) => useContext ( Auth0Context ) ,
950+ { wrapper }
951+ ) ;
952+ await waitFor ( ( ) => {
953+ expect ( result . current . exchangeToken ) . toBeInstanceOf ( Function ) ;
954+ } ) ;
955+ await act ( async ( ) => {
956+ await result . current . exchangeToken ( {
957+ subject_token : '__test_token__' ,
958+ subject_token_type : 'urn:test:token-type' ,
959+ } ) ;
960+ } ) ;
961+ expect ( clientMock . getUser ) . toHaveBeenCalled ( ) ;
962+ expect ( result . current . user ) . toStrictEqual ( user ) ;
963+ } ) ;
964+
965+ it ( 'should memoize the exchangeToken method' , async ( ) => {
966+ const wrapper = createWrapper ( ) ;
967+ const { result, rerender } = renderHook (
968+ ( ) => useContext ( Auth0Context ) ,
969+ { wrapper }
970+ ) ;
971+ await waitFor ( ( ) => {
972+ const memoized = result . current . exchangeToken ;
973+ rerender ( ) ;
974+ expect ( result . current . exchangeToken ) . toBe ( memoized ) ;
975+ } ) ;
976+ } ) ;
977+
883978 it ( 'should provide a handleRedirectCallback method' , async ( ) => {
884979 clientMock . handleRedirectCallback . mockResolvedValue ( {
885980 appState : { redirectUri : '/' } ,
0 commit comments