@@ -88,12 +88,74 @@ describe('OAuth Token API Routes', () => {
8888
8989 expect ( response . status ) . toBe ( 200 )
9090 expect ( data ) . toHaveProperty ( 'accessToken' , 'fresh-token' )
91+ expect ( data ) . not . toHaveProperty ( 'realmId' )
9192
9293 expect ( mockAuthorizeCredentialUse ) . toHaveBeenCalled ( )
9394 expect ( authOAuthUtilsMockFns . mockGetCredential ) . toHaveBeenCalled ( )
9495 expect ( authOAuthUtilsMockFns . mockRefreshTokenIfNeeded ) . toHaveBeenCalled ( )
9596 } )
9697
98+ it ( 'returns realmId only for QuickBooks credentials' , async ( ) => {
99+ mockAuthorizeCredentialUse . mockResolvedValueOnce ( {
100+ ok : true ,
101+ authType : 'session' ,
102+ requesterUserId : 'test-user-id' ,
103+ credentialOwnerUserId : 'owner-user-id' ,
104+ } )
105+ authOAuthUtilsMockFns . mockGetCredential . mockResolvedValueOnce ( {
106+ id : 'credential-id' ,
107+ accountId : 'quickbooks:123456789:intuit-subject-01234567-89ab-4def-8abc-0123456789ab' ,
108+ accessToken : 'test-token' ,
109+ refreshToken : 'refresh-token' ,
110+ accessTokenExpiresAt : new Date ( Date . now ( ) + 3600 * 1000 ) ,
111+ providerId : 'quickbooks' ,
112+ } )
113+ authOAuthUtilsMockFns . mockRefreshTokenIfNeeded . mockResolvedValueOnce ( {
114+ accessToken : 'fresh-token' ,
115+ refreshed : false ,
116+ } )
117+
118+ const response = await POST (
119+ createMockRequest ( 'POST' , {
120+ credentialId : 'credential-id' ,
121+ } )
122+ )
123+
124+ expect ( response . status ) . toBe ( 200 )
125+ expect ( await response . json ( ) ) . toEqual ( {
126+ accessToken : 'fresh-token' ,
127+ realmId : '123456789' ,
128+ } )
129+ } )
130+
131+ it ( 'rejects a malformed QuickBooks company identity with reconnect guidance' , async ( ) => {
132+ mockAuthorizeCredentialUse . mockResolvedValueOnce ( {
133+ ok : true ,
134+ authType : 'session' ,
135+ requesterUserId : 'test-user-id' ,
136+ credentialOwnerUserId : 'owner-user-id' ,
137+ } )
138+ authOAuthUtilsMockFns . mockGetCredential . mockResolvedValueOnce ( {
139+ id : 'credential-id' ,
140+ accountId : 'malformed' ,
141+ accessToken : 'test-token' ,
142+ refreshToken : 'refresh-token' ,
143+ accessTokenExpiresAt : new Date ( Date . now ( ) + 3600 * 1000 ) ,
144+ providerId : 'quickbooks' ,
145+ } )
146+
147+ const response = await POST (
148+ createMockRequest ( 'POST' , {
149+ credentialId : 'credential-id' ,
150+ } )
151+ )
152+ const data = await response . json ( )
153+
154+ expect ( response . status ) . toBe ( 401 )
155+ expect ( data . error ) . toMatch ( / R e c o n n e c t t h e Q u i c k B o o k s c r e d e n t i a l / )
156+ expect ( authOAuthUtilsMockFns . mockRefreshTokenIfNeeded ) . not . toHaveBeenCalled ( )
157+ } )
158+
97159 it ( 'should handle workflowId for server-side authentication' , async ( ) => {
98160 mockAuthorizeCredentialUse . mockResolvedValueOnce ( {
99161 ok : true ,
@@ -734,6 +796,33 @@ describe('OAuth Token API Routes', () => {
734796 expect ( data ) . toHaveProperty ( 'error' )
735797 } )
736798
799+ it ( 'rejects a malformed QuickBooks identity before reporting a missing token' , async ( ) => {
800+ mockAuthorizeCredentialUse . mockResolvedValueOnce ( {
801+ ok : true ,
802+ authType : 'session' ,
803+ requesterUserId : 'test-user-id' ,
804+ credentialOwnerUserId : 'test-user-id' ,
805+ } )
806+ authOAuthUtilsMockFns . mockGetCredential . mockResolvedValueOnce ( {
807+ id : 'credential-id' ,
808+ accountId : 'malformed' ,
809+ accessToken : null ,
810+ refreshToken : 'refresh-token' ,
811+ providerId : 'quickbooks' ,
812+ } )
813+
814+ const response = await GET (
815+ new NextRequest (
816+ 'http://localhost:3000/api/auth/oauth/token?credentialId=credential-id'
817+ ) as any
818+ )
819+ const data = await response . json ( )
820+
821+ expect ( response . status ) . toBe ( 401 )
822+ expect ( data . error ) . toMatch ( / R e c o n n e c t t h e Q u i c k B o o k s c r e d e n t i a l / )
823+ expect ( authOAuthUtilsMockFns . mockRefreshTokenIfNeeded ) . not . toHaveBeenCalled ( )
824+ } )
825+
737826 it ( 'should handle token refresh failure' , async ( ) => {
738827 mockAuthorizeCredentialUse . mockResolvedValueOnce ( {
739828 ok : true ,
0 commit comments