mirror of
https://github.com/boolean-maybe/tiki
synced 2026-04-21 13:37:20 +00:00
557 lines
17 KiB
Go
557 lines
17 KiB
Go
package integration
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/boolean-maybe/tiki/model"
|
|
taskpkg "github.com/boolean-maybe/tiki/task"
|
|
"github.com/boolean-maybe/tiki/testutil"
|
|
|
|
"github.com/gdamore/tcell/v2"
|
|
)
|
|
|
|
// setupPluginViewTest creates a test app with plugins loaded and test data
|
|
func setupPluginViewTest(t *testing.T) *testutil.TestApp {
|
|
ta := testutil.NewTestApp(t)
|
|
if err := ta.LoadPlugins(); err != nil {
|
|
t.Fatalf("Failed to load plugins: %v", err)
|
|
}
|
|
|
|
// Create tasks for Backlog plugin (status = backlog)
|
|
tasks := []struct {
|
|
id string
|
|
title string
|
|
status taskpkg.Status
|
|
typ taskpkg.Type
|
|
}{
|
|
{"TIKI-1", "First Backlog Task", taskpkg.StatusBacklog, taskpkg.TypeStory},
|
|
{"TIKI-2", "Second Backlog Task", taskpkg.StatusBacklog, taskpkg.TypeBug},
|
|
{"TIKI-3", "Third Backlog Task", taskpkg.StatusBacklog, taskpkg.TypeStory},
|
|
{"TIKI-4", "Fourth Backlog Task", taskpkg.StatusBacklog, taskpkg.TypeBug},
|
|
{"TIKI-5", "Todo Task (not in backlog)", taskpkg.StatusReady, taskpkg.TypeStory},
|
|
}
|
|
|
|
for _, task := range tasks {
|
|
if err := testutil.CreateTestTask(ta.TaskDir, task.id, task.title, task.status, task.typ); err != nil {
|
|
t.Fatalf("Failed to create task: %v", err)
|
|
}
|
|
}
|
|
|
|
if err := ta.TaskStore.Reload(); err != nil {
|
|
t.Fatalf("Failed to reload tasks: %v", err)
|
|
}
|
|
|
|
return ta
|
|
}
|
|
|
|
// TestPluginView_GridNavigation verifies arrow key navigation in 4-column grid
|
|
func TestPluginView_GridNavigation(t *testing.T) {
|
|
t.Skip("SimulationScreen test framework issue - navigation works correctly in actual app")
|
|
ta := setupPluginViewTest(t)
|
|
defer ta.Cleanup()
|
|
|
|
// Navigate: Board → Backlog Plugin
|
|
ta.NavController.PushView(model.MakePluginViewID("Kanban"), nil)
|
|
ta.Draw()
|
|
ta.SendKey(tcell.KeyF3, 0, tcell.ModNone) // F3 = Backlog plugin
|
|
ta.Draw() // Redraw after view change
|
|
|
|
// Verify we're on plugin view
|
|
currentView := ta.NavController.CurrentView()
|
|
if !model.IsPluginViewID(currentView.ViewID) {
|
|
t.Fatalf("expected plugin view, got %v", currentView.ViewID)
|
|
}
|
|
|
|
// Get plugin config
|
|
pluginConfig := ta.GetPluginConfig("Backlog")
|
|
if pluginConfig == nil {
|
|
t.Fatalf("Backlog plugin config not found")
|
|
}
|
|
|
|
// Initial selection should be 0
|
|
if pluginConfig.GetSelectedIndex() != 0 {
|
|
t.Errorf("initial selection = %d, want 0", pluginConfig.GetSelectedIndex())
|
|
}
|
|
|
|
// With 5 tasks in 4-column grid:
|
|
// [0, 1, 2, 3]
|
|
// [4]
|
|
// Only index 0 can move down to index 4
|
|
|
|
// Press Right arrow (move to next column in same row)
|
|
ta.SendKey(tcell.KeyRight, 0, tcell.ModNone)
|
|
|
|
// Selection should move to index 1 (same row, next column)
|
|
if pluginConfig.GetSelectedIndex() != 1 {
|
|
t.Errorf("after Right, selection = %d, want 1", pluginConfig.GetSelectedIndex())
|
|
}
|
|
|
|
// Press Down arrow - should NOT move (no task in column 1 of row 2)
|
|
ta.SendKey(tcell.KeyDown, 0, tcell.ModNone)
|
|
|
|
// Selection should stay at index 1 (can't move down to non-existent index 5)
|
|
if pluginConfig.GetSelectedIndex() != 1 {
|
|
t.Errorf("after Down from index 1, selection = %d, want 1 (no task below)", pluginConfig.GetSelectedIndex())
|
|
}
|
|
|
|
// Go back to index 0
|
|
ta.SendKey(tcell.KeyLeft, 0, tcell.ModNone)
|
|
if pluginConfig.GetSelectedIndex() != 0 {
|
|
t.Errorf("after Left, selection = %d, want 0", pluginConfig.GetSelectedIndex())
|
|
}
|
|
|
|
// Press Down arrow from index 0 - should move to index 4
|
|
ta.SendKey(tcell.KeyDown, 0, tcell.ModNone)
|
|
|
|
// Selection should move to index 4 (only valid down move)
|
|
if pluginConfig.GetSelectedIndex() != 4 {
|
|
t.Errorf("after Down from index 0, selection = %d, want 4", pluginConfig.GetSelectedIndex())
|
|
}
|
|
|
|
// Press Up arrow - should move back to index 0
|
|
ta.SendKey(tcell.KeyUp, 0, tcell.ModNone)
|
|
|
|
// Selection should move back to index 0
|
|
if pluginConfig.GetSelectedIndex() != 0 {
|
|
t.Errorf("after Up, selection = %d, want 0", pluginConfig.GetSelectedIndex())
|
|
}
|
|
}
|
|
|
|
// TestPluginView_FilterByStatus verifies plugin filters tasks by status
|
|
func TestPluginView_FilterByStatus(t *testing.T) {
|
|
ta := setupPluginViewTest(t)
|
|
defer ta.Cleanup()
|
|
|
|
// Navigate: Board → Backlog Plugin
|
|
ta.NavController.PushView(model.MakePluginViewID("Kanban"), nil)
|
|
ta.Draw()
|
|
ta.SendKey(tcell.KeyF3, 0, tcell.ModNone) // F3 = Backlog plugin
|
|
|
|
// Verify backlog tasks are visible
|
|
found1, _, _ := ta.FindText("TIKI-1")
|
|
found2, _, _ := ta.FindText("TIKI-2")
|
|
if !found1 || !found2 {
|
|
ta.DumpScreen()
|
|
t.Errorf("backlog tasks should be visible in backlog plugin")
|
|
}
|
|
|
|
// Verify non-backlog task is NOT visible
|
|
found5, _, _ := ta.FindText("TIKI-5")
|
|
if found5 {
|
|
ta.DumpScreen()
|
|
t.Errorf("todo task TIKI-5 should NOT be visible in backlog plugin")
|
|
}
|
|
}
|
|
|
|
// TestPluginView_OpenTask verifies Enter opens task detail from plugin
|
|
func TestPluginView_OpenTask(t *testing.T) {
|
|
ta := setupPluginViewTest(t)
|
|
defer ta.Cleanup()
|
|
|
|
// Navigate: Board → Backlog Plugin
|
|
ta.NavController.PushView(model.MakePluginViewID("Kanban"), nil)
|
|
ta.Draw()
|
|
ta.SendKey(tcell.KeyF3, 0, tcell.ModNone) // F3 = Backlog plugin
|
|
|
|
// Press Enter to open first task
|
|
ta.SendKey(tcell.KeyEnter, 0, tcell.ModNone)
|
|
|
|
// Verify we're on task detail view
|
|
currentView := ta.NavController.CurrentView()
|
|
if currentView.ViewID != model.TaskDetailViewID {
|
|
t.Errorf("expected task detail view, got %v", currentView.ViewID)
|
|
}
|
|
|
|
// Verify correct task is displayed
|
|
found, _, _ := ta.FindText("TIKI-1")
|
|
if !found {
|
|
ta.DumpScreen()
|
|
t.Errorf("TIKI-1 should be displayed in task detail")
|
|
}
|
|
}
|
|
|
|
// TestPluginView_CreateTask verifies 'n' creates new task
|
|
func TestPluginView_CreateTask(t *testing.T) {
|
|
ta := setupPluginViewTest(t)
|
|
defer ta.Cleanup()
|
|
|
|
// Navigate: Board → Backlog Plugin
|
|
ta.NavController.PushView(model.MakePluginViewID("Kanban"), nil)
|
|
ta.Draw()
|
|
ta.SendKey(tcell.KeyF3, 0, tcell.ModNone)
|
|
|
|
// Press 'n' to create new task
|
|
ta.SendKey(tcell.KeyRune, 'n', tcell.ModNone)
|
|
|
|
// Verify we're on task edit view
|
|
currentView := ta.NavController.CurrentView()
|
|
if currentView.ViewID != model.TaskEditViewID {
|
|
t.Errorf("expected task edit view, got %v", currentView.ViewID)
|
|
}
|
|
|
|
// Type title and save
|
|
ta.SendText("New Plugin Task")
|
|
ta.SendKey(tcell.KeyCtrlS, 0, tcell.ModNone)
|
|
|
|
// Reload and verify task exists
|
|
if err := ta.TaskStore.Reload(); err != nil {
|
|
t.Fatalf("failed to reload: %v", err)
|
|
}
|
|
|
|
allTasks := ta.TaskStore.GetAllTasks()
|
|
var found bool
|
|
for _, task := range allTasks {
|
|
if task.Title == "New Plugin Task" {
|
|
found = true
|
|
// Task created from backlog plugin should have backlog status
|
|
if task.Status != taskpkg.StatusBacklog {
|
|
t.Errorf("new task status = %v, want %v", task.Status, taskpkg.StatusBacklog)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Errorf("new task not found in store")
|
|
}
|
|
}
|
|
|
|
// TestPluginView_DeleteTask verifies 'd' deletes selected task
|
|
func TestPluginView_DeleteTask(t *testing.T) {
|
|
ta := setupPluginViewTest(t)
|
|
defer ta.Cleanup()
|
|
|
|
// Navigate: Board → Backlog Plugin
|
|
ta.NavController.PushView(model.MakePluginViewID("Kanban"), nil)
|
|
ta.Draw()
|
|
ta.SendKey(tcell.KeyF3, 0, tcell.ModNone)
|
|
|
|
// Verify TIKI-1 is visible
|
|
found, _, _ := ta.FindText("TIKI-1")
|
|
if !found {
|
|
ta.DumpScreen()
|
|
t.Fatalf("TIKI-1 should be visible before delete")
|
|
}
|
|
|
|
// Press 'd' to delete first task (TIKI-1)
|
|
ta.SendKey(tcell.KeyRune, 'd', tcell.ModNone)
|
|
|
|
// Reload and verify task is deleted
|
|
if err := ta.TaskStore.Reload(); err != nil {
|
|
t.Fatalf("failed to reload: %v", err)
|
|
}
|
|
|
|
task := ta.TaskStore.GetTask("TIKI-1")
|
|
if task != nil {
|
|
t.Errorf("TIKI-1 should be deleted from store")
|
|
}
|
|
|
|
// Verify file is removed
|
|
taskPath := filepath.Join(ta.TaskDir, "tiki-1.md")
|
|
if _, err := os.Stat(taskPath); !os.IsNotExist(err) {
|
|
t.Errorf("TIKI-1 file should be deleted")
|
|
}
|
|
}
|
|
|
|
// TestPluginView_Search verifies '/' opens search in plugin
|
|
func TestPluginView_Search(t *testing.T) {
|
|
ta := setupPluginViewTest(t)
|
|
defer ta.Cleanup()
|
|
|
|
// Navigate: Board → Backlog Plugin
|
|
ta.NavController.PushView(model.MakePluginViewID("Kanban"), nil)
|
|
ta.Draw()
|
|
ta.SendKey(tcell.KeyF3, 0, tcell.ModNone)
|
|
|
|
// Verify multiple tasks visible initially
|
|
found1, _, _ := ta.FindText("TIKI-1")
|
|
found2, _, _ := ta.FindText("TIKI-2")
|
|
if !found1 || !found2 {
|
|
ta.DumpScreen()
|
|
t.Fatalf("both tasks should be visible initially")
|
|
}
|
|
|
|
// Press '/' to open search
|
|
ta.SendKey(tcell.KeyRune, '/', tcell.ModNone)
|
|
|
|
// Verify search box is visible
|
|
foundPrompt, _, _ := ta.FindText(">")
|
|
if !foundPrompt {
|
|
ta.DumpScreen()
|
|
t.Errorf("search box prompt should be visible")
|
|
}
|
|
|
|
// Type search query
|
|
ta.SendText("First")
|
|
ta.SendKey(tcell.KeyEnter, 0, tcell.ModNone)
|
|
|
|
// Verify only TIKI-1 is visible
|
|
found1After, _, _ := ta.FindText("TIKI-1")
|
|
found2After, _, _ := ta.FindText("TIKI-2")
|
|
if !found1After {
|
|
ta.DumpScreen()
|
|
t.Errorf("TIKI-1 should be visible after search")
|
|
}
|
|
if found2After {
|
|
ta.DumpScreen()
|
|
t.Errorf("TIKI-2 should NOT be visible after search")
|
|
}
|
|
}
|
|
|
|
// TestPluginView_EmptyPlugin verifies plugin view with no matching tasks
|
|
func TestPluginView_EmptyPlugin(t *testing.T) {
|
|
ta := testutil.NewTestApp(t)
|
|
defer ta.Cleanup()
|
|
|
|
if err := ta.LoadPlugins(); err != nil {
|
|
t.Fatalf("Failed to load plugins: %v", err)
|
|
}
|
|
|
|
// Create only todo tasks (no backlog tasks)
|
|
if err := testutil.CreateTestTask(ta.TaskDir, "TIKI-1", "Todo Task", taskpkg.StatusReady, taskpkg.TypeStory); err != nil {
|
|
t.Fatalf("failed to create task: %v", err)
|
|
}
|
|
if err := ta.TaskStore.Reload(); err != nil {
|
|
t.Fatalf("failed to reload: %v", err)
|
|
}
|
|
|
|
// Navigate: Board → Backlog Plugin
|
|
ta.NavController.PushView(model.MakePluginViewID("Kanban"), nil)
|
|
ta.Draw()
|
|
ta.SendKey(tcell.KeyF3, 0, tcell.ModNone) // F3 = Backlog plugin
|
|
|
|
// Verify no tasks are visible (empty plugin)
|
|
found, _, _ := ta.FindText("TIKI-1")
|
|
if found {
|
|
ta.DumpScreen()
|
|
t.Errorf("todo task should NOT be visible in backlog plugin")
|
|
}
|
|
|
|
// Verify we can still navigate (no crash)
|
|
ta.SendKey(tcell.KeyDown, 0, tcell.ModNone)
|
|
ta.SendKey(tcell.KeyUp, 0, tcell.ModNone)
|
|
// Should not crash
|
|
}
|
|
|
|
// TestPluginView_NavigateBetweenColumns verifies horizontal navigation wraps
|
|
func TestPluginView_NavigateBetweenColumns(t *testing.T) {
|
|
ta := setupPluginViewTest(t)
|
|
defer ta.Cleanup()
|
|
|
|
// Navigate: Board → Backlog Plugin
|
|
ta.NavController.PushView(model.MakePluginViewID("Kanban"), nil)
|
|
ta.Draw()
|
|
ta.SendKey(tcell.KeyF3, 0, tcell.ModNone)
|
|
|
|
pluginConfig := ta.GetPluginConfig("Backlog")
|
|
if pluginConfig == nil {
|
|
t.Fatalf("Backlog plugin config not found")
|
|
}
|
|
|
|
// Start at index 0
|
|
if pluginConfig.GetSelectedIndex() != 0 {
|
|
t.Fatalf("initial selection = %d, want 0", pluginConfig.GetSelectedIndex())
|
|
}
|
|
|
|
// Press Right 3 times to reach column 3 (index 3)
|
|
for i := 0; i < 3; i++ {
|
|
ta.SendKey(tcell.KeyRight, 0, tcell.ModNone)
|
|
}
|
|
|
|
if pluginConfig.GetSelectedIndex() != 3 {
|
|
t.Errorf("after 3x Right, selection = %d, want 3", pluginConfig.GetSelectedIndex())
|
|
}
|
|
|
|
// Press Right again - should wrap or stay at boundary
|
|
ta.SendKey(tcell.KeyRight, 0, tcell.ModNone)
|
|
|
|
// Verify no crash and selection is valid
|
|
selectedIndex := pluginConfig.GetSelectedIndex()
|
|
if selectedIndex < 0 {
|
|
t.Errorf("selection should be valid, got %d", selectedIndex)
|
|
}
|
|
}
|
|
|
|
// TestPluginView_EscAtRootDoesNothing verifies Esc at root plugin does nothing
|
|
func TestPluginView_EscAtRootDoesNothing(t *testing.T) {
|
|
ta := setupPluginViewTest(t)
|
|
defer ta.Cleanup()
|
|
|
|
// Start at Kanban, switch to Backlog (uses ReplaceView, so still at depth 1)
|
|
ta.NavController.PushView(model.MakePluginViewID("Kanban"), nil)
|
|
ta.Draw()
|
|
ta.SendKey(tcell.KeyF3, 0, tcell.ModNone)
|
|
|
|
// Verify we're on Backlog plugin view at depth 1
|
|
currentView := ta.NavController.CurrentView()
|
|
if currentView.ViewID != model.MakePluginViewID("Backlog") {
|
|
t.Fatalf("expected Backlog plugin view, got %v", currentView.ViewID)
|
|
}
|
|
if ta.NavController.Depth() != 1 {
|
|
t.Fatalf("expected depth 1, got %d", ta.NavController.Depth())
|
|
}
|
|
|
|
// Press Esc - should do nothing since we're at root
|
|
ta.SendKey(tcell.KeyEscape, 0, tcell.ModNone)
|
|
|
|
// Verify we're still on Backlog (Esc does nothing at root)
|
|
currentView = ta.NavController.CurrentView()
|
|
if currentView.ViewID != model.MakePluginViewID("Backlog") {
|
|
t.Errorf("expected to stay on Backlog after Esc at root, got %v", currentView.ViewID)
|
|
}
|
|
}
|
|
|
|
// TestPluginView_MultiplePlugins verifies switching between different plugins
|
|
func TestPluginView_MultiplePlugins(t *testing.T) {
|
|
ta := testutil.NewTestApp(t)
|
|
defer ta.Cleanup()
|
|
|
|
if err := ta.LoadPlugins(); err != nil {
|
|
t.Fatalf("Failed to load plugins: %v", err)
|
|
}
|
|
|
|
// Create tasks for multiple plugins
|
|
// Backlog: status = backlog (also recent since just created)
|
|
if err := testutil.CreateTestTask(ta.TaskDir, "TIKI-1", "Backlog Task", taskpkg.StatusBacklog, taskpkg.TypeStory); err != nil {
|
|
t.Fatalf("failed to create task: %v", err)
|
|
}
|
|
|
|
// Recent: status = todo (also recent since just created)
|
|
if err := testutil.CreateTestTask(ta.TaskDir, "TIKI-2", "Recent Task", taskpkg.StatusReady, taskpkg.TypeStory); err != nil {
|
|
t.Fatalf("failed to create task: %v", err)
|
|
}
|
|
|
|
if err := ta.TaskStore.Reload(); err != nil {
|
|
t.Fatalf("failed to reload: %v", err)
|
|
}
|
|
|
|
// Navigate: Board → Backlog Plugin
|
|
ta.NavController.PushView(model.MakePluginViewID("Kanban"), nil)
|
|
ta.Draw()
|
|
ta.SendKey(tcell.KeyF3, 0, tcell.ModNone) // F3 = Backlog
|
|
|
|
// Verify only backlog task visible in Backlog plugin
|
|
found1, _, _ := ta.FindText("TIKI-1")
|
|
if !found1 {
|
|
ta.DumpScreen()
|
|
t.Errorf("backlog task should be visible in backlog plugin")
|
|
}
|
|
|
|
found2InBacklog, _, _ := ta.FindText("TIKI-2")
|
|
if found2InBacklog {
|
|
ta.DumpScreen()
|
|
t.Errorf("todo task should NOT be visible in backlog plugin (filtered by status)")
|
|
}
|
|
|
|
// Switch to Recent plugin (Ctrl-R)
|
|
ta.SendKey(tcell.KeyRune, 'R', tcell.ModCtrl)
|
|
|
|
// Verify BOTH tasks visible in Recent plugin (both were just created)
|
|
// Recent shows all recently modified/created tasks regardless of status
|
|
found1InRecent, _, _ := ta.FindText("TIKI-1")
|
|
if !found1InRecent {
|
|
ta.DumpScreen()
|
|
t.Errorf("backlog task should be visible in recent plugin (recently created)")
|
|
}
|
|
|
|
found2InRecent, _, _ := ta.FindText("TIKI-2")
|
|
if !found2InRecent {
|
|
ta.DumpScreen()
|
|
t.Errorf("todo task should be visible in recent plugin (recently created)")
|
|
}
|
|
}
|
|
|
|
// TestPluginView_ViKeysNavigation verifies vi-style keys (h/j/k/l) work in plugin
|
|
func TestPluginView_ViKeysNavigation(t *testing.T) {
|
|
t.Skip("SimulationScreen test framework issue - navigation works correctly in actual app")
|
|
ta := setupPluginViewTest(t)
|
|
defer ta.Cleanup()
|
|
|
|
// Navigate: Board → Backlog Plugin
|
|
ta.NavController.PushView(model.MakePluginViewID("Kanban"), nil)
|
|
ta.Draw()
|
|
ta.SendKey(tcell.KeyF3, 0, tcell.ModNone)
|
|
|
|
pluginConfig := ta.GetPluginConfig("Backlog")
|
|
if pluginConfig == nil {
|
|
t.Fatalf("Backlog plugin config not found")
|
|
}
|
|
|
|
// Start at index 0
|
|
if pluginConfig.GetSelectedIndex() != 0 {
|
|
t.Fatalf("initial selection = %d, want 0", pluginConfig.GetSelectedIndex())
|
|
}
|
|
|
|
// With 5 tasks in 4-column grid: [0, 1, 2, 3] / [4]
|
|
|
|
// Press 'l' (vi Right)
|
|
ta.SendKey(tcell.KeyRune, 'l', tcell.ModNone)
|
|
ta.Draw() // Redraw after navigation
|
|
|
|
if pluginConfig.GetSelectedIndex() != 1 {
|
|
t.Errorf("after 'l', selection = %d, want 1", pluginConfig.GetSelectedIndex())
|
|
}
|
|
|
|
// Press 'j' (vi Down) - should NOT move (no task at index 5)
|
|
ta.SendKey(tcell.KeyRune, 'j', tcell.ModNone)
|
|
|
|
if pluginConfig.GetSelectedIndex() != 1 {
|
|
t.Errorf("after 'j' from index 1, selection = %d, want 1 (no task below)", pluginConfig.GetSelectedIndex())
|
|
}
|
|
|
|
// Go back to index 0
|
|
ta.SendKey(tcell.KeyRune, 'h', tcell.ModNone)
|
|
if pluginConfig.GetSelectedIndex() != 0 {
|
|
t.Errorf("after 'h', selection = %d, want 0", pluginConfig.GetSelectedIndex())
|
|
}
|
|
|
|
// Press 'j' (vi Down) from index 0 - should move to index 4
|
|
ta.SendKey(tcell.KeyRune, 'j', tcell.ModNone)
|
|
|
|
if pluginConfig.GetSelectedIndex() != 4 {
|
|
t.Errorf("after 'j' from index 0, selection = %d, want 4", pluginConfig.GetSelectedIndex())
|
|
}
|
|
|
|
// Press 'k' (vi Up) - should move back to index 0
|
|
ta.SendKey(tcell.KeyRune, 'k', tcell.ModNone)
|
|
|
|
if pluginConfig.GetSelectedIndex() != 0 {
|
|
t.Errorf("after 'k', selection = %d, want 0", pluginConfig.GetSelectedIndex())
|
|
}
|
|
}
|
|
|
|
// TestPluginView_SelectionPersistsAcrossViews verifies selection is maintained
|
|
func TestPluginView_SelectionPersistsAcrossViews(t *testing.T) {
|
|
ta := setupPluginViewTest(t)
|
|
defer ta.Cleanup()
|
|
|
|
// Navigate: Board → Backlog Plugin
|
|
ta.NavController.PushView(model.MakePluginViewID("Kanban"), nil)
|
|
ta.Draw()
|
|
ta.SendKey(tcell.KeyF3, 0, tcell.ModNone)
|
|
|
|
pluginConfig := ta.GetPluginConfig("Backlog")
|
|
if pluginConfig == nil {
|
|
t.Fatalf("Backlog plugin config not found")
|
|
}
|
|
|
|
// Move to index 2
|
|
ta.SendKey(tcell.KeyRight, 0, tcell.ModNone)
|
|
ta.SendKey(tcell.KeyRight, 0, tcell.ModNone)
|
|
|
|
if pluginConfig.GetSelectedIndex() != 2 {
|
|
t.Fatalf("selection = %d, want 2", pluginConfig.GetSelectedIndex())
|
|
}
|
|
|
|
// Open task detail
|
|
ta.SendKey(tcell.KeyEnter, 0, tcell.ModNone)
|
|
|
|
// Go back to plugin
|
|
ta.SendKey(tcell.KeyEscape, 0, tcell.ModNone)
|
|
|
|
// Verify selection is still at index 2
|
|
if pluginConfig.GetSelectedIndex() != 2 {
|
|
t.Errorf("selection after return = %d, want 2 (should be preserved)", pluginConfig.GetSelectedIndex())
|
|
}
|
|
}
|