@@ -371,6 +371,174 @@ async fn watch_and_vite_integration_test() {
371371 vite_errors
372372 ) ;
373373
374+ // Modify hello world source file and monitor for rebuild
375+ let hello_world_file = "contracts/hello_world/src/lib.rs" ;
376+ let modified_content = r#"#![no_std]
377+ use soroban_sdk::{contract, contractimpl, vec, Env, String, Vec};
378+
379+ #[contract]
380+ pub struct HelloContract;
381+
382+ #[contractimpl]
383+ impl HelloContract {
384+ pub fn hello(env: Env, to: String) -> Vec<String> {
385+ vec![&env, String::from_str(&env, "Hello modified world"), to]
386+ }
387+ }
388+
389+ mod test;
390+ "# ;
391+
392+ env. modify_file ( hello_world_file, modified_content) ;
393+ let file_changed_path = env. cwd . join ( hello_world_file) ;
394+
395+ // Monitor for file change detection and rebuild
396+ let mut file_change_detected = false ;
397+ let mut rebuild_started = false ;
398+ let mut rebuild_completed = false ;
399+ let mut new_vite_errors = Vec :: new ( ) ;
400+
401+ let client = reqwest:: Client :: new ( ) ;
402+ let hello_world_client_path = "/src/contracts/stellar_hello_world_contract.ts" ;
403+
404+ // Monitor for 60 seconds for the rebuild process
405+ let rebuild_timeout = tokio:: time:: Duration :: from_secs ( 60 ) ;
406+ let rebuild_start_time = tokio:: time:: Instant :: now ( ) ;
407+
408+ while rebuild_start_time. elapsed ( ) < rebuild_timeout {
409+ // Check for output from watch process
410+ match tokio:: time:: timeout (
411+ tokio:: time:: Duration :: from_millis ( 500 ) ,
412+ output_receiver. recv ( ) ,
413+ )
414+ . await
415+ {
416+ Ok ( Some ( ( source, line) ) ) => {
417+ println ! ( "📝 [{}] {}" , source, line) ;
418+
419+ // Check for file change detection
420+ if !file_change_detected
421+ && line. contains ( "File changed:" )
422+ && line. contains ( & format ! ( "{file_changed_path:?}" ) )
423+ {
424+ file_change_detected = true ;
425+ }
426+
427+ // Check for rebuild start
428+ if !rebuild_started && line. contains ( "cargo rustc" ) {
429+ rebuild_started = true ;
430+ }
431+
432+ // Check for rebuild completion
433+ if !rebuild_completed
434+ && file_change_detected
435+ && rebuild_started
436+ && line. contains ( "Watching for changes. Press Ctrl+C to stop." )
437+ {
438+ rebuild_completed = true ;
439+ }
440+
441+ // Check for new vite errors during rebuild
442+ if line. contains ( "Internal server error" )
443+ || line. contains ( "Failed to resolve import" )
444+ || line. contains ( "Does the file exist?" )
445+ {
446+ new_vite_errors. push ( line. clone ( ) ) ;
447+ }
448+ }
449+ Ok ( None ) => {
450+ panic ! ( "Output channel closed unexpectedly during rebuild test" ) ;
451+ }
452+ Err ( _) => {
453+ // Timeout occurred, periodically query the hello world client file
454+ if file_change_detected {
455+ match client
456+ . get ( & format ! (
457+ "http://localhost:{}{}" ,
458+ port, hello_world_client_path
459+ ) )
460+ . timeout ( tokio:: time:: Duration :: from_secs ( 5 ) )
461+ . send ( )
462+ . await
463+ {
464+ Ok ( response) => {
465+ if response. status ( ) . is_success ( ) {
466+ println ! (
467+ "✅ Hello world client file accessible during rebuild"
468+ ) ;
469+ } else {
470+ println ! (
471+ "⚠️ Hello world client file returned status: {}" ,
472+ response. status( )
473+ ) ;
474+ }
475+ }
476+ Err ( e) => {
477+ println ! ( "⚠️ Error querying hello world client file: {}" , e) ;
478+ }
479+ }
480+ }
481+ continue ;
482+ }
483+ }
484+
485+ // Break if rebuild is complete
486+ if rebuild_completed {
487+ break ;
488+ }
489+ }
490+
491+ assert ! (
492+ file_change_detected,
493+ "File change was not detected by watch process"
494+ ) ;
495+
496+ assert ! (
497+ rebuild_started,
498+ "Rebuild process did not start after file change"
499+ ) ;
500+
501+ assert ! (
502+ rebuild_completed,
503+ "Rebuild process did not complete within timeout"
504+ ) ;
505+
506+ // Final check for any vite errors that occurred during rebuild
507+ tokio:: time:: sleep ( tokio:: time:: Duration :: from_secs ( 2 ) ) . await ;
508+ while let Ok ( ( _, line) ) = output_receiver. try_recv ( ) {
509+ if line. contains ( "Internal server error" )
510+ || line. contains ( "Failed to resolve import" )
511+ || line. contains ( "Does the file exist?" )
512+ {
513+ new_vite_errors. push ( line. clone ( ) ) ;
514+ }
515+ }
516+
517+ assert ! (
518+ new_vite_errors. is_empty( ) ,
519+ "Vite errors detected during hello world rebuild. Errors found: {:?}" ,
520+ new_vite_errors
521+ ) ;
522+
523+ // Final verification that hello world client is accessible after rebuild
524+ let final_response = client
525+ . get ( & format ! (
526+ "http://localhost:{}{}" ,
527+ port, hello_world_client_path
528+ ) )
529+ . timeout ( tokio:: time:: Duration :: from_secs ( 10 ) )
530+ . send ( )
531+ . await
532+ . expect ( "Failed to query hello world client after rebuild" ) ;
533+
534+ assert ! (
535+ final_response. status( ) . is_success( ) ,
536+ "Hello world client file not accessible after rebuild: {}" ,
537+ final_response. status( )
538+ ) ;
539+
540+ println ! ( "✅ Hello world modification and rebuild test completed successfully" ) ;
541+
374542 // Cleanup
375543 stdout_monitor. abort ( ) ;
376544 stderr_monitor. abort ( ) ;
0 commit comments