@@ -49,19 +49,28 @@ function installChromeMock() {
4949 ( globalThis as any ) . addEventListener = ( ) => { } ;
5050 }
5151 ( globalThis as any ) . self = globalThis ;
52+ Object . defineProperty ( globalThis , "navigator" , {
53+ value : { onLine : true } ,
54+ configurable : true ,
55+ writable : true ,
56+ } ) ;
5257
5358 ( globalThis as any ) . chrome = {
5459 runtime : {
5560 getURL : ( p : string ) => `chrome-extension://ext/${ p } ` ,
56- sendMessage : async ( ) => { } ,
57- getContexts : async ( ) => [ ] ,
61+ sendMessage : async ( msg : any ) => {
62+ if ( msg ?. type === "GET_REMAINING_CHUNKS" ) return { pending : 0 } ;
63+ return { } ;
64+ } ,
65+ getContexts : async ( ) => [ { } ] ,
5866 onMessage : {
5967 addListener : ( cb : MessageHandler ) => {
6068 onMessageListeners . push ( cb ) ;
6169 } ,
6270 } ,
6371 onInstalled : { addListener : ( ) => { } } ,
6472 onStartup : { addListener : ( ) => { } } ,
73+ onSuspend : { addListener : ( ) => { } } ,
6574 } ,
6675 alarms : {
6776 onAlarm : {
@@ -91,10 +100,22 @@ function installChromeMock() {
91100 create : ( ) => { } ,
92101 } ,
93102 sidePanel : { open : async ( ) => { } } ,
103+ offscreen : { hasDocument : async ( ) => true , closeDocument : async ( ) => { } } ,
94104 storage : {
95105 local : {
96- get : async ( key : string ) => {
97- if ( key === "settings" ) return mockStorage ;
106+ get : async ( keys : string | string [ ] ) => {
107+ if ( Array . isArray ( keys ) ) {
108+ const result : any = { } ;
109+ for ( const k of keys ) {
110+ if ( k === "settings" ) result [ k ] = mockStorage . settings ;
111+ else if ( k === "credentials" )
112+ result . credentials = { OPENAI_API_KEY : { key : "foo" , isEncrypted : false } } ;
113+ else result [ k ] = mockStorage [ k ] ;
114+ }
115+ return result ;
116+ }
117+ const key = keys as string ;
118+ if ( key === "settings" ) return { settings : mockStorage . settings } ;
98119 if ( key === "credentials" )
99120 return { credentials : { OPENAI_API_KEY : { key : "foo" , isEncrypted : false } } } ;
100121 return { [ key ] : mockStorage [ key ] } ;
@@ -107,9 +128,9 @@ function installChromeMock() {
107128 } ,
108129 } ,
109130 session : {
110- get : async ( key : string ) => ( { openai_api_key : "foo" } ) ,
111- set : async ( items : any ) => { } ,
112- remove : async ( key : string ) => { } ,
131+ get : async ( _key : string ) => ( { openai_api_key : "foo" } ) ,
132+ set : async ( _items : any ) => { } ,
133+ remove : async ( _key : string ) => { } ,
113134 } ,
114135 } ,
115136 } ;
@@ -146,7 +167,7 @@ test("Interval guard schedules an alarm if elapsed time is less than interval",
146167 } ) ;
147168
148169 // Wait for it to process
149- await sleep ( 200 ) ;
170+ await sleep ( 1500 ) ;
150171
151172 // Now state.lastSummarizedAt is recent. Send second chunk to hit the interval guard.
152173 await sendMessage ( {
@@ -156,7 +177,7 @@ test("Interval guard schedules an alarm if elapsed time is less than interval",
156177 } ) ;
157178
158179 // Wait for the queue to process it
159- await sleep ( 100 ) ;
180+ await sleep ( 1500 ) ;
160181
161182 // We expect SUMMARY_RETRY_ALARM to be created because it's been less than 30s since the first summary
162183 assert . ok ( createdAlarms [ "summarize-retry" ] , "Alarm should be scheduled" ) ;
@@ -171,7 +192,7 @@ test("Manual stop audio forces final summary flush", async () => {
171192
172193 // Trigger manual stop
173194 await sendMessage ( { type : "MANUAL_STOP_AUDIO" } ) ;
174- await sleep ( 500 ) ;
195+ await sleep ( 1500 ) ;
175196
176197 // The final flush clears the retry alarm
177198 assert . ok (
0 commit comments