-
Notifications
You must be signed in to change notification settings - Fork 19
Add: Unit tests for internal packages #105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Covers chatgpt, claude, gemini, grok, display, - http client, ollama, and stats modules to ensure - functionality and error handling.
WalkthroughAdds extensive unit tests across providers (ChatGPT, Claude, Gemini, Grok, Ollama), HTTP client, display utilities, and repository statistics. Introduces or validates GenerateCommitMessage flows, request/response serialization, error handling, and option handling. One public API addition is inferred for chatgpt.GenerateCommitMessage. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Dev as Caller
participant Prov as Provider (e.g., ChatGPT/Claude/Grok/Gemini/Ollama)
participant HTTP as HTTP Client
participant API as LLM API
Dev->>Prov: GenerateCommitMessage(cfg, changes, apiKey, opts)
Prov->>Prov: Validate inputs (apiKey, changes, opts)
Prov->>HTTP: Build request (model, headers, prompt/style)
HTTP->>API: POST /messages (payload)
API-->>HTTP: Response (message/content or error)
HTTP-->>Prov: Deserialize response
Prov-->>Dev: Commit message or error
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (3)
internal/claude/claude_test.go (3)
95-110: Critical: Mock server created but never used.Same issue as the previous test - the mock server (lines 98-102) is created to simulate an API error response, but the test calls the real API instead (line 106).
112-136: Critical: Mock server created but never used.Same issue - the mock server simulating an empty response (lines 124-128) is never actually used by the test (line 132).
233-248: Critical: Mock server created but never used.The test creates a mock server returning invalid JSON (lines 236-239) but then calls the real API with "invalid-key" (line 244) instead of using the mock.
🧹 Nitpick comments (4)
internal/gemini/gemini_test.go (1)
101-109: Drop or rework the “context cancellation” testThis subtest only repeats the “invalid key” assertion you already cover elsewhere, while the comment admits context isn’t wired yet. Until the production function accepts a
context.Context, this brings zero new signal. Please either implement context handling and assert it here, or remove the subtest to keep the suite focused.internal/grok/grok_test.go (1)
38-176: Refactor the “mock server” tests to exercise real success pathsEach subtest here stands up an
httptestserver but still callsGenerateCommitMessagewith"invalid-key". Because the production code doesn’t accept an override for the base URL/client, none of these handlers ever run — the call exits early with the same invalid-key error you already assert elsewhere. That makes the whole block misleading and duplicative. Please either add injection points (e.g., allow passing an HTTP client/base URL) so the mock server is actually hit and you can assert on the request/response, or drop these subtests entirely.internal/chatgpt/chatgpt_test.go (1)
33-46: Remove the unused mock server (or make the client injectable)This subtest spins up an
httptestserver butGenerateCommitMessagenever points at it; the code still calls the real OpenAI endpoint and immediately fails with the invalid key, so the handler is dead code. Please either expose an injectable HTTP client/base URL so the server is exercised, or drop the mock to keep the test honest.internal/claude/claude_test.go (1)
250-261: Add a mock-server assertion for long-prompt handling
The current test only asserts an error on an invalid API key and never inspects the request body. InTestGenerateCommitMessageWithLongPrompt, spin up anhttptest.NewServerto capture the JSON payload and assert that:
- the prompt sent (
req.Messages[0].Content) contains (or is truncated to) the expected length (e.g. ≥1000 bytes)- no unintended modifications occur before sending
- the function succeeds with a valid API key and returns the expected response
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
internal/chatgpt/chatgpt_test.go(1 hunks)internal/claude/claude_test.go(1 hunks)internal/display/display_test.go(1 hunks)internal/gemini/gemini_test.go(1 hunks)internal/grok/grok_test.go(1 hunks)internal/http/client_test.go(1 hunks)internal/ollama/ollama_test.go(1 hunks)internal/stats/statistics_test.go(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (8)
internal/http/client_test.go (1)
internal/http/client.go (3)
GetClient(32-40)GetOllamaClient(43-51)createTransport(19-29)
internal/display/display_test.go (1)
internal/display/display.go (7)
FileStatistics(16-23)ShowFileStatistics(26-102)MaxStagedFiles(10-10)ShowCommitMessage(105-121)ShowChangesPreview(124-139)MaxUnstagedFiles(11-11)MaxUntrackedFiles(12-12)
internal/chatgpt/chatgpt_test.go (4)
internal/claude/claude_test.go (1)
TestGenerateCommitMessage(13-33)internal/gemini/gemini_test.go (1)
TestGenerateCommitMessage(9-38)internal/ollama/ollama_test.go (1)
TestGenerateCommitMessage(13-104)pkg/types/options.go (1)
GenerationOptions(4-10)
internal/grok/grok_test.go (2)
pkg/types/types.go (4)
GrokResponse(86-94)Message(80-83)GrokRequest(72-77)Choice(97-101)pkg/types/options.go (1)
GenerationOptions(4-10)
internal/gemini/gemini_test.go (3)
internal/chatgpt/chatgpt_test.go (1)
TestGenerateCommitMessage(11-64)internal/grok/grok_test.go (5)
TestGenerateCommitMessage(13-33)TestGenerateCommitMessageWithLongChanges(193-204)TestGenerateCommitMessageWithSpecialCharacters(206-222)TestGenerateCommitMessageWithConfig(312-324)TestGenerateCommitMessageWithNilConfig(326-334)pkg/types/options.go (1)
GenerationOptions(4-10)
internal/claude/claude_test.go (3)
internal/claude/claude.go (2)
ClaudeResponse(22-29)ClaudeRequest(15-19)pkg/types/options.go (1)
GenerationOptions(4-10)pkg/types/types.go (1)
Message(80-83)
internal/ollama/ollama_test.go (2)
internal/ollama/ollama.go (2)
OllamaResponse(21-24)OllamaRequest(15-18)pkg/types/options.go (1)
GenerationOptions(4-10)
internal/stats/statistics_test.go (2)
pkg/types/types.go (1)
RepoConfig(66-69)internal/stats/statistics.go (1)
GetFileStatistics(14-74)
🔇 Additional comments (3)
internal/claude/claude_test.go (3)
13-33: LGTM! Input validation tests are correct.The basic validation tests for empty API key and empty changes are well-structured and correctly use
t.Parallel()for concurrent execution.
155-190: LGTM! Serialization test is thorough.The test correctly verifies that
ClaudeRequestcan be marshaled and unmarshaled, checking all fields including model, max tokens, and messages.
192-231: LGTM! Deserialization test is comprehensive.The test properly validates that
ClaudeResponseJSON can be parsed and that all fields (ID, Type, Content array) are correctly deserialized.
| package claude | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "net/http" | ||
| "net/http/httptest" | ||
| "strings" | ||
| "testing" | ||
|
|
||
| "github.com/dfanso/commit-msg/pkg/types" | ||
| ) | ||
|
|
||
| func TestGenerateCommitMessage(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| t.Run("returns error for empty API key", func(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| _, err := GenerateCommitMessage(&types.Config{}, "some changes", "", nil) | ||
| if err == nil { | ||
| t.Fatal("expected error for empty API key") | ||
| } | ||
| }) | ||
|
|
||
| t.Run("returns error for empty changes", func(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| _, err := GenerateCommitMessage(&types.Config{}, "", "test-key", nil) | ||
| if err == nil { | ||
| t.Fatal("expected error for empty changes") | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| func TestGenerateCommitMessageWithMockServer(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| t.Run("successful response", func(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| expectedResponse := ClaudeResponse{ | ||
| ID: "msg_123", | ||
| Type: "message", | ||
| Content: []struct { | ||
| Type string `json:"type"` | ||
| Text string `json:"text"` | ||
| }{ | ||
| { | ||
| Type: "text", | ||
| Text: "feat: add new feature", | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| if r.Method != http.MethodPost { | ||
| t.Fatalf("expected POST method, got %s", r.Method) | ||
| } | ||
|
|
||
| if got := r.Header.Get("x-api-key"); got != "test-key" { | ||
| t.Fatalf("expected API key 'test-key', got %s", got) | ||
| } | ||
|
|
||
| if got := r.Header.Get("anthropic-version"); got != "2023-06-01" { | ||
| t.Fatalf("expected anthropic-version '2023-06-01', got %s", got) | ||
| } | ||
|
|
||
| var req ClaudeRequest | ||
| if err := json.NewDecoder(r.Body).Decode(&req); err != nil { | ||
| t.Fatalf("failed to decode request: %v", err) | ||
| } | ||
|
|
||
| if req.Model != "claude-3-5-sonnet-20241022" { | ||
| t.Fatalf("expected model 'claude-3-5-sonnet-20241022', got %s", req.Model) | ||
| } | ||
|
|
||
| w.Header().Set("Content-Type", "application/json") | ||
| json.NewEncoder(w).Encode(expectedResponse) | ||
| })) | ||
| t.Cleanup(server.Close) | ||
|
|
||
| // Override the API URL for testing | ||
| originalURL := "https://api.anthropic.com/v1/messages" | ||
|
|
||
| // This would require modifying the function to accept a URL parameter | ||
| // For now, we'll test the error handling path | ||
| _, err := GenerateCommitMessage(&types.Config{}, "some changes", "invalid-key", nil) | ||
| if err == nil { | ||
| t.Fatal("expected error for invalid API key") | ||
| } | ||
|
|
||
| _ = originalURL // Avoid unused variable warning | ||
| }) | ||
|
|
||
| t.Run("API error response", func(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| w.WriteHeader(http.StatusBadRequest) | ||
| w.Write([]byte(`{"error": "invalid request"}`)) | ||
| })) | ||
| t.Cleanup(server.Close) | ||
|
|
||
| // This would require modifying the function to accept a URL parameter | ||
| // For now, we'll test the error handling path | ||
| _, err := GenerateCommitMessage(&types.Config{}, "some changes", "invalid-key", nil) | ||
| if err == nil { | ||
| t.Fatal("expected error for invalid API key") | ||
| } | ||
| }) | ||
|
|
||
| t.Run("empty response content", func(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| expectedResponse := ClaudeResponse{ | ||
| ID: "msg_123", | ||
| Type: "message", | ||
| Content: []struct { | ||
| Type string `json:"type"` | ||
| Text string `json:"text"` | ||
| }{}, | ||
| } | ||
|
|
||
| server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| w.Header().Set("Content-Type", "application/json") | ||
| json.NewEncoder(w).Encode(expectedResponse) | ||
| })) | ||
| t.Cleanup(server.Close) | ||
|
|
||
| // This would require modifying the function to accept a URL parameter | ||
| // For now, we'll test the error handling path | ||
| _, err := GenerateCommitMessage(&types.Config{}, "some changes", "invalid-key", nil) | ||
| if err == nil { | ||
| t.Fatal("expected error for invalid API key") | ||
| } | ||
| }) | ||
| } | ||
|
|
||
| func TestGenerateCommitMessageIncludesStyleInstructions(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| // Test that style instructions are included in the prompt | ||
| opts := &types.GenerationOptions{ | ||
| StyleInstruction: "Use a casual tone", | ||
| Attempt: 2, | ||
| } | ||
|
|
||
| // Test with invalid key to verify the function processes the options | ||
| _, err := GenerateCommitMessage(&types.Config{}, "some changes", "invalid-key", opts) | ||
| if err == nil { | ||
| t.Fatal("expected error for invalid API key") | ||
| } | ||
| } | ||
|
|
||
| func TestClaudeRequestSerialization(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| req := ClaudeRequest{ | ||
| Model: "claude-3-5-sonnet-20241022", | ||
| MaxTokens: 200, | ||
| Messages: []types.Message{ | ||
| { | ||
| Role: "user", | ||
| Content: "test prompt", | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| data, err := json.Marshal(req) | ||
| if err != nil { | ||
| t.Fatalf("failed to marshal request: %v", err) | ||
| } | ||
|
|
||
| var unmarshaled ClaudeRequest | ||
| if err := json.Unmarshal(data, &unmarshaled); err != nil { | ||
| t.Fatalf("failed to unmarshal request: %v", err) | ||
| } | ||
|
|
||
| if unmarshaled.Model != req.Model { | ||
| t.Fatalf("expected model %s, got %s", req.Model, unmarshaled.Model) | ||
| } | ||
|
|
||
| if unmarshaled.MaxTokens != req.MaxTokens { | ||
| t.Fatalf("expected max tokens %d, got %d", req.MaxTokens, unmarshaled.MaxTokens) | ||
| } | ||
|
|
||
| if len(unmarshaled.Messages) != len(req.Messages) { | ||
| t.Fatalf("expected %d messages, got %d", len(req.Messages), len(unmarshaled.Messages)) | ||
| } | ||
| } | ||
|
|
||
| func TestClaudeResponseDeserialization(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| jsonData := `{ | ||
| "id": "msg_123", | ||
| "type": "message", | ||
| "content": [ | ||
| { | ||
| "type": "text", | ||
| "text": "feat: add new feature" | ||
| } | ||
| ] | ||
| }` | ||
|
|
||
| var resp ClaudeResponse | ||
| if err := json.Unmarshal([]byte(jsonData), &resp); err != nil { | ||
| t.Fatalf("failed to unmarshal response: %v", err) | ||
| } | ||
|
|
||
| if resp.ID != "msg_123" { | ||
| t.Fatalf("expected ID 'msg_123', got %s", resp.ID) | ||
| } | ||
|
|
||
| if resp.Type != "message" { | ||
| t.Fatalf("expected type 'message', got %s", resp.Type) | ||
| } | ||
|
|
||
| if len(resp.Content) != 1 { | ||
| t.Fatalf("expected 1 content item, got %d", len(resp.Content)) | ||
| } | ||
|
|
||
| if resp.Content[0].Type != "text" { | ||
| t.Fatalf("expected content type 'text', got %s", resp.Content[0].Type) | ||
| } | ||
|
|
||
| expectedText := "feat: add new feature" | ||
| if resp.Content[0].Text != expectedText { | ||
| t.Fatalf("expected text '%s', got %s", expectedText, resp.Content[0].Text) | ||
| } | ||
| } | ||
|
|
||
| func TestGenerateCommitMessageWithInvalidJSON(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| w.Header().Set("Content-Type", "application/json") | ||
| w.Write([]byte(`{invalid json}`)) | ||
| })) | ||
| t.Cleanup(server.Close) | ||
|
|
||
| // This would require modifying the function to accept a URL parameter | ||
| // For now, we'll test the error handling path | ||
| _, err := GenerateCommitMessage(&types.Config{}, "some changes", "invalid-key", nil) | ||
| if err == nil { | ||
| t.Fatal("expected error for invalid API key") | ||
| } | ||
| } | ||
|
|
||
| func TestGenerateCommitMessageWithLongPrompt(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| // Create a very long prompt | ||
| longChanges := strings.Repeat("This is a test change. ", 1000) | ||
|
|
||
| // Test with invalid key to verify the function handles long prompts | ||
| _, err := GenerateCommitMessage(&types.Config{}, longChanges, "invalid-key", nil) | ||
| if err == nil { | ||
| t.Fatal("expected error for invalid API key") | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Consider refactoring GenerateCommitMessage to accept URL parameter.
Multiple tests throughout the file create mock servers but cannot use them because GenerateCommitMessage hardcodes the API URL. The recurring comment "This would require modifying the function to accept a URL parameter" appears in lines 85-86, 104-105, 130-131, and 242-243.
Options to fix this:
- Add an optional URL parameter to
GenerateCommitMessage - Use dependency injection to pass in an HTTP client
- Create a separate internal helper function that accepts a URL for testing
This refactor would enable all the mock server tests to actually test the function logic.
Would you like me to generate a refactored version of the GenerateCommitMessage function signature that supports testing with mock servers?
🤖 Prompt for AI Agents
internal/claude/claude_test.go lines 1-261: tests create httptest servers but
cannot use them because GenerateCommitMessage hardcodes the API URL; update the
function to accept an injectable API endpoint (or HTTP client) so tests can pass
server.URL. Change GenerateCommitMessage signature to accept an extra apiURL
string (or an optional client) and in production calls pass the default
"https://api.anthropic.com/v1/messages" when apiURL is empty; update all
internal callers and tests to provide the mock server URL (or a test HTTP
client), and ensure backward-compatible behavior by defaulting to the original
URL when the new parameter is not provided.
| server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| if r.Method != http.MethodPost { | ||
| t.Fatalf("expected POST method, got %s", r.Method) | ||
| } | ||
|
|
||
| if got := r.Header.Get("x-api-key"); got != "test-key" { | ||
| t.Fatalf("expected API key 'test-key', got %s", got) | ||
| } | ||
|
|
||
| if got := r.Header.Get("anthropic-version"); got != "2023-06-01" { | ||
| t.Fatalf("expected anthropic-version '2023-06-01', got %s", got) | ||
| } | ||
|
|
||
| var req ClaudeRequest | ||
| if err := json.NewDecoder(r.Body).Decode(&req); err != nil { | ||
| t.Fatalf("failed to decode request: %v", err) | ||
| } | ||
|
|
||
| if req.Model != "claude-3-5-sonnet-20241022" { | ||
| t.Fatalf("expected model 'claude-3-5-sonnet-20241022', got %s", req.Model) | ||
| } | ||
|
|
||
| w.Header().Set("Content-Type", "application/json") | ||
| json.NewEncoder(w).Encode(expectedResponse) | ||
| })) | ||
| t.Cleanup(server.Close) | ||
|
|
||
| // Override the API URL for testing | ||
| originalURL := "https://api.anthropic.com/v1/messages" | ||
|
|
||
| // This would require modifying the function to accept a URL parameter | ||
| // For now, we'll test the error handling path | ||
| _, err := GenerateCommitMessage(&types.Config{}, "some changes", "invalid-key", nil) | ||
| if err == nil { | ||
| t.Fatal("expected error for invalid API key") | ||
| } | ||
|
|
||
| _ = originalURL // Avoid unused variable warning | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Mock server created but never used.
The test creates a mock httptest.Server with expectations (lines 55-79) but then calls GenerateCommitMessage with the real API URL and an "invalid-key" (line 87). This means:
- The mock server is never exercised
- The test makes actual network calls to Claude's API (which will fail)
- None of the server's assertions (HTTP method, headers, request body) are verified
To fix this, the GenerateCommitMessage function needs to accept a configurable API URL parameter (as the comment on lines 85-86 suggests), or use dependency injection for the HTTP client.
Apply this pattern to make the mock server useful:
-// This would require modifying the function to accept a URL parameter
-// For now, we'll test the error handling path
-_, err := GenerateCommitMessage(&types.Config{}, "some changes", "invalid-key", nil)
-if err == nil {
- t.Fatal("expected error for invalid API key")
-}
-
-_ = originalURL // Avoid unused variable warning
+// Modify GenerateCommitMessage to accept a URL parameter or use dependency injection
+result, err := GenerateCommitMessageWithURL(&types.Config{}, "some changes", "test-key", nil, server.URL)
+if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+}
+
+if result != "feat: add new feature" {
+ t.Fatalf("expected 'feat: add new feature', got %s", result)
+}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In internal/claude/claude_test.go around lines 55 to 93, the httptest.Server is
created but never used because GenerateCommitMessage calls the real API URL;
change GenerateCommitMessage to accept an API base URL (or an options struct
that includes apiURL and http.Client) with a sane default of
"https://api.anthropic.com/v1/messages", update all call sites to pass the new
parameter or default, then update this test to call GenerateCommitMessage with
server.URL as the API base and a matching API key so the mock server is
exercised and its assertions are verified; ensure backward-compatible defaults
and update tests accordingly.
| func TestGenerateCommitMessageIncludesStyleInstructions(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| // Test that style instructions are included in the prompt | ||
| opts := &types.GenerationOptions{ | ||
| StyleInstruction: "Use a casual tone", | ||
| Attempt: 2, | ||
| } | ||
|
|
||
| // Test with invalid key to verify the function processes the options | ||
| _, err := GenerateCommitMessage(&types.Config{}, "some changes", "invalid-key", opts) | ||
| if err == nil { | ||
| t.Fatal("expected error for invalid API key") | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Test doesn't verify style instructions are included.
The test creates GenerationOptions with style instructions (lines 143-146) but only verifies that an error occurs with an invalid key. It doesn't confirm that the style instructions are actually incorporated into the prompt sent to the Claude API.
To properly test this, use a mock server to capture and inspect the request body.
After fixing the mock server issues, verify that the style instructions appear in the request:
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var req ClaudeRequest
json.NewDecoder(r.Body).Decode(&req)
// Verify style instruction is in the prompt
prompt := req.Messages[0].Content
if !strings.Contains(prompt, "Use a casual tone") {
t.Fatal("style instruction not included in prompt")
}
// Verify attempt number is handled
if opts.Attempt > 1 && !strings.Contains(prompt, "alternative") {
t.Fatal("attempt number not reflected in prompt")
}
// Return mock response
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(ClaudeResponse{...})
}))🏁 Script executed:
#!/bin/bash
rg -n 'TestGenerateCommitMessageIncludesStyleInstructions' -C5 internal/claude/claude_test.go
rg -n 'httptest\.NewServer' -C3 internal/claude/claude_test.goLength of output: 1375
Add assertions for style instructions and attempt in TestGenerateCommitMessageIncludesStyleInstructions
TestGenerateCommitMessageIncludesStyleInstructions only checks for an error and doesn’t verify that opts.StyleInstruction (“Use a casual tone”) or opts.Attempt (e.g. “alternative”) appear in the prompt sent to Claude. Use httptest.NewServer to capture the JSON request, then assert that req.Messages[0].Content contains both the StyleInstruction and a reference to the attempt number. [internal/claude/claude_test.go:139]
🤖 Prompt for AI Agents
In internal/claude/claude_test.go around lines 139 to 153, the test only
verifies an error for an invalid API key and does not assert that the style
instruction or attempt number are present in the prompt sent to Claude; replace
the invalid-key flow with an httptest.NewServer that captures the JSON request
body, parse the request to extract the sent messages, and add assertions that
the message content includes opts.StyleInstruction ("Use a casual tone") and a
clear reference to opts.Attempt (e.g., "Attempt 2" or the attempt number string
you embed); configure the test Config to point the client to the test server URL
and use a dummy valid key so GenerateCommitMessage returns without an API-key
error, then assert the captured request contains both the style instruction and
the attempt reference before finishing the test.
| if req["model"] != "llama3:latest" { | ||
| t.Fatalf("expected model 'llama3:latest', got %v", req["model"]) | ||
| } | ||
|
|
||
| if req["stream"] != false { | ||
| t.Fatalf("expected stream false, got %v", req["stream"]) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the stream assertion — it can never pass
GenerateCommitMessage currently marshals the OllamaRequest struct (see internal/ollama/ollama.go lines 14-17), which only carries model and prompt. No stream field is emitted, so decoding the request into a map leaves req["stream"] undefined (nil). This assertion will fail every run, blocking the suite. Either add a stream field to the real request payload or, if streaming is intentionally unmanaged, drop this expectation. Suggested quick fix if you decide to keep today’s payload:
- if req["stream"] != false {
- t.Fatalf("expected stream false, got %v", req["stream"])
- }
+ if _, ok := req["stream"]; ok {
+ t.Fatalf("stream flag is not sent today; got %v", req["stream"])
+ }
Description
Type of Change
Related Issue
Fixes #(issue number)
Changes Made
Testing
Checklist
Screenshots (if applicable)
Additional Notes
For Hacktoberfest Participants
Thank you for your contribution! 🎉
Summary by CodeRabbit