Update deps and boost test coverage from 70.8% to 90%

Update go-git v6, gopsutil v4.26.1, x/term v0.39.0, and transitive deps.
Refactor main() into testable run() function, add injectable processLister
and termWidthFunc for test isolation, and add tests covering detached HEAD,
dirty/clean worktree, empty repo, process listing errors, and terminal
width fallback.
This commit is contained in:
2026-02-08 22:58:08 +01:00
parent 99ad5b9d7f
commit ed312a3ed0
4 changed files with 333 additions and 37 deletions

View File

@@ -3,9 +3,14 @@ package main
import (
"bufio"
"encoding/json"
"errors"
"os"
"strings"
"testing"
"github.com/go-git/go-git/v6"
"github.com/go-git/go-git/v6/plumbing/object"
"github.com/shirou/gopsutil/v4/process"
)
func TestFormatContextInfo_NilUsage(t *testing.T) {
@@ -758,6 +763,277 @@ func TestStatuslineWidthOffset_Constant(t *testing.T) {
}
}
// --- Coverage gap tests ---
func TestRun_ValidInput(t *testing.T) {
jsonStr := `{"model":{"display_name":"Test"},"workspace":{"current_dir":"/tmp"},"context_window":{"context_window_size":100000}}`
r := bufio.NewReader(strings.NewReader(jsonStr))
var out strings.Builder
err := run(r, &out)
if err != nil {
t.Fatalf("run() returned error: %v", err)
}
result := out.String()
if result == "" {
t.Error("run() produced empty output")
}
if !contains(result, "Test") {
t.Errorf("run() output missing model name: %q", result)
}
}
func TestRun_InvalidJSON(t *testing.T) {
r := bufio.NewReader(strings.NewReader("not json"))
var out strings.Builder
err := run(r, &out)
if err == nil {
t.Error("run() should return error on invalid JSON")
}
}
func TestRun_EmptyInput(t *testing.T) {
r := bufio.NewReader(strings.NewReader(""))
var out strings.Builder
err := run(r, &out)
if err == nil {
t.Error("run() should return error on empty input")
}
}
func TestGetGitInfo_DetachedHEAD(t *testing.T) {
// Create a temp git repo and detach HEAD
dir := t.TempDir()
// Initialize repo, create a commit, then detach
repo, err := git.PlainInit(dir, false)
if err != nil {
t.Fatalf("git init: %v", err)
}
wt, err := repo.Worktree()
if err != nil {
t.Fatalf("worktree: %v", err)
}
// Create a file and commit
if err := os.WriteFile(dir+"/file.txt", []byte("hello"), 0o644); err != nil {
t.Fatalf("write: %v", err)
}
wt.Add("file.txt")
hash, err := wt.Commit("initial", &git.CommitOptions{
Author: &object.Signature{
Name: "test",
Email: "test@test.com",
},
})
if err != nil {
t.Fatalf("commit: %v", err)
}
// Detach HEAD by checking out the commit hash
err = wt.Checkout(&git.CheckoutOptions{
Hash: hash,
})
if err != nil {
t.Fatalf("checkout: %v", err)
}
result := getGitInfo(dir)
shortHash := hash.String()[:7]
expected := " git:(" + shortHash + ")"
if result != expected {
t.Errorf("getGitInfo(detached) = %q, want %q", result, expected)
}
}
func TestGetGitInfo_DirtyWorktree(t *testing.T) {
dir := t.TempDir()
repo, err := git.PlainInit(dir, false)
if err != nil {
t.Fatalf("git init: %v", err)
}
wt, err := repo.Worktree()
if err != nil {
t.Fatalf("worktree: %v", err)
}
// Create a file, commit, then modify it
if err := os.WriteFile(dir+"/file.txt", []byte("hello"), 0o644); err != nil {
t.Fatalf("write: %v", err)
}
wt.Add("file.txt")
_, err = wt.Commit("initial", &git.CommitOptions{
Author: &object.Signature{
Name: "test",
Email: "test@test.com",
},
})
if err != nil {
t.Fatalf("commit: %v", err)
}
// Make the working tree dirty
if err := os.WriteFile(dir+"/file.txt", []byte("modified"), 0o644); err != nil {
t.Fatalf("write: %v", err)
}
result := getGitInfo(dir)
if !contains(result, "✗") {
t.Errorf("getGitInfo(dirty) = %q, expected dirty marker ✗", result)
}
if !contains(result, "git:(master)") {
t.Errorf("getGitInfo(dirty) = %q, expected branch name", result)
}
}
func TestGetGitInfo_CleanWorktree(t *testing.T) {
dir := t.TempDir()
repo, err := git.PlainInit(dir, false)
if err != nil {
t.Fatalf("git init: %v", err)
}
wt, err := repo.Worktree()
if err != nil {
t.Fatalf("worktree: %v", err)
}
if err := os.WriteFile(dir+"/file.txt", []byte("hello"), 0o644); err != nil {
t.Fatalf("write: %v", err)
}
wt.Add("file.txt")
_, err = wt.Commit("initial", &git.CommitOptions{
Author: &object.Signature{
Name: "test",
Email: "test@test.com",
},
})
if err != nil {
t.Fatalf("commit: %v", err)
}
result := getGitInfo(dir)
expected := " git:(master)"
if result != expected {
t.Errorf("getGitInfo(clean) = %q, want %q", result, expected)
}
}
func TestGetGitInfo_EmptyRepo(t *testing.T) {
// A repo with no commits — HEAD doesn't exist
dir := t.TempDir()
_, err := git.PlainInit(dir, false)
if err != nil {
t.Fatalf("git init: %v", err)
}
result := getGitInfo(dir)
// HEAD doesn't exist yet, so repo.Head() returns error
if result != "" {
t.Errorf("getGitInfo(empty repo) = %q, want empty", result)
}
}
func TestGetGitInfo_UntrackedFile(t *testing.T) {
dir := t.TempDir()
repo, err := git.PlainInit(dir, false)
if err != nil {
t.Fatalf("git init: %v", err)
}
wt, err := repo.Worktree()
if err != nil {
t.Fatalf("worktree: %v", err)
}
if err := os.WriteFile(dir+"/tracked.txt", []byte("tracked"), 0o644); err != nil {
t.Fatalf("write: %v", err)
}
wt.Add("tracked.txt")
_, err = wt.Commit("initial", &git.CommitOptions{
Author: &object.Signature{
Name: "test",
Email: "test@test.com",
},
})
if err != nil {
t.Fatalf("commit: %v", err)
}
// Add an untracked file — this makes the tree dirty
if err := os.WriteFile(dir+"/untracked.txt", []byte("new"), 0o644); err != nil {
t.Fatalf("write: %v", err)
}
result := getGitInfo(dir)
if !contains(result, "✗") {
t.Errorf("getGitInfo(untracked) = %q, expected dirty marker", result)
}
}
func TestGetGiteaStatus_ProcessListError(t *testing.T) {
// Save and restore original
orig := processLister
t.Cleanup(func() { processLister = orig })
processLister = func() ([]*process.Process, error) {
return nil, errors.New("mock error")
}
result := getGiteaStatus()
expected := red + "●" + reset
if result != expected {
t.Errorf("getGiteaStatus(error) = %q, want red dot", result)
}
}
func TestGetGiteaStatus_NoGiteaProcess(t *testing.T) {
orig := processLister
t.Cleanup(func() { processLister = orig })
processLister = func() ([]*process.Process, error) {
return []*process.Process{}, nil
}
result := getGiteaStatus()
expected := red + "●" + reset
if result != expected {
t.Errorf("getGiteaStatus(no gitea) = %q, want red dot", result)
}
}
func TestGetTerminalWidth_Success(t *testing.T) {
orig := termWidthFunc
t.Cleanup(func() { termWidthFunc = orig })
termWidthFunc = func() (int, error) {
return 120, nil
}
width := getTerminalWidth()
if width != 120 {
t.Errorf("getTerminalWidth() = %d, want 120", width)
}
}
func TestGetTerminalWidth_Error(t *testing.T) {
orig := termWidthFunc
t.Cleanup(func() { termWidthFunc = orig })
termWidthFunc = func() (int, error) {
return 0, errors.New("not a terminal")
}
width := getTerminalWidth()
if width != 80 {
t.Errorf("getTerminalWidth(error) = %d, want 80", width)
}
}
// Benchmark tests
func BenchmarkFormatContextInfo(b *testing.B) {