@@ -136,7 +136,6 @@ describe("BinaryManager", () => {
136136 expect ( mockLogger . warn ) . toHaveBeenCalledWith (
137137 expect . stringContaining ( "Unable to get version" ) ,
138138 ) ;
139-
140139 // Should attempt to download now
141140 expect ( mockAxios . get ) . toHaveBeenCalled ( ) ;
142141 expect ( mockLogger . info ) . toHaveBeenCalledWith (
@@ -150,6 +149,9 @@ describe("BinaryManager", () => {
150149 const result = await manager . fetchBinary ( mockApi , "test" ) ;
151150 expect ( result ) . toBe ( BINARY_PATH ) ;
152151 expect ( mockAxios . get ) . toHaveBeenCalled ( ) ;
152+ expect ( mockLogger . info ) . toHaveBeenCalledWith (
153+ "No existing binary found, starting download" ,
154+ ) ;
153155 expect ( mockLogger . info ) . toHaveBeenCalledWith (
154156 "Downloaded binary version is" ,
155157 TEST_VERSION ,
@@ -221,21 +223,8 @@ describe("BinaryManager", () => {
221223 } ) ;
222224
223225 it ( "backs up existing binary before replacement" , async ( ) => {
224- // Setup existing old binary
225- vi . mocked ( cli . stat ) . mockReset ( ) ;
226- vi . mocked ( cli . stat )
227- . mockResolvedValueOnce ( { size : 1024 } as fs . Stats ) // Existing binary
228- . mockResolvedValueOnce ( { size : 5242880 } as fs . Stats ) ; // After download
229- vi . mocked ( cli . version ) . mockReset ( ) ;
230- vi . mocked ( cli . version )
231- . mockResolvedValueOnce ( "1.0.0" ) // Old version
232- . mockResolvedValueOnce ( TEST_VERSION ) ; // New version after download
233-
234- // Setup download
235- const stream = createMockStream ( ) ;
236- const writeStream = createMockWriteStream ( ) ;
237- withHttpResponse ( 200 , { "content-length" : "1024" } , stream ) ;
238- vi . mocked ( fs . createWriteStream ) . mockReturnValue ( writeStream ) ;
226+ withExistingBinary ( "1.0.0" ) ;
227+ withSuccessfulDownload ( ) ;
239228
240229 await manager . fetchBinary ( mockApi , "test" ) ;
241230 expect ( fse . rename ) . toHaveBeenCalledWith (
@@ -260,6 +249,9 @@ describe("BinaryManager", () => {
260249 withHttpResponse ( 304 ) ;
261250 const result = await manager . fetchBinary ( mockApi , "test" ) ;
262251 expect ( result ) . toBe ( BINARY_PATH ) ;
252+ expect ( mockLogger . info ) . toHaveBeenCalledWith (
253+ "Using existing binary since server returned a 304" ,
254+ ) ;
263255 } ) ;
264256
265257 it ( "handles 404 platform not supported" , async ( ) => {
@@ -268,14 +260,28 @@ describe("BinaryManager", () => {
268260 await expect ( manager . fetchBinary ( mockApi , "test" ) ) . rejects . toThrow (
269261 "Platform not supported" ,
270262 ) ;
271- expect ( vscode . env . openExternal ) . toHaveBeenCalled ( ) ;
263+ expect ( vscode . env . openExternal ) . toHaveBeenCalledWith (
264+ expect . objectContaining ( {
265+ path : expect . stringContaining (
266+ "github.com/coder/vscode-coder/issues/new?" ,
267+ ) ,
268+ } ) ,
269+ ) ;
272270 } ) ;
273271
274272 it ( "handles server errors" , async ( ) => {
275273 withHttpResponse ( 500 ) ;
274+ mockUI . setResponse ( "Open an Issue" ) ;
276275 await expect ( manager . fetchBinary ( mockApi , "test" ) ) . rejects . toThrow (
277276 "Failed to download binary" ,
278277 ) ;
278+ expect ( vscode . env . openExternal ) . toHaveBeenCalledWith (
279+ expect . objectContaining ( {
280+ path : expect . stringContaining (
281+ "github.com/coder/vscode-coder/issues/new?" ,
282+ ) ,
283+ } ) ,
284+ ) ;
279285 } ) ;
280286 } ) ;
281287
@@ -336,35 +342,46 @@ describe("BinaryManager", () => {
336342
337343 describe ( "Signature Verification" , ( ) => {
338344 it ( "verifies valid signatures" , async ( ) => {
339- withSuccessfulDownloadAndSignature ( ) ;
340- vi . mocked ( pgp . verifySignature ) . mockResolvedValueOnce ( ) ;
345+ withSuccessfulDownload ( ) ;
346+ withSignatureResponses ( [ 200 ] ) ;
341347 const result = await manager . fetchBinary ( mockApi , "test" ) ;
342348 expect ( result ) . toBe ( BINARY_PATH ) ;
343349 expect ( pgp . verifySignature ) . toHaveBeenCalled ( ) ;
344350 } ) ;
345351
346352 it ( "tries fallback signature on 404" , async ( ) => {
347- withBinaryDownload ( ) ;
353+ withSuccessfulDownload ( ) ;
348354 withSignatureResponses ( [ 404 , 200 ] ) ;
349- vi . mocked ( pgp . verifySignature ) . mockResolvedValueOnce ( ) ;
350355 mockUI . setResponse ( "Download signature" ) ;
351356 const result = await manager . fetchBinary ( mockApi , "test" ) ;
352357 expect ( result ) . toBe ( BINARY_PATH ) ;
358+ expect ( vscode . window . showWarningMessage ) . toHaveBeenCalledWith (
359+ "Signature not found" ,
360+ expect . any ( Object ) ,
361+ expect . any ( String ) ,
362+ expect . any ( String ) ,
363+ ) ;
364+ // First download and when verfiying twice (404 then 200)
353365 expect ( mockAxios . get ) . toHaveBeenCalledTimes ( 3 ) ;
354366 } ) ;
355367
356368 it ( "allows running despite invalid signature" , async ( ) => {
357- withSuccessfulDownloadAndSignature ( ) ;
369+ withSuccessfulDownload ( ) ;
370+ withSignatureResponses ( [ 200 ] ) ;
358371 vi . mocked ( pgp . verifySignature ) . mockRejectedValueOnce (
359372 createVerificationError ( "Invalid signature" ) ,
360373 ) ;
361374 mockUI . setResponse ( "Run anyway" ) ;
362375 const result = await manager . fetchBinary ( mockApi , "test" ) ;
363376 expect ( result ) . toBe ( BINARY_PATH ) ;
377+ expect ( mockLogger . info ) . toHaveBeenCalledWith (
378+ "Binary will be ran anyway at user request" ,
379+ ) ;
364380 } ) ;
365381
366382 it ( "aborts on signature rejection" , async ( ) => {
367- withSuccessfulDownloadAndSignature ( ) ;
383+ withSuccessfulDownload ( ) ;
384+ withSignatureResponses ( [ 200 ] ) ;
368385 vi . mocked ( pgp . verifySignature ) . mockRejectedValueOnce (
369386 createVerificationError ( "Invalid signature" ) ,
370387 ) ;
@@ -380,19 +397,25 @@ describe("BinaryManager", () => {
380397 const result = await manager . fetchBinary ( mockApi , "test" ) ;
381398 expect ( result ) . toBe ( BINARY_PATH ) ;
382399 expect ( pgp . verifySignature ) . not . toHaveBeenCalled ( ) ;
400+ expect ( mockLogger . info ) . toHaveBeenCalledWith (
401+ "Skipping binary signature verification due to settings" ,
402+ ) ;
383403 } ) ;
384404
385405 it ( "allows skipping verification on 404" , async ( ) => {
386- withBinaryDownload ( ) ;
406+ withSuccessfulDownload ( ) ;
387407 withHttpResponse ( 404 ) ;
388408 mockUI . setResponse ( "Run without verification" ) ;
389409 const result = await manager . fetchBinary ( mockApi , "test" ) ;
390410 expect ( result ) . toBe ( BINARY_PATH ) ;
391411 expect ( pgp . verifySignature ) . not . toHaveBeenCalled ( ) ;
412+ expect ( mockLogger . info ) . toHaveBeenCalledWith (
413+ expect . stringMatching ( / S i g n a t u r e d o w n l o a d f r o m ( .+ ) d e c l i n e d / ) ,
414+ ) ;
392415 } ) ;
393416
394417 it ( "handles signature download failure" , async ( ) => {
395- withBinaryDownload ( ) ;
418+ withSuccessfulDownload ( ) ;
396419 withHttpResponse ( 500 ) ;
397420 mockUI . setResponse ( "Run without verification" ) ;
398421 const result = await manager . fetchBinary ( mockApi , "test" ) ;
@@ -406,7 +429,7 @@ describe("BinaryManager", () => {
406429 } ) ;
407430
408431 it ( "aborts when user declines missing signature" , async ( ) => {
409- withBinaryDownload ( ) ;
432+ withSuccessfulDownload ( ) ;
410433 withHttpResponse ( 404 ) ;
411434 mockUI . setResponse ( undefined ) ; // User cancels
412435 await expect ( manager . fetchBinary ( mockApi , "test" ) ) . rejects . toThrow (
@@ -482,11 +505,12 @@ describe("BinaryManager", () => {
482505 vi . mocked ( cli . stat ) . mockReset ( ) ;
483506 vi . mocked ( cli . stat ) . mockResolvedValueOnce ( { size : 1024 } as fs . Stats ) ; // Existing binary exists
484507 vi . mocked ( cli . version ) . mockReset ( ) ;
485- vi . mocked ( cli . version )
486- . mockRejectedValueOnce ( new Error ( "corrupted" ) ) // Existing binary is corrupted
487- . mockResolvedValueOnce ( TEST_VERSION ) ; // New download works
508+ vi . mocked ( cli . version ) . mockRejectedValueOnce ( new Error ( "corrupted" ) ) ; // Existing binary is corrupted
488509 }
489510
511+ /**
512+ * Shouldn't reset mocks since this method is combined with other mocks.
513+ */
490514 function withSuccessfulDownload ( opts ?: {
491515 headers ?: Record < string , unknown > ;
492516 } ) {
@@ -506,25 +530,6 @@ describe("BinaryManager", () => {
506530 vi . mocked ( cli . version ) . mockResolvedValueOnce ( TEST_VERSION ) ;
507531 }
508532
509- function withBinaryDownload ( ) {
510- const stream = createMockStream ( ) ;
511- const writeStream = createMockWriteStream ( ) ;
512- withHttpResponse ( 200 , { "content-length" : "1024" } , stream ) ;
513- vi . mocked ( fs . createWriteStream ) . mockReturnValue ( writeStream ) ;
514- // Override to ensure no existing binary initially
515- vi . mocked ( cli . stat ) . mockReset ( ) ;
516- vi . mocked ( cli . stat )
517- . mockResolvedValueOnce ( undefined ) // No existing binary
518- . mockResolvedValueOnce ( { size : 5242880 } as fs . Stats ) ; // After download
519- vi . mocked ( cli . version ) . mockReset ( ) ;
520- vi . mocked ( cli . version ) . mockResolvedValueOnce ( TEST_VERSION ) ;
521- }
522-
523- function withSuccessfulDownloadAndSignature ( ) {
524- withBinaryDownload ( ) ;
525- withHttpResponse ( 200 , { "content-length" : "256" } , createMockStream ( ) ) ;
526- }
527-
528533 function withSignatureResponses ( statuses : number [ ] ) {
529534 statuses . forEach ( ( status ) => {
530535 if ( status === 200 ) {
0 commit comments