open-code-review/cmd/opencodereview/output_test.go
kite e2d75b732a
Some checks are pending
CI / test (push) Waiting to run
test: fix golangci-lint errcheck/staticcheck issues in test code (#323)
2026-07-08 22:46:18 +08:00

107 lines
3.4 KiB
Go

package main
import (
"strings"
"testing"
"github.com/open-code-review/open-code-review/internal/model"
)
func TestBuildBadge(t *testing.T) {
tests := []struct {
name string
comment model.LlmComment
want string
}{
{"both fields", model.LlmComment{Category: "security", Severity: "high"}, "[security · high]"},
{"category only", model.LlmComment{Category: "bug"}, "[bug]"},
{"severity only", model.LlmComment{Severity: "low"}, "[low]"},
{"neither", model.LlmComment{}, ""},
{"strips control chars", model.LlmComment{Category: "bug\x1b[0m", Severity: "high"}, "[bug[0m · high]"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := buildBadge(tt.comment); got != tt.want {
t.Errorf("buildBadge() = %q, want %q", got, tt.want)
}
})
}
}
func TestSeverityColor(t *testing.T) {
// Each known severity must map to a distinct color; unknown falls back to dim.
seen := map[string]string{}
for _, sev := range []string{"critical", "high", "medium", "low"} {
c := severityColor(sev)
if c == "" {
t.Errorf("severityColor(%q) is empty", sev)
}
if prev, ok := seen[c]; ok {
t.Errorf("severityColor(%q) shares color with %q", sev, prev)
}
seen[c] = sev
}
if got := severityColor("bogus"); got != "\033[2m" {
t.Errorf("severityColor(unknown) = %q, want dim", got)
}
if got := severityColor(""); got != "\033[2m" {
t.Errorf("severityColor(empty) = %q, want dim", got)
}
}
// TestRenderComment_BadgeInline verifies the badge is colorized and rendered inline
// with the first line of the comment content.
func TestRenderComment_BadgeInline(t *testing.T) {
out := captureStdout(t, func() {
renderComment(model.LlmComment{
Path: "internal/mcp/client.go",
StartLine: 27,
EndLine: 27,
Content: "Potential environment variable leak.",
Category: "security",
Severity: "high",
})
})
if !strings.Contains(out, "[security · high]") {
t.Errorf("expected badge in output, got:\n%s", out)
}
// severity high → bright red; the badge must be wrapped in the color + reset.
if !strings.Contains(out, "\033[91m[security · high]\033[0m") {
t.Errorf("expected colorized badge, got:\n%q", out)
}
if !strings.Contains(out, "Potential environment variable leak.") {
t.Errorf("expected content in output, got:\n%s", out)
}
}
func TestSanitizeTerminal(t *testing.T) {
tests := []struct {
name string
in string
want string
}{
{"plain text unchanged", "hello world", "hello world"},
{"preserves tab", "col1\tcol2", "col1\tcol2"},
{"preserves newline", "line1\nline2", "line1\nline2"},
{"strips ESC", "before\x1b[2Jafter", "before[2Jafter"},
{"strips OSC 52", "\x1b]52;c;dGVzdA==\x07", "]52;c;dGVzdA=="},
{"strips BEL alone", "beep\x07done", "beepdone"},
{"strips null byte", "a\x00b", "ab"},
{"strips DEL", "a\x7fb", "ab"},
{"strips carriage return", "fake\rreal", "fakereal"},
{"empty string", "", ""},
{"only control chars", "\x1b\x07\x00\x7f", ""},
{"unicode preserved", "代码审查 レビュー 🔍", "代码审查 レビュー 🔍"},
{"mixed safe and unsafe", "path\x1b[0m/file.go", "path[0m/file.go"},
{"strips C1 CSI (U+009B)", "before\u009bafter", "beforeafter"},
{"strips C1 OSC (U+009D)", "before\u009dafter", "beforeafter"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := sanitizeTerminal(tt.in)
if got != tt.want {
t.Errorf("sanitizeTerminal(%q) = %q, want %q", tt.in, got, tt.want)
}
})
}
}