@@ -196,4 +196,158 @@ private List<Media> buildMediaList() {
196196		return  List .of (imageMedia , pdfMedia );
197197	}
198198
199+ 	@ Test 
200+ 	public  void  userMessageWithEmptyMediaList () {
201+ 		given (this .openAiApi .chatCompletionEntity (this .pomptCaptor .capture (), this .headersCaptor .capture ()))
202+ 			.willReturn (Mockito .mock (ResponseEntity .class ));
203+ 
204+ 		this .chatModel .call (new  Prompt (List .of (UserMessage .builder ()
205+ 			.text ("test message" )
206+ 			.media (List .of ()) // Empty media list 
207+ 			.build ())));
208+ 
209+ 		validateStringContent (this .pomptCaptor .getValue ());
210+ 		assertThat (this .headersCaptor .getValue ()).isEmpty ();
211+ 	}
212+ 
213+ 	@ Test 
214+ 	public  void  userMessageWithEmptyText () {
215+ 		given (this .openAiApi .chatCompletionEntity (this .pomptCaptor .capture (), this .headersCaptor .capture ()))
216+ 			.willReturn (Mockito .mock (ResponseEntity .class ));
217+ 
218+ 		this .chatModel .call (new  Prompt (List .of (UserMessage .builder ().text ("" ).media (this .buildMediaList ()).build ())));
219+ 
220+ 		ChatCompletionRequest  request  = this .pomptCaptor .getValue ();
221+ 		assertThat (request .messages ()).hasSize (1 );
222+ 		var  userMessage  = request .messages ().get (0 );
223+ 		assertThat (userMessage .rawContent ()).isInstanceOf (List .class );
224+ 
225+ 		@ SuppressWarnings ("unchecked" )
226+ 		List <Map <String , Object >> mediaContents  = (List <Map <String , Object >>) userMessage .rawContent ();
227+ 
228+ 		// Should have empty text content plus media 
229+ 		assertThat (mediaContents ).hasSize (3 );
230+ 		Map <String , Object > textContent  = mediaContents .get (0 );
231+ 		assertThat (textContent .get ("type" )).isEqualTo ("text" );
232+ 		assertThat (textContent .get ("text" )).isEqualTo ("" );
233+ 	}
234+ 
235+ 	@ Test 
236+ 	public  void  multipleMessagesWithMixedContentTypes () {
237+ 		given (this .openAiApi .chatCompletionEntity (this .pomptCaptor .capture (), this .headersCaptor .capture ()))
238+ 			.willReturn (Mockito .mock (ResponseEntity .class ));
239+ 
240+ 		this .chatModel .call (
241+ 				new  Prompt (List .of (new  SystemMessage ("You are a helpful assistant" ), new  UserMessage ("Simple message" ),
242+ 						UserMessage .builder ().text ("Message with media" ).media (this .buildMediaList ()).build ())));
243+ 
244+ 		ChatCompletionRequest  request  = this .pomptCaptor .getValue ();
245+ 		assertThat (request .messages ()).hasSize (3 );
246+ 
247+ 		// First message - system message with string content 
248+ 		var  systemMessage  = request .messages ().get (0 );
249+ 		assertThat (systemMessage .rawContent ()).isInstanceOf (String .class );
250+ 		assertThat (systemMessage .content ()).isEqualTo ("You are a helpful assistant" );
251+ 
252+ 		// Second message - user message with string content 
253+ 		var  simpleUserMessage  = request .messages ().get (1 );
254+ 		assertThat (simpleUserMessage .rawContent ()).isInstanceOf (String .class );
255+ 		assertThat (simpleUserMessage .content ()).isEqualTo ("Simple message" );
256+ 
257+ 		// Third message - user message with complex content 
258+ 		var  complexUserMessage  = request .messages ().get (2 );
259+ 		assertThat (complexUserMessage .rawContent ()).isInstanceOf (List .class );
260+ 	}
261+ 
262+ 	@ Test 
263+ 	public  void  userMessageWithSingleImageMedia () {
264+ 		given (this .openAiApi .chatCompletionEntity (this .pomptCaptor .capture (), this .headersCaptor .capture ()))
265+ 			.willReturn (Mockito .mock (ResponseEntity .class ));
266+ 
267+ 		URI  imageUri  = URI .create ("http://example.com/image.jpg" );
268+ 		Media  imageMedia  = Media .builder ().mimeType (MimeTypeUtils .IMAGE_JPEG ).data (imageUri ).build ();
269+ 
270+ 		this .chatModel .call (new  Prompt (
271+ 				List .of (UserMessage .builder ().text ("Describe this image" ).media (List .of (imageMedia )).build ())));
272+ 
273+ 		ChatCompletionRequest  request  = this .pomptCaptor .getValue ();
274+ 		assertThat (request .messages ()).hasSize (1 );
275+ 		var  userMessage  = request .messages ().get (0 );
276+ 		assertThat (userMessage .rawContent ()).isInstanceOf (List .class );
277+ 
278+ 		@ SuppressWarnings ("unchecked" )
279+ 		List <Map <String , Object >> mediaContents  = (List <Map <String , Object >>) userMessage .rawContent ();
280+ 		assertThat (mediaContents ).hasSize (2 );
281+ 
282+ 		// Text content 
283+ 		Map <String , Object > textContent  = mediaContents .get (0 );
284+ 		assertThat (textContent .get ("type" )).isEqualTo ("text" );
285+ 		assertThat (textContent .get ("text" )).isEqualTo ("Describe this image" );
286+ 
287+ 		// Image content 
288+ 		Map <String , Object > imageContent  = mediaContents .get (1 );
289+ 		assertThat (imageContent .get ("type" )).isEqualTo ("image_url" );
290+ 		assertThat (imageContent ).containsKey ("image_url" );
291+ 	}
292+ 
293+ 	@ Test 
294+ 	public  void  streamWithMultipleMessagesAndMedia () {
295+ 		given (this .openAiApi .chatCompletionStream (this .pomptCaptor .capture (), this .headersCaptor .capture ()))
296+ 			.willReturn (this .fluxResponse );
297+ 
298+ 		this .chatModel 
299+ 			.stream (new  Prompt (List .of (new  SystemMessage ("System prompt" ),
300+ 					UserMessage .builder ().text ("User message with media" ).media (this .buildMediaList ()).build ())))
301+ 			.subscribe ();
302+ 
303+ 		ChatCompletionRequest  request  = this .pomptCaptor .getValue ();
304+ 		assertThat (request .messages ()).hasSize (2 );
305+ 
306+ 		// System message should be string 
307+ 		assertThat (request .messages ().get (0 ).rawContent ()).isInstanceOf (String .class );
308+ 
309+ 		// User message should be complex 
310+ 		assertThat (request .messages ().get (1 ).rawContent ()).isInstanceOf (List .class );
311+ 		assertThat (this .headersCaptor .getValue ()).isEmpty ();
312+ 	}
313+ 
314+ 	// Helper method for testing different image formats 
315+ 	private  List <Media > buildImageMediaList () {
316+ 		URI  jpegUri  = URI .create ("http://example.com/image.jpg" );
317+ 		Media  jpegMedia  = Media .builder ().mimeType (MimeTypeUtils .IMAGE_JPEG ).data (jpegUri ).build ();
318+ 
319+ 		URI  pngUri  = URI .create ("http://example.com/image.png" );
320+ 		Media  pngMedia  = Media .builder ().mimeType (MimeTypeUtils .IMAGE_PNG ).data (pngUri ).build ();
321+ 
322+ 		URI  webpUri  = URI .create ("http://example.com/image.webp" );
323+ 		Media  webpMedia  = Media .builder ().mimeType (MimeType .valueOf ("image/webp" )).data (webpUri ).build ();
324+ 
325+ 		return  List .of (jpegMedia , pngMedia , webpMedia );
326+ 	}
327+ 
328+ 	@ Test 
329+ 	public  void  userMessageWithMultipleImageFormats () {
330+ 		given (this .openAiApi .chatCompletionEntity (this .pomptCaptor .capture (), this .headersCaptor .capture ()))
331+ 			.willReturn (Mockito .mock (ResponseEntity .class ));
332+ 
333+ 		this .chatModel .call (new  Prompt (
334+ 				List .of (UserMessage .builder ().text ("Compare these images" ).media (this .buildImageMediaList ()).build ())));
335+ 
336+ 		ChatCompletionRequest  request  = this .pomptCaptor .getValue ();
337+ 		assertThat (request .messages ()).hasSize (1 );
338+ 		var  userMessage  = request .messages ().get (0 );
339+ 		assertThat (userMessage .rawContent ()).isInstanceOf (List .class );
340+ 
341+ 		@ SuppressWarnings ("unchecked" )
342+ 		List <Map <String , Object >> mediaContents  = (List <Map <String , Object >>) userMessage .rawContent ();
343+ 		assertThat (mediaContents ).hasSize (4 ); // text + 3 images 
344+ 
345+ 		// Verify all are image types 
346+ 		for  (int  i  = 1 ; i  < mediaContents .size (); i ++) {
347+ 			Map <String , Object > imageContent  = mediaContents .get (i );
348+ 			assertThat (imageContent .get ("type" )).isEqualTo ("image_url" );
349+ 			assertThat (imageContent ).containsKey ("image_url" );
350+ 		}
351+ 	}
352+ 
199353}
0 commit comments