Add unit tests and test tasks
- Add main_test.go with tests for formatContextInfo, stripANSI, StatusInput parsing, getGitInfo, and getGiteaStatus - Add test, test:cover, test:fixture tasks to Taskfile - 45% code coverage
This commit is contained in:
205
main_test.go
Normal file
205
main_test.go
Normal file
@ -0,0 +1,205 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFormatContextInfo_NilUsage(t *testing.T) {
|
||||
result := formatContextInfo(200000, nil)
|
||||
expected := "0/200k"
|
||||
if result != expected {
|
||||
t.Errorf("formatContextInfo(200000, nil) = %q, want %q", result, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatContextInfo_WithUsage(t *testing.T) {
|
||||
usage := &struct {
|
||||
InputTokens int `json:"input_tokens"`
|
||||
CacheCreationTokens int `json:"cache_creation_input_tokens"`
|
||||
CacheReadInputTokens int `json:"cache_read_input_tokens"`
|
||||
}{
|
||||
InputTokens: 8500,
|
||||
CacheCreationTokens: 5000,
|
||||
CacheReadInputTokens: 2000,
|
||||
}
|
||||
result := formatContextInfo(200000, usage)
|
||||
expected := "15k/200k"
|
||||
if result != expected {
|
||||
t.Errorf("formatContextInfo(200000, usage) = %q, want %q", result, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatContextInfo_SmallValues(t *testing.T) {
|
||||
usage := &struct {
|
||||
InputTokens int `json:"input_tokens"`
|
||||
CacheCreationTokens int `json:"cache_creation_input_tokens"`
|
||||
CacheReadInputTokens int `json:"cache_read_input_tokens"`
|
||||
}{
|
||||
InputTokens: 500,
|
||||
CacheCreationTokens: 0,
|
||||
CacheReadInputTokens: 0,
|
||||
}
|
||||
result := formatContextInfo(100000, usage)
|
||||
expected := "0k/100k"
|
||||
if result != expected {
|
||||
t.Errorf("formatContextInfo(100000, usage) = %q, want %q", result, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStripANSI(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "no ansi",
|
||||
input: "hello world",
|
||||
expected: "hello world",
|
||||
},
|
||||
{
|
||||
name: "single color",
|
||||
input: "\033[32mgreen\033[0m",
|
||||
expected: "green",
|
||||
},
|
||||
{
|
||||
name: "multiple colors",
|
||||
input: "\033[31mred\033[0m \033[32mgreen\033[0m",
|
||||
expected: "red green",
|
||||
},
|
||||
{
|
||||
name: "bold",
|
||||
input: "\033[1mbold\033[0m",
|
||||
expected: "bold",
|
||||
},
|
||||
{
|
||||
name: "complex",
|
||||
input: "\033[32m●\033[0m \033[35mOpus\033[0m \033[1;32m➜\033[0m",
|
||||
expected: "● Opus ➜",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := stripANSI(tt.input)
|
||||
if result != tt.expected {
|
||||
t.Errorf("stripANSI(%q) = %q, want %q", tt.input, result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatusInputParsing(t *testing.T) {
|
||||
jsonData := `{
|
||||
"model": {"display_name": "Opus 4.5"},
|
||||
"workspace": {"current_dir": "/root/projects/statusline"},
|
||||
"context_window": {
|
||||
"context_window_size": 200000,
|
||||
"current_usage": {
|
||||
"input_tokens": 5000,
|
||||
"cache_creation_input_tokens": 1000,
|
||||
"cache_read_input_tokens": 500
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
var data StatusInput
|
||||
err := json.Unmarshal([]byte(jsonData), &data)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse JSON: %v", err)
|
||||
}
|
||||
|
||||
if data.Model.DisplayName != "Opus 4.5" {
|
||||
t.Errorf("Model.DisplayName = %q, want %q", data.Model.DisplayName, "Opus 4.5")
|
||||
}
|
||||
|
||||
if data.Workspace.CurrentDir != "/root/projects/statusline" {
|
||||
t.Errorf("Workspace.CurrentDir = %q, want %q", data.Workspace.CurrentDir, "/root/projects/statusline")
|
||||
}
|
||||
|
||||
if data.ContextWindow.ContextWindowSize != 200000 {
|
||||
t.Errorf("ContextWindow.ContextWindowSize = %d, want %d", data.ContextWindow.ContextWindowSize, 200000)
|
||||
}
|
||||
|
||||
if data.ContextWindow.CurrentUsage == nil {
|
||||
t.Fatal("ContextWindow.CurrentUsage is nil")
|
||||
}
|
||||
|
||||
if data.ContextWindow.CurrentUsage.InputTokens != 5000 {
|
||||
t.Errorf("CurrentUsage.InputTokens = %d, want %d", data.ContextWindow.CurrentUsage.InputTokens, 5000)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatusInputParsing_NilUsage(t *testing.T) {
|
||||
jsonData := `{
|
||||
"model": {"display_name": "Sonnet"},
|
||||
"workspace": {"current_dir": "/tmp"},
|
||||
"context_window": {
|
||||
"context_window_size": 100000
|
||||
}
|
||||
}`
|
||||
|
||||
var data StatusInput
|
||||
err := json.Unmarshal([]byte(jsonData), &data)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse JSON: %v", err)
|
||||
}
|
||||
|
||||
if data.ContextWindow.CurrentUsage != nil {
|
||||
t.Errorf("ContextWindow.CurrentUsage should be nil, got %+v", data.ContextWindow.CurrentUsage)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetGitInfo_CurrentRepo(t *testing.T) {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Skipf("Could not get working directory: %v", err)
|
||||
}
|
||||
|
||||
result := getGitInfo(cwd)
|
||||
|
||||
// Should return something like " git:(master)" or " git:(master) ✗"
|
||||
if result == "" {
|
||||
t.Skip("Not in a git repository")
|
||||
}
|
||||
|
||||
if !contains(result, "git:(") {
|
||||
t.Errorf("getGitInfo(%q) = %q, expected to contain 'git:('", cwd, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetGitInfo_NonRepo(t *testing.T) {
|
||||
result := getGitInfo("/tmp")
|
||||
|
||||
// /tmp is unlikely to be a git repo
|
||||
if result != "" && !contains(result, "git:(") {
|
||||
t.Errorf("getGitInfo(/tmp) = %q, expected empty or valid git info", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetGiteaStatus(t *testing.T) {
|
||||
result := getGiteaStatus()
|
||||
|
||||
// Should return either green or red dot
|
||||
greenDot := green + "●" + reset
|
||||
redDot := red + "●" + reset
|
||||
|
||||
if result != greenDot && result != redDot {
|
||||
t.Errorf("getGiteaStatus() = %q, expected green or red dot", result)
|
||||
}
|
||||
}
|
||||
|
||||
func contains(s, substr string) bool {
|
||||
return len(s) >= len(substr) && (s == substr || len(s) > 0 && containsHelper(s, substr))
|
||||
}
|
||||
|
||||
func containsHelper(s, substr string) bool {
|
||||
for i := 0; i <= len(s)-len(substr); i++ {
|
||||
if s[i:i+len(substr)] == substr {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user