1package component
2
3import (
4 "testing"
5
6 layoutmocks "github.com/bnema/dumber/internal/ui/layout/mocks"
7 "github.com/stretchr/testify/assert"
8)
9
10func TestCalculateModalDimensions_NilParent(t *testing.T) {
11 cfg := ModalSizeConfig{
12 WidthPct: 0.6,
13 MaxWidth: 600,
14 TopMarginPct: 0.15,
15 FallbackWidth: 800,
16 FallbackHeight: 600,
17 }
18
19 width, marginTop := CalculateModalDimensions(nil, cfg)
20
21 // Should use fallback values
22 expectedWidth := int(float64(cfg.FallbackWidth) * cfg.WidthPct)
23 expectedMargin := int(float64(cfg.FallbackHeight) * cfg.TopMarginPct)
24
25 assert.Equal(t, expectedWidth, width)
26 assert.Equal(t, expectedMargin, marginTop)
27}
28
29func TestCalculateModalDimensions_ZeroAllocatedSize(t *testing.T) {
30 cfg := ModalSizeConfig{
31 WidthPct: 0.5,
32 MaxWidth: 500,
33 TopMarginPct: 0.2,
34 FallbackWidth: 1000,
35 FallbackHeight: 800,
36 }
37
38 parent := layoutmocks.NewMockOverlayWidget(t)
39 parent.EXPECT().GetAllocatedWidth().Return(0)
40 parent.EXPECT().GetAllocatedHeight().Return(0)
41
42 width, marginTop := CalculateModalDimensions(parent, cfg)
43
44 // Should use fallback values when allocated size is 0
45 expectedWidth := int(float64(cfg.FallbackWidth) * cfg.WidthPct)
46 expectedMargin := int(float64(cfg.FallbackHeight) * cfg.TopMarginPct)
47
48 assert.Equal(t, expectedWidth, width)
49 assert.Equal(t, expectedMargin, marginTop)
50}
51
52func TestCalculateModalDimensions_WidthCapped(t *testing.T) {
53 cfg := ModalSizeConfig{
54 WidthPct: 0.8,
55 MaxWidth: 600,
56 TopMarginPct: 0.1,
57 FallbackWidth: 800,
58 FallbackHeight: 600,
59 }
60
61 parent := layoutmocks.NewMockOverlayWidget(t)
62 parent.EXPECT().GetAllocatedWidth().Return(1920) // Large screen
63 parent.EXPECT().GetAllocatedHeight().Return(1080)
64
65 width, marginTop := CalculateModalDimensions(parent, cfg)
66
67 // 0.8 * 1920 = 1536, but capped at MaxWidth 600
68 assert.Equal(t, cfg.MaxWidth, width)
69 assert.Equal(t, int(float64(1080)*cfg.TopMarginPct), marginTop)
70}
71
72func TestCalculateModalDimensions_WidthPercentage(t *testing.T) {
73 cfg := ModalSizeConfig{
74 WidthPct: 0.6,
75 MaxWidth: 1000, // High cap, won't be hit
76 TopMarginPct: 0.15,
77 FallbackWidth: 800,
78 FallbackHeight: 600,
79 }
80
81 parent := layoutmocks.NewMockOverlayWidget(t)
82 parent.EXPECT().GetAllocatedWidth().Return(800)
83 parent.EXPECT().GetAllocatedHeight().Return(600)
84
85 width, marginTop := CalculateModalDimensions(parent, cfg)
86
87 assert.Equal(t, 480, width)
88 assert.Equal(t, 90, marginTop)
89}
90
91func TestScaleValue_DefaultScale(t *testing.T) {
92 // When scale is 0 or negative, should default to 1.0
93 assert.Equal(t, 50, ScaleValue(50, 0))
94 assert.Equal(t, 50, ScaleValue(50, -1.0))
95}
96
97func TestScaleValue_NormalScale(t *testing.T) {
98 assert.Equal(t, 50, ScaleValue(50, 1.0))
99}
100
101func TestScaleValue_Scaling(t *testing.T) {
102 // 1.5x scale
103 assert.Equal(t, 75, ScaleValue(50, 1.5))
104 // 2x scale
105 assert.Equal(t, 100, ScaleValue(50, 2.0))
106 // 1.2x scale (common UI scale)
107 assert.Equal(t, 60, ScaleValue(50, 1.2))
108}
109
110func TestMeasureWidgetHeight_NilWidget(t *testing.T) {
111 height := MeasureWidgetHeight(nil, 100)
112 assert.Equal(t, 0, height)
113}
114
115func TestDefaultRowHeights_Values(t *testing.T) {
116 // Ensure defaults are sensible
117 assert.Positive(t, DefaultRowHeights.Standard)
118 assert.Positive(t, DefaultRowHeights.Compact)
119 assert.Positive(t, DefaultRowHeights.Divider)
120 // Standard should be larger than compact
121 assert.Greater(t, DefaultRowHeights.Standard, DefaultRowHeights.Compact)
122}
123
124func TestOmniboxSizeDefaults_Values(t *testing.T) {
125 assert.Greater(t, OmniboxSizeDefaults.WidthPct, 0.0)
126 assert.LessOrEqual(t, OmniboxSizeDefaults.WidthPct, 1.0)
127 assert.Positive(t, OmniboxSizeDefaults.MaxWidth)
128 assert.Greater(t, OmniboxSizeDefaults.TopMarginPct, 0.0)
129 assert.LessOrEqual(t, OmniboxSizeDefaults.TopMarginPct, 1.0)
130}
131
132func TestSessionManagerSizeDefaults_Values(t *testing.T) {
133 assert.Greater(t, SessionManagerSizeDefaults.WidthPct, 0.0)
134 assert.LessOrEqual(t, SessionManagerSizeDefaults.WidthPct, 1.0)
135 assert.Positive(t, SessionManagerSizeDefaults.MaxWidth)
136 assert.Greater(t, SessionManagerSizeDefaults.TopMarginPct, 0.0)
137 assert.LessOrEqual(t, SessionManagerSizeDefaults.TopMarginPct, 1.0)
138}
139
140func TestPermissionPopupSizeDefaults_Values(t *testing.T) {
141 assert.Greater(t, PermissionPopupSizeDefaults.WidthPct, 0.0)
142 assert.LessOrEqual(t, PermissionPopupSizeDefaults.WidthPct, 1.0)
143 assert.Positive(t, PermissionPopupSizeDefaults.MaxWidth)
144 assert.Greater(t, PermissionPopupSizeDefaults.TopMarginPct, 0.0)
145 assert.LessOrEqual(t, PermissionPopupSizeDefaults.TopMarginPct, 1.0)
146 assert.Equal(t, 300, PermissionPopupSizeDefaults.FallbackHeight)
147}
148
149func TestListDisplayDefaults_Values(t *testing.T) {
150 assert.Positive(t, OmniboxListDefaults.MaxVisibleRows)
151 assert.Positive(t, OmniboxListDefaults.MaxResults)
152 assert.Positive(t, SessionManagerListDefaults.MaxVisibleRows)
153 assert.Positive(t, SessionManagerListDefaults.MaxResults)
154}
155
156func TestEffectiveMaxRows(t *testing.T) {
157 sizeCfg := ModalSizeConfig{TopMarginPct: 0.2}
158 defaults := ListDisplayDefaults{
159 MaxVisibleRows: 10,
160 MaxResults: 10,
161 SmallMaxVisibleRows: 5,
162 }
163
164 tests := []struct {
165 name string
166 parentHeight int
167 rowHeight int
168 want int
169 }{
170 {
171 name: "tall pane returns MaxVisibleRows",
172 parentHeight: 1200,
173 rowHeight: 72,
174 want: 10,
175 },
176 {
177 name: "short pane returns SmallMaxVisibleRows",
178 parentHeight: 800,
179 rowHeight: 72,
180 want: 5,
181 },
182 {
183 name: "zero parentHeight returns MaxVisibleRows",
184 parentHeight: 0,
185 rowHeight: 72,
186 want: 10,
187 },
188 {
189 name: "zero rowHeight returns MaxVisibleRows",
190 parentHeight: 800,
191 rowHeight: 0,
192 want: 10,
193 },
194 {
195 name: "negative parentHeight returns MaxVisibleRows",
196 parentHeight: -100,
197 rowHeight: 72,
198 want: 10,
199 },
200 {
201 name: "exact fit returns MaxVisibleRows",
202 parentHeight: 1150, // available = 1150 - 230 - 144 = 776, needed = 720
203 rowHeight: 72,
204 want: 10,
205 },
206 {
207 name: "boundary: available equals needed still fits",
208 parentHeight: 1080, // available = 1080 - 216 - 144 = 720, needed = 720 → fits
209 rowHeight: 72,
210 want: 10,
211 },
212 {
213 name: "boundary: one pixel under triggers small",
214 parentHeight: 1079, // available = 1079 - 215 - 144 = 720, needed = 720 → check
215 rowHeight: 72,
216 want: 10, // int(1079*0.2) = 215, 1079-215-144 = 720 → still fits
217 },
218 {
219 name: "just below boundary triggers small",
220 parentHeight: 1078, // available = 1078 - 215 - 144 = 719, needed = 720 → doesn't fit
221 rowHeight: 72,
222 want: 5,
223 },
224 }
225
226 for _, tt := range tests {
227 t.Run(tt.name, func(t *testing.T) {
228 got := EffectiveMaxRows(tt.parentHeight, tt.rowHeight, sizeCfg, defaults)
229 assert.Equal(t, tt.want, got)
230 })
231 }
232}
233
234func TestEffectiveMaxRows_NoAdaptation(t *testing.T) {
235 sizeCfg := ModalSizeConfig{TopMarginPct: 0.2}
236 defaults := ListDisplayDefaults{
237 MaxVisibleRows: 10,
238 MaxResults: 10,
239 SmallMaxVisibleRows: 0, // adaptation disabled
240 }
241
242 // Even with a short pane, should return MaxVisibleRows when SmallMaxVisibleRows is 0
243 got := EffectiveMaxRows(500, 72, sizeCfg, defaults)
244 assert.Equal(t, 10, got)
245}