@@ -145,6 +145,30 @@ describe("installFromArchive", () => {
145145 expect ( progressCalls [ 0 ] [ 0 ] ) . toMatch ( / \d + \. \d + M B \/ s / ) ;
146146 } ) ;
147147
148+ it ( "skips progress log when threshold is not reached" , async ( ) => {
149+ // 20 small chunks, each 5% of total — only even thresholds (10%, 20%, …) log
150+ const chunkSize = 32 ;
151+ const totalSize = chunkSize * 20 ;
152+ const chunks = Array . from ( { length : 20 } , ( ) =>
153+ Buffer . alloc ( chunkSize , "a" ) ,
154+ ) ;
155+ const sha = crypto
156+ . createHash ( "sha256" )
157+ . update ( Buffer . concat ( chunks ) )
158+ . digest ( "hex" ) ;
159+ mockHttpGetWith ( 200 , String ( totalSize ) , chunks ) ;
160+ const r = { ...resolved , sha256 : sha } ;
161+ await installFromArchive ( r , "/opt/flutter" , "linux" ) ;
162+
163+ const progressCalls = mockedCore . info . mock . calls . filter ( ( c ) =>
164+ String ( c [ 0 ] ) . includes ( "Download progress:" ) ,
165+ ) ;
166+ // 10%, 20%, ..., 100% = 10 log lines (5% chunks don't trigger logs)
167+ expect ( progressCalls ) . toHaveLength ( 10 ) ;
168+ expect ( progressCalls [ 0 ] [ 0 ] ) . toContain ( "10%" ) ;
169+ expect ( progressCalls [ 0 ] [ 0 ] ) . not . toContain ( "5%" ) ;
170+ } ) ;
171+
148172 it ( "logs MB progress when content-length is missing" , async ( ) => {
149173 // First chunk (50 MB) does NOT cross a 100 MB boundary → false branch
150174 // Second chunk (60 MB) crosses the 100 MB boundary → true branch
@@ -167,6 +191,24 @@ describe("installFromArchive", () => {
167191 expect ( progressCalls [ 0 ] [ 0 ] ) . toMatch ( / \d + \. \d + M B \/ s / ) ;
168192 } ) ;
169193
194+ it ( "uses fallback speed when elapsed is zero" , async ( ) => {
195+ const now = Date . now ( ) ;
196+ const spy = vi . spyOn ( Date , "now" ) . mockReturnValue ( now ) ;
197+ // content-length missing, single large chunk crossing 100 MB boundary
198+ const chunk = Buffer . alloc ( 101 * 1024 * 1024 , "a" ) ;
199+ const sha = crypto . createHash ( "sha256" ) . update ( chunk ) . digest ( "hex" ) ;
200+ mockHttpGetWith ( 200 , undefined , [ chunk ] ) ;
201+ const r = { ...resolved , sha256 : sha } ;
202+ await installFromArchive ( r , "/opt/flutter" , "linux" ) ;
203+
204+ const progressCalls = mockedCore . info . mock . calls . filter ( ( c ) =>
205+ String ( c [ 0 ] ) . includes ( "MB downloaded" ) ,
206+ ) ;
207+ expect ( progressCalls ) . toHaveLength ( 1 ) ;
208+ expect ( progressCalls [ 0 ] [ 0 ] ) . toContain ( "MB/s" ) ;
209+ spy . mockRestore ( ) ;
210+ } ) ;
211+
170212 it ( "moves flutter directory to sdkPath" , async ( ) => {
171213 await installFromArchive ( resolved , "/opt/flutter" , "linux" ) ;
172214 expect ( mockedIo . mv ) . toHaveBeenCalledWith (
0 commit comments