From 4e1efac69bfca996e27bd0725a2bed6f489e7f7c Mon Sep 17 00:00:00 2001 From: eunwoo song Date: Sun, 6 Sep 2026 14:51:19 +0900 Subject: [PATCH 1/2] test(tui): cover repository table header --- .../repostableheader/reposTableHeader_test.go | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 internal/render/tui/repostableheader/reposTableHeader_test.go diff --git a/internal/render/tui/repostableheader/reposTableHeader_test.go b/internal/render/tui/repostableheader/reposTableHeader_test.go new file mode 100644 index 0000000..52bc10d --- /dev/null +++ b/internal/render/tui/repostableheader/reposTableHeader_test.go @@ -0,0 +1,49 @@ +package repostableheader + +import ( + "strings" + "testing" + + "github.com/mabd-dev/reposcan/pkg/report" +) + +func TestHeaderSetReportCountsRepositoriesAndDirtyStates(t *testing.T) { + reportWithStash := report.ScanReport{RepoStates: []report.RepoState{ + {UncommitedFiles: []string{"changed.txt"}}, + {Stashes: []string{"stash@{0}"}}, + {}, + }} + + for _, tc := range []struct { + name string + countStashAsDirty bool + wantDirty int + }{ + {name: "ignore stashes", countStashAsDirty: false, wantDirty: 1}, + {name: "count stashes", countStashAsDirty: true, wantDirty: 2}, + } { + t.Run(tc.name, func(t *testing.T) { + header := Header{} + header.SetReport(reportWithStash, tc.countStashAsDirty) + + if header.repoStatesCount != 3 { + t.Fatalf("repoStatesCount = %d, want 3", header.repoStatesCount) + } + if header.dirtyRepos != tc.wantDirty { + t.Fatalf("dirtyRepos = %d, want %d", header.dirtyRepos, tc.wantDirty) + } + }) + } +} + +func TestHeaderViewIncludesApplicationNameAndRepositoryCount(t *testing.T) { + header := Header{} + header.SetReport(report.ScanReport{RepoStates: make([]report.RepoState, 2)}, false) + + view := header.View() + for _, want := range []string{"reposcan", "• 2 repos"} { + if !strings.Contains(view, want) { + t.Fatalf("View() = %q, want it to contain %q", view, want) + } + } +} From 73dcbad75cd19be4adadf96875a952dec2fb3e1c Mon Sep 17 00:00:00 2001 From: eunwoo song Date: Mon, 7 Sep 2026 11:53:28 +0900 Subject: [PATCH 2/2] fix(tui): render repository summary header --- internal/render/tui/view.go | 6 +++-- internal/render/tui/view_test.go | 38 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 internal/render/tui/view_test.go diff --git a/internal/render/tui/view.go b/internal/render/tui/view.go index 202318c..ebebaec 100644 --- a/internal/render/tui/view.go +++ b/internal/render/tui/view.go @@ -18,10 +18,12 @@ func (m Model) View() tea.View { } footer := m.getFooterView() + header := m.rtHeader.View() // Calculate heights footerHeight := lipgloss.Height(footer) - bodyHeight := m.height - footerHeight + headerHeight := lipgloss.Height(header) + bodyHeight := m.height - headerHeight - footerHeight reposTableHeight := bodyHeight * sizeReposTableHeightPercent / 100 m.reposTable = m.reposTable.UpdateWindowSize(m.width, reposTableHeight) @@ -37,7 +39,7 @@ func (m Model) View() tea.View { MaxHeight(bodyHeight). Render(body) - view := lipgloss.JoinVertical(lipgloss.Left, body, footer) + view := lipgloss.JoinVertical(lipgloss.Left, header, body, footer) view = lipgloss.NewStyle(). Width(m.width). diff --git a/internal/render/tui/view_test.go b/internal/render/tui/view_test.go new file mode 100644 index 0000000..022b717 --- /dev/null +++ b/internal/render/tui/view_test.go @@ -0,0 +1,38 @@ +package tui + +import ( + "strings" + "testing" + + "charm.land/lipgloss/v2" + "github.com/mabd-dev/reposcan/internal/render/tui/repodetails" + "github.com/mabd-dev/reposcan/internal/render/tui/repostable" + rth "github.com/mabd-dev/reposcan/internal/render/tui/repostableheader" + "github.com/mabd-dev/reposcan/internal/theme" + "github.com/mabd-dev/reposcan/pkg/report" +) + +func TestViewIncludesRepositoryHeader(t *testing.T) { + colors := theme.ColorScheme{Foreground: lipgloss.Color("#ffffff"), Muted: lipgloss.Color("#888888")} + theme := theme.Theme{Colors: colors, Styles: theme.Styles{Base: lipgloss.NewStyle(), Muted: lipgloss.NewStyle()}} + report := report.ScanReport{RepoStates: []report.RepoState{{Repo: "alpha", Branch: "main", ID: "alpha"}}} + header := rth.Header{Theme: theme} + header.SetReport(report, false) + + m := Model{ + width: 80, + height: 24, + theme: theme, + rtHeader: header, + reposTable: repostable.New(theme, report, 80, 12, repostable.Options{}), + repoDetails: repodetails.New(&report.RepoStates[0], theme), + focusStack: []FocusState{FocusReposTable}, + } + + view := m.View().Content + for _, want := range []string{"reposcan", "1 repos"} { + if !strings.Contains(view, want) { + t.Fatalf("production view missing %q:\n%s", want, view) + } + } +}