@@ -8,17 +8,24 @@ import { afterEach, describe, expect, it, vi } from 'vitest'
88import type { SyncLogData } from '@/lib/api/contracts/knowledge/connectors'
99import { CONNECTOR_SYNC_STALE_LOCK_TTL_MS } from '@/lib/knowledge/connectors/sync-limits'
1010
11- const { consumeOAuthReturnContextMock, connectOAuthModalMock, icon, oauthCredentialsState } =
12- vi . hoisted ( ( ) => ( {
13- consumeOAuthReturnContextMock : vi . fn ( ) ,
14- connectOAuthModalMock : vi . fn ( ) ,
15- icon : ( name : string ) => ( props : SVGProps < SVGSVGElement > ) => (
16- < svg data-testid = { `icon-${ name } ` } className = { props . className } />
17- ) ,
18- oauthCredentialsState : {
19- current : [ ] as Array < { id : string ; name : string ; provider : string } > ,
20- } ,
21- } ) )
11+ const {
12+ consumeOAuthReturnContextMock,
13+ connectOAuthModalMock,
14+ credentialRefreshTriggersMock,
15+ icon,
16+ oauthCredentialsState,
17+ } = vi . hoisted ( ( ) => ( {
18+ consumeOAuthReturnContextMock : vi . fn ( ) ,
19+ connectOAuthModalMock : vi . fn ( ) ,
20+ credentialRefreshTriggersMock : vi . fn ( ) ,
21+ icon : ( name : string ) => ( props : SVGProps < SVGSVGElement > ) => (
22+ < svg data-testid = { `icon-${ name } ` } className = { props . className } />
23+ ) ,
24+ oauthCredentialsState : {
25+ current : [ ] as Array < { id : string ; name : string ; provider : string } > ,
26+ isFetching : false ,
27+ } ,
28+ } ) )
2229
2330vi . mock ( '@sim/emcn/icons' , ( ) => ( {
2431 ChevronDown : icon ( 'chevron-down' ) ,
@@ -101,10 +108,14 @@ vi.mock('@/hooks/queries/kb/connectors', () => ({
101108 useUpdateConnector : vi . fn ( ( ) => ( { mutate : vi . fn ( ) } ) ) ,
102109} ) )
103110vi . mock ( '@/hooks/queries/oauth/oauth-credentials' , ( ) => ( {
104- useOAuthCredentials : vi . fn ( ( ) => ( { data : oauthCredentialsState . current } ) ) ,
111+ useOAuthCredentials : vi . fn ( ( ) => ( {
112+ data : oauthCredentialsState . current ,
113+ isFetching : oauthCredentialsState . isFetching ,
114+ refetch : vi . fn ( ) ,
115+ } ) ) ,
105116} ) )
106117vi . mock ( '@/hooks/use-credential-refresh-triggers' , ( ) => ( {
107- useCredentialRefreshTriggers : vi . fn ( ) ,
118+ useCredentialRefreshTriggers : credentialRefreshTriggersMock ,
108119} ) )
109120
110121import {
@@ -191,6 +202,7 @@ afterEach(() => {
191202 root = null
192203 document . body . innerHTML = ''
193204 oauthCredentialsState . current = [ ]
205+ oauthCredentialsState . isFetching = false
194206 vi . clearAllMocks ( )
195207} )
196208
@@ -231,6 +243,60 @@ describe('Connector credential reauthorization', () => {
231243 } ,
232244 } )
233245 )
246+ expect ( credentialRefreshTriggersMock ) . toHaveBeenLastCalledWith (
247+ expect . any ( Function ) ,
248+ 'slack-custom' ,
249+ 'workspace-1'
250+ )
251+ } )
252+
253+ it ( 'keeps reauthorization open while the credential query is loading' , ( ) => {
254+ oauthCredentialsState . current = [
255+ { id : 'credential-1' , name : 'Workspace Slack' , provider : 'slack-custom' } ,
256+ ]
257+ const connector = makeConnector ( )
258+ const container = renderSection ( connector )
259+ const reconnectButton = Array . from ( container . querySelectorAll ( 'button' ) ) . find (
260+ ( button ) => button . textContent === 'Reconnect'
261+ )
262+
263+ act ( ( ) => reconnectButton ?. click ( ) )
264+ expect ( connectOAuthModalMock ) . toHaveBeenCalledOnce ( )
265+
266+ connectOAuthModalMock . mockClear ( )
267+ oauthCredentialsState . current = [ ]
268+ oauthCredentialsState . isFetching = true
269+ act ( ( ) =>
270+ root ?. render (
271+ < ConnectorsSection
272+ workspaceId = 'workspace-1'
273+ knowledgeBaseId = 'knowledge-1'
274+ connectors = { [ connector ] }
275+ isLoading = { false }
276+ canEdit
277+ />
278+ )
279+ )
280+
281+ expect ( consumeOAuthReturnContextMock ) . not . toHaveBeenCalled ( )
282+
283+ oauthCredentialsState . current = [
284+ { id : 'credential-1' , name : 'Workspace Slack' , provider : 'slack-custom' } ,
285+ ]
286+ oauthCredentialsState . isFetching = false
287+ act ( ( ) =>
288+ root ?. render (
289+ < ConnectorsSection
290+ workspaceId = 'workspace-1'
291+ knowledgeBaseId = 'knowledge-1'
292+ connectors = { [ connector ] }
293+ isLoading = { false }
294+ canEdit
295+ />
296+ )
297+ )
298+
299+ expect ( connectOAuthModalMock ) . toHaveBeenCalledOnce ( )
234300 } )
235301
236302 it ( 'clears the OAuth return context if the credential disappears while open' , ( ) => {
0 commit comments