Files
nebara-tui/internal/ui/navigation/navigator_test.go
T
2026-10-13 19:36:58 +07:00

171 lines
4.5 KiB
Go

package navigation_test
import (
"testing"
"github.com/nebara/nebara-os/internal/model"
"github.com/nebara/nebara-os/internal/ui/navigation"
)
func sampleItems() []model.MenuItem {
return []model.MenuItem{
{Label: "Item A", Description: "Desc A", Children: []model.MenuItem{
{Label: "Child A1", Description: "Desc A1"},
{Label: "Child A2", Description: "Desc A2"},
}},
{Label: "Item B", Description: "Desc B"},
{Label: "Item C", Description: "Desc C"},
}
}
func TestNewNavigator_InitialIndex(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 1)
if nav.Current().SelectedIdx != 1 {
t.Errorf("expected initial index 1, got %d", nav.Current().SelectedIdx)
}
}
func TestNewNavigator_InvalidIndex(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 99)
if nav.Current().SelectedIdx != 0 {
t.Errorf("out-of-range index should clamp to 0, got %d", nav.Current().SelectedIdx)
}
}
func TestMoveDown(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 0)
nav.MoveDown()
if nav.Current().SelectedIdx != 1 {
t.Errorf("expected index 1 after MoveDown, got %d", nav.Current().SelectedIdx)
}
}
func TestMoveDown_Clamps(t *testing.T) {
items := sampleItems()
nav := navigation.NewNavigator(items, len(items)-1)
nav.MoveDown()
if nav.Current().SelectedIdx != len(items)-1 {
t.Errorf("MoveDown should clamp at last item")
}
}
func TestMoveUp(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 2)
nav.MoveUp()
if nav.Current().SelectedIdx != 1 {
t.Errorf("expected index 1 after MoveUp, got %d", nav.Current().SelectedIdx)
}
}
func TestMoveUp_Clamps(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 0)
nav.MoveUp()
if nav.Current().SelectedIdx != 0 {
t.Errorf("MoveUp should clamp at 0")
}
}
func TestMoveFirst(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 2)
nav.MoveFirst()
if nav.Current().SelectedIdx != 0 {
t.Errorf("MoveFirst should jump to 0")
}
}
func TestMoveLast(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 0)
nav.MoveLast()
last := len(sampleItems()) - 1
if nav.Current().SelectedIdx != last {
t.Errorf("MoveLast should jump to %d, got %d", last, nav.Current().SelectedIdx)
}
}
func TestEnter_HasChildren(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 0) // Item A has children
ok := nav.Enter()
if !ok {
t.Fatal("Enter on item with children should return true")
}
if nav.Depth() != 1 {
t.Errorf("expected depth 1, got %d", nav.Depth())
}
if nav.Current().Items[0].Label != "Child A1" {
t.Errorf("expected Child A1, got %s", nav.Current().Items[0].Label)
}
}
func TestEnter_NoChildren(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 1) // Item B has no children
ok := nav.Enter()
if ok {
t.Fatal("Enter on leaf item should return false")
}
if nav.Depth() != 0 {
t.Errorf("depth should remain 0 for leaf enter")
}
}
func TestBack(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 0)
nav.Enter()
ok := nav.Back()
if !ok {
t.Fatal("Back from submenu should return true")
}
if nav.Depth() != 0 {
t.Errorf("expected depth 0 after back, got %d", nav.Depth())
}
}
func TestBack_AtRoot(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 0)
ok := nav.Back()
if ok {
t.Fatal("Back at root should return false")
}
}
func TestIsAtRoot(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 0)
if !nav.IsAtRoot() {
t.Error("should be at root initially")
}
nav.Enter()
if nav.IsAtRoot() {
t.Error("should not be at root after Enter")
}
nav.Back()
if !nav.IsAtRoot() {
t.Error("should be at root after Back")
}
}
func TestSelectionPreservedAfterBack(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 0)
nav.MoveDown() // idx=1
nav.MoveDown() // idx=2
nav.Back() // at root, nothing changes
if nav.Current().SelectedIdx != 2 {
t.Errorf("selection should be 2, got %d", nav.Current().SelectedIdx)
}
nav.MoveFirst() // idx=0
nav.Enter() // into Item A's children
nav.Back() // back to root, parent should restore idx=0
if nav.Current().SelectedIdx != 0 {
t.Errorf("after returning from submenu, root selection should be 0, got %d", nav.Current().SelectedIdx)
}
}
func TestBreadcrumbTitle(t *testing.T) {
nav := navigation.NewNavigator(sampleItems(), 0)
if nav.BreadcrumbTitle() != "" {
t.Error("breadcrumb should be empty at root")
}
nav.Enter()
if nav.BreadcrumbTitle() != "Item A" {
t.Errorf("breadcrumb should be 'Item A', got %q", nav.BreadcrumbTitle())
}
}