1package usecase
2
3import (
4 "context"
5 "errors"
6 "testing"
7
8 "github.com/bnema/dumber/internal/domain/entity"
9)
10
11func TestManagePanesUseCase_Resize_Errors(t *testing.T) {
12 uc := NewManagePanesUseCase(func() string { return "id" }, nil)
13
14 ctx := context.Background()
15
16 err := uc.Resize(ctx, nil, nil, ResizeIncreaseDown, 5, 10)
17 if err == nil {
18 t.Fatalf("expected error when workspace is nil")
19 }
20
21 ws := &entity.Workspace{}
22 err = uc.Resize(ctx, ws, nil, ResizeIncreaseDown, 5, 10)
23 if err == nil {
24 t.Fatalf("expected error when pane node is nil")
25 }
26
27 // Root nil should return ErrNothingToResize.
28 leaf := &entity.PaneNode{ID: "p1", Pane: &entity.Pane{ID: "p1"}}
29 err = uc.Resize(ctx, ws, leaf, ResizeIncreaseDown, 5, 10)
30 if !errors.Is(err, ErrNothingToResize) {
31 t.Fatalf("expected ErrNothingToResize, got %v", err)
32 }
33}
34
35func TestManagePanesUseCase_Resize_VerticalDividerMove(t *testing.T) {
36 uc := NewManagePanesUseCase(func() string { return "id" }, nil)
37 ctx := context.Background()
38
39 top := &entity.PaneNode{ID: "top", Pane: &entity.Pane{ID: "top"}}
40 bottom := &entity.PaneNode{ID: "bottom", Pane: &entity.Pane{ID: "bottom"}}
41 root := &entity.PaneNode{
42 ID: "split",
43 SplitDir: entity.SplitVertical,
44 SplitRatio: 0.5,
45 Children: []*entity.PaneNode{top, bottom},
46 }
47 top.Parent = root
48 bottom.Parent = root
49
50 ws := &entity.Workspace{Root: root, ActivePaneID: "bottom"}
51
52 // Moving divider down increases the first child's ratio.
53 if err := uc.Resize(ctx, ws, bottom, ResizeIncreaseDown, 5.0, 10.0); err != nil {
54 t.Fatalf("unexpected error: %v", err)
55 }
56 if got, want := root.SplitRatio, 0.55; got != want {
57 t.Fatalf("split ratio = %v, want %v", got, want)
58 }
59
60 // Moving divider up decreases the first child's ratio.
61 if err := uc.Resize(ctx, ws, bottom, ResizeIncreaseUp, 5.0, 10.0); err != nil {
62 t.Fatalf("unexpected error: %v", err)
63 }
64 if got, want := root.SplitRatio, 0.5; got != want {
65 t.Fatalf("split ratio = %v, want %v", got, want)
66 }
67}
68
69func TestManagePanesUseCase_Resize_SmartResizeGrowsAndShrinksActivePane(t *testing.T) {
70 uc := NewManagePanesUseCase(func() string { return "id" }, nil)
71 ctx := context.Background()
72
73 top := &entity.PaneNode{ID: "top", Pane: &entity.Pane{ID: "top"}}
74 bottom := &entity.PaneNode{ID: "bottom", Pane: &entity.Pane{ID: "bottom"}}
75 root := &entity.PaneNode{
76 ID: "split",
77 SplitDir: entity.SplitVertical,
78 SplitRatio: 0.5,
79 Children: []*entity.PaneNode{top, bottom},
80 }
81 top.Parent = root
82 bottom.Parent = root
83
84 ws := &entity.Workspace{Root: root, ActivePaneID: "bottom"}
85
86 // Smart increase should grow the active (bottom) pane: decrease SplitRatio.
87 if err := uc.Resize(ctx, ws, bottom, ResizeIncrease, 5.0, 10.0); err != nil {
88 t.Fatalf("unexpected error: %v", err)
89 }
90 if got, want := root.SplitRatio, 0.45; got != want {
91 t.Fatalf("split ratio = %v, want %v", got, want)
92 }
93
94 // Smart decrease should shrink the active pane: increase SplitRatio.
95 if err := uc.Resize(ctx, ws, bottom, ResizeDecrease, 5.0, 10.0); err != nil {
96 t.Fatalf("unexpected error: %v", err)
97 }
98 if got, want := root.SplitRatio, 0.5; got != want {
99 t.Fatalf("split ratio = %v, want %v", got, want)
100 }
101}
102
103func TestManagePanesUseCase_Resize_ClampsToMinPanePercent(t *testing.T) {
104 uc := NewManagePanesUseCase(func() string { return "id" }, nil)
105 ctx := context.Background()
106
107 left := &entity.PaneNode{ID: "left", Pane: &entity.Pane{ID: "left"}}
108 right := &entity.PaneNode{ID: "right", Pane: &entity.Pane{ID: "right"}}
109 root := &entity.PaneNode{
110 ID: "split",
111 SplitDir: entity.SplitHorizontal,
112 SplitRatio: 0.9,
113 Children: []*entity.PaneNode{left, right},
114 }
115 left.Parent = root
116 right.Parent = root
117
118 ws := &entity.Workspace{Root: root, ActivePaneID: "left"}
119
120 // maxRatio = 1 - (minPanePercent/100) = 0.9
121 if err := uc.Resize(ctx, ws, left, ResizeIncreaseRight, 5.0, 10.0); err != nil {
122 t.Fatalf("unexpected error: %v", err)
123 }
124 if got, want := root.SplitRatio, 0.9; got != want {
125 t.Fatalf("split ratio = %v, want %v", got, want)
126 }
127}
128
129func TestManagePanesUseCase_Resize_TargetsStackContainer(t *testing.T) {
130 uc := NewManagePanesUseCase(func() string { return "id" }, nil)
131 ctx := context.Background()
132
133 stackLeaf1 := &entity.PaneNode{ID: "s1", Pane: &entity.Pane{ID: "s1"}}
134 stackLeaf2 := &entity.PaneNode{ID: "s2", Pane: &entity.Pane{ID: "s2"}}
135 stack := &entity.PaneNode{
136 ID: "stack",
137 IsStacked: true,
138 ActiveStackIndex: 0,
139 Children: []*entity.PaneNode{stackLeaf1, stackLeaf2},
140 }
141 stackLeaf1.Parent = stack
142 stackLeaf2.Parent = stack
143
144 right := &entity.PaneNode{ID: "right", Pane: &entity.Pane{ID: "right"}}
145 root := &entity.PaneNode{
146 ID: "split",
147 SplitDir: entity.SplitHorizontal,
148 SplitRatio: 0.5,
149 Children: []*entity.PaneNode{stack, right},
150 }
151 stack.Parent = root
152 right.Parent = root
153
154 ws := &entity.Workspace{Root: root, ActivePaneID: "s1"}
155
156 // Pass the leaf inside the stack; Resize should act on the split above the stack.
157 if err := uc.Resize(ctx, ws, stackLeaf1, ResizeIncreaseRight, 5.0, 10.0); err != nil {
158 t.Fatalf("unexpected error: %v", err)
159 }
160 if got, want := root.SplitRatio, 0.55; got != want {
161 t.Fatalf("split ratio = %v, want %v", got, want)
162 }
163}