package main import ( "strings" "testing" "time" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/x/ansi" ) func TestBranchSuggestionsPreferLikelyAndFreshBranches(t *testing.T) { now := time.Date(2026, 7, 28, 12, 0, 0, 0, time.UTC) branches := []RepositoryBranch{ {Name: "old-feature", UpdatedAt: now.AddDate(-2, 0, 0)}, {Name: "recent-feature", UpdatedAt: now.Add(-time.Hour)}, {Name: "main", UpdatedAt: now.AddDate(0, -6, 0), IsDefault: true}, } suggestions := rankBranchSuggestions(branches, "", "main", now) if len(suggestions) != 3 || suggestions[0].branch.Name != "main" || suggestions[1].branch.Name != "recent-feature" { t.Fatalf("unexpected ranking: %#v", suggestions) } } func TestBranchSuggestionsReactToFuzzyInput(t *testing.T) { now := time.Date(2026, 7, 28, 12, 0, 0, 0, time.UTC) branches := []RepositoryBranch{ {Name: "feature/relation", UpdatedAt: now}, {Name: "release/2.0", UpdatedAt: now.AddDate(-1, 0, 0)}, {Name: "main", UpdatedAt: now, IsDefault: true}, } suggestions := rankBranchSuggestions(branches, "rel", "main", now) if len(suggestions) != 2 || suggestions[0].branch.Name != "release/2.0" { t.Fatalf("prefix match was not preferred: %#v", suggestions) } suggestions = rankBranchSuggestions(branches, "frel", "main", now) if len(suggestions) != 1 || suggestions[0].branch.Name != "feature/relation" { t.Fatalf("fuzzy match failed: %#v", suggestions) } } func TestTargetBranchCompletionIsKeyboardFirst(t *testing.T) { service := &recordingPRService{branches: []RepositoryBranch{ {Name: "main", IsDefault: true}, {Name: "release/2.0"}, {Name: "release/1.0"}, }} m := NewApp(service, "o", "r", false, 50, time.Second) m.screen, m.loading, m.width, m.height = dashboardScreen, false, 80, 30 m.details = PRDetails{ PullRequest: PullRequest{ ID: "pr", Owner: "o", Repository: "r", RepoWithOwner: "o/r", Number: 1, Title: "Title", }, BaseRef: "main", Permissions: ViewerPermissions{CanUpdatePR: true}, } if command := m.startPREdit(); command == nil { t.Fatal("opening the editor did not request branches") } updated, _ := m.Update(m.loadPREditBranches()()) m = updated.(App) m.prEditField = prEditBaseField m.prEditEditors[prEditBaseField] = newTextEditor("release", false) updated, _ = m.updatePREditInput(tea.KeyMsg{Type: tea.KeyCtrlN}) m = updated.(App) updated, _ = m.updatePREditInput(tea.KeyMsg{Type: tea.KeyTab}) m = updated.(App) if got := m.prEditEditors[prEditBaseField].Text; got != "release/2.0" && got != "release/1.0" { t.Fatalf("tab did not complete selected branch: %q", got) } if m.prEditField != prEditBaseField { t.Fatalf("completion moved away from target branch: field=%d", m.prEditField) } updated, _ = m.updatePREditInput(tea.KeyMsg{Type: tea.KeyTab}) m = updated.(App) if m.prEditField != prEditReviewersField { t.Fatalf("second tab did not advance: field=%d", m.prEditField) } } func TestTargetBranchSuggestionsRenderAndValidationRejectsUnknownBranch(t *testing.T) { m := NewApp(&recordingPRService{}, "o", "r", false, 50, time.Second) m.width = 80 m.prEditField = prEditBaseField m.prEditOriginal = PullRequestMetadata{BaseRef: "main"} m.prEditEditors[prEditTitleField] = newTextEditor("Title", false) m.prEditEditors[prEditBaseField] = newTextEditor("rel", false) m.prEditEditors[prEditBodyField] = newTextEditor("", true) m.prEditBranches = []RepositoryBranch{{Name: "main"}, {Name: "release/2.0"}} view := ansi.Strip(strings.Join(m.prEditFieldLines("target branch", prEditBaseField, 80), "\n")) if !strings.Contains(view, "release/2.0") || !strings.Contains(view, "tab / enter complete") { t.Fatalf("branch suggestions missing:\n%s", view) } if err := m.validatePREdit(); err == nil || !strings.Contains(err.Error(), "not an available") { t.Fatalf("unknown branch validation error = %v", err) } }