gitcrawl/internal/cli/tui_coverage_extra_test.go
2026-05-08 06:20:35 +01:00

180 lines
6.3 KiB
Go

package cli
import (
"context"
"strings"
"testing"
"time"
"github.com/openclaw/gitcrawl/internal/store"
)
func TestTUIRemainingActionAndErrorBranches(t *testing.T) {
thread := store.Thread{
ID: 1, Number: 10, Kind: "issue", State: "open", Title: "Thread title",
Body: "Body with https://example.com/docs", HTMLURL: "https://github.com/openclaw/openclaw/issues/10",
UpdatedAt: "2026-05-08T00:00:00Z",
}
cluster := store.ClusterSummary{
ID: 7, Source: store.ClusterSourceRun, StableSlug: "cluster-7", Status: "active",
Title: "Cluster title", RepresentativeNumber: 10, RepresentativeKind: "issue",
RepresentativeTitle: "Thread title", MemberCount: 1, UpdatedAt: "2026-05-08T00:00:00Z",
}
detail := store.ClusterDetail{
Cluster: cluster,
Members: []store.ClusterMemberDetail{{
Thread: thread,
Role: "member",
State: "active",
BodySnippet: "Body with https://example.com/docs",
Summaries: map[string]string{"problem_summary": "summary"},
}},
}
model := newClusterBrowserModel(context.Background(), nil, 0, clusterBrowserPayload{
Repository: "openclaw/openclaw",
Sort: "size",
MinSize: 1,
Clusters: []store.ClusterSummary{cluster},
})
model.detailCache[7] = detail
model.loadSelectedCluster()
model.memberIndex = 0
model.neighborCache[thread.ID] = []tuiNeighbor{{Thread: thread, Score: 0.9}}
for _, action := range []string{"sort-oldest", "member-sort-oldest", "toggle-closed", "close-menu"} {
if !model.runAction(action) {
t.Fatalf("action %s was not handled", action)
}
}
if model.payload.Sort != "oldest" || model.memberSort != memberSortOldest {
t.Fatalf("sort actions failed sort=%q member=%q", model.payload.Sort, model.memberSort)
}
t.Setenv("PATH", "")
errorActions := []string{
"open-cluster-representative",
"copy-cluster-url",
"copy-thread-detail",
"copy-body-preview",
"copy-summaries",
"copy-neighbors",
"copy-cluster-id",
"copy-cluster-name",
"copy-cluster-title",
"copy-member-list",
"copy-cluster",
"copy-visible-clusters",
"copy-reference-links",
"open",
"copy-url",
"copy-markdown",
"copy-title",
"open-first-link",
"copy-first-link",
}
for _, action := range errorActions {
model.status = ""
handled := model.runMenuItem(tuiMenuItem{label: action, action: action, value: "https://example.com/docs"})
if !handled || model.status == "" {
t.Fatalf("error action %s handled=%v status=%q", action, handled, model.status)
}
}
model.openReferenceLinkMenu("copy")
model.runAction("back-to-actions")
if model.menuTitle != "Actions" {
t.Fatalf("back to actions failed title=%q", model.menuTitle)
}
model.runMenuItem(tuiMenuItem{label: "Open picked", action: "open-picked-link", value: "https://example.com/docs"})
model.runMenuItem(tuiMenuItem{label: "Copy picked", action: "copy-picked-link", value: "https://example.com/docs"})
model.closeSelectedClusterLocally()
if !strings.Contains(model.status, "only available for durable clusters") {
t.Fatalf("raw cluster local close status=%q", model.status)
}
model.reopenSelectedClusterLocally()
model.excludeSelectedClusterMemberLocally()
model.includeSelectedClusterMemberLocally()
model.setSelectedClusterCanonicalLocally()
if !strings.Contains(model.status, "only available for durable clusters") {
t.Fatalf("raw member local action status=%q", model.status)
}
}
func TestTUIRemainingHelperBranches(t *testing.T) {
model := newClusterBrowserModel(context.Background(), nil, 0, clusterBrowserPayload{
Repository: "openclaw/openclaw",
MinSize: 1,
Limit: 1,
Clusters: []store.ClusterSummary{
{ID: 1, Status: "active", RepresentativeNumber: 101, MemberCount: 1, UpdatedAt: "2026-05-08T00:00:00Z"},
},
})
if model.currentClusterID() != 1 {
t.Fatalf("current cluster id = %d", model.currentClusterID())
}
if model.clusterRefreshLimit() != 1 {
t.Fatalf("cluster refresh limit = %d", model.clusterRefreshLimit())
}
model.ensureClusterInWorkingSet(store.ClusterSummary{ID: 2, Status: "closed", ClosedAt: "2026-05-08T00:00:00Z", MemberCount: 2})
if !model.selectClusterIDForJump(2) || !model.showClosed || model.minSize != 1 {
t.Fatalf("jump selection showClosed=%v minSize=%d selected=%d", model.showClosed, model.minSize, model.selected)
}
model.payload.Clusters = nil
if model.currentClusterID() != 0 || model.clusterSignature() != "" {
t.Fatalf("empty cluster helpers id=%d sig=%q", model.currentClusterID(), model.clusterSignature())
}
if _, ok := model.clusterFromWorkingSet(999); ok {
t.Fatal("missing working-set cluster should not resolve")
}
model.applyClusterRefresh(nil, 0)
if model.payload.Clusters == nil {
t.Fatal("nil refresh should normalize clusters")
}
model.autoRefreshFromStore()
if model.status != "Refresh unavailable for this view" {
t.Fatalf("auto refresh status=%q", model.status)
}
if cmd := model.autoRefreshCmd(); cmd != nil {
t.Fatalf("auto refresh command without store = %v", cmd)
}
model.switchRepository("")
if model.status != "Repository picker unavailable for this view" {
t.Fatalf("switch repository no store status=%q", model.status)
}
if label := (clusterBrowserModel{}).clusterPositionLabel(); label != "0" {
t.Fatalf("zero cluster position label = %q", label)
}
if label := model.clusterPositionLabel(); label != "0" {
t.Fatalf("empty model cluster position label = %q", label)
}
memberModel := model
memberModel.memberRows = []memberRow{}
if label := memberModel.memberPositionLabel(); label != "0" {
t.Fatalf("zero member position label = %q", label)
}
if got := formatRelativeTime(time.Now().Add(-30 * time.Minute).Format(time.RFC3339Nano)); got != "30m ago" {
t.Fatalf("minute age = %q", got)
}
if got := formatRelativeTime(time.Now().Add(-75 * 24 * time.Hour).Format(time.RFC3339Nano)); !strings.Contains(got, "mo ago") {
t.Fatalf("month age = %q", got)
}
if got := formatRelativeTime(""); got != "never" {
t.Fatalf("empty age = %q", got)
}
if got := formatRelativeTime("bad-time"); got != "bad-time" {
t.Fatalf("bad age = %q", got)
}
if got := wrapPlain("", 10); len(got) != 1 || got[0] != "" {
t.Fatalf("empty wrap = %+v", got)
}
if got := clampInt(5, 10, 1); got != 10 {
t.Fatalf("inverted clamp = %d", got)
}
if got := padCells("abcdef", 0); got != "" {
t.Fatalf("zero pad = %q", got)
}
if got := fitBlock("a\nb", 2, 1); got != "a " {
t.Fatalf("fit block = %q", got)
}
}