1package daemon
2
3import (
4 "testing"
5
6 renderer "github.com/bnema/vev-vt"
7 "github.com/bnema/vev/internal/domain"
8 "github.com/bnema/vev/internal/usecase/layout"
9 "github.com/stretchr/testify/require"
10)
11
12// TestComposeFrameDividerFollowsWeights proves rendered divider glyphs track
13// weight-aware pane geometry rather than an equal-split recomputation.
14func TestComposeFrameDividerFollowsWeights(t *testing.T) {
15 tests := []struct {
16 name string
17 direction layout.SplitDir
18 area domain.Rect
19 glyph rune
20 equalX, equalY int
21 weightedX, weightedY int
22 }{
23 {
24 name: "horizontal split",
25 direction: layout.Horizontal,
26 area: domain.Rect{Width: 61, Height: 5},
27 glyph: '│',
28 equalX: 30,
29 equalY: 1,
30 weightedX: 40,
31 weightedY: 1,
32 },
33 {
34 name: "vertical split",
35 direction: layout.Vertical,
36 area: domain.Rect{Width: 41, Height: 10},
37 glyph: '─',
38 equalX: 1,
39 equalY: 6,
40 weightedX: 1,
41 weightedY: 7,
42 },
43 }
44
45 for _, tt := range tests {
46 t.Run(tt.name, func(t *testing.T) {
47 root := &layout.Node{Kind: layout.Split, Dir: tt.direction, Children: []*layout.Node{
48 {Kind: layout.Leaf, Leaf: "first", Weight: 1},
49 {Kind: layout.Leaf, Leaf: "second", Weight: 1},
50 }}
51 stateFor := func() capturedRenderState {
52 placements, dividers, ok := layout.SolveWithDividers(root, tt.area)
53 require.True(t, ok)
54 panes := make([]capturedPaneRenderState, 0, len(placements))
55 for _, placement := range placements {
56 frame := cachePaneFrame(placement.Content.Width, placement.Content.Height, rune(placement.ID[0]))
57 panes = append(panes, capturedPaneRenderState{
58 id: placement.ID, frame: frame, placement: placement, focused: placement.ID == "first",
59 damage: []renderer.Damage{renderer.FullRedraw()},
60 })
61 }
62 return capturedRenderState{
63 reset: true,
64 layout: capturedTabLayout{area: tt.area, focus: "first", placements: placements, dividers: dividers, fingerprint: layoutFingerprint(root), valid: true},
65 panes: panes, styles: resolveStyles(nil),
66 }
67 }
68
69 equal := stateFor()
70 out := composeFrame(equal, composeCacheInput{})
71 require.Equal(t, tt.glyph, out.frame.At(tt.equalX, tt.equalY).Rune, "equal weights must place the divider at the equal-split gap")
72
73 root.Children[0].Weight = 2
74 weighted := stateFor()
75 require.NotEqual(t, equal.layout.fingerprint, weighted.layout.fingerprint)
76
77 out = composeFrame(weighted, out.cache, composeCacheInput{})
78 require.Equal(t, tt.glyph, out.frame.At(tt.weightedX, tt.weightedY).Rune, "the divider must follow the weight-derived gap")
79 require.NotEqual(t, tt.glyph, out.frame.At(tt.equalX, tt.equalY).Rune, "the divider must not linger at the old equal-split gap")
80 })
81 }
82}