@@ -98,7 +98,7 @@ describe('geminiClient', () => {
9898 expect ( result . success ) . toBe ( true )
9999 if ( result . success ) {
100100 expect ( result . data . imageData ) . toBeInstanceOf ( Buffer )
101- expect ( result . data . metadata . model ) . toBe ( 'gemini-2.5-flash-image-preview ' )
101+ expect ( result . data . metadata . model ) . toBe ( 'gemini-2.5-flash-image' )
102102 expect ( result . data . metadata . prompt ) . toBe ( 'Generate a beautiful landscape' )
103103 expect ( result . data . metadata . mimeType ) . toBe ( 'image/png' )
104104 }
@@ -146,13 +146,13 @@ describe('geminiClient', () => {
146146 expect ( result . success ) . toBe ( true )
147147 if ( result . success ) {
148148 expect ( result . data . imageData ) . toBeInstanceOf ( Buffer )
149- expect ( result . data . metadata . model ) . toBe ( 'gemini-2.5-flash-image-preview ' )
149+ expect ( result . data . metadata . model ) . toBe ( 'gemini-2.5-flash-image' )
150150 expect ( result . data . metadata . prompt ) . toBe ( 'Enhance this image' )
151151 expect ( result . data . metadata . mimeType ) . toBe ( 'image/jpeg' )
152152 }
153153
154154 expect ( mockGeminiClientInstance . models . generateContent ) . toHaveBeenCalledWith ( {
155- model : 'gemini-2.5-flash-image-preview ' ,
155+ model : 'gemini-2.5-flash-image' ,
156156 contents : [
157157 {
158158 parts : [
@@ -168,6 +168,9 @@ describe('geminiClient', () => {
168168 ] ,
169169 } ,
170170 ] ,
171+ config : {
172+ responseModalities : [ 'IMAGE' ] ,
173+ } ,
171174 } )
172175 } )
173176
@@ -482,14 +485,14 @@ describe('geminiClient', () => {
482485 expect ( result . success ) . toBe ( true )
483486 if ( result . success ) {
484487 expect ( result . data . imageData ) . toBeInstanceOf ( Buffer )
485- expect ( result . data . metadata . model ) . toBe ( 'gemini-2.5-flash-image-preview ' )
488+ expect ( result . data . metadata . model ) . toBe ( 'gemini-2.5-flash-image' )
486489 // Features are passed to the API but not stored in metadata
487490 expect ( result . data . metadata . prompt ) . toBe ( 'Generate character with blending' )
488491 }
489492
490493 // Verify API was called with original prompt (no enhancement at GeminiClient level)
491494 expect ( mockGeminiClientInstance . models . generateContent ) . toHaveBeenCalledWith ( {
492- model : 'gemini-2.5-flash-image-preview ' ,
495+ model : 'gemini-2.5-flash-image' ,
493496 contents : [
494497 {
495498 parts : [
@@ -499,6 +502,9 @@ describe('geminiClient', () => {
499502 ] ,
500503 } ,
501504 ] ,
505+ config : {
506+ responseModalities : [ 'IMAGE' ] ,
507+ } ,
502508 } )
503509 } )
504510
@@ -542,12 +548,12 @@ describe('geminiClient', () => {
542548 if ( result . success ) {
543549 // Features are passed to the API but not stored in metadata
544550 expect ( result . data . metadata . prompt ) . toBe ( 'Generate factually accurate historical scene' )
545- expect ( result . data . metadata . model ) . toBe ( 'gemini-2.5-flash-image-preview ' )
551+ expect ( result . data . metadata . model ) . toBe ( 'gemini-2.5-flash-image' )
546552 }
547553
548554 // Verify API was called with original prompt (no processing at GeminiClient level)
549555 expect ( mockGeminiClientInstance . models . generateContent ) . toHaveBeenCalledWith ( {
550- model : 'gemini-2.5-flash-image-preview ' ,
556+ model : 'gemini-2.5-flash-image' ,
551557 contents : [
552558 {
553559 parts : [
@@ -557,6 +563,9 @@ describe('geminiClient', () => {
557563 ] ,
558564 } ,
559565 ] ,
566+ config : {
567+ responseModalities : [ 'IMAGE' ] ,
568+ } ,
560569 } )
561570 } )
562571
@@ -599,12 +608,12 @@ describe('geminiClient', () => {
599608 if ( result . success ) {
600609 // Features not specified - standard metadata only
601610 expect ( result . data . metadata . prompt ) . toBe ( 'Generate simple landscape' )
602- expect ( result . data . metadata . model ) . toBe ( 'gemini-2.5-flash-image-preview ' )
611+ expect ( result . data . metadata . model ) . toBe ( 'gemini-2.5-flash-image' )
603612 }
604613
605- // Verify API was called without generation config
614+ // Verify API was called with config
606615 expect ( mockGeminiClientInstance . models . generateContent ) . toHaveBeenCalledWith ( {
607- model : 'gemini-2.5-flash-image-preview ' ,
616+ model : 'gemini-2.5-flash-image' ,
608617 contents : [
609618 {
610619 parts : [
@@ -614,6 +623,9 @@ describe('geminiClient', () => {
614623 ] ,
615624 } ,
616625 ] ,
626+ config : {
627+ responseModalities : [ 'IMAGE' ] ,
628+ } ,
617629 } )
618630 } )
619631
@@ -663,12 +675,12 @@ describe('geminiClient', () => {
663675 expect ( result . data . metadata . inputImageProvided ) . toBe ( true )
664676 // Features are passed to the API but not stored in metadata
665677 expect ( result . data . metadata . prompt ) . toBe ( 'Blend this character with fantasy elements' )
666- expect ( result . data . metadata . model ) . toBe ( 'gemini-2.5-flash-image-preview ' )
678+ expect ( result . data . metadata . model ) . toBe ( 'gemini-2.5-flash-image' )
667679 }
668680
669681 // Verify API was called with input image and original prompt (no processing at GeminiClient level)
670682 expect ( mockGeminiClientInstance . models . generateContent ) . toHaveBeenCalledWith ( {
671- model : 'gemini-2.5-flash-image-preview ' ,
683+ model : 'gemini-2.5-flash-image' ,
672684 contents : [
673685 {
674686 parts : [
@@ -684,6 +696,177 @@ describe('geminiClient', () => {
684696 ] ,
685697 } ,
686698 ] ,
699+ config : {
700+ responseModalities : [ 'IMAGE' ] ,
701+ } ,
702+ } )
703+ } )
704+ } )
705+
706+ describe ( 'GeminiClient.generateImage with aspectRatio' , ( ) => {
707+ it ( 'should call API with imageConfig when aspectRatio is specified' , async ( ) => {
708+ // Arrange
709+ const mockResponse = {
710+ response : {
711+ candidates : [
712+ {
713+ content : {
714+ parts : [
715+ {
716+ inlineData : {
717+ data : 'base64-image-data-16-9' ,
718+ mimeType : 'image/png' ,
719+ } ,
720+ } ,
721+ ] ,
722+ } ,
723+ } ,
724+ ] ,
725+ } ,
726+ }
727+
728+ mockGeminiClientInstance . models . generateContent = vi . fn ( ) . mockResolvedValue ( mockResponse )
729+
730+ const clientResult = createGeminiClient ( testConfig )
731+ expect ( clientResult . success ) . toBe ( true )
732+
733+ if ( ! clientResult . success ) return
734+ const client = clientResult . data
735+
736+ // Act
737+ const result = await client . generateImage ( {
738+ prompt : 'test prompt for aspect ratio' ,
739+ aspectRatio : '16:9' ,
740+ } )
741+
742+ // Assert
743+ expect ( result . success ) . toBe ( true )
744+ expect ( mockGeminiClientInstance . models . generateContent ) . toHaveBeenCalledWith ( {
745+ model : 'gemini-2.5-flash-image' ,
746+ contents : [
747+ {
748+ parts : [
749+ {
750+ text : 'test prompt for aspect ratio' ,
751+ } ,
752+ ] ,
753+ } ,
754+ ] ,
755+ config : {
756+ imageConfig : { aspectRatio : '16:9' } ,
757+ responseModalities : [ 'IMAGE' ] ,
758+ } ,
759+ } )
760+ } )
761+
762+ it ( 'should use default when aspectRatio is not specified' , async ( ) => {
763+ // Arrange
764+ const mockResponse = {
765+ response : {
766+ candidates : [
767+ {
768+ content : {
769+ parts : [
770+ {
771+ inlineData : {
772+ data : 'base64-default-image' ,
773+ mimeType : 'image/png' ,
774+ } ,
775+ } ,
776+ ] ,
777+ } ,
778+ } ,
779+ ] ,
780+ } ,
781+ }
782+
783+ mockGeminiClientInstance . models . generateContent = vi . fn ( ) . mockResolvedValue ( mockResponse )
784+
785+ const clientResult = createGeminiClient ( testConfig )
786+ expect ( clientResult . success ) . toBe ( true )
787+
788+ if ( ! clientResult . success ) return
789+ const client = clientResult . data
790+
791+ // Act
792+ const result = await client . generateImage ( {
793+ prompt : 'test prompt without aspect ratio' ,
794+ } )
795+
796+ // Assert
797+ expect ( result . success ) . toBe ( true )
798+ expect ( mockGeminiClientInstance . models . generateContent ) . toHaveBeenCalledWith ( {
799+ model : 'gemini-2.5-flash-image' ,
800+ contents : [
801+ {
802+ parts : [
803+ {
804+ text : 'test prompt without aspect ratio' ,
805+ } ,
806+ ] ,
807+ } ,
808+ ] ,
809+ config : {
810+ responseModalities : [ 'IMAGE' ] ,
811+ } ,
812+ } )
813+ // Verify imageConfig.aspectRatio is not included
814+ const callArgs = ( mockGeminiClientInstance . models . generateContent as any ) . mock . calls [ 0 ] [ 0 ]
815+ expect ( callArgs . config . imageConfig ) . toBeUndefined ( )
816+ } )
817+
818+ it ( 'should include responseModalities: ["IMAGE"] in API call with aspectRatio' , async ( ) => {
819+ // Arrange
820+ const mockResponse = {
821+ response : {
822+ candidates : [
823+ {
824+ content : {
825+ parts : [
826+ {
827+ inlineData : {
828+ data : 'base64-image-data-21-9' ,
829+ mimeType : 'image/png' ,
830+ } ,
831+ } ,
832+ ] ,
833+ } ,
834+ } ,
835+ ] ,
836+ } ,
837+ }
838+
839+ mockGeminiClientInstance . models . generateContent = vi . fn ( ) . mockResolvedValue ( mockResponse )
840+
841+ const clientResult = createGeminiClient ( testConfig )
842+ expect ( clientResult . success ) . toBe ( true )
843+
844+ if ( ! clientResult . success ) return
845+ const client = clientResult . data
846+
847+ // Act
848+ const result = await client . generateImage ( {
849+ prompt : 'test prompt with 21:9 aspect ratio' ,
850+ aspectRatio : '21:9' ,
851+ } )
852+
853+ // Assert
854+ expect ( result . success ) . toBe ( true )
855+ expect ( mockGeminiClientInstance . models . generateContent ) . toHaveBeenCalledWith ( {
856+ model : 'gemini-2.5-flash-image' ,
857+ contents : [
858+ {
859+ parts : [
860+ {
861+ text : 'test prompt with 21:9 aspect ratio' ,
862+ } ,
863+ ] ,
864+ } ,
865+ ] ,
866+ config : {
867+ imageConfig : { aspectRatio : '21:9' } ,
868+ responseModalities : [ 'IMAGE' ] ,
869+ } ,
687870 } )
688871 } )
689872 } )
0 commit comments