@@ -20,13 +20,20 @@ vi.mock("./utils/store", () => ({
2020import { adjustWindowZoom , restoreWindowZoom , setupWindowZoom } from "./zoom" ;
2121
2222class FakeWebContents extends EventEmitter {
23+ public destroyed = false ;
24+ public readonly setZoomLevelCalls : number [ ] = [ ] ;
2325 public zoomLevel = 0 ;
2426
27+ public isDestroyed ( ) : boolean {
28+ return this . destroyed ;
29+ }
30+
2531 public getZoomLevel ( ) : number {
2632 return this . zoomLevel ;
2733 }
2834
2935 public setZoomLevel ( level : number ) : void {
36+ this . setZoomLevelCalls . push ( level ) ;
3037 this . zoomLevel = level ;
3138 }
3239}
@@ -89,50 +96,174 @@ describe("window zoom", () => {
8996 expect ( window . webContents . zoomLevel ) . toBe ( 0.5 ) ;
9097 } ) ;
9198
92- it ( "persists wheel zoom after Chromium updates its level " , ( ) => {
99+ it ( "restores the current level after an external window resize " , ( ) => {
93100 const window = createWindow ( ) ;
94101 setupWindowZoom ( window ) ;
95102
96- window . webContents . emit ( "zoom-changed" ) ;
97- window . webContents . zoomLevel = 1.5 ;
103+ window . webContents . emit ( "zoom-changed" , { preventDefault : vi . fn ( ) } , "in" ) ;
104+ vi . runAllTimers ( ) ;
105+ window . webContents . zoomLevel = 0 ;
106+
107+ window . emit ( "resize" ) ;
98108 vi . runAllTimers ( ) ;
109+ const restoredZoomLevel = window . webContents . zoomLevel ;
110+ adjustWindowZoom ( window , 0.5 ) ;
99111
100- expect ( store . save ) . toHaveBeenCalledWith ( 1.5 ) ;
112+ expect ( {
113+ restoredZoomLevel,
114+ zoomLevel : window . webContents . zoomLevel ,
115+ saved : store . save . mock . calls ,
116+ } ) . toEqual ( {
117+ restoredZoomLevel : 1 ,
118+ zoomLevel : 1.5 ,
119+ saved : [ [ 1 ] , [ 1.5 ] ] ,
120+ } ) ;
101121 } ) ;
102122
103- it ( "waits for native zoom before applying a menu adjustment" , ( ) => {
123+ it . each ( [
124+ [ "in" , 1 ] ,
125+ [ "out" , 0 ] ,
126+ ] as const ) (
127+ "applies wheel zoom %s from the persisted level" ,
128+ ( direction , expected ) => {
129+ const window = createWindow ( ) ;
130+ setupWindowZoom ( window ) ;
131+ const event = { preventDefault : vi . fn ( ) } ;
132+
133+ window . webContents . emit ( "zoom-changed" , event , direction ) ;
134+ vi . runAllTimers ( ) ;
135+
136+ expect ( {
137+ prevented : event . preventDefault . mock . calls . length ,
138+ zoomLevel : window . webContents . zoomLevel ,
139+ saved : store . save . mock . calls ,
140+ } ) . toEqual ( {
141+ prevented : 1 ,
142+ zoomLevel : expected ,
143+ saved : [ [ expected ] ] ,
144+ } ) ;
145+ } ,
146+ ) ;
147+
148+ it . each ( [ "resize" , "resized" ] as const ) (
149+ "keeps wheel zoom after %s" ,
150+ ( resizeEvent ) => {
151+ const window = createWindow ( ) ;
152+ setupWindowZoom ( window ) ;
153+
154+ window . webContents . emit (
155+ "zoom-changed" ,
156+ { preventDefault : vi . fn ( ) } ,
157+ "in" ,
158+ ) ;
159+ window . emit ( resizeEvent ) ;
160+ vi . runAllTimers ( ) ;
161+
162+ expect ( {
163+ zoomLevel : window . webContents . zoomLevel ,
164+ saved : store . save . mock . calls ,
165+ } ) . toEqual ( {
166+ zoomLevel : 1 ,
167+ saved : [ [ 1 ] ] ,
168+ } ) ;
169+ } ,
170+ ) ;
171+
172+ it ( "skips redundant restoration during a resize storm" , ( ) => {
104173 const window = createWindow ( ) ;
105174 setupWindowZoom ( window ) ;
175+ window . webContents . zoomLevel = 0.5 ;
176+
177+ window . emit ( "resize" ) ;
178+ vi . runAllTimers ( ) ;
179+ vi . advanceTimersByTime ( 16 ) ;
180+ window . emit ( "resize" ) ;
181+ vi . runAllTimers ( ) ;
182+ const callsBeforeReset = [ ...window . webContents . setZoomLevelCalls ] ;
183+
184+ window . webContents . zoomLevel = 0 ;
185+ window . emit ( "resize" ) ;
186+ vi . runAllTimers ( ) ;
106187
107- window . webContents . emit ( "zoom-changed" ) ;
108- window . webContents . zoomLevel = 1.5 ;
188+ expect ( {
189+ callsBeforeReset,
190+ callsAfterReset : window . webContents . setZoomLevelCalls ,
191+ } ) . toEqual ( {
192+ callsBeforeReset : [ ] ,
193+ callsAfterReset : [ 0.5 ] ,
194+ } ) ;
195+ } ) ;
196+
197+ it ( "ignores queued zoom work after the window is destroyed" , ( ) => {
198+ const window = createWindow ( ) ;
199+ setupWindowZoom ( window ) ;
200+
201+ window . webContents . emit ( "zoom-changed" , { preventDefault : vi . fn ( ) } , "in" ) ;
202+ window . emit ( "resize" ) ;
203+ window . webContents . destroyed = true ;
204+ vi . runAllTimers ( ) ;
205+
206+ expect ( {
207+ zoomLevelCalls : window . webContents . setZoomLevelCalls ,
208+ saved : store . save . mock . calls ,
209+ } ) . toEqual ( {
210+ zoomLevelCalls : [ ] ,
211+ saved : [ ] ,
212+ } ) ;
213+ } ) ;
214+
215+ it ( "keeps wheel zoom after a renderer reload" , ( ) => {
216+ const window = createWindow ( ) ;
217+ setupWindowZoom ( window ) ;
218+
219+ window . webContents . emit ( "zoom-changed" , { preventDefault : vi . fn ( ) } , "in" ) ;
220+ window . webContents . emit ( "did-finish-load" ) ;
221+ vi . runAllTimers ( ) ;
222+
223+ expect ( {
224+ zoomLevel : window . webContents . zoomLevel ,
225+ saved : store . save . mock . calls ,
226+ } ) . toEqual ( {
227+ zoomLevel : 1 ,
228+ saved : [ [ 1 ] ] ,
229+ } ) ;
230+ } ) ;
231+
232+ it ( "serializes wheel and menu zoom changes" , ( ) => {
233+ const window = createWindow ( ) ;
234+ setupWindowZoom ( window ) ;
235+
236+ window . webContents . emit ( "zoom-changed" , { preventDefault : vi . fn ( ) } , "in" ) ;
109237 adjustWindowZoom ( window , 0.5 ) ;
110238 vi . runAllTimers ( ) ;
111239
112240 expect ( {
113241 zoomLevel : window . webContents . zoomLevel ,
114242 saved : store . save . mock . calls ,
115243 } ) . toEqual ( {
116- zoomLevel : 2 ,
117- saved : [ [ 1.5 ] , [ 2 ] ] ,
244+ zoomLevel : 1.5 ,
245+ saved : [ [ 1 ] , [ 1.5 ] ] ,
118246 } ) ;
119247 } ) ;
120248
121- it ( "waits for native zoom before restoring after a reload " , ( ) => {
249+ it ( "uses the in-memory zoom level when persistence fails " , ( ) => {
122250 const window = createWindow ( ) ;
123251 setupWindowZoom ( window ) ;
252+ store . save . mockImplementation ( ( ) => { } ) ;
124253
125- window . webContents . emit ( "zoom-changed" ) ;
126- window . webContents . zoomLevel = 1.5 ;
127- window . webContents . emit ( "did-finish-load " ) ;
254+ window . webContents . emit ( "zoom-changed" , { preventDefault : vi . fn ( ) } , "in" ) ;
255+ vi . runAllTimers ( ) ;
256+ window . webContents . emit ( "zoom-changed" , { preventDefault : vi . fn ( ) } , "in ") ;
128257 vi . runAllTimers ( ) ;
129258
130259 expect ( {
260+ persistedZoomLevel : store . state . zoomLevel ,
131261 zoomLevel : window . webContents . zoomLevel ,
132262 saved : store . save . mock . calls ,
133263 } ) . toEqual ( {
264+ persistedZoomLevel : 0.5 ,
134265 zoomLevel : 1.5 ,
135- saved : [ [ 1.5 ] ] ,
266+ saved : [ [ 1 ] , [ 1 .5] ] ,
136267 } ) ;
137268 } ) ;
138269
0 commit comments