@@ -34,6 +34,7 @@ import { McpOAuthService, type McpOAuthEvent } from '#/mcpCore/oauth/service';
3434import { HostFileSystem } from '#/os/backends/node-local/hostFsService' ;
3535import { HostProcessService } from '#/os/backends/node-local/hostProcessService' ;
3636import { IHostEnvironment } from '#/os/interface/hostEnvironment' ;
37+ import { IHostClock } from '#/os/interface/hostClock' ;
3738import { IHostFileSystem } from '#/os/interface/hostFileSystem' ;
3839import { IHostProcessService } from '#/os/interface/hostProcess' ;
3940import { InMemoryStorageService } from '#/persistence/backends/memory/inMemoryStorageService' ;
@@ -80,6 +81,7 @@ describe('McpManagementService', () => {
8081 let getOrCreate : Mock < IWorkspaceInstanceManager [ 'getOrCreate' ] > ;
8182 let findContaining : Mock < IWorkspaceInstanceManager [ 'findContaining' ] > ;
8283 let management : IMcpManagementService ;
84+ let clockNowMs : number ;
8385
8486 beforeEach ( ( ) => {
8587 home = mkdtempSync ( join ( tmpdir ( ) , 'pythinker-mcp-management-home-' ) ) ;
@@ -95,6 +97,7 @@ describe('McpManagementService', () => {
9597 identitySnapshot = stubAgentIdentity ( { slug : 'test-agent' } ) . current ( ) ;
9698 identityReady = Promise . resolve ( identitySnapshot ) ;
9799 trusted = true ;
100+ clockNowMs = Date . UTC ( 2026 , 0 , 1 ) ;
98101 getOrCreate = vi . fn < IWorkspaceInstanceManager [ 'getOrCreate' ] > ( async ( ) =>
99102 ( { id : 'test-workspace' } ) as unknown as WorkspaceInstance ,
100103 ) ;
@@ -130,6 +133,11 @@ describe('McpManagementService', () => {
130133 homeDir : home ,
131134 ready : Promise . resolve ( ) ,
132135 } ) ;
136+ reg . defineInstance ( IHostClock , {
137+ _serviceBrand : undefined ,
138+ now : ( ) => new Date ( clockNowMs ) ,
139+ timeZone : ( ) => 'UTC' ,
140+ } ) ;
133141 reg . defineInstance ( IHostProcessService , hostProcess ) ;
134142 reg . definePartialInstance ( IAtomicDocumentStore , {
135143 get : async < T > ( ) => ( trusted ? ( { } as T ) : undefined ) ,
@@ -1571,31 +1579,25 @@ describe('McpManagementService', () => {
15711579 auth : 'oauth' ,
15721580 } ) ;
15731581 const cancel = vi . fn ( async ( ) => undefined ) ;
1574- const beginSpy = vi . spyOn ( oauth , 'beginAuthorization' ) . mockResolvedValue ( {
1582+ vi . spyOn ( oauth , 'beginAuthorization' ) . mockResolvedValue ( {
15751583 authorizationUrl : new URL ( 'https://oauthable.example.test/authorize' ) ,
15761584 complete : vi . fn ( async ( ) => undefined ) ,
15771585 cancel,
15781586 } ) ;
1579- vi . useFakeTimers ( ) ;
1580- try {
1581- const begun = await management . beginServerAuth ( { source : 'global' , name : 'oauthable' } ) ;
1582- if ( begun . status !== 'authorization-required' ) {
1583- throw new Error ( `expected authorization-required, got ${ begun . status } ` ) ;
1584- }
1587+ const begun = await management . beginServerAuth ( { source : 'global' , name : 'oauthable' } ) ;
1588+ if ( begun . status !== 'authorization-required' ) {
1589+ throw new Error ( `expected authorization-required, got ${ begun . status } ` ) ;
1590+ }
15851591
1586- await vi . advanceTimersByTimeAsync ( 15 * 60_000 ) ;
1592+ clockNowMs += 15 * 60_000 ;
15871593
1588- expect ( cancel ) . toHaveBeenCalledTimes ( 1 ) ;
1589- await expect (
1590- management . completeServerAuth ( { flowId : begun . flowId , timeoutMs : 1000 } ) ,
1591- ) . rejects . toMatchObject ( {
1592- code : ErrorCodes . REQUEST_INVALID ,
1593- message : `Unknown MCP OAuth flow: ${ begun . flowId } ` ,
1594- } ) ;
1595- } finally {
1596- vi . useRealTimers ( ) ;
1597- beginSpy . mockRestore ( ) ;
1598- }
1594+ await expect (
1595+ management . completeServerAuth ( { flowId : begun . flowId , timeoutMs : 1000 } ) ,
1596+ ) . rejects . toMatchObject ( {
1597+ code : ErrorCodes . REQUEST_INVALID ,
1598+ message : `Unknown MCP OAuth flow: ${ begun . flowId } ` ,
1599+ } ) ;
1600+ expect ( cancel ) . toHaveBeenCalledTimes ( 1 ) ;
15991601 } ) ;
16001602
16011603 it ( 'complete rejects on timeout when the browser callback never arrives' , async ( ) => {
0 commit comments