3c536c42d5
- gitea/client_test.go: mock HTTP tests for all API methods + error cases - llm/client_test.go: mock tests for completion, errors, timeouts - review/parser_test.go: JSON parsing, markdown fences, validation - review/formatter_test.go: markdown output, empty/multiple findings - review/prompt_test.go: system/user prompt construction - integration_test.go: full end-to-end flow (build tag: integration) - .gitea/workflows/ci.yml: test + vet + build on push, dual LLM review on PRs - CONVENTIONS.md: coding standards for self-review dogfooding - README.md: usage docs, env vars, architecture
115 lines
3.6 KiB
Go
115 lines
3.6 KiB
Go
package review
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestParseResponse_ValidJSON(t *testing.T) {
|
|
input := `{
|
|
"verdict": "APPROVE",
|
|
"summary": "Looks good",
|
|
"findings": [
|
|
{"severity": "NIT", "file": "main.go", "line": 10, "finding": "Consider renaming"}
|
|
],
|
|
"recommendation": "Ship it"
|
|
}`
|
|
|
|
result, err := ParseResponse(input)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if result.Verdict != "APPROVE" {
|
|
t.Errorf("expected verdict APPROVE, got %q", result.Verdict)
|
|
}
|
|
if result.Summary != "Looks good" {
|
|
t.Errorf("expected summary %q, got %q", "Looks good", result.Summary)
|
|
}
|
|
if len(result.Findings) != 1 {
|
|
t.Fatalf("expected 1 finding, got %d", len(result.Findings))
|
|
}
|
|
if result.Findings[0].Severity != "NIT" {
|
|
t.Errorf("expected severity NIT, got %q", result.Findings[0].Severity)
|
|
}
|
|
if result.Findings[0].File != "main.go" {
|
|
t.Errorf("expected file main.go, got %q", result.Findings[0].File)
|
|
}
|
|
if result.Findings[0].Line != 10 {
|
|
t.Errorf("expected line 10, got %d", result.Findings[0].Line)
|
|
}
|
|
if result.Recommendation != "Ship it" {
|
|
t.Errorf("expected recommendation %q, got %q", "Ship it", result.Recommendation)
|
|
}
|
|
}
|
|
|
|
func TestParseResponse_MarkdownFences(t *testing.T) {
|
|
input := "```json\n{\"verdict\": \"REQUEST_CHANGES\", \"summary\": \"Issues found\", \"findings\": [{\"severity\": \"MAJOR\", \"file\": \"a.go\", \"line\": 5, \"finding\": \"Bug\"}], \"recommendation\": \"Fix it\"}\n```"
|
|
|
|
result, err := ParseResponse(input)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if result.Verdict != "REQUEST_CHANGES" {
|
|
t.Errorf("expected verdict REQUEST_CHANGES, got %q", result.Verdict)
|
|
}
|
|
if len(result.Findings) != 1 {
|
|
t.Fatalf("expected 1 finding, got %d", len(result.Findings))
|
|
}
|
|
if result.Findings[0].Severity != "MAJOR" {
|
|
t.Errorf("expected severity MAJOR, got %q", result.Findings[0].Severity)
|
|
}
|
|
}
|
|
|
|
func TestParseResponse_InvalidJSON(t *testing.T) {
|
|
_, err := ParseResponse("this is not json")
|
|
if err == nil {
|
|
t.Fatal("expected error for invalid JSON, got nil")
|
|
}
|
|
}
|
|
|
|
func TestParseResponse_InvalidVerdict(t *testing.T) {
|
|
input := `{"verdict": "MAYBE", "summary": "Hmm", "findings": [], "recommendation": "Dunno"}`
|
|
_, err := ParseResponse(input)
|
|
if err == nil {
|
|
t.Fatal("expected error for invalid verdict, got nil")
|
|
}
|
|
}
|
|
|
|
func TestParseResponse_InvalidSeverity(t *testing.T) {
|
|
input := `{"verdict": "APPROVE", "summary": "Ok", "findings": [{"severity": "CRITICAL", "file": "x.go", "line": 1, "finding": "bad"}], "recommendation": "Fix"}`
|
|
_, err := ParseResponse(input)
|
|
if err == nil {
|
|
t.Fatal("expected error for invalid severity, got nil")
|
|
}
|
|
}
|
|
|
|
func TestParseResponse_EmptyFindings(t *testing.T) {
|
|
input := `{"verdict": "APPROVE", "summary": "All good", "findings": [], "recommendation": "Merge"}`
|
|
result, err := ParseResponse(input)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(result.Findings) != 0 {
|
|
t.Errorf("expected 0 findings, got %d", len(result.Findings))
|
|
}
|
|
}
|
|
|
|
func TestParseResponse_MissingFields(t *testing.T) {
|
|
// verdict is empty string — should fail validation
|
|
input := `{"summary": "Ok", "findings": [], "recommendation": "Merge"}`
|
|
_, err := ParseResponse(input)
|
|
if err == nil {
|
|
t.Fatal("expected error for missing verdict, got nil")
|
|
}
|
|
}
|
|
|
|
func TestParseResponse_MarkdownFencesNoLang(t *testing.T) {
|
|
input := "```\n{\"verdict\": \"APPROVE\", \"summary\": \"Fine\", \"findings\": [], \"recommendation\": \"Good\"}\n```"
|
|
result, err := ParseResponse(input)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if result.Verdict != "APPROVE" {
|
|
t.Errorf("expected APPROVE, got %q", result.Verdict)
|
|
}
|
|
}
|