@@ -247,6 +247,14 @@ const stdinIsTTYDescriptor = Object.getOwnPropertyDescriptor(
247247 process . stdin ,
248248 "isTTY" ,
249249) ;
250+ const stdinReadableEndedDescriptor = Object . getOwnPropertyDescriptor (
251+ process . stdin ,
252+ "readableEnded" ,
253+ ) ;
254+ const stdinDestroyedDescriptor = Object . getOwnPropertyDescriptor (
255+ process . stdin ,
256+ "destroyed" ,
257+ ) ;
250258const stdoutIsTTYDescriptor = Object . getOwnPropertyDescriptor (
251259 process . stdout ,
252260 "isTTY" ,
@@ -269,13 +277,38 @@ function restoreTTYDescriptors(): void {
269277 } else {
270278 delete ( process . stdin as unknown as { isTTY ?: boolean } ) . isTTY ;
271279 }
280+ if ( stdinReadableEndedDescriptor ) {
281+ Object . defineProperty (
282+ process . stdin ,
283+ "readableEnded" ,
284+ stdinReadableEndedDescriptor ,
285+ ) ;
286+ } else {
287+ delete ( process . stdin as unknown as { readableEnded ?: boolean } ) . readableEnded ;
288+ }
289+ if ( stdinDestroyedDescriptor ) {
290+ Object . defineProperty ( process . stdin , "destroyed" , stdinDestroyedDescriptor ) ;
291+ } else {
292+ delete ( process . stdin as unknown as { destroyed ?: boolean } ) . destroyed ;
293+ }
272294 if ( stdoutIsTTYDescriptor ) {
273295 Object . defineProperty ( process . stdout , "isTTY" , stdoutIsTTYDescriptor ) ;
274296 } else {
275297 delete ( process . stdout as unknown as { isTTY ?: boolean } ) . isTTY ;
276298 }
277299}
278300
301+ function setOpenStdinState ( ) : void {
302+ Object . defineProperty ( process . stdin , "readableEnded" , {
303+ value : false ,
304+ configurable : true ,
305+ } ) ;
306+ Object . defineProperty ( process . stdin , "destroyed" , {
307+ value : false ,
308+ configurable : true ,
309+ } ) ;
310+ }
311+
279312function createDeferred < T > ( ) : {
280313 promise : Promise < T > ;
281314 resolve : ( value : T | PromiseLike < T > ) => void ;
@@ -557,7 +590,7 @@ function readSettingsHubPanelContract(): string[] {
557590}
558591
559592describe ( "codex manager cli commands" , ( ) => {
560- beforeEach ( ( ) => {
593+ beforeEach ( async ( ) => {
561594 vi . resetModules ( ) ;
562595 vi . clearAllMocks ( ) ;
563596 loadAccountsMock . mockReset ( ) ;
@@ -574,6 +607,7 @@ describe("codex manager cli commands", () => {
574607 loadCodexCliStateMock . mockReset ( ) ;
575608 promptAddAnotherAccountMock . mockReset ( ) ;
576609 promptLoginModeMock . mockReset ( ) ;
610+ promptQuestionMock . mockReset ( ) ;
577611 fetchCodexQuotaSnapshotMock . mockReset ( ) ;
578612 loadDashboardDisplaySettingsMock . mockReset ( ) ;
579613 saveDashboardDisplaySettingsMock . mockReset ( ) ;
@@ -583,6 +617,12 @@ describe("codex manager cli commands", () => {
583617 savePluginConfigMock . mockReset ( ) ;
584618 selectMock . mockReset ( ) ;
585619 confirmMock . mockReset ( ) ;
620+ planOcChatgptSyncMock . mockReset ( ) ;
621+ applyOcChatgptSyncMock . mockReset ( ) ;
622+ runNamedBackupExportMock . mockReset ( ) ;
623+ exportNamedBackupMock . mockReset ( ) ;
624+ detectOcChatgptMultiAuthTargetMock . mockReset ( ) ;
625+ normalizeAccountStorageMock . mockReset ( ) ;
586626 confirmMock . mockResolvedValue ( true ) ;
587627 fetchCodexQuotaSnapshotMock . mockResolvedValue ( {
588628 status : 200 ,
@@ -727,8 +767,35 @@ describe("codex manager cli commands", () => {
727767 selectMock . mockResolvedValue ( undefined ) ;
728768 getNamedBackupsMock . mockResolvedValue ( [ ] ) ;
729769 restoreTTYDescriptors ( ) ;
770+ setOpenStdinState ( ) ;
730771 setStoragePathMock . mockReset ( ) ;
731772 getStoragePathMock . mockReturnValue ( "/mock/openai-codex-accounts.json" ) ;
773+ normalizeAccountStorageMock . mockImplementation ( ( value ) => value ) ;
774+
775+ const authModule = await import ( "../lib/auth/auth.js" ) ;
776+ vi . mocked ( authModule . createAuthorizationFlow ) . mockReset ( ) ;
777+ vi . mocked ( authModule . exchangeAuthorizationCode ) . mockReset ( ) ;
778+ vi . mocked ( authModule . parseAuthorizationInput ) . mockReset ( ) ;
779+ vi . mocked ( authModule . parseAuthorizationInput ) . mockImplementation (
780+ ( input : string ) => {
781+ const codeMatch = input . match ( / c o d e = ( [ ^ & ] + ) / ) ;
782+ const stateMatch = input . match ( / s t a t e = ( [ ^ & # ] + ) / ) ;
783+ return {
784+ code : codeMatch ?. [ 1 ] ,
785+ state : stateMatch ?. [ 1 ] ,
786+ } ;
787+ } ,
788+ ) ;
789+
790+ const browserModule = await import ( "../lib/auth/browser.js" ) ;
791+ vi . mocked ( browserModule . isBrowserLaunchSuppressed ) . mockReset ( ) ;
792+ vi . mocked ( browserModule . isBrowserLaunchSuppressed ) . mockReturnValue ( false ) ;
793+ vi . mocked ( browserModule . openBrowserUrl ) . mockReset ( ) ;
794+ vi . mocked ( browserModule . copyTextToClipboard ) . mockReset ( ) ;
795+ vi . mocked ( browserModule . copyTextToClipboard ) . mockReturnValue ( true ) ;
796+
797+ const serverModule = await import ( "../lib/auth/server.js" ) ;
798+ vi . mocked ( serverModule . startLocalOAuthServer ) . mockReset ( ) ;
732799 } ) ;
733800
734801 afterEach ( ( ) => {
0 commit comments