API Key Handling
Relevant source files
The following files were used as context for generating this wiki page:
The TestGen AI application utilizes the Google Gemini API to generate test cases, which requires a valid API key for authentication. The system is designed to handle this key by capturing it from the user via the frontend and using it to make requests to the Gemini service. The project's architecture has evolved, presenting two distinct methods for handling the API key: a Go backend proxy and a direct client-side implementation.
This document outlines the complete workflow for API key handling, from user input on the frontend to its use in API requests in both architectural patterns.
Frontend: API Key Input and Storage
The user provides their Gemini API key through the "Settings" tab in the main application dashboard.
Sources: testgen/src/pages/Dashboard.tsx
UI Component
The Dashboard.tsx component contains a dedicated "Settings" tab with an input field for the API key.
- The key is entered into an
<Input>component withtype="password"to obscure the value from view. - The entered key is stored in the component's local state using the
useStatehook:const [geminiKey, setGeminiKey] = useState("");. - An
onChangeevent handler updates the state with the user's input.
Sources: testgen/src/pages/Dashboard.tsx:45, testgen/src/pages/Dashboard.tsx:351-364
// testgen/src/pages/Dashboard.tsx:355-361
<Input
id="gemini-key"
type="password"
placeholder="Enter your Gemini API key"
value={geminiKey}
onChange={(e) => setGeminiKey(e.target.value)}
/>
Data Flow from Input to API Call
The following diagram illustrates how the API key flows from the user input to the API service layer when test generation is triggered.
This diagram shows the user interaction and state management for the API key within the Dashboard.tsx component.
Sources: testgen/src/pages/Dashboard.tsx:115-152
API Key Transmission and Usage
Once the user initiates test generation, the stored API key is included in the request payload. The project supports two different backend architectures for processing this request.
Architecture 1: Go Backend Proxy (Legacy)
In the original architecture, the React frontend communicates with a Go backend, which acts as a proxy to the Google Gemini API.
Sources: testgen-backend/main.go, README.md
Data Structures
The Go backend defines a GeminiRequest struct to unmarshal the incoming JSON payload from the frontend.
| Field | Type | Description |
|---|---|---|
APIKey | string | The user's Google Gemini API key. |
CodeContext | string | The code context for test generation. |
AdditionalPrompt | string | An optional additional prompt. |
Sources: testgen-backend/main.go:53-57
API Endpoint: POST /api/generate-tests
The Go backend exposes this endpoint to handle test generation requests.
- It receives the
GeminiRequestcontaining the API key. - It validates that the
APIKeyis not empty. - It constructs the URL for the Google Gemini API, appending the key as a query parameter.
- It forwards the request to the Gemini API and streams the response back to the client.
Sources: testgen-backend/main.go:450-606
Sequence Diagram (Go Backend)
This diagram shows the API key flow through the Go backend proxy.
Sources: README.md, testgen-backend/main.go:527
Architecture 2: Client-Side Backend
The project has since migrated to a client-side backend model, eliminating the need for the Go server. In this architecture, the frontend calls the Google Gemini API directly from the browser.
Sources: testgen/src/lib/backend.ts, testgen/CLIENT_BACKEND.md, testgen/src/lib/api.ts
API Service Layer
The ApiService class in api.ts abstracts the backend communication. It now delegates the generateTests call directly to the ClientBackend.
Sources: testgen/src/lib/api.ts:28-30
Direct API Call
The ClientBackend.generateTests function orchestrates the direct call to the Gemini API.
- It receives a
GeminiRequestobject containing theapiKey. - It constructs the Gemini API URL, including the
apiKeyas a query parameter. - It uses the browser's
fetchAPI to make aPOSTrequest directly tohttps://generativelanguage.googleapis.com/....
Sources: testgen/src/lib/backend.ts:429-509
// testgen/src/lib/backend.ts:481-498
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key=${request.apiKey}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
contents: [{
parts: [{
text: prompt
}]
}],
generationConfig: {
temperature: 0.7,
topK: 40,
topP: 0.95,
maxOutputTokens: 8192,
}
})
});
Sequence Diagram (Client-Side Backend)
This diagram illustrates the direct-to-API flow from the browser.
Security Considerations
The move to a client-side backend introduces a significant security consideration. As noted in the documentation, API keys are exposed in the browser's network traffic when making direct calls to the Gemini API. The documentation suggests using environment variables as a mitigation strategy, though the implementation details for this are not specified in the provided files.
Sources: testgen/CLIENT_BACKEND.md
Summary
The TestGen AI application handles the Gemini API key by capturing it on the client-side and passing it with each test generation request. The system has two architectural patterns for this process:
- Go Backend Proxy: The key is sent to a proprietary Go backend, which then securely communicates with the Gemini API. This abstracts the key from the public-facing client.
- Client-Side Backend: The key is used directly in the browser to make a
fetchrequest to the Gemini API. This simplifies deployment by removing the Go server but exposes the API key in client-side network requests.
The current implementation favors the client-side backend approach for its simplicity and ease of deployment.