Frontend API Service
Relevant source files
The following files were used as context for generating this wiki page:The Frontend API Service is a client-side module that replaces the original Go backend, shifting all backend functionality directly into the browser. It is responsible for interacting with external services, primarily the GitHub API for fetching repository code and the Google Gemini API for generating test cases. This architectural change simplifies deployment, reduces server costs, and consolidates the project into a single frontend codebase.
The service is exposed to the React application through the ApiService class, which acts as a facade for the more complex logic contained within the ClientBackend class. This design provides a clean separation of concerns, where UI components interact with a simple API layer, while the ClientBackend handles the intricacies of API calls, data processing, and error handling.
Sources: testgen/CLIENT_BACKEND.md, testgen/src/lib/api.ts, testgen/src/lib/backend.ts
Architecture
The application's architecture transitioned from a traditional client-server model with a Go backend to a serverless, client-side model. The ApiService and ClientBackend modules are central to this new architecture, running entirely within the user's browser.
This diagram illustrates the data flow in the client-side architecture.
Core Components
The service is composed of two main classes that work together.
ApiService (api.ts):* A simple facade class that provides a clean, high-level API for the frontend UI. It directly delegates calls to the ClientBackend.
ClientBackend(backend.ts): The core implementation class containing all the logic for fetching data from the GitHub API, processing files, generating context prompts, and calling the Gemini API.
Sources: testgen/src/lib/api.ts:18-34, testgen/src/lib/backend.ts:59-524, testgen/src/pages/Dashboard.tsx
Key Functionality
Repository Cloning
The cloneRepository function orchestrates fetching source code from a public GitHub repository without using the git command.
This flowchart shows the steps involved in the cloning process.
File Filtering:
A predefined list of patterns is used to exclude unnecessary files and directories. This logic is nearly identical to the one used in the original Go backend.
- Excluded Patterns:
node_modules,.git,dist,build,*.log,*.md,test,docs, etc. - Size Limit: Files larger than 50KB are excluded.
- File Types: Only common source code, config, and script files are included.
Sources: testgen/src/lib/backend.ts:62-81, 154-171, 237-313, testgen-backend/main.go:68-87
Test Generation
The generateTests function is responsible for communicating with the Google Gemini API to produce test cases.
This sequence diagram shows the interaction between the UI and the external Gemini API.
The function constructs a detailed prompt that instructs the AI to return a JSON object with a specific structure, including fields for id, name, description, input, expected, code, testType, and priority.
Sources: testgen/src/lib/backend.ts:430-510, testgen/CLIENT_BACKEND.md, testgen/src/pages/Dashboard.tsx:114-152
Data Models and Interfaces
The service relies on a set of TypeScript interfaces to model requests and responses.
Sources: testgen/src/lib/backend.ts:4-56
RepoResponse
Object returned after a successful repository clone.
| Field | Type | Description |
|---|---|---|
success | boolean | Indicates if the operation was successful. |
message | string | A status message. |
filesCount | number | The total number of files fetched. |
contextPath | string | A virtual path for the generated context file. |
files | FileContent[] | An array of fetched file objects. |
FileContent
Represents a single file fetched from the repository.
| Field | Type | Description |
|---|---|---|
path | string | The relative path of the file in the repository. |
content | string | The decoded content of the file. |
size | number | The size of the file in bytes. |
GeminiRequest
The request object sent to the generateTests function.
| Field | Type | Description |
|---|---|---|
apiKey | string | The user's Google Gemini API key. |
codeContext | string | The aggregated source code from the repository. |
additionalPrompt | string (optional) | Extra instructions for the AI. |
GeminiTestCase
Represents a single test case generated by the Gemini API.
| Field | Type | Description |
|---|---|---|
id | string | A unique identifier for the test. |
name | string | A descriptive name for the test. |
description | string | A detailed explanation of the test's purpose. |
input | any | The input data for the function being tested. |
expected | any | The expected output or result. |
code | string | The function or code snippet being tested. |
testType | 'unit' | 'integration' | ... | The type of test. |
priority | 'high' | 'medium' | 'low' | The priority of the test. |
Usage from Frontend
The Dashboard.tsx component integrates with the ApiService to provide the core application functionality.
Sources: testgen/src/pages/Dashboard.tsx:60-152
Cloning a Repository
The handleCloneRepository function in Dashboard.tsx is triggered by the user. It calls ApiService.cloneRepository, processes the response, and updates the UI state with the fetched file paths and the generated code context.
// testgen/src/pages/Dashboard.tsx:78-98
const handleCloneRepository = async () => {
// ...
try {
// Clone repository using backend API
const response = await ApiService.cloneRepository(repoUrl);
if (!response.success) {
throw new Error(response.message);
}
// Generate prompt context from files using the backend
const promptContext = ClientBackend.generatePromptContext(response.files);
// Update state
setClonedFiles(response.files.map(f => f.path));
setCurrentRepo(`${repoInfo.owner}/${repoInfo.repo}`);
setCodeInput(promptContext);
// ...
}
// ...
};
Generating Tests
Similarly, handleGenerateTests collects the API key and code context from the UI and passes them to ApiService.generateTests. The returned test cases are then converted to the application's internal format and displayed.
// testgen/src/pages/Dashboard.tsx:114-138
const handleGenerateTests = async () => {
// ...
setIsGenerating(true);
try {
// Generate test cases using backend API
const geminiResponse = await ApiService.generateTests({
apiKey: geminiKey,
codeContext: codeInput,
additionalPrompt: currentRepo ? `Repository: ${currentRepo}` : undefined
});
// Convert Gemini format to app format
const appTests = convertGeminiTestsToAppFormat(geminiResponse.testCases);
setTestCases(appTests);
// ...
}
// ...
};
Security & Performance Considerations
The move to a client-side backend introduces several trade-offs:
- API Key Exposure: The Gemini API key is handled in the browser, which is a security risk. The application mitigates this by storing it in component state and not persisting it, but it is still exposed during the API call.
- CORS Limitations: Direct calls to the GitHub API from the browser are subject to Cross-Origin Resource Sharing (CORS) policies, which can cause issues when running locally.
- API Rate Limits: Unauthenticated calls to the GitHub API are rate-limited (typically 60 requests/hour per IP), which could affect users who analyze many repositories.
- Performance: All processing occurs on the user's machine, which offloads work from a central server but can be constrained by the user's browser and network performance.
Sources: testgen/CLIENT_BACKEND.md, testgen/src/lib/backend.ts:302-308