1
+ import { Display , Rectangle } from 'electron' ;
1
2
import { config } from '../src/app/config-handler' ;
2
3
import { mainEvents } from '../src/app/main-event-handler' ;
3
4
import {
6
7
miniViewHandler ,
7
8
} from '../src/app/mini-view-handler' ;
8
9
import { windowHandler } from '../src/app/window-handler' ;
10
+ import { screen } from './__mocks__/electron' ;
9
11
10
12
jest . mock ( '../src/app/config-handler' , ( ) => ( {
11
13
config : {
@@ -34,18 +36,23 @@ jest.mock('../src/app/window-handler', () => ({
34
36
jest . mock ( '../src/app/window-utils' , ( ) => {
35
37
return {
36
38
windowExists : jest . fn ( ( ) => true ) ,
39
+ isValidBounds : jest . fn ( ( ) => true ) ,
37
40
} ;
38
41
} ) ;
39
42
43
+ jest . mock ( 'electron' ) ;
44
+
40
45
describe ( 'MiniViewHandler' , ( ) => {
41
46
let mockMainWindow : any ;
42
47
let mockMainWebContents : any ;
48
+ let mockDisplay : Partial < Display > ;
43
49
44
50
beforeEach ( ( ) => {
45
51
jest . clearAllMocks ( ) ;
46
52
47
53
mockMainWindow = {
48
54
setBounds : jest . fn ( ) ,
55
+ getBounds : jest . fn ( ) ,
49
56
getSize : jest . fn ( ( ) => [ 800 , 600 ] ) ,
50
57
isFullScreen : jest . fn ( ( ) => false ) ,
51
58
isMaximized : jest . fn ( ( ) => false ) ,
@@ -56,6 +63,14 @@ describe('MiniViewHandler', () => {
56
63
once : jest . fn ( ) ,
57
64
} ;
58
65
66
+ mockDisplay = {
67
+ id : 1 ,
68
+ bounds : { x : 0 , y : 0 , width : 1920 , height : 1080 } ,
69
+ workArea : { x : 0 , y : 0 , width : 1920 , height : 1080 } ,
70
+ size : { width : 1920 , height : 1080 } ,
71
+ workAreaSize : { width : 1920 , height : 1080 } ,
72
+ } ;
73
+
59
74
mockMainWebContents = {
60
75
send : jest . fn ( ) ,
61
76
isDestroyed : jest . fn ( ( ) => false ) ,
@@ -71,22 +86,91 @@ describe('MiniViewHandler', () => {
71
86
) ;
72
87
( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( { } ) ;
73
88
( config . updateUserConfig as jest . Mock ) . mockResolvedValue ( undefined ) ;
89
+ ( screen . getDisplayMatching as jest . Mock ) . mockReturnValue ( mockDisplay ) ;
90
+ } ) ;
91
+
92
+ describe ( 'constrainBoundsToCurrentDisplay' , ( ) => {
93
+ it ( 'should constrain bounds within the current display' , async ( ) => {
94
+ const bounds : Rectangle = { x : - 100 , y : - 50 , width : 500 , height : 400 } ;
95
+ ( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
96
+ mainWinPosInMiniView : bounds ,
97
+ } ) ;
98
+ await miniViewHandler . activateMiniView ( ) ;
99
+ expect ( mockMainWindow . setBounds ) . toHaveBeenCalledWith (
100
+ expect . objectContaining ( { x : 0 , y : 0 } ) ,
101
+ ) ;
102
+ } ) ;
103
+
104
+ it ( 'should not modify bounds if already within the display' , async ( ) => {
105
+ const bounds : Rectangle = { x : 100 , y : 50 , width : 500 , height : 400 } ;
106
+ ( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
107
+ mainWinPosInMiniView : bounds ,
108
+ } ) ;
109
+ await miniViewHandler . activateMiniView ( ) ;
110
+ expect ( mockMainWindow . setBounds ) . toHaveBeenCalledWith (
111
+ expect . objectContaining ( bounds ) ,
112
+ ) ;
113
+ } ) ;
114
+
115
+ it ( 'should handle bounds exceeding display width' , async ( ) => {
116
+ const bounds : Rectangle = { x : 1800 , y : 100 , width : 500 , height : 400 } ;
117
+ ( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
118
+ mainWinPosInMiniView : bounds ,
119
+ } ) ;
120
+ await miniViewHandler . activateMiniView ( ) ;
121
+ expect ( mockMainWindow . setBounds ) . toHaveBeenCalledWith (
122
+ expect . objectContaining ( { x : 1420 } ) ,
123
+ ) ;
124
+ } ) ;
125
+
126
+ it ( 'should handle bounds exceeding display height' , async ( ) => {
127
+ const bounds : Rectangle = { x : 100 , y : 900 , width : 500 , height : 400 } ;
128
+ ( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
129
+ mainWinPosInMiniView : bounds ,
130
+ } ) ;
131
+ await miniViewHandler . activateMiniView ( ) ;
132
+ expect ( mockMainWindow . setBounds ) . toHaveBeenCalledWith (
133
+ expect . objectContaining ( { y : 680 } ) ,
134
+ ) ;
135
+ } ) ;
74
136
} ) ;
75
137
76
138
describe ( 'activateMiniView' , ( ) => {
139
+ const validBounds : Rectangle = {
140
+ x : 10 ,
141
+ y : 20 ,
142
+ width : 600 ,
143
+ height : 600 ,
144
+ } ;
145
+
146
+ const invalidBounds = {
147
+ x : 100 ,
148
+ y : 100 ,
149
+ } ;
150
+
77
151
it ( 'should set correct bounds when mainWinPosInMiniView exists' , async ( ) => {
152
+ ( screen . getDisplayMatching as jest . Mock ) . mockReturnValue ( mockDisplay ) ;
78
153
( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
79
- mainWinPosInMiniView : { x : 10 , y : 20 , width : 500 , height : 400 } ,
154
+ mainWinPosInMiniView : validBounds ,
80
155
} ) ;
81
156
82
157
await miniViewHandler . activateMiniView ( ) ;
83
158
84
- expect ( mockMainWindow . setBounds ) . toHaveBeenCalledWith ( {
85
- x : 10 ,
86
- y : 20 ,
87
- width : 500 ,
88
- height : 400 ,
159
+ expect ( mockMainWindow . setBounds ) . toHaveBeenCalledWith ( validBounds ) ;
160
+ } ) ;
161
+
162
+ it ( 'should use primary display when saved bounds are invalid' , async ( ) => {
163
+ ( screen . getDisplayMatching as jest . Mock ) . mockReturnValue ( { } ) ;
164
+ ( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
165
+ mainWinPosInMiniView : invalidBounds ,
89
166
} ) ;
167
+
168
+ await miniViewHandler . activateMiniView ( ) ;
169
+
170
+ expect ( mockMainWindow . setSize ) . toHaveBeenCalledWith (
171
+ DEFAULT_MINI_VIEW_WINDOW_WIDTH ,
172
+ 600 ,
173
+ ) ;
90
174
} ) ;
91
175
92
176
it ( 'should set default width and preserve height when mainWinPosInMiniView does not exist or has width > DEFAULT_MINI_VIEW_WINDOW_WIDTH' , async ( ) => {
@@ -146,9 +230,77 @@ describe('MiniViewHandler', () => {
146
230
expect ( mockMainWindow . unmaximize ) . toHaveBeenCalled ( ) ;
147
231
expect ( mainEvents . publish ) . toHaveBeenCalledWith ( 'unmaximize' ) ;
148
232
} ) ;
233
+
234
+ it ( 'should constrain bounds to current display when activating mini view with out-of-bounds position - top-left' , async ( ) => {
235
+ const outOfBounds : Rectangle = {
236
+ x : - 100 ,
237
+ y : - 50 ,
238
+ width : 500 ,
239
+ height : 400 ,
240
+ } ;
241
+ ( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
242
+ mainWinPosInMiniView : outOfBounds ,
243
+ } ) ;
244
+
245
+ await miniViewHandler . activateMiniView ( ) ;
246
+
247
+ expect ( mockMainWindow . setBounds ) . toHaveBeenCalledWith ( {
248
+ x : 0 ,
249
+ y : 0 ,
250
+ width : 500 ,
251
+ height : 400 ,
252
+ } ) ;
253
+ } ) ;
254
+
255
+ it ( 'should constrain bounds to current display when activating mini view with out-of-bounds position - bottom-right' , async ( ) => {
256
+ const outOfBounds : Rectangle = {
257
+ x : 1800 ,
258
+ y : 900 ,
259
+ width : 500 ,
260
+ height : 400 ,
261
+ } ;
262
+ ( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
263
+ mainWinPosInMiniView : outOfBounds ,
264
+ } ) ;
265
+
266
+ await miniViewHandler . activateMiniView ( ) ;
267
+
268
+ expect ( mockMainWindow . setBounds ) . toHaveBeenCalledWith ( {
269
+ x : 1420 ,
270
+ y : 680 ,
271
+ width : 500 ,
272
+ height : 400 ,
273
+ } ) ;
274
+ } ) ;
275
+
276
+ it ( 'should constrain bounds to current display when activating mini view with out-of-bounds position - partially out' , async ( ) => {
277
+ const outOfBounds : Rectangle = {
278
+ x : - 50 ,
279
+ y : - 25 ,
280
+ width : 600 ,
281
+ height : 500 ,
282
+ } ;
283
+ ( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
284
+ mainWinPosInMiniView : outOfBounds ,
285
+ } ) ;
286
+
287
+ await miniViewHandler . activateMiniView ( ) ;
288
+
289
+ expect ( mockMainWindow . setBounds ) . toHaveBeenCalledWith ( {
290
+ x : 0 ,
291
+ y : 0 ,
292
+ width : 600 ,
293
+ height : 500 ,
294
+ } ) ;
295
+ } ) ;
149
296
} ) ;
150
297
151
298
describe ( 'deactivateMiniView' , ( ) => {
299
+ const invalidBounds = {
300
+ x : 100 ,
301
+ y : 100 ,
302
+ } ;
303
+
152
304
it ( 'should set correct bounds when mainWinPos exists and width > MINI_VIEW_THRESHOLD_WINDOW_WIDTH' , ( ) => {
153
305
( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
154
306
mainWinPos : { x : 10 , y : 20 , width : 800 , height : 400 } ,
@@ -164,6 +316,20 @@ describe('MiniViewHandler', () => {
164
316
} ) ;
165
317
} ) ;
166
318
319
+ it ( 'should use primary display when saved bounds are invalid' , async ( ) => {
320
+ ( screen . getDisplayMatching as jest . Mock ) . mockReturnValue ( { } ) ;
321
+ ( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
322
+ mainWinPosInMiniView : invalidBounds ,
323
+ } ) ;
324
+
325
+ await miniViewHandler . deactivateMiniView ( ) ;
326
+
327
+ expect ( mockMainWindow . setSize ) . toHaveBeenCalledWith (
328
+ MINI_VIEW_THRESHOLD_WINDOW_WIDTH ,
329
+ 600 ,
330
+ ) ;
331
+ } ) ;
332
+
167
333
it ( 'should set default width and preserve height when mainWinPos does not exist or has width <= MINI_VIEW_THRESHOLD_WINDOW_WIDTH' , ( ) => {
168
334
( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
169
335
mainWinPos : { x : 10 , y : 20 , width : 600 , height : 400 } ,
@@ -193,6 +359,69 @@ describe('MiniViewHandler', () => {
193
359
) ;
194
360
done ( ) ;
195
361
} ) ;
362
+
363
+ it ( 'should constrain bounds to current display when deactivating mini view with out-of-bounds position - top-left' , async ( ) => {
364
+ const outOfBounds : Rectangle = {
365
+ x : - 100 ,
366
+ y : - 50 ,
367
+ width : 800 ,
368
+ height : 600 ,
369
+ } ;
370
+ ( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
371
+ mainWinPos : outOfBounds ,
372
+ } ) ;
373
+
374
+ await miniViewHandler . deactivateMiniView ( ) ;
375
+
376
+ expect ( mockMainWindow . setBounds ) . toHaveBeenCalledWith ( {
377
+ x : 0 ,
378
+ y : 0 ,
379
+ width : 800 ,
380
+ height : 600 ,
381
+ } ) ;
382
+ } ) ;
383
+
384
+ it ( 'should constrain bounds to current display when deactivating mini view with out-of-bounds position - bottom-right' , async ( ) => {
385
+ const outOfBounds : Rectangle = {
386
+ x : 1800 ,
387
+ y : 900 ,
388
+ width : 800 ,
389
+ height : 600 ,
390
+ } ;
391
+ ( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
392
+ mainWinPos : outOfBounds ,
393
+ } ) ;
394
+
395
+ await miniViewHandler . deactivateMiniView ( ) ;
396
+
397
+ expect ( mockMainWindow . setBounds ) . toHaveBeenCalledWith ( {
398
+ x : 1120 ,
399
+ y : 480 ,
400
+ width : 800 ,
401
+ height : 600 ,
402
+ } ) ;
403
+ } ) ;
404
+
405
+ it ( 'should constrain bounds to current display when deactivating mini view with out-of-bounds position - partially out' , async ( ) => {
406
+ const outOfBounds : Rectangle = {
407
+ x : - 50 ,
408
+ y : - 25 ,
409
+ width : 900 ,
410
+ height : 700 ,
411
+ } ;
412
+ ( config . getUserConfigFields as jest . Mock ) . mockReturnValue ( {
413
+ mainWinPos : outOfBounds ,
414
+ } ) ;
415
+
416
+ await miniViewHandler . deactivateMiniView ( ) ;
417
+
418
+ expect ( mockMainWindow . setBounds ) . toHaveBeenCalledWith ( {
419
+ x : 0 ,
420
+ y : 0 ,
421
+ width : 900 ,
422
+ height : 700 ,
423
+ } ) ;
424
+ } ) ;
196
425
} ) ;
197
426
198
427
describe ( 'notifyClient' , ( ) => {
0 commit comments