Skip to content

Commit a6dc1db

Browse files
committed
test: harden codex manager cli isolation
1 parent e3f5dfc commit a6dc1db

1 file changed

Lines changed: 68 additions & 1 deletion

File tree

test/codex-manager-cli.test.ts

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
);
250258
const 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+
279312
function createDeferred<T>(): {
280313
promise: Promise<T>;
281314
resolve: (value: T | PromiseLike<T>) => void;
@@ -557,7 +590,7 @@ function readSettingsHubPanelContract(): string[] {
557590
}
558591

559592
describe("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(/code=([^&]+)/);
782+
const stateMatch = input.match(/state=([^&#]+)/);
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

Comments
 (0)