@@ -756,6 +756,93 @@ mod tests {
756756 assert ! ( result. is_err( ) ) ;
757757 }
758758
759+ #[ tokio:: test]
760+ async fn test_execute_malformed_upload_workitem_attachment_returns_err ( ) {
761+ // Missing required fields (work_item_id, file_path)
762+ let entry = serde_json:: json!( { "name" : "upload-workitem-attachment" } ) ;
763+ let ctx = ExecutionContext :: default ( ) ;
764+
765+ let result = execute_safe_output ( & entry, & ctx) . await ;
766+ assert ! ( result. is_err( ) ) ;
767+ }
768+
769+ #[ tokio:: test]
770+ async fn test_execute_upload_workitem_attachment_missing_context ( ) {
771+ let entry = serde_json:: json!( {
772+ "name" : "upload-workitem-attachment" ,
773+ "work_item_id" : 12345 ,
774+ "file_path" : "report.log"
775+ } ) ;
776+
777+ // Context without required fields (ado_org_url, etc.)
778+ let ctx = ExecutionContext {
779+ ado_org_url : None ,
780+ ado_organization : None ,
781+ ado_project : None ,
782+ access_token : None ,
783+ working_directory : PathBuf :: from ( "." ) ,
784+ source_directory : PathBuf :: from ( "." ) ,
785+ tool_configs : HashMap :: new ( ) ,
786+ repository_id : None ,
787+ repository_name : None ,
788+ allowed_repositories : HashMap :: new ( ) ,
789+ agent_stats : None ,
790+ dry_run : false ,
791+ ..Default :: default ( )
792+ } ;
793+
794+ let result = execute_safe_output ( & entry, & ctx) . await ;
795+ assert ! ( result. is_err( ) ) ;
796+ assert ! (
797+ result
798+ . unwrap_err( )
799+ . to_string( )
800+ . contains( "AZURE_DEVOPS_ORG_URL" )
801+ ) ;
802+ }
803+
804+ #[ tokio:: test]
805+ async fn test_execute_malformed_upload_build_attachment_returns_err ( ) {
806+ // Missing required fields (artifact_name, file_path, staged_file, etc.)
807+ let entry = serde_json:: json!( { "name" : "upload-build-attachment" } ) ;
808+ let ctx = ExecutionContext :: default ( ) ;
809+
810+ let result = execute_safe_output ( & entry, & ctx) . await ;
811+ assert ! ( result. is_err( ) ) ;
812+ }
813+
814+ #[ tokio:: test]
815+ async fn test_execute_upload_build_attachment_missing_context ( ) {
816+ let entry = serde_json:: json!( {
817+ "name" : "upload-build-attachment" ,
818+ "artifact_name" : "my-artifact" ,
819+ "file_path" : "staged_file.txt" ,
820+ "staged_file" : "staged_file.txt" ,
821+ "file_size" : 5_u64 ,
822+ "staged_sha256" : "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
823+ } ) ;
824+
825+ // Context without required fields (ado_org_url, etc.)
826+ let ctx = ExecutionContext {
827+ ado_org_url : None ,
828+ ado_organization : None ,
829+ ado_project : None ,
830+ access_token : None ,
831+ working_directory : PathBuf :: from ( "." ) ,
832+ source_directory : PathBuf :: from ( "." ) ,
833+ tool_configs : HashMap :: new ( ) ,
834+ repository_id : None ,
835+ repository_name : None ,
836+ allowed_repositories : HashMap :: new ( ) ,
837+ agent_stats : None ,
838+ dry_run : false ,
839+ ..Default :: default ( )
840+ } ;
841+
842+ let result = execute_safe_output ( & entry, & ctx) . await ;
843+ assert ! ( result. is_err( ) ) ;
844+ }
845+
759846 #[ tokio:: test]
760847 async fn test_execute_comment_on_work_item_missing_context ( ) {
761848 let entry = serde_json:: json!( {
0 commit comments