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