11
This commit is contained in:
commit
e6f1776d4f
264 files changed
+54215
No files matched your search
@@ -0,0 +1,264 @@
|
||||
package tui
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"superwork-tui/internal/cc"
|
||||
"superwork-tui/internal/config"
|
||||
"superwork-tui/internal/issue"
|
||||
"superwork-tui/internal/store"
|
||||
)
|
||||
|
||||
// ── profile picker tests ──────────────────────────────────────────────────────
|
||||
|
||||
func TestProfilePicker_NoProfilesDir_ShowsStatus(t *testing.T) {
|
||||
m := New()
|
||||
m.settings = &config.Settings{ProfilesDir: ""}
|
||||
m.state = stateDetail
|
||||
iss := issue.Issue{Number: 42}
|
||||
m.detailIss = &iss
|
||||
|
||||
m2, _ := m.openProfilePicker(false)
|
||||
if m2.state != stateDetail {
|
||||
t.Errorf("state should stay stateDetail when no ProfilesDir, got %v", m2.state)
|
||||
}
|
||||
if !strings.Contains(m2.statusMsg, "profiles") {
|
||||
t.Errorf("statusMsg should mention profiles, got %q", m2.statusMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfilePicker_EscReturnsToDetail(t *testing.T) {
|
||||
m := New()
|
||||
m.settings = &config.Settings{ProfilesDir: t.TempDir()}
|
||||
m.profilePickerPrevState = stateDetail
|
||||
m.state = stateProfilePicker
|
||||
m.profilePickerProfiles = []cc.ClaudeProfile{{Name: "dev", Path: "/p/dev.json"}}
|
||||
|
||||
result, _ := m.handleProfilePickerKey(keyMsg("esc"))
|
||||
m2 := result.(Model)
|
||||
if m2.state != stateDetail {
|
||||
t.Errorf("expected stateDetail after esc, got %v", m2.state)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfilePicker_SelectSetsProfilePath(t *testing.T) {
|
||||
m := New()
|
||||
m.settings = &config.Settings{ProfilesDir: t.TempDir()}
|
||||
m.state = stateProfilePicker
|
||||
m.profilePickerPrevState = stateDetail
|
||||
m.profilePickerForTest = false
|
||||
m.profilePickerProfiles = []cc.ClaudeProfile{
|
||||
{Name: "dev", Path: "/profiles/dev.json"},
|
||||
{Name: "prod", Path: "/profiles/prod.json"},
|
||||
}
|
||||
m.profilePickerCursor = 1
|
||||
iss := issue.Issue{Number: 7}
|
||||
m.detailIss = &iss
|
||||
|
||||
result, _ := m.handleProfilePickerKey(keyMsg("enter"))
|
||||
m2 := result.(Model)
|
||||
|
||||
if m2.state != stateDetail {
|
||||
t.Errorf("expected stateDetail after selection, got %v", m2.state)
|
||||
}
|
||||
if m2.detailIss.ProfilePath != "/profiles/prod.json" {
|
||||
t.Errorf("ProfilePath = %q, want /profiles/prod.json", m2.detailIss.ProfilePath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfilePicker_SelectSetsTestProfilePath(t *testing.T) {
|
||||
m := New()
|
||||
m.settings = &config.Settings{ProfilesDir: t.TempDir()}
|
||||
m.state = stateProfilePicker
|
||||
m.profilePickerPrevState = stateDetail
|
||||
m.profilePickerForTest = true
|
||||
m.profilePickerProfiles = []cc.ClaudeProfile{
|
||||
{Name: "test", Path: "/profiles/test.json"},
|
||||
}
|
||||
m.profilePickerCursor = 0
|
||||
iss := issue.Issue{Number: 7}
|
||||
m.detailIss = &iss
|
||||
|
||||
result, _ := m.handleProfilePickerKey(keyMsg("enter"))
|
||||
m2 := result.(Model)
|
||||
|
||||
if m2.detailIss.TestProfilePath != "/profiles/test.json" {
|
||||
t.Errorf("TestProfilePath = %q, want /profiles/test.json", m2.detailIss.TestProfilePath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfilePicker_CursorNavigation(t *testing.T) {
|
||||
m := New()
|
||||
m.state = stateProfilePicker
|
||||
m.profilePickerProfiles = []cc.ClaudeProfile{
|
||||
{Name: "a", Path: "/a.json"},
|
||||
{Name: "b", Path: "/b.json"},
|
||||
{Name: "c", Path: "/c.json"},
|
||||
}
|
||||
m.profilePickerCursor = 0
|
||||
|
||||
result, _ := m.handleProfilePickerKey(keyMsg("j"))
|
||||
m2 := result.(Model)
|
||||
if m2.profilePickerCursor != 1 {
|
||||
t.Errorf("cursor after j = %d, want 1", m2.profilePickerCursor)
|
||||
}
|
||||
|
||||
result2, _ := m2.handleProfilePickerKey(keyMsg("k"))
|
||||
m3 := result2.(Model)
|
||||
if m3.profilePickerCursor != 0 {
|
||||
t.Errorf("cursor after k = %d, want 0", m3.profilePickerCursor)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfilePickerView_ContainsProfiles(t *testing.T) {
|
||||
m := New()
|
||||
m.state = stateProfilePicker
|
||||
m.profilePickerProfiles = []cc.ClaudeProfile{
|
||||
{Name: "dev", Path: "/profiles/dev.json"},
|
||||
{Name: "prod", Path: "/profiles/prod.json"},
|
||||
}
|
||||
m.profilePickerCursor = 0
|
||||
|
||||
out := m.profilePickerView()
|
||||
for _, want := range []string{"dev", "prod", "/profiles/dev.json"} {
|
||||
if !strings.Contains(out, want) {
|
||||
t.Errorf("profilePickerView missing %q", want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── profile grid tests ────────────────────────────────────────────────────────
|
||||
|
||||
func TestProfileGrid_OpenLoadsData(t *testing.T) {
|
||||
m := New()
|
||||
m2, cmd := m.openProfileGrid()
|
||||
if m2.state != stateProfileGrid {
|
||||
t.Errorf("state = %v, want stateProfileGrid", m2.state)
|
||||
}
|
||||
if cmd == nil {
|
||||
t.Error("openProfileGrid should return a load cmd")
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfileGrid_EscReturnsToBoard(t *testing.T) {
|
||||
m := New()
|
||||
m.state = stateProfileGrid
|
||||
m.profileGridData = store.ProfilesData{Profiles: []string{"dev"}, Rows: nil}
|
||||
|
||||
result, _ := m.handleProfileGridKey(keyMsg("esc"))
|
||||
m2 := result.(Model)
|
||||
if m2.state != stateLoaded {
|
||||
t.Errorf("expected stateLoaded after esc, got %v", m2.state)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfileGrid_EditCellAndSave(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
restore := overrideWorkspaceRoot(tmpDir)
|
||||
defer restore()
|
||||
|
||||
m := New()
|
||||
m.state = stateProfileGrid
|
||||
m.profileGridData = store.ProfilesData{
|
||||
Profiles: []string{"dev", "prod"},
|
||||
Rows: []store.ProfileRow{
|
||||
{Key: "model", Values: map[string]string{"dev": "opus", "prod": "sonnet"}},
|
||||
},
|
||||
}
|
||||
m.profileGridRow = 0
|
||||
m.profileGridCol = 1 // "dev" column
|
||||
|
||||
// Enter edit mode
|
||||
result, _ := m.handleProfileGridKey(keyMsg("enter"))
|
||||
m2 := result.(Model)
|
||||
if !m2.profileGridEditing {
|
||||
t.Fatal("expected editing mode after enter on value cell")
|
||||
}
|
||||
|
||||
// Type a new value
|
||||
m2.profileGridEdit.SetValue("haiku")
|
||||
|
||||
// Commit
|
||||
result2, _ := m2.handleProfileGridKey(keyMsg("enter"))
|
||||
m3 := result2.(Model)
|
||||
if m3.profileGridEditing {
|
||||
t.Error("editing should be false after commit")
|
||||
}
|
||||
if m3.profileGridData.Rows[0].Values["dev"] != "haiku" {
|
||||
t.Errorf("dev value = %q, want haiku", m3.profileGridData.Rows[0].Values["dev"])
|
||||
}
|
||||
|
||||
// Save
|
||||
_, saveCmd := m3.handleProfileGridKey(keyMsg("ctrl+s"))
|
||||
if saveCmd == nil {
|
||||
t.Fatal("ctrl+s should return a save cmd")
|
||||
}
|
||||
msg := saveCmd()
|
||||
saved, ok := msg.(profileGridSavedMsg)
|
||||
if !ok {
|
||||
t.Fatalf("expected profileGridSavedMsg, got %T", msg)
|
||||
}
|
||||
if saved.err != nil {
|
||||
t.Errorf("save error: %v", saved.err)
|
||||
}
|
||||
|
||||
// Verify persisted
|
||||
loaded, err := store.ReadProfiles(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if loaded.Rows[0].Values["dev"] != "haiku" {
|
||||
t.Errorf("persisted dev = %q, want haiku", loaded.Rows[0].Values["dev"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfileGrid_AddRow(t *testing.T) {
|
||||
m := New()
|
||||
m.state = stateProfileGrid
|
||||
m.profileGridData = store.ProfilesData{
|
||||
Profiles: []string{"dev"},
|
||||
Rows: []store.ProfileRow{},
|
||||
}
|
||||
|
||||
// Press 'a' to add row
|
||||
result, _ := m.handleProfileGridKey(keyMsg("a"))
|
||||
m2 := result.(Model)
|
||||
if !m2.profileGridAddingKey {
|
||||
t.Error("expected profileGridAddingKey = true after pressing a")
|
||||
}
|
||||
|
||||
// Type key name
|
||||
m2.profileGridNewKey.SetValue("timeout")
|
||||
|
||||
// Confirm
|
||||
result2, _ := m2.handleProfileGridKey(keyMsg("enter"))
|
||||
m3 := result2.(Model)
|
||||
if m3.profileGridAddingKey {
|
||||
t.Error("profileGridAddingKey should be false after confirm")
|
||||
}
|
||||
if len(m3.profileGridData.Rows) != 1 {
|
||||
t.Errorf("rows = %d, want 1", len(m3.profileGridData.Rows))
|
||||
}
|
||||
if m3.profileGridData.Rows[0].Key != "timeout" {
|
||||
t.Errorf("row key = %q, want timeout", m3.profileGridData.Rows[0].Key)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfileGridView_ContainsData(t *testing.T) {
|
||||
m := New()
|
||||
m.state = stateProfileGrid
|
||||
m.profileGridData = store.ProfilesData{
|
||||
Profiles: []string{"dev", "prod"},
|
||||
Rows: []store.ProfileRow{
|
||||
{Key: "model", Values: map[string]string{"dev": "opus", "prod": "sonnet"}},
|
||||
},
|
||||
}
|
||||
|
||||
out := m.profileGridView()
|
||||
for _, want := range []string{"Profile Grid", "dev", "prod", "model", "opus", "sonnet"} {
|
||||
if !strings.Contains(out, want) {
|
||||
t.Errorf("profileGridView missing %q", want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user