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:

All 13 helpers now at 100%. The interactive pickers, RunE handlers, and git/SSE side-effecting functions remain integration-test territory.

Sessions

Changes

2

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.