review: unit-test pure helpers for the review/trail commands · Entire
review: unit-test pure helpers for the review/trail commands
These deterministic helpers added on this branch sat at 0% coverage. Add focused unit tests (no I/O, no interactive forms, no network) covering:
- review: finalJudgeDisplayName, exampleAgentList, nonLaunchableEligibleNames, launchableInstalledAgentNames, slotLabel, defaultAgentPick, filterOutBuiltinCollisions, dedupeStrings
- cli (trail): severityDisplay, trailReviewTargetDisplay, defaultTrailReviewStatusReason, parseOptionalTrailSelector, truncateForLog
All 13 helpers now at 100%. The interactive pickers, RunE handlers, and git/SSE side-effecting functions remain integration-test territory.
Sessions
Changes
2
- cmd/entire/cli
- review
- Ahelpers_internal_test.go+172
- Atrail_helpers_test.go+130
- review
package review
import (
"context"
"errors"
"reflect"
"testing"
"github.com/entireio/cli/cmd/entire/cli/agent"
"github.com/entireio/cli/cmd/entire/cli/agent/types"
reviewtypes "github.com/entireio/cli/cmd/entire/cli/review/types"
"github.com/entireio/cli/cmd/entire/cli/settings"
)
const helperTestAgent = "agent-x"
var errStubReviewerStart = errors.New("pureHelperReviewer.Start not implemented")
type pureHelperReviewer struct{ name string }
func (p pureHelperReviewer) Name() string { return p.name }
func (p pureHelperReviewer) Start(context.Context, reviewtypes.RunConfig) (reviewtypes.Process, error) {
return nil, errStubReviewerStart
}
func reviewerForSet(launchable ...string) func(string) reviewtypes.AgentReviewer {
set := make(map[string]struct{}, len(launchable))
for _, n := range launchable {
set[n] = struct{}{}
}
return func(name string) reviewtypes.AgentReviewer {
if _, ok := set[name]; ok {
return pureHelperReviewer{name: name}
}
return nil
}
}
func TestFinalJudgeDisplayName(t *testing.T) {
t.Parallel()
tests := []struct {
in, want string
}{
{"", "final judge"},
{" ", "final judge"},
{"claude-code", "judge: claude-code"},
{" codex ", "judge: codex"},
}
for _, tt := range tests {
if got := finalJudgeDisplayName(tt.in); got != tt.want {
t.Errorf("finalJudgeDisplayName(%q) = %q, want %q", tt.in, got, tt.want)
}
}
}
func TestExampleAgentList(t *testing.T) {
t.Parallel()
const fallback = "claude-code,codex"
if got := exampleAgentList(nil); got != fallback {
t.Errorf("empty catalog = %q, want fallback", got)
}
if got := exampleAgentList([]reviewAgentCatalogEntry{{Name: "a"}, {Name: "b"}}); got != fallback {
t.Errorf("no installed = %q, want fallback", got)
}
catalog := []reviewAgentCatalogEntry{
{Name: "claude-code", Installed: true},
{Name: "codex", Installed: false},
{Name: "gemini", Installed: true},
{Name: "pi", Installed: true},
}
if got := exampleAgentList(catalog); got != "claude-code,gemini" {
t.Errorf("installed list = %q, want first two installed", got)
}
}
// Additional tests omitted for brevity.
package cli
import (
"strings"
"testing"
"github.com/entireio/cli/cmd/entire/cli/api"
)
func TestSeverityDisplay(t *testing.T) {
t.Parallel()
high := trailReviewSeverityHigh
blank := " "
tests := []struct {
name string
in *string
want string
}{
{"nil", nil, "-"},
{"blank", &blank, "-"},
{"value", &high, trailReviewSeverityHigh},
}
for _, tt := range tests {
if got := severityDisplay(tt.in); got != tt.want {
t.Errorf("%s: severityDisplay = %q, want %q", tt.name, got, tt.want)
}
}
}
func TestTrailReviewTargetDisplay(t *testing.T) {
t.Parallel()
tests := []struct {
name string
target trailReviewTarget
want string
}{
{
name: "number wins",
target: trailReviewTarget{Trail: api.TrailResource{Number: 7, Title: "Fix auth", ID: "abc", Branch: "fix/auth"}},
want: "trail #7 (Fix auth)",
},
{
name: "branch when no number",
target: trailReviewTarget{Trail: api.TrailResource{ID: "abc", Branch: "fix/auth"}},
want: "trail abc on fix/auth",
},
{
name: "id only",
target: trailReviewTarget{Trail: api.TrailResource{ID: "abc"}},
want: "trail abc",
},
}
for _, tt := range tests {
if got := trailReviewTargetDisplay(tt.target); got != tt.want {
t.Errorf("%s: trailReviewTargetDisplay = %q, want %q", tt.name, got, tt.want)
}
}
}
// Additional tests omitted for brevity.