1package core
2
3import (
4 "slices"
5 "testing"
6)
7
8func heights(w *Workspace) map[WindowID]int {
9 out := map[WindowID]int{}
10 for _, p := range w.Layout() {
11 if !p.Floating {
12 out[p.ID] = p.Rect.H
13 }
14 }
15 return out
16}
17
18func sum(v []int) int {
19 t := 0
20 for _, x := range v {
21 t += x
22 }
23 return t
24}
25
26func TestRowRectsEqualWithoutShares(t *testing.T) {
27 r := Rect{X: 0, Y: 0, W: 50, H: 103}
28 c := Column{Windows: []WindowID{1, 2, 3}}
29 if !slices.Equal(rowRects(r, c, 5), stackRects(r, 3, 5)) {
30 t.Fatal(rowRects(r, c, 5))
31 }
32 c.Shares = []int{50, 50} // wrong length: ignored
33 if !slices.Equal(rowRects(r, c, 5), stackRects(r, 3, 5)) {
34 t.Fatal(rowRects(r, c, 5))
35 }
36 c.Shares = []int{50, 30, 30} // wrong sum: ignored
37 if !slices.Equal(rowRects(r, c, 5), stackRects(r, 3, 5)) {
38 t.Fatal(rowRects(r, c, 5))
39 }
40 c.Shares = []int{50, 30, 20}
41 rows := rowRects(r, c, 5)
42 if rows[0].H != 46 || rows[1].H != 27 || rows[2].H != 93-46-27 || rows[2].Y+rows[2].H != 103 {
43 t.Fatal(rows)
44 }
45}
46
47func TestResizeRow(t *testing.T) {
48 for _, o := range []Overflow{OverflowScroll, OverflowFixed} {
49 w := workspace()
50 w.Overflow = o
51 w.SetOutput(1000, 800)
52 w.Columns = []Column{{Windows: []WindowID{1, 2}}}
53 w.Apply("set-window-height +10%")
54 if !slices.Equal(w.Columns[0].Shares, []int{60, 40}) {
55 t.Fatal(o, w.Columns[0].Shares)
56 }
57 h := heights(w)
58 if h[1] <= h[2] {
59 t.Fatal(o, h)
60 }
61 for range 10 {
62 w.Apply("set-window-height +10%")
63 }
64 if !slices.Equal(w.Columns[0].Shares, []int{90, 10}) {
65 t.Fatal(o, w.Columns[0].Shares)
66 }
67 for range 10 {
68 w.Apply("set-window-height -10%")
69 }
70 if !slices.Equal(w.Columns[0].Shares, []int{10, 90}) {
71 t.Fatal(o, w.Columns[0].Shares)
72 }
73 }
74}
75
76func TestResizeRowThree(t *testing.T) {
77 w := workspace()
78 w.SetOutput(1000, 800)
79 w.Columns = []Column{{Windows: []WindowID{1, 2, 3}, Focus: 1}}
80 w.Apply("set-window-height +10%")
81 s := w.Columns[0].Shares
82 if sum(s) != 100 || s[1] != 43 || s[0] < 10 || s[2] < 10 {
83 t.Fatal(s)
84 }
85 for _, step := range []string{"+25%", "+25%", "-7%", "-100%", "+100%", "-3%"} {
86 w.Apply(Action("set-window-height " + step))
87 s := w.Columns[0].Shares
88 if sum(s) != 100 || slices.Min(s) < 10 {
89 t.Fatal(step, s)
90 }
91 }
92 if s := w.Columns[0].Shares; s[1] != 77 {
93 t.Fatal(s)
94 }
95 // Proportional: the others shrink by their room above the minimum.
96 w.Columns[0].Shares = []int{50, 20, 30}
97 w.Columns[0].Focus = 1
98 w.Apply("set-window-height +20%")
99 if s := w.Columns[0].Shares; !slices.Equal(s, []int{37, 40, 23}) {
100 t.Fatal(s)
101 }
102}
103
104func TestResizeRowNoops(t *testing.T) {
105 w := workspace()
106 w.Columns = []Column{{Windows: []WindowID{1}}}
107 w.Apply("set-window-height +10%")
108 if w.Columns[0].Shares != nil {
109 t.Fatal(w.Columns[0].Shares)
110 }
111 w.Columns = []Column{{Windows: []WindowID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}}
112 w.Apply("set-window-height +10%")
113 if w.Columns[0].Shares != nil {
114 t.Fatal(w.Columns[0].Shares)
115 }
116 w.Columns = []Column{{Windows: []WindowID{1, 2}}}
117 w.AddFloating(3, 10, 10)
118 w.Apply("set-window-height +10%")
119 if w.Columns[0].Shares != nil {
120 t.Fatal(w.Columns[0].Shares)
121 }
122 // A fullscreen window hides its column.
123 w = workspace()
124 w.Columns = []Column{{Windows: []WindowID{1, 2}}}
125 w.SetFullscreen(1, true)
126 w.Apply("set-window-height +10%")
127 if w.Columns[0].Shares != nil {
128 t.Fatal(w.Columns[0].Shares)
129 }
130}
131
132func TestSharesResetAndTravel(t *testing.T) {
133 m := monitor()
134 m.SetOutput(1000, 800)
135 m.AddWindow(1)
136 m.AddWindow(2)
137 w := m.Current()
138 w.ConsumeOrExpel(-1)
139 if len(w.Columns) != 1 {
140 t.Fatal(w.Columns)
141 }
142 w.Apply("set-window-height +20%")
143 if !slices.Equal(w.Columns[0].Shares, []int{30, 70}) {
144 t.Fatal(w.Columns[0].Shares)
145 }
146 // Moving the window inside the column swaps the shares with it.
147 w.Apply(ActionMoveWindowUp)
148 if !slices.Equal(w.Columns[0].Shares, []int{70, 30}) || w.Columns[0].Windows[0] != 2 {
149 t.Fatal(w.Columns[0])
150 }
151 // The column takes its shares to another workspace.
152 m.MoveToWorkspace(1, true)
153 m.FocusNumber(2)
154 if c := m.Current().Columns[0]; !slices.Equal(c.Shares, []int{70, 30}) {
155 t.Fatal(c)
156 }
157 // MoveColumn keeps them.
158 m.AddWindow(3)
159 m.Current().FocusColumn(-1)
160 m.Current().MoveColumn(1)
161 if c := m.Current().Columns[1]; !slices.Equal(c.Shares, []int{70, 30}) {
162 t.Fatal(m.Current().Columns)
163 }
164 // A window leaving resets the column to equal rows.
165 m.RemoveWindow(2)
166 m.AddWindow(4)
167 w = m.Current()
168 for _, c := range w.Columns {
169 if c.Shares != nil {
170 t.Fatal(w.Columns)
171 }
172 }
173 // A window joining invalidates them: equal rows.
174 w.Columns = []Column{{Windows: []WindowID{1, 3}, Shares: []int{80, 20}}}
175 w.Columns[0].Windows = append(w.Columns[0].Windows, 4)
176 h := heights(w)
177 if h[1] != h[3] {
178 t.Fatal(h)
179 }
180}
181
182func TestOverviewPreviewUsesShares(t *testing.T) {
183 w := workspace()
184 w.SetOutput(1000, 800)
185 w.Columns = []Column{{Windows: []WindowID{1, 2}, Shares: []int{70, 30}}}
186 tiles, _, _ := w.previewTiles()
187 h := map[WindowID]int{}
188 for _, p := range tiles {
189 h[p.ID] = p.Rect.H
190 }
191 live := heights(w)
192 if h[1] != live[1] || h[2] != live[2] {
193 t.Fatal(h, live)
194 }
195}