@@ -325,6 +325,156 @@ def test_upload_to_sg(self, mock_send_form):
325325 mock_send_form .assert_called_once ()
326326 self .sg .server_info ["s3_direct_uploads_enabled" ] = True
327327
328+ @unittest .mock .patch ("shotgun_api3.Shotgun._send_form" )
329+ def test_upload_to_sg_with_created_at (self , mock_send_form ):
330+ """
331+ Verify that created_at is passed as a form parameter when uploading
332+ non-thumbnail attachments via _upload_to_sg().
333+ """
334+ self .sg .server_info ["s3_direct_uploads_enabled" ] = False
335+ mock_send_form .return_value = "1\n :456\n asd"
336+ this_dir , _ = os .path .split (__file__ )
337+ u_path = os .path .abspath (
338+ os .path .expanduser (glob .glob (os .path .join (this_dir , "Noëlご.jpg" ))[0 ])
339+ )
340+ custom_time = datetime .datetime (2026 , 2 , 15 , 10 , 30 , 0 )
341+ self .sg .upload (
342+ "Version" ,
343+ self .version ["id" ],
344+ u_path ,
345+ "attachments" ,
346+ created_at = custom_time ,
347+ )
348+ mock_send_form .assert_called_once ()
349+ mock_send_form_args , _ = mock_send_form .call_args
350+ params = mock_send_form_args [1 ]
351+ self .assertIn ("created_at" , params )
352+ self .assertEqual (params ["created_at" ], custom_time )
353+ self .sg .server_info ["s3_direct_uploads_enabled" ] = True
354+
355+ @unittest .mock .patch ("shotgun_api3.Shotgun._send_form" )
356+ def test_upload_to_sg_without_created_at (self , mock_send_form ):
357+ """
358+ Verify that created_at is NOT included in form parameters when omitted.
359+ """
360+ self .sg .server_info ["s3_direct_uploads_enabled" ] = False
361+ mock_send_form .return_value = "1\n :456\n asd"
362+ this_dir , _ = os .path .split (__file__ )
363+ u_path = os .path .abspath (
364+ os .path .expanduser (glob .glob (os .path .join (this_dir , "Noëlご.jpg" ))[0 ])
365+ )
366+ self .sg .upload (
367+ "Version" ,
368+ self .version ["id" ],
369+ u_path ,
370+ "attachments" ,
371+ )
372+ mock_send_form .assert_called_once ()
373+ mock_send_form_args , _ = mock_send_form .call_args
374+ params = mock_send_form_args [1 ]
375+ self .assertNotIn ("created_at" , params )
376+ self .sg .server_info ["s3_direct_uploads_enabled" ] = True
377+
378+ @unittest .mock .patch ("shotgun_api3.Shotgun._send_form" )
379+ @unittest .mock .patch ("shotgun_api3.Shotgun._upload_file_to_storage" )
380+ @unittest .mock .patch ("shotgun_api3.Shotgun._get_attachment_upload_info" )
381+ def test_upload_to_storage_with_created_at (
382+ self , mock_get_info , mock_upload_file , mock_send_form
383+ ):
384+ """
385+ Verify that created_at is passed as a form parameter when uploading
386+ non-thumbnail attachments via _upload_to_storage() (S3/cloud path).
387+ """
388+ self .sg .server_info ["s3_direct_uploads_enabled" ] = True
389+ self .sg .server_info ["s3_enabled_upload_types" ] = {"Version" : "*" }
390+ mock_get_info .return_value = {
391+ "upload_url" : "https://example.com/upload" ,
392+ "upload_info" : {"upload_type" : "s3" },
393+ }
394+ mock_send_form .return_value = "1\n :456\n asd"
395+ this_dir , _ = os .path .split (__file__ )
396+ u_path = os .path .abspath (
397+ os .path .expanduser (glob .glob (os .path .join (this_dir , "Noëlご.jpg" ))[0 ])
398+ )
399+ custom_time = datetime .datetime (2026 , 2 , 15 , 10 , 30 , 0 )
400+ self .sg .upload (
401+ "Version" ,
402+ self .version ["id" ],
403+ u_path ,
404+ "attachments" ,
405+ created_at = custom_time ,
406+ )
407+ mock_get_info .assert_called_once ()
408+ mock_send_form .assert_called_once ()
409+ mock_send_form_args , _ = mock_send_form .call_args
410+ params = mock_send_form_args [1 ]
411+ self .assertIn ("created_at" , params )
412+ self .assertEqual (params ["created_at" ], custom_time )
413+
414+ @unittest .mock .patch ("shotgun_api3.Shotgun._send_form" )
415+ @unittest .mock .patch ("shotgun_api3.Shotgun._upload_file_to_storage" )
416+ @unittest .mock .patch ("shotgun_api3.Shotgun._get_attachment_upload_info" )
417+ def test_upload_to_storage_without_created_at (
418+ self , mock_get_info , mock_upload_file , mock_send_form
419+ ):
420+ """
421+ Verify that created_at is NOT included in form parameters when omitted
422+ via _upload_to_storage() (S3/cloud path).
423+ """
424+ self .sg .server_info ["s3_direct_uploads_enabled" ] = True
425+ self .sg .server_info ["s3_enabled_upload_types" ] = {"Version" : "*" }
426+ mock_get_info .return_value = {
427+ "upload_url" : "https://example.com/upload" ,
428+ "upload_info" : {"upload_type" : "s3" },
429+ }
430+ mock_send_form .return_value = "1\n :456\n asd"
431+ this_dir , _ = os .path .split (__file__ )
432+ u_path = os .path .abspath (
433+ os .path .expanduser (glob .glob (os .path .join (this_dir , "Noëlご.jpg" ))[0 ])
434+ )
435+ self .sg .upload (
436+ "Version" ,
437+ self .version ["id" ],
438+ u_path ,
439+ "attachments" ,
440+ )
441+ mock_get_info .assert_called_once ()
442+ mock_send_form .assert_called_once ()
443+ mock_send_form_args , _ = mock_send_form .call_args
444+ params = mock_send_form_args [1 ]
445+ self .assertNotIn ("created_at" , params )
446+
447+ def test_upload_created_at_invalid_type (self ):
448+ """
449+ Verify that passing a non-datetime value for created_at raises ShotgunError.
450+ """
451+ this_dir , _ = os .path .split (__file__ )
452+ u_path = os .path .abspath (
453+ os .path .expanduser (glob .glob (os .path .join (this_dir , "Noëlご.jpg" ))[0 ])
454+ )
455+ with self .assertRaisesRegex (
456+ shotgun_api3 .ShotgunError ,
457+ "created_at must be a datetime.datetime instance" ,
458+ ):
459+ self .sg .upload (
460+ "Version" ,
461+ self .version ["id" ],
462+ u_path ,
463+ "attachments" ,
464+ created_at = "2026-02-15T10:30:00Z" ,
465+ )
466+ with self .assertRaisesRegex (
467+ shotgun_api3 .ShotgunError ,
468+ "created_at must be a datetime.datetime instance" ,
469+ ):
470+ self .sg .upload (
471+ "Version" ,
472+ self .version ["id" ],
473+ u_path ,
474+ "attachments" ,
475+ created_at = 1234567890 ,
476+ )
477+
328478 def test_upload_thumbnail_in_create (self ):
329479 """Upload a thumbnail via the create method"""
330480 this_dir , _ = os .path .split (__file__ )
0 commit comments