@@ -23,11 +23,13 @@ import {
2323 readOutlookMessages ,
2424} from '@/lib/organizations/home/provider-reads'
2525import { gmailThreadUrl } from '@/connectors/gmail/mailbox'
26+ import { GoogleApiError } from '@/connectors/google-workspace/api-errors'
2627
28+ const { mailboxEmail } = vi . hoisted ( ( ) => ( { mailboxEmail : vi . fn ( ) } ) )
2729vi . mock ( '@/lib/core/security/input-validation.server' , ( ) => inputValidationMock )
2830vi . mock ( '@/connectors/gmail/mailbox' , async ( importOriginal ) => ( {
2931 ...( await importOriginal < typeof import ( '@/connectors/gmail/mailbox' ) > ( ) ) ,
30- getGmailMailboxEmail : async ( ) => 'reader@example.com' ,
32+ getGmailMailboxEmail : mailboxEmail ,
3133} ) )
3234
3335const { mockSecureFetchWithValidation : providerFetch } = inputValidationMockFns
@@ -70,10 +72,35 @@ function metadataMessage(from: string, subject: string, snippet: string) {
7072}
7173
7274beforeEach ( ( ) => {
75+ mailboxEmail . mockResolvedValue ( 'reader@example.com' )
7376 providerFetch . mockReset ( )
7477} )
7578
7679describe ( 'provider status classification' , ( ) => {
80+ it ( 'does not ask for a reconnect when Google reports quota in a 403 body' , async ( ) => {
81+ providerFetch . mockResolvedValue (
82+ respond ( { error : { errors : [ { reason : 'userRateLimitExceeded' } ] } } , 403 , { } )
83+ )
84+ await expect ( readOutlookMessages ( { accessToken : 'token' , signal } ) ) . rejects . toMatchObject ( {
85+ failure : 'unavailable' ,
86+ } )
87+ } )
88+
89+ it . each ( [
90+ [ 401 , [ ] , 'token_rejected' ] ,
91+ [ 403 , [ 'insufficientPermissions' ] , 'needs_reauth' ] ,
92+ [ 403 , [ 'userRateLimitExceeded' ] , 'unavailable' ] ,
93+ [ 500 , [ ] , 'unavailable' ] ,
94+ ] ) ( 'maps a %i mailbox lookup %o to %s' , async ( status , reasons , failure ) => {
95+ providerFetch . mockResolvedValue ( respond ( { threads : [ { id : 'thread-1' } ] } , 200 , { } ) )
96+ mailboxEmail . mockRejectedValueOnce (
97+ new GoogleApiError ( 'gmail.users.getProfile' , status , reasons )
98+ )
99+ await expect ( readGmailThreads ( { accessToken : 'token' , signal } ) ) . rejects . toMatchObject ( {
100+ failure,
101+ } )
102+ } )
103+
77104 it . each ( [
78105 [ 401 , { } , 'token_rejected' ] ,
79106 [ 403 , { } , 'needs_reauth' ] ,
0 commit comments