diff --git a/integration-tests/context-compress-interactive.test.ts b/integration-tests/context-compress-interactive.test.ts index 3a626150f8..f8b318c482 100644 --- a/integration-tests/context-compress-interactive.test.ts +++ b/integration-tests/context-compress-interactive.test.ts @@ -24,26 +24,7 @@ describe('Interactive Mode', () => { await rig.setup('interactive-compress-test'); const { ptyProcess } = rig.runInteractive(); - - let fullOutput = ''; - ptyProcess.onData((data) => (fullOutput += data)); - - const authDialogAppeared = await rig.waitForText( - 'How would you like to authenticate', - 5000, - ); - - // select the second option if auth dialog come's up - if (authDialogAppeared) { - ptyProcess.write('2'); - } - - // Wait for the app to be ready - const isReady = await rig.waitForText('Type your message', 15000); - expect( - isReady, - 'CLI did not start up in interactive mode correctly', - ).toBe(true); + await rig.ensureReadyForInput(ptyProcess); const longPrompt = 'Dont do anything except returning a 1000 token long paragragh with the at the end to indicate end of response. This is a moderately long sentence.'; @@ -74,26 +55,7 @@ describe('Interactive Mode', () => { await rig.setup('interactive-compress-test'); const { ptyProcess } = rig.runInteractive(); - - let fullOutput = ''; - ptyProcess.onData((data) => (fullOutput += data)); - - const authDialogAppeared = await rig.waitForText( - 'How would you like to authenticate', - 5000, - ); - - // select the second option if auth dialog come's up - if (authDialogAppeared) { - ptyProcess.write('2'); - } - - // Wait for the app to be ready - const isReady = await rig.waitForText('Type your message', 25000); - expect( - isReady, - 'CLI did not start up in interactive mode correctly', - ).toBe(true); + await rig.ensureReadyForInput(ptyProcess); await type(ptyProcess, '/compress'); await new Promise((resolve) => setTimeout(resolve, 100)); diff --git a/integration-tests/test-helper.ts b/integration-tests/test-helper.ts index 7610c27d7c..440286da31 100644 --- a/integration-tests/test-helper.ts +++ b/integration-tests/test-helper.ts @@ -855,4 +855,48 @@ export class TestRig { return { ptyProcess, promise }; } + + /** + * Waits for an interactive session to be fully ready for input. + * This is a higher-level utility to be used with `runInteractive`. + * + * It handles the initial setup boilerplate: + * 1. Automatically handles the authentication prompt if it appears. + * 2. Waits for the "Type your message" prompt to ensure the CLI is ready for input. + * + * Throws an error if the session fails to become ready within the timeout. + * + * @param ptyProcess The process returned from `runInteractive`. + */ + async ensureReadyForInput(ptyProcess: pty.IPty): Promise { + const timeout = 25000; + const pollingInterval = 200; + const startTime = Date.now(); + let authPromptHandled = false; + + while (Date.now() - startTime < timeout) { + const output = stripAnsi(this._interactiveOutput).toLowerCase(); + + // If the ready prompt appears, we're done. + if (output.includes('type your message')) { + return; + } + + // If the auth prompt appears and we haven't handled it yet. + if ( + !authPromptHandled && + output.includes('how would you like to authenticate') + ) { + ptyProcess.write('2'); + authPromptHandled = true; + } + + // Wait for the next poll. + await new Promise((resolve) => setTimeout(resolve, pollingInterval)); + } + + throw new Error( + `CLI did not start up in interactive mode correctly. Output: ${this._interactiveOutput}`, + ); + } }