@@ -140,11 +140,15 @@ describe("Image Mentions", () => {
140140 20 ,
141141 )
142142
143- expect ( result . images ) . toHaveLength ( 2 )
144- expect ( result . images [ 0 ] ) . toBe ( mockImageDataUrl1 )
145- expect ( result . images [ 1 ] ) . toBe ( mockImageDataUrl2 )
146- expect ( result . text ) . toContain ( "'image1.png' (see below for image)" )
147- expect ( result . text ) . toContain ( "'image2.jpg' (see below for image)" )
143+ // Type guard for TypeScript
144+ expect ( typeof result ) . toBe ( "object" )
145+ if ( typeof result === "object" ) {
146+ expect ( result . images ) . toHaveLength ( 2 )
147+ expect ( result . images [ 0 ] ) . toBe ( mockImageDataUrl1 )
148+ expect ( result . images [ 1 ] ) . toBe ( mockImageDataUrl2 )
149+ expect ( result . text ) . toContain ( "'image1.png' (see below for image)" )
150+ expect ( result . text ) . toContain ( "'image2.jpg' (see below for image)" )
151+ }
148152 } )
149153
150154 it ( "should handle image size limit exceeded" , async ( ) => {
@@ -177,8 +181,11 @@ describe("Image Mentions", () => {
177181 20 ,
178182 )
179183
180- expect ( result . images ) . toHaveLength ( 0 )
181- expect ( result . text ) . toContain ( "Image file is too large (10 MB). Maximum allowed size is 5 MB." )
184+ // When validation fails, we still get an object but with no images
185+ expect ( typeof result ) . toBe ( "string" )
186+ if ( typeof result === "string" ) {
187+ expect ( result ) . toContain ( "Image file is too large (10 MB). Maximum allowed size is 5 MB." )
188+ }
182189 } )
183190
184191 it ( "should handle model that doesn't support images" , async ( ) => {
@@ -210,8 +217,11 @@ describe("Image Mentions", () => {
210217 20 ,
211218 )
212219
213- expect ( result . images ) . toHaveLength ( 0 )
214- expect ( result . text ) . toContain ( "Image file detected but current model does not support images" )
220+ // When model doesn't support images, result should be a string
221+ expect ( typeof result ) . toBe ( "string" )
222+ if ( typeof result === "string" ) {
223+ expect ( result ) . toContain ( "Image file detected but current model does not support images" )
224+ }
215225 } )
216226
217227 it ( "should handle mixed content with images and regular files" , async ( ) => {
@@ -263,12 +273,16 @@ describe("Image Mentions", () => {
263273 20 ,
264274 )
265275
266- expect ( result . images ) . toHaveLength ( 1 )
267- expect ( result . images [ 0 ] ) . toBe ( mockImageDataUrl )
268- expect ( result . text ) . toContain ( "'image.png' (see below for image)" )
269- // The script.js file will have an error because we're not fully mocking the file system
270- // but that's okay for this test - we're mainly testing that images and non-images are handled differently
271- expect ( result . text ) . toContain ( "script.js" )
276+ // Type guard for TypeScript
277+ expect ( typeof result ) . toBe ( "object" )
278+ if ( typeof result === "object" ) {
279+ expect ( result . images ) . toHaveLength ( 1 )
280+ expect ( result . images [ 0 ] ) . toBe ( mockImageDataUrl )
281+ expect ( result . text ) . toContain ( "'image.png' (see below for image)" )
282+ // The script.js file will have an error because we're not fully mocking the file system
283+ // but that's okay for this test - we're mainly testing that images and non-images are handled differently
284+ expect ( result . text ) . toContain ( "script.js" )
285+ }
272286 } )
273287
274288 it ( "should respect .rooignore for image files" , async ( ) => {
@@ -299,8 +313,11 @@ describe("Image Mentions", () => {
299313 20 ,
300314 )
301315
302- expect ( result . images ) . toHaveLength ( 0 )
303- expect ( result . text ) . toContain ( "(Image ignored-image.png is ignored by .rooignore)" )
316+ // When image is ignored, result should be a string
317+ expect ( typeof result ) . toBe ( "string" )
318+ if ( typeof result === "string" ) {
319+ expect ( result ) . toContain ( "(Image ignored-image.png is ignored by .rooignore)" )
320+ }
304321 } )
305322
306323 it ( "should handle total memory limit for multiple images" , async ( ) => {
@@ -348,8 +365,159 @@ describe("Image Mentions", () => {
348365 20 , // maxTotalImageSize
349366 )
350367
351- expect ( result . images ) . toHaveLength ( 1 )
352- expect ( result . text ) . toContain ( "Image skipped to avoid size limit" )
368+ // Type guard for TypeScript
369+ expect ( typeof result ) . toBe ( "object" )
370+ if ( typeof result === "object" ) {
371+ expect ( result . images ) . toHaveLength ( 1 )
372+ expect ( result . text ) . toContain ( "Image skipped to avoid size limit" )
373+ }
374+ } )
375+
376+ it ( "should handle SVG image format" , async ( ) => {
377+ const mockSvgDataUrl =
378+ "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg=="
379+
380+ vi . mocked ( imageHelpers . isSupportedImageFormat ) . mockImplementation ( ( ext ) => ext === ".svg" )
381+ vi . mocked ( imageHelpers . validateImageForProcessing ) . mockResolvedValue ( {
382+ isValid : true ,
383+ sizeInMB : 0.1 ,
384+ } )
385+
386+ vi . mocked ( imageHelpers . processImageFile ) . mockResolvedValue ( {
387+ dataUrl : mockSvgDataUrl ,
388+ buffer : Buffer . from ( '<svg xmlns="http://www.w3.org/2000/svg"></svg>' ) ,
389+ sizeInKB : 100 ,
390+ sizeInMB : 0.1 ,
391+ notice : "Image (100 KB)" ,
392+ } )
393+
394+ vi . mocked ( fs . stat ) . mockResolvedValue ( {
395+ isFile : ( ) => true ,
396+ isDirectory : ( ) => false ,
397+ size : 102400 ,
398+ } as any )
399+
400+ const result = await parseMentions (
401+ "Check @/logo.svg" ,
402+ "/workspace" ,
403+ mockUrlContentFetcher ,
404+ undefined ,
405+ undefined ,
406+ true ,
407+ true ,
408+ 50 ,
409+ undefined ,
410+ true ,
411+ 5 ,
412+ 20 ,
413+ )
414+
415+ // Type guard for TypeScript
416+ expect ( typeof result ) . toBe ( "object" )
417+ if ( typeof result === "object" ) {
418+ expect ( result ) . toHaveProperty ( "images" )
419+ expect ( result . images ) . toHaveLength ( 1 )
420+ expect ( result . images [ 0 ] ) . toBe ( mockSvgDataUrl )
421+ expect ( result . text ) . toContain ( "'logo.svg' (see below for image)" )
422+ }
423+ } )
424+
425+ it ( "should handle WebP image format" , async ( ) => {
426+ const mockWebpDataUrl =
427+ "data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAQAcJaQAA3AA/v3AgAA="
428+
429+ vi . mocked ( imageHelpers . isSupportedImageFormat ) . mockImplementation ( ( ext ) => ext === ".webp" )
430+ vi . mocked ( imageHelpers . validateImageForProcessing ) . mockResolvedValue ( {
431+ isValid : true ,
432+ sizeInMB : 0.2 ,
433+ } )
434+
435+ vi . mocked ( imageHelpers . processImageFile ) . mockResolvedValue ( {
436+ dataUrl : mockWebpDataUrl ,
437+ buffer : Buffer . from ( "webp data" ) ,
438+ sizeInKB : 200 ,
439+ sizeInMB : 0.2 ,
440+ notice : "Image (200 KB)" ,
441+ } )
442+
443+ vi . mocked ( fs . stat ) . mockResolvedValue ( {
444+ isFile : ( ) => true ,
445+ isDirectory : ( ) => false ,
446+ size : 204800 ,
447+ } as any )
448+
449+ const result = await parseMentions (
450+ "Check @/photo.webp" ,
451+ "/workspace" ,
452+ mockUrlContentFetcher ,
453+ undefined ,
454+ undefined ,
455+ true ,
456+ true ,
457+ 50 ,
458+ undefined ,
459+ true ,
460+ 5 ,
461+ 20 ,
462+ )
463+
464+ // Type guard for TypeScript
465+ expect ( typeof result ) . toBe ( "object" )
466+ if ( typeof result === "object" ) {
467+ expect ( result ) . toHaveProperty ( "images" )
468+ expect ( result . images ) . toHaveLength ( 1 )
469+ expect ( result . images [ 0 ] ) . toBe ( mockWebpDataUrl )
470+ expect ( result . text ) . toContain ( "'photo.webp' (see below for image)" )
471+ }
472+ } )
473+
474+ it ( "should handle AVIF image format" , async ( ) => {
475+ const mockAvifDataUrl =
476+ "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAEAAAABAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIABoAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg=="
477+
478+ vi . mocked ( imageHelpers . isSupportedImageFormat ) . mockImplementation ( ( ext ) => ext === ".avif" )
479+ vi . mocked ( imageHelpers . validateImageForProcessing ) . mockResolvedValue ( {
480+ isValid : true ,
481+ sizeInMB : 0.3 ,
482+ } )
483+
484+ vi . mocked ( imageHelpers . processImageFile ) . mockResolvedValue ( {
485+ dataUrl : mockAvifDataUrl ,
486+ buffer : Buffer . from ( "avif data" ) ,
487+ sizeInKB : 300 ,
488+ sizeInMB : 0.3 ,
489+ notice : "Image (300 KB)" ,
490+ } )
491+
492+ vi . mocked ( fs . stat ) . mockResolvedValue ( {
493+ isFile : ( ) => true ,
494+ isDirectory : ( ) => false ,
495+ size : 307200 ,
496+ } as any )
497+
498+ const result = await parseMentions (
499+ "Check @/modern.avif" ,
500+ "/workspace" ,
501+ mockUrlContentFetcher ,
502+ undefined ,
503+ undefined ,
504+ true ,
505+ true ,
506+ 50 ,
507+ undefined ,
508+ true ,
509+ 5 ,
510+ 20 ,
511+ )
512+
513+ // Type guard for TypeScript
514+ expect ( typeof result ) . toBe ( "object" )
515+ if ( typeof result === "object" ) {
516+ expect ( result ) . toHaveProperty ( "images" )
517+ expect ( result . images ) . toHaveLength ( 1 )
518+ expect ( result . images [ 0 ] ) . toBe ( mockAvifDataUrl )
519+ expect ( result . text ) . toContain ( "'modern.avif' (see below for image)" )
520+ }
353521 } )
354522 } )
355523} )
0 commit comments