@@ -760,4 +760,102 @@ mod tests {
760760 result. to_string_lossy( ) . contains( "src" ) && result. to_string_lossy( ) . contains( "routes" )
761761 ) ;
762762 }
763+
764+ // ========== Error path coverage tests ==========
765+
766+ #[ test]
767+ fn test_generate_and_write_openapi_file_write_error ( ) {
768+ // Line 95: fs::write failure when output path is a directory
769+ let temp_dir = TempDir :: new ( ) . expect ( "Failed to create temp dir" ) ;
770+
771+ // Create a directory where the output file should be
772+ let output_path = temp_dir. path ( ) . join ( "openapi.json" ) ;
773+ fs:: create_dir ( & output_path) . expect ( "Failed to create directory" ) ;
774+
775+ let processed = ProcessedVesperaInput {
776+ folder_name : "routes" . to_string ( ) ,
777+ openapi_file_names : vec ! [ output_path. to_string_lossy( ) . to_string( ) ] ,
778+ title : Some ( "Test API" . to_string ( ) ) ,
779+ version : Some ( "1.0.0" . to_string ( ) ) ,
780+ docs_url : None ,
781+ redoc_url : None ,
782+ servers : None ,
783+ merge : vec ! [ ] ,
784+ } ;
785+ let metadata = CollectedMetadata :: new ( ) ;
786+
787+ let result = generate_and_write_openapi ( & processed, & metadata) ;
788+ assert ! ( result. is_err( ) ) ;
789+ let err = result. unwrap_err ( ) . to_string ( ) ;
790+ assert ! ( err. contains( "failed to write file" ) ) ;
791+ }
792+
793+ #[ test]
794+ fn test_process_export_app_collect_metadata_error ( ) {
795+ // Lines 210-212: collect_metadata returns error for invalid Rust syntax
796+ let temp_dir = TempDir :: new ( ) . expect ( "Failed to create temp dir" ) ;
797+
798+ // Create a file with invalid Rust syntax that will cause parse error
799+ create_temp_file ( & temp_dir, "invalid.rs" , "fn broken( { syntax error" ) ;
800+
801+ let name: syn:: Ident = syn:: parse_quote!( TestApp ) ;
802+ let folder_path = temp_dir. path ( ) . to_string_lossy ( ) . to_string ( ) ;
803+
804+ let result =
805+ process_export_app ( & name, & folder_path, & [ ] , & temp_dir. path ( ) . to_string_lossy ( ) ) ;
806+
807+ assert ! ( result. is_err( ) ) ;
808+ let err = result. unwrap_err ( ) . to_string ( ) ;
809+ assert ! ( err. contains( "failed to scan route folder" ) ) ;
810+ }
811+
812+ #[ test]
813+ fn test_process_export_app_create_dir_error ( ) {
814+ // Lines 232-234: create_dir_all failure when path contains a file
815+ let temp_dir = TempDir :: new ( ) . expect ( "Failed to create temp dir" ) ;
816+
817+ // Create an empty valid Rust file
818+ create_temp_file ( & temp_dir, "empty.rs" , "// empty file\n " ) ;
819+
820+ // Create target directory but make 'vespera' a file instead of directory
821+ let target_dir = temp_dir. path ( ) . join ( "target" ) ;
822+ fs:: create_dir ( & target_dir) . expect ( "Failed to create target dir" ) ;
823+ fs:: write ( target_dir. join ( "vespera" ) , "blocking file" ) . expect ( "Failed to write file" ) ;
824+
825+ let name: syn:: Ident = syn:: parse_quote!( TestApp ) ;
826+ let folder_path = temp_dir. path ( ) . to_string_lossy ( ) . to_string ( ) ;
827+
828+ let result =
829+ process_export_app ( & name, & folder_path, & [ ] , & temp_dir. path ( ) . to_string_lossy ( ) ) ;
830+
831+ assert ! ( result. is_err( ) ) ;
832+ let err = result. unwrap_err ( ) . to_string ( ) ;
833+ assert ! ( err. contains( "failed to create build cache directory" ) ) ;
834+ }
835+
836+ #[ test]
837+ fn test_process_export_app_write_spec_error ( ) {
838+ // Lines 239-241: fs::write failure when spec file path is a directory
839+ let temp_dir = TempDir :: new ( ) . expect ( "Failed to create temp dir" ) ;
840+
841+ // Create an empty valid Rust file
842+ create_temp_file ( & temp_dir, "empty.rs" , "// empty file\n " ) ;
843+
844+ // Create target/vespera directory and make spec file name a directory
845+ let vespera_dir = temp_dir. path ( ) . join ( "target" ) . join ( "vespera" ) ;
846+ fs:: create_dir_all ( & vespera_dir) . expect ( "Failed to create vespera dir" ) ;
847+ // Create a directory where the spec file should be written
848+ fs:: create_dir ( vespera_dir. join ( "TestApp.openapi.json" ) )
849+ . expect ( "Failed to create blocking dir" ) ;
850+
851+ let name: syn:: Ident = syn:: parse_quote!( TestApp ) ;
852+ let folder_path = temp_dir. path ( ) . to_string_lossy ( ) . to_string ( ) ;
853+
854+ let result =
855+ process_export_app ( & name, & folder_path, & [ ] , & temp_dir. path ( ) . to_string_lossy ( ) ) ;
856+
857+ assert ! ( result. is_err( ) ) ;
858+ let err = result. unwrap_err ( ) . to_string ( ) ;
859+ assert ! ( err. contains( "failed to write OpenAPI spec file" ) ) ;
860+ }
763861}
0 commit comments