e234dca474
Major improvements to review quality: 1. Full file context: fetch complete content of all modified files from the PR branch and include as reference. This eliminates false-positive "missing import" findings since the model sees the entire file. 2. Patterns repo: new --patterns-repo / PATTERNS_REPO flag fetches language idiom files from a separate Gitea repo (e.g. rodin/elixir-patterns) and includes them as review criteria. 3. Multi-file patterns: --patterns-files / PATTERNS_FILES accepts comma-separated file paths to fetch from the patterns repo. New API methods: - GetPullRequestFiles: list changed files in a PR - GetFileContentRef: fetch file content from a specific branch/ref Prompt changes: - BuildSystemPrompt now accepts (conventions, patterns) - BuildUserPrompt now accepts fileContext parameter - File context displayed before diff for model reference - Patterns presented as "review criteria" in system prompt Composite action updated with patterns-repo and patterns-files inputs.
119 lines
3.5 KiB
Go
119 lines
3.5 KiB
Go
package review
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestBuildSystemPrompt_NoConventions(t *testing.T) {
|
|
prompt := BuildSystemPrompt("", "")
|
|
|
|
if !strings.Contains(prompt, "expert code reviewer") {
|
|
t.Error("expected system prompt to mention code reviewer role")
|
|
}
|
|
if strings.Contains(prompt, "coding conventions") {
|
|
t.Error("should not mention conventions when empty")
|
|
}
|
|
}
|
|
|
|
func TestBuildSystemPrompt_WithConventions(t *testing.T) {
|
|
conventions := "- Use stdlib only\n- No panics\n"
|
|
prompt := BuildSystemPrompt(conventions, "")
|
|
|
|
if !strings.Contains(prompt, "coding conventions") {
|
|
t.Error("expected conventions section")
|
|
}
|
|
if !strings.Contains(prompt, "Use stdlib only") {
|
|
t.Error("expected conventions content")
|
|
}
|
|
}
|
|
|
|
func TestBuildUserPrompt_Basic(t *testing.T) {
|
|
prompt := BuildUserPrompt("Fix bug", "Fixes the crash", "diff content here", "", true, "all checks passed")
|
|
|
|
if !strings.Contains(prompt, "Fix bug") {
|
|
t.Error("expected PR title")
|
|
}
|
|
if !strings.Contains(prompt, "Fixes the crash") {
|
|
t.Error("expected PR description")
|
|
}
|
|
if !strings.Contains(prompt, "diff content here") {
|
|
t.Error("expected diff content")
|
|
}
|
|
if !strings.Contains(prompt, "PASSED") {
|
|
t.Error("expected CI status PASSED")
|
|
}
|
|
}
|
|
|
|
func TestBuildUserPrompt_CIFailed(t *testing.T) {
|
|
prompt := BuildUserPrompt("Add tests", "", "some diff", "", false, "lint: failed")
|
|
|
|
if !strings.Contains(prompt, "FAILED") {
|
|
t.Error("expected CI status FAILED")
|
|
}
|
|
if !strings.Contains(prompt, "lint: failed") {
|
|
t.Error("expected CI details")
|
|
}
|
|
}
|
|
|
|
func TestBuildUserPrompt_NoDescription(t *testing.T) {
|
|
prompt := BuildUserPrompt("Quick fix", "", "diff", "", true, "")
|
|
|
|
if strings.Contains(prompt, "### Description") {
|
|
t.Error("should not contain Description header when body is empty")
|
|
}
|
|
}
|
|
|
|
func TestBuildUserPrompt_DiffIncluded(t *testing.T) {
|
|
diff := "+func Hello() string {\n+\treturn \"hello\"\n+}"
|
|
prompt := BuildUserPrompt("Greeting", "Add greeting func", diff, "", true, "")
|
|
|
|
if !strings.Contains(prompt, "```diff") {
|
|
t.Error("expected diff fence")
|
|
}
|
|
if !strings.Contains(prompt, diff) {
|
|
t.Error("expected diff content in prompt")
|
|
}
|
|
}
|
|
|
|
func TestBuildSystemPrompt_WithPatterns(t *testing.T) {
|
|
patterns := "## Naming: use snake_case for functions"
|
|
prompt := BuildSystemPrompt("", patterns)
|
|
if !strings.Contains(prompt, "Language Patterns") {
|
|
t.Error("expected patterns section header")
|
|
}
|
|
if !strings.Contains(prompt, "snake_case") {
|
|
t.Error("expected patterns content")
|
|
}
|
|
}
|
|
|
|
func TestBuildSystemPrompt_WithBoth(t *testing.T) {
|
|
conventions := "Run mix format before commit"
|
|
patterns := "Use pipe operator for transformations"
|
|
prompt := BuildSystemPrompt(conventions, patterns)
|
|
if !strings.Contains(prompt, "Repository Conventions") {
|
|
t.Error("expected conventions section")
|
|
}
|
|
if !strings.Contains(prompt, "Language Patterns") {
|
|
t.Error("expected patterns section")
|
|
}
|
|
}
|
|
|
|
func TestBuildUserPrompt_WithFileContext(t *testing.T) {
|
|
fileContext := "--- main.go ---\npackage main\n"
|
|
prompt := BuildUserPrompt("Fix", "desc", "diff here", fileContext, true, "")
|
|
if !strings.Contains(prompt, "Full File Context") {
|
|
t.Error("expected file context section")
|
|
}
|
|
if !strings.Contains(prompt, "package main") {
|
|
t.Error("expected file content in prompt")
|
|
}
|
|
}
|
|
|
|
func TestBuildUserPrompt_WithoutFileContext(t *testing.T) {
|
|
prompt := BuildUserPrompt("Fix", "desc", "diff here", "", true, "")
|
|
if strings.Contains(prompt, "Full File Context") {
|
|
t.Error("should not include file context section when empty")
|
|
}
|
|
}
|