Download integration-tests/acp-env-auth.test.ts from SaylorTwift/gemini-cli: direct link, hf CLI and curl.
- Browser
- Download file 4.99 kB
-
https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/integration-tests/acp-env-auth.test.ts
- Command line
-
hf download hf://SaylorTwift/gemini-cli/integration-tests/acp-env-auth.test.ts
-
curl -L -o acp-env-auth.test.ts https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/integration-tests/acp-env-auth.test.ts
4.99 kB
| /** | |
| * @license | |
| * Copyright 2025 Google LLC | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import { describe, it, expect, beforeEach, afterEach } from 'vitest'; | |
| import { TestRig } from './test-helper.js'; | |
| import { spawn, ChildProcess } from 'node:child_process'; | |
| import { join, resolve } from 'node:path'; | |
| import { writeFileSync, mkdirSync } from 'node:fs'; | |
| import { Writable, Readable } from 'node:stream'; | |
| import { env } from 'node:process'; | |
| import * as acp from '@agentclientprotocol/sdk'; | |
| const sandboxEnv = env['GEMINI_SANDBOX']; | |
| const itMaybe = sandboxEnv && sandboxEnv !== 'false' ? it.skip : it; | |
| class MockClient implements acp.Client { | |
| updates: acp.SessionNotification[] = []; | |
| sessionUpdate = async (params: acp.SessionNotification) => { | |
| this.updates.push(params); | |
| }; | |
| requestPermission = async (): Promise<acp.RequestPermissionResponse> => { | |
| throw new Error('unexpected'); | |
| }; | |
| } | |
| describe.skip('ACP Environment and Auth', () => { | |
| let rig: TestRig; | |
| let child: ChildProcess | undefined; | |
| beforeEach(() => { | |
| rig = new TestRig(); | |
| }); | |
| afterEach(async () => { | |
| child?.kill(); | |
| child = undefined; | |
| await rig.cleanup(); | |
| }); | |
| itMaybe( | |
| 'should load .env from project directory and use the provided API key', | |
| async () => { | |
| rig.setup('acp-env-loading'); | |
| // Create a project directory with a .env file containing a recognizable invalid key | |
| const projectDir = resolve(join(rig.testDir!, 'project')); | |
| mkdirSync(projectDir, { recursive: true }); | |
| writeFileSync( | |
| join(projectDir, '.env'), | |
| 'GEMINI_API_KEY=test-key-from-env\n', | |
| ); | |
| const bundlePath = join(import.meta.dirname, '..', 'bundle/gemini.js'); | |
| child = spawn('node', [bundlePath, '--acp'], { | |
| cwd: rig.homeDir!, | |
| stdio: ['pipe', 'pipe', 'inherit'], | |
| env: { | |
| ...process.env, | |
| GEMINI_CLI_HOME: rig.homeDir!, | |
| GEMINI_API_KEY: undefined, | |
| VERBOSE: 'true', | |
| }, | |
| }); | |
| const input = Writable.toWeb(child.stdin!); | |
| const output = Readable.toWeb( | |
| child.stdout!, | |
| ) as ReadableStream<Uint8Array>; | |
| const testClient = new MockClient(); | |
| const stream = acp.ndJsonStream(input, output); | |
| const connection = new acp.ClientSideConnection(() => testClient, stream); | |
| await connection.initialize({ | |
| protocolVersion: acp.PROTOCOL_VERSION, | |
| clientCapabilities: { | |
| fs: { readTextFile: false, writeTextFile: false }, | |
| }, | |
| }); | |
| // 1. newSession should succeed because it finds the key in .env | |
| const { sessionId } = await connection.newSession({ | |
| cwd: projectDir, | |
| mcpServers: [], | |
| }); | |
| expect(sessionId).toBeDefined(); | |
| // 2. prompt should fail because the key is invalid, | |
| // but the error should come from the API, not the internal auth check. | |
| await expect( | |
| connection.prompt({ | |
| sessionId, | |
| prompt: [{ type: 'text', text: 'hello' }], | |
| }), | |
| ).rejects.toSatisfy((error: unknown) => { | |
| const acpError = error as acp.RequestError; | |
| const errorData = acpError.data as | |
| | { error?: { message?: string } } | |
| | undefined; | |
| const message = String(errorData?.error?.message || acpError.message); | |
| // It should NOT be our internal "Authentication required" message | |
| expect(message).not.toContain('Authentication required'); | |
| // It SHOULD be an API error mentioning the invalid key | |
| expect(message).toContain('API key not valid'); | |
| return true; | |
| }); | |
| child.stdin!.end(); | |
| }, | |
| ); | |
| itMaybe( | |
| 'should fail with authRequired when no API key is found', | |
| async () => { | |
| rig.setup('acp-auth-failure'); | |
| const bundlePath = join(import.meta.dirname, '..', 'bundle/gemini.js'); | |
| child = spawn('node', [bundlePath, '--acp'], { | |
| cwd: rig.homeDir!, | |
| stdio: ['pipe', 'pipe', 'inherit'], | |
| env: { | |
| ...process.env, | |
| GEMINI_CLI_HOME: rig.homeDir!, | |
| GEMINI_API_KEY: undefined, | |
| VERBOSE: 'true', | |
| }, | |
| }); | |
| const input = Writable.toWeb(child.stdin!); | |
| const output = Readable.toWeb( | |
| child.stdout!, | |
| ) as ReadableStream<Uint8Array>; | |
| const testClient = new MockClient(); | |
| const stream = acp.ndJsonStream(input, output); | |
| const connection = new acp.ClientSideConnection(() => testClient, stream); | |
| await connection.initialize({ | |
| protocolVersion: acp.PROTOCOL_VERSION, | |
| clientCapabilities: { | |
| fs: { readTextFile: false, writeTextFile: false }, | |
| }, | |
| }); | |
| await expect( | |
| connection.newSession({ | |
| cwd: resolve(rig.testDir!), | |
| mcpServers: [], | |
| }), | |
| ).rejects.toMatchObject({ | |
| message: expect.stringContaining( | |
| 'Gemini API key is missing or not configured.', | |
| ), | |
| }); | |
| child.stdin!.end(); | |
| }, | |
| ); | |
| }); | |