1package layout_test
2
3import (
4 "context"
5 "testing"
6
7 "github.com/stretchr/testify/assert"
8 "github.com/stretchr/testify/mock"
9 "github.com/stretchr/testify/require"
10
11 "github.com/bnema/dumber/internal/domain/entity"
12 "github.com/bnema/dumber/internal/ui/layout"
13 "github.com/bnema/dumber/internal/ui/layout/mocks"
14)
15
16func setupStackedLeafMocks(t *testing.T, mockFactory *mocks.MockWidgetFactory) (*mocks.MockBoxWidget, *mocks.MockWidget) {
17 mockStackBox := mocks.NewMockBoxWidget(t)
18 mockFactory.EXPECT().NewBox(layout.OrientationVertical, 0).Return(mockStackBox).Once()
19 mockStackBox.EXPECT().SetHexpand(true).Once()
20 mockStackBox.EXPECT().SetVexpand(true).Once()
21
22 mockTitleBar, mockFavicon, mockOverlay, mockSpinner, mockContainer := setupPaneMocks(t, mockFactory, mockStackBox)
23 _ = mockFavicon
24 _ = mockOverlay
25 _ = mockSpinner
26 mockTitleBar.EXPECT().GetParent().Return(nil).Maybe()
27 mockContainer.EXPECT().SetVisible(true).Once()
28 mockTitleBar.EXPECT().AddCssClass("active").Once()
29
30 return mockStackBox, mockContainer
31}
32
33func TestNewTreeRenderer_CreatesRenderer(t *testing.T) {
34 // Arrange
35 ctx := context.Background()
36 mockFactory := mocks.NewMockWidgetFactory(t)
37 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
38
39 // Act
40 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
41
42 // Assert
43 require.NotNil(t, renderer)
44 assert.Equal(t, 0, renderer.NodeCount())
45}
46
47func TestBuild_NilRoot_ReturnsError(t *testing.T) {
48 // Arrange
49 ctx := context.Background()
50 mockFactory := mocks.NewMockWidgetFactory(t)
51 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
52
53 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
54
55 // Act
56 widget, err := renderer.Build(ctx, nil)
57
58 // Assert
59 assert.Nil(t, widget)
60 assert.ErrorIs(t, err, layout.ErrNilRoot)
61}
62
63func TestBuild_SingleLeafPane(t *testing.T) {
64 // Arrange
65 ctx := context.Background()
66 mockFactory := mocks.NewMockWidgetFactory(t)
67 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
68 mockStackBox, mockContainer := setupStackedLeafMocks(t, mockFactory)
69
70 pane := entity.NewPane(entity.PaneID("pane-1"))
71 node := &entity.PaneNode{
72 ID: "node-1",
73 Pane: pane,
74 }
75
76 mockPaneViewFactory.EXPECT().CreatePaneView(node).Return(mockContainer).Once()
77
78 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
79
80 // Act
81 widget, err := renderer.Build(ctx, node)
82
83 // Assert
84 require.NoError(t, err)
85 assert.Equal(t, mockStackBox, widget)
86 assert.Equal(t, 1, renderer.NodeCount())
87
88 // Verify lookup works
89 assert.Equal(t, mockStackBox, renderer.Lookup("node-1"))
90}
91
92func TestBuild_HorizontalSplit(t *testing.T) {
93 // Arrange
94 ctx := context.Background()
95 mockFactory := mocks.NewMockWidgetFactory(t)
96 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
97 mockPaned := mocks.NewMockPanedWidget(t)
98 mockLeftStackBox, mockLeftContainer := setupStackedLeafMocks(t, mockFactory)
99 mockRightStackBox, mockRightContainer := setupStackedLeafMocks(t, mockFactory)
100
101 leftPane := entity.NewPane(entity.PaneID("pane-left"))
102 rightPane := entity.NewPane(entity.PaneID("pane-right"))
103
104 leftNode := &entity.PaneNode{ID: "node-left", Pane: leftPane}
105 rightNode := &entity.PaneNode{ID: "node-right", Pane: rightPane}
106
107 splitNode := &entity.PaneNode{
108 ID: "node-split",
109 SplitDir: entity.SplitHorizontal,
110 SplitRatio: 0.5,
111 Children: []*entity.PaneNode{leftNode, rightNode},
112 }
113
114 mockPaneViewFactory.EXPECT().CreatePaneView(leftNode).Return(mockLeftContainer).Once()
115 mockPaneViewFactory.EXPECT().CreatePaneView(rightNode).Return(mockRightContainer).Once()
116
117 // SplitView creation expectations
118 mockFactory.EXPECT().NewPaned(layout.OrientationHorizontal).Return(mockPaned).Once()
119 mockPaned.EXPECT().SetResizeStartChild(true).Once()
120 mockPaned.EXPECT().SetResizeEndChild(true).Once()
121 mockPaned.EXPECT().SetVisible(true).Once()
122 mockLeftStackBox.EXPECT().SetVisible(true).Once()
123 mockRightStackBox.EXPECT().SetVisible(true).Once()
124 mockPaned.EXPECT().SetStartChild(mockLeftStackBox).Once()
125 mockPaned.EXPECT().SetEndChild(mockRightStackBox).Once()
126 mockPaned.EXPECT().GetAllocatedWidth().Return(0).Once()
127 mockPaned.EXPECT().ConnectMap(mock.Anything).Return(uint32(0)).Once()
128 mockPaned.EXPECT().AddTickCallback(mock.Anything).Return(uint(0)).Once()
129
130 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
131
132 // Act
133 widget, err := renderer.Build(ctx, splitNode)
134
135 // Assert
136 require.NoError(t, err)
137 assert.NotNil(t, widget)
138 assert.Equal(t, 3, renderer.NodeCount()) // split + 2 leaves
139}
140
141func TestBuild_VerticalSplit(t *testing.T) {
142 // Arrange
143 ctx := context.Background()
144 mockFactory := mocks.NewMockWidgetFactory(t)
145 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
146 mockPaned := mocks.NewMockPanedWidget(t)
147 mockTopStackBox, mockTopContainer := setupStackedLeafMocks(t, mockFactory)
148 mockBottomStackBox, mockBottomContainer := setupStackedLeafMocks(t, mockFactory)
149
150 topPane := entity.NewPane(entity.PaneID("pane-top"))
151 bottomPane := entity.NewPane(entity.PaneID("pane-bottom"))
152
153 topNode := &entity.PaneNode{ID: "node-top", Pane: topPane}
154 bottomNode := &entity.PaneNode{ID: "node-bottom", Pane: bottomPane}
155
156 splitNode := &entity.PaneNode{
157 ID: "node-split",
158 SplitDir: entity.SplitVertical,
159 SplitRatio: 0.3,
160 Children: []*entity.PaneNode{topNode, bottomNode},
161 }
162
163 mockPaneViewFactory.EXPECT().CreatePaneView(topNode).Return(mockTopContainer).Once()
164 mockPaneViewFactory.EXPECT().CreatePaneView(bottomNode).Return(mockBottomContainer).Once()
165
166 // SplitView creation expectations - should be vertical
167 mockFactory.EXPECT().NewPaned(layout.OrientationVertical).Return(mockPaned).Once()
168 mockPaned.EXPECT().SetResizeStartChild(true).Once()
169 mockPaned.EXPECT().SetResizeEndChild(true).Once()
170 mockPaned.EXPECT().SetVisible(true).Once()
171 mockTopStackBox.EXPECT().SetVisible(true).Once()
172 mockBottomStackBox.EXPECT().SetVisible(true).Once()
173 mockPaned.EXPECT().SetStartChild(mockTopStackBox).Once()
174 mockPaned.EXPECT().SetEndChild(mockBottomStackBox).Once()
175 mockPaned.EXPECT().GetAllocatedHeight().Return(0).Once()
176 mockPaned.EXPECT().ConnectMap(mock.Anything).Return(uint32(0)).Once()
177 mockPaned.EXPECT().AddTickCallback(mock.Anything).Return(uint(0)).Once()
178
179 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
180
181 // Act
182 widget, err := renderer.Build(ctx, splitNode)
183
184 // Assert
185 require.NoError(t, err)
186 assert.NotNil(t, widget)
187}
188
189func TestBuild_NestedSplits(t *testing.T) {
190 // Arrange
191 ctx := context.Background()
192 mockFactory := mocks.NewMockWidgetFactory(t)
193 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
194 mockOuterPaned := mocks.NewMockPanedWidget(t)
195 mockInnerPaned := mocks.NewMockPanedWidget(t)
196 mockStackBox1, mockContainer1 := setupStackedLeafMocks(t, mockFactory)
197 mockStackBox2, mockContainer2 := setupStackedLeafMocks(t, mockFactory)
198 mockStackBox3, mockContainer3 := setupStackedLeafMocks(t, mockFactory)
199
200 // Create tree structure:
201 // outer (horizontal)
202 // / \
203 // inner (vertical) pane3
204 // / \
205 // pane1 pane2
206
207 pane1 := entity.NewPane(entity.PaneID("pane-1"))
208 pane2 := entity.NewPane(entity.PaneID("pane-2"))
209 pane3 := entity.NewPane(entity.PaneID("pane-3"))
210
211 node1 := &entity.PaneNode{ID: "node-1", Pane: pane1}
212 node2 := &entity.PaneNode{ID: "node-2", Pane: pane2}
213 node3 := &entity.PaneNode{ID: "node-3", Pane: pane3}
214
215 innerSplit := &entity.PaneNode{
216 ID: "inner-split",
217 SplitDir: entity.SplitVertical,
218 SplitRatio: 0.5,
219 Children: []*entity.PaneNode{node1, node2},
220 }
221
222 outerSplit := &entity.PaneNode{
223 ID: "outer-split",
224 SplitDir: entity.SplitHorizontal,
225 SplitRatio: 0.6,
226 Children: []*entity.PaneNode{innerSplit, node3},
227 }
228
229 // Setup expectations for leaf nodes
230 mockPaneViewFactory.EXPECT().CreatePaneView(node1).Return(mockContainer1).Once()
231 mockPaneViewFactory.EXPECT().CreatePaneView(node2).Return(mockContainer2).Once()
232 mockPaneViewFactory.EXPECT().CreatePaneView(node3).Return(mockContainer3).Once()
233
234 // Inner split (vertical) is created first
235 mockFactory.EXPECT().NewPaned(layout.OrientationVertical).Return(mockInnerPaned).Once()
236 mockInnerPaned.EXPECT().SetResizeStartChild(true).Once()
237 mockInnerPaned.EXPECT().SetResizeEndChild(true).Once()
238 mockInnerPaned.EXPECT().SetVisible(true).Once()
239 mockStackBox1.EXPECT().SetVisible(true).Once()
240 mockStackBox2.EXPECT().SetVisible(true).Once()
241 mockInnerPaned.EXPECT().SetStartChild(mockStackBox1).Once()
242 mockInnerPaned.EXPECT().SetEndChild(mockStackBox2).Once()
243 mockInnerPaned.EXPECT().GetAllocatedHeight().Return(0).Once()
244 mockInnerPaned.EXPECT().ConnectMap(mock.Anything).Return(uint32(0)).Once()
245 mockInnerPaned.EXPECT().AddTickCallback(mock.Anything).Return(uint(0)).Once()
246
247 // Outer split (horizontal) gets inner paned and pane3
248 mockFactory.EXPECT().NewPaned(layout.OrientationHorizontal).Return(mockOuterPaned).Once()
249 mockOuterPaned.EXPECT().SetResizeStartChild(true).Once()
250 mockOuterPaned.EXPECT().SetResizeEndChild(true).Once()
251 mockOuterPaned.EXPECT().SetVisible(true).Once()
252 mockInnerPaned.EXPECT().SetVisible(true).Once()
253 mockStackBox3.EXPECT().SetVisible(true).Once()
254 mockOuterPaned.EXPECT().SetStartChild(mockInnerPaned).Once()
255 mockOuterPaned.EXPECT().SetEndChild(mockStackBox3).Once()
256 mockOuterPaned.EXPECT().GetAllocatedWidth().Return(0).Once()
257 mockOuterPaned.EXPECT().ConnectMap(mock.Anything).Return(uint32(0)).Once()
258 mockOuterPaned.EXPECT().AddTickCallback(mock.Anything).Return(uint(0)).Once()
259
260 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
261
262 // Act
263 widget, err := renderer.Build(ctx, outerSplit)
264
265 // Assert
266 require.NoError(t, err)
267 assert.NotNil(t, widget)
268 assert.Equal(t, 5, renderer.NodeCount()) // 2 splits + 3 leaves
269}
270
271// Note: TestBuild_StackedPanes is omitted because StackedView has complex internal
272// widget creation that makes mocking unwieldy. StackedView is thoroughly tested
273// in stacked_test.go. TreeRenderer's stacked rendering is verified implicitly
274// through integration tests.
275
276func TestLookup_ExistingNode(t *testing.T) {
277 // Arrange
278 ctx := context.Background()
279 mockFactory := mocks.NewMockWidgetFactory(t)
280 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
281 mockStackBox, mockContainer := setupStackedLeafMocks(t, mockFactory)
282
283 pane := entity.NewPane(entity.PaneID("pane-1"))
284 node := &entity.PaneNode{ID: "test-node-id", Pane: pane}
285
286 mockPaneViewFactory.EXPECT().CreatePaneView(node).Return(mockContainer).Once()
287
288 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
289 _, _ = renderer.Build(ctx, node)
290
291 // Act
292 result := renderer.Lookup("test-node-id")
293
294 // Assert
295 assert.Equal(t, mockStackBox, result)
296}
297
298func TestLookup_NonExistentNode(t *testing.T) {
299 // Arrange
300 ctx := context.Background()
301 mockFactory := mocks.NewMockWidgetFactory(t)
302 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
303 _, mockContainer := setupStackedLeafMocks(t, mockFactory)
304
305 pane := entity.NewPane(entity.PaneID("pane-1"))
306 node := &entity.PaneNode{ID: "node-1", Pane: pane}
307
308 mockPaneViewFactory.EXPECT().CreatePaneView(node).Return(mockContainer).Once()
309
310 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
311 _, _ = renderer.Build(ctx, node)
312
313 // Act
314 result := renderer.Lookup("non-existent-id")
315
316 // Assert
317 assert.Nil(t, result)
318}
319
320func TestLookupNode_Existing(t *testing.T) {
321 // Arrange
322 ctx := context.Background()
323 mockFactory := mocks.NewMockWidgetFactory(t)
324 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
325 mockStackBox, mockContainer := setupStackedLeafMocks(t, mockFactory)
326
327 pane := entity.NewPane(entity.PaneID("pane-1"))
328 node := &entity.PaneNode{ID: "node-1", Pane: pane}
329
330 mockPaneViewFactory.EXPECT().CreatePaneView(node).Return(mockContainer).Once()
331
332 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
333 _, _ = renderer.Build(ctx, node)
334
335 // Act
336 widget, found := renderer.LookupNode("node-1")
337
338 // Assert
339 assert.True(t, found)
340 assert.Equal(t, mockStackBox, widget)
341}
342
343func TestLookupNode_NonExistent(t *testing.T) {
344 // Arrange
345 ctx := context.Background()
346 mockFactory := mocks.NewMockWidgetFactory(t)
347 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
348
349 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
350
351 // Act
352 widget, found := renderer.LookupNode("non-existent")
353
354 // Assert
355 assert.False(t, found)
356 assert.Nil(t, widget)
357}
358
359func TestClear_RemovesAllMappings(t *testing.T) {
360 // Arrange
361 ctx := context.Background()
362 mockFactory := mocks.NewMockWidgetFactory(t)
363 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
364 _, mockContainer := setupStackedLeafMocks(t, mockFactory)
365
366 pane := entity.NewPane(entity.PaneID("pane-1"))
367 node := &entity.PaneNode{ID: "node-1", Pane: pane}
368
369 mockPaneViewFactory.EXPECT().CreatePaneView(node).Return(mockContainer).Once()
370
371 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
372 _, _ = renderer.Build(ctx, node)
373
374 require.Equal(t, 1, renderer.NodeCount())
375
376 // Act
377 renderer.Clear()
378
379 // Assert
380 assert.Equal(t, 0, renderer.NodeCount())
381 assert.Nil(t, renderer.Lookup("node-1"))
382}
383
384func TestGetNodeIDs_ReturnsAllIDs(t *testing.T) {
385 // Arrange
386 mockFactory := mocks.NewMockWidgetFactory(t)
387 ctx := context.Background()
388 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
389 mockPaned := mocks.NewMockPanedWidget(t)
390 mockLeftStackBox, mockLeftContainer := setupStackedLeafMocks(t, mockFactory)
391 mockRightStackBox, mockRightContainer := setupStackedLeafMocks(t, mockFactory)
392
393 pane1 := entity.NewPane(entity.PaneID("pane-1"))
394 pane2 := entity.NewPane(entity.PaneID("pane-2"))
395
396 node1 := &entity.PaneNode{ID: "left-node", Pane: pane1}
397 node2 := &entity.PaneNode{ID: "right-node", Pane: pane2}
398
399 splitNode := &entity.PaneNode{
400 ID: "split-node",
401 SplitDir: entity.SplitHorizontal,
402 SplitRatio: 0.5,
403 Children: []*entity.PaneNode{node1, node2},
404 }
405
406 mockPaneViewFactory.EXPECT().CreatePaneView(node1).Return(mockLeftContainer).Once()
407 mockPaneViewFactory.EXPECT().CreatePaneView(node2).Return(mockRightContainer).Once()
408
409 mockFactory.EXPECT().NewPaned(layout.OrientationHorizontal).Return(mockPaned).Once()
410 mockPaned.EXPECT().SetResizeStartChild(true).Once()
411 mockPaned.EXPECT().SetResizeEndChild(true).Once()
412 mockPaned.EXPECT().SetVisible(true).Once()
413 mockLeftStackBox.EXPECT().SetVisible(true).Once()
414 mockRightStackBox.EXPECT().SetVisible(true).Once()
415 mockPaned.EXPECT().SetStartChild(mockLeftStackBox).Once()
416 mockPaned.EXPECT().SetEndChild(mockRightStackBox).Once()
417 mockPaned.EXPECT().GetAllocatedWidth().Return(0).Once()
418 mockPaned.EXPECT().ConnectMap(mock.Anything).Return(uint32(0)).Once()
419 mockPaned.EXPECT().AddTickCallback(mock.Anything).Return(uint(0)).Once()
420
421 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
422 _, _ = renderer.Build(ctx, splitNode)
423
424 // Act
425 ids := renderer.GetNodeIDs()
426
427 // Assert
428 assert.Len(t, ids, 3)
429 assert.Contains(t, ids, "split-node")
430 assert.Contains(t, ids, "left-node")
431 assert.Contains(t, ids, "right-node")
432}
433
434func TestBuild_ClearsPreviousMappings(t *testing.T) {
435 // Arrange
436 ctx := context.Background()
437 mockFactory := mocks.NewMockWidgetFactory(t)
438 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
439 mockOldStackBox, mockOldContainer := setupStackedLeafMocks(t, mockFactory)
440 mockNewStackBox, mockNewContainer := setupStackedLeafMocks(t, mockFactory)
441
442 pane1 := entity.NewPane(entity.PaneID("pane-1"))
443 node1 := &entity.PaneNode{ID: "old-node", Pane: pane1}
444
445 pane2 := entity.NewPane(entity.PaneID("pane-2"))
446 node2 := &entity.PaneNode{ID: "new-node", Pane: pane2}
447
448 mockPaneViewFactory.EXPECT().CreatePaneView(node1).Return(mockOldContainer).Once()
449 mockPaneViewFactory.EXPECT().CreatePaneView(node2).Return(mockNewContainer).Once()
450
451 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
452
453 // First build
454 _, _ = renderer.Build(ctx, node1)
455 require.Equal(t, 1, renderer.NodeCount())
456 require.Equal(t, mockOldStackBox, renderer.Lookup("old-node"))
457
458 // Act - second build should clear old mappings
459 _, _ = renderer.Build(ctx, node2)
460
461 // Assert
462 assert.Equal(t, 1, renderer.NodeCount())
463 assert.Nil(t, renderer.Lookup("old-node"))
464 assert.Equal(t, mockNewStackBox, renderer.Lookup("new-node"))
465}
466
467func TestBuild_NilPaneViewFactory_ReturnsNilForLeaves(t *testing.T) {
468 // Arrange
469 ctx := context.Background()
470 mockFactory := mocks.NewMockWidgetFactory(t)
471
472 pane := entity.NewPane(entity.PaneID("pane-1"))
473 node := &entity.PaneNode{ID: "node-1", Pane: pane}
474
475 renderer := layout.NewTreeRenderer(ctx, mockFactory, nil)
476
477 // Act
478 widget, err := renderer.Build(ctx, node)
479
480 // Assert
481 require.NoError(t, err)
482 assert.Nil(t, widget) // nil because paneViewFactory is nil
483}
484
485func TestBuild_EmptyNodeID_NotStored(t *testing.T) {
486 // Arrange
487 ctx := context.Background()
488 mockFactory := mocks.NewMockWidgetFactory(t)
489 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
490 _, mockContainer := setupStackedLeafMocks(t, mockFactory)
491
492 pane := entity.NewPane(entity.PaneID("pane-1"))
493 node := &entity.PaneNode{ID: "", Pane: pane} // Empty ID
494
495 mockPaneViewFactory.EXPECT().CreatePaneView(node).Return(mockContainer).Once()
496
497 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
498
499 // Act
500 widget, err := renderer.Build(ctx, node)
501
502 // Assert
503 require.NoError(t, err)
504 assert.NotNil(t, widget)
505 assert.Equal(t, 0, renderer.NodeCount()) // Empty ID nodes aren't stored
506}
507
508func TestUpdateSplitRatio_ExistingNode(t *testing.T) {
509 // Arrange
510 mockFactory := mocks.NewMockWidgetFactory(t)
511 ctx := context.Background()
512 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
513 mockPaned := mocks.NewMockPanedWidget(t)
514 mockLeftStackBox, mockLeftContainer := setupStackedLeafMocks(t, mockFactory)
515 mockRightStackBox, mockRightContainer := setupStackedLeafMocks(t, mockFactory)
516
517 pane1 := entity.NewPane(entity.PaneID("pane-1"))
518 pane2 := entity.NewPane(entity.PaneID("pane-2"))
519
520 node1 := &entity.PaneNode{ID: "node-1", Pane: pane1}
521 node2 := &entity.PaneNode{ID: "node-2", Pane: pane2}
522
523 splitNode := &entity.PaneNode{
524 ID: "split-node",
525 SplitDir: entity.SplitHorizontal,
526 SplitRatio: 0.5,
527 Children: []*entity.PaneNode{node1, node2},
528 }
529
530 mockPaneViewFactory.EXPECT().CreatePaneView(node1).Return(mockLeftContainer).Once()
531 mockPaneViewFactory.EXPECT().CreatePaneView(node2).Return(mockRightContainer).Once()
532
533 mockFactory.EXPECT().NewPaned(layout.OrientationHorizontal).Return(mockPaned).Once()
534 mockPaned.EXPECT().SetResizeStartChild(true).Once()
535 mockPaned.EXPECT().SetResizeEndChild(true).Once()
536 mockPaned.EXPECT().SetVisible(true).Once()
537 mockLeftStackBox.EXPECT().SetVisible(true).Once()
538 mockRightStackBox.EXPECT().SetVisible(true).Once()
539 mockPaned.EXPECT().SetStartChild(mockLeftStackBox).Once()
540 mockPaned.EXPECT().SetEndChild(mockRightStackBox).Once()
541 mockPaned.EXPECT().GetAllocatedWidth().Return(0).Once()
542 mockPaned.EXPECT().ConnectMap(mock.Anything).Return(uint32(0)).Once()
543 mockPaned.EXPECT().AddTickCallback(mock.Anything).Return(uint(0)).Once()
544
545 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
546 _, _ = renderer.Build(ctx, splitNode)
547
548 // Act
549 err := renderer.UpdateSplitRatio("split-node", 0.7)
550
551 // Assert
552 assert.NoError(t, err)
553}
554
555func TestUpdateSplitRatio_NonExistentNode(t *testing.T) {
556 // Arrange
557 mockFactory := mocks.NewMockWidgetFactory(t)
558 ctx := context.Background()
559 mockPaneViewFactory := mocks.NewMockPaneViewFactory(t)
560
561 renderer := layout.NewTreeRenderer(ctx, mockFactory, mockPaneViewFactory)
562
563 // Act
564 err := renderer.UpdateSplitRatio("non-existent", 0.7)
565
566 // Assert
567 assert.ErrorIs(t, err, layout.ErrNodeNotFound)
568}