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:
276
main_test.go
276
main_test.go
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user