@@ -28,11 +28,18 @@ function withServiceWorker(controller: Partial<ServiceWorker> & { postMessage: (
2828 swListener = undefined ;
2929 } ) ;
3030
31+ // Mock getRegistration to return an active service worker
32+ // The active property should have the postMessage method
33+ const getRegistration = vi . fn ( async ( ) => ( {
34+ active : controller as ServiceWorker ,
35+ } ) ) ;
36+
3137 Object . defineProperty ( navigator , 'serviceWorker' , {
3238 value : {
3339 controller,
3440 addEventListener,
3541 removeEventListener,
42+ getRegistration,
3643 } ,
3744 configurable : true ,
3845 } ) ;
@@ -97,13 +104,28 @@ describe('utils', () => {
97104 } ) ;
98105
99106 it ( 'does nothing when no service worker controller (store)' , async ( ) => {
100- Object . defineProperty ( navigator , 'serviceWorker' , { value : { controller : null } , configurable : true } ) ;
107+ Object . defineProperty ( navigator , 'serviceWorker' , {
108+ value : {
109+ controller : null ,
110+ getRegistration : vi . fn ( async ( ) => null ) ,
111+ } ,
112+ configurable : true
113+ } ) ;
101114 await utils . storeSecretKeyInServiceWorker ( 'abc' ) ;
102115 // no error thrown
103116 } ) ;
104117
105118 it ( 'requests secret and resolves with response (getSecretKeyFromServiceWorker)' , async ( ) => {
106- const postMessage = vi . fn ( ) ;
119+ const postMessage = vi . fn ( ( msg : any ) => {
120+ // When the service worker receives a RequestSecret message,
121+ // simulate it responding with the secret
122+ if ( msg . type === MessageType . RequestSecret ) {
123+ // Use queueMicrotask to ensure the message handler is set up first
124+ queueMicrotask ( ( ) => {
125+ triggerSWMessage ( { type : MessageType . StoreSecret , data : 'encoded' } ) ;
126+ } ) ;
127+ }
128+ } ) ;
107129 withServiceWorker ( { postMessage } as any ) ;
108130
109131 const promise = utils . getSecretKeyFromServiceWorker ( ) ;
@@ -115,14 +137,18 @@ describe('utils', () => {
115137 } ) ;
116138
117139 it ( 'returns null when no service worker controller available' , async ( ) => {
118- // Setup no controller scenario which should return null immediately
140+ // Setup no controller scenario - will retry 3 times with 500ms delays each = 1500ms total
119141 Object . defineProperty ( navigator , 'serviceWorker' , {
120- value : { controller : null } ,
142+ value : {
143+ controller : null ,
144+ getRegistration : vi . fn ( async ( ) => null ) ,
145+ } ,
121146 configurable : true ,
122147 } ) ;
148+
123149 const result = await utils . getSecretKeyFromServiceWorker ( ) ;
124150 expect ( result ) . toBeNull ( ) ;
125- } ) ;
151+ } , 10000 ) ; // Generous timeout to allow for multiple retries
126152
127153 it ( 'clears secret key via service worker' , async ( ) => {
128154 const postMessage = vi . fn ( ) ;
@@ -160,6 +186,7 @@ describe('utils', () => {
160186 Object . defineProperty ( navigator , 'serviceWorker' , {
161187 value : {
162188 controller : { postMessage } ,
189+ getRegistration : vi . fn ( async ( ) => ( { active : { postMessage } } ) ) ,
163190 } ,
164191 configurable : true ,
165192 } ) ;
@@ -249,6 +276,7 @@ describe('utils', () => {
249276 }
250277 return { error : null , response : { status : 200 } } ;
251278 } ) ;
279+
252280 await utils . refresh_access_token ( ) ;
253281 expect ( utils . loggedIn . value ) . toBe ( utils . AppState . LoggedIn ) ;
254282 } ) ;
@@ -262,14 +290,21 @@ describe('utils', () => {
262290 }
263291 return { error : null , response : { status : 200 } } ;
264292 } ) ;
293+
265294 await utils . refresh_access_token ( ) ;
266295 expect ( utils . loggedIn . value ) . toBe ( utils . AppState . LoggedIn ) ;
267296 } ) ;
268297
269298 it ( 'catch block resets secret if tokens missing' , async ( ) => {
270299 ( window . localStorage . getItem as any ) . mockImplementation ( ( ) => null ) ;
271- // Ensure no service worker controller so helper returns fast null
272- Object . defineProperty ( navigator , 'serviceWorker' , { value : { controller : null } , configurable : true } ) ;
300+ // Ensure no service worker controller - will retry 3 times with 500ms delays each
301+ Object . defineProperty ( navigator , 'serviceWorker' , {
302+ value : {
303+ controller : null ,
304+ getRegistration : vi . fn ( async ( ) => null ) ,
305+ } ,
306+ configurable : true
307+ } ) ;
273308 // Start from LoggedOut so we can ensure it does not become LoggedIn
274309 utils . loggedIn . value = utils . AppState . LoggedOut ;
275310 ( utils . fetchClient as any ) . GET = vi . fn ( async ( path : string ) => {
@@ -278,6 +313,7 @@ describe('utils', () => {
278313 }
279314 return { error : null , response : { status : 200 } } ;
280315 } ) ;
316+
281317 await utils . refresh_access_token ( ) ;
282318 // Should not have transitioned to LoggedIn
283319 expect ( utils . loggedIn . value ) . not . toBe ( utils . AppState . LoggedIn ) ;
0 commit comments