@@ -633,5 +633,67 @@ public void FrontendUpdateTimer_Execute_ConcurrentDictionaryModification_ShouldN
633
633
Assert . Fail ( $ "Unexpected exceptions occurred: { exceptionSummary } ") ;
634
634
}
635
635
}
636
+
637
+ [ TestMethod ]
638
+ public void ExecuteConfig_WithNoControllersConnected_ShouldStillExecuteConfigItems ( )
639
+ {
640
+ // Arrange
641
+ var outputConfigItem = new OutputConfigItem
642
+ {
643
+ GUID = Guid . NewGuid ( ) . ToString ( ) ,
644
+ Active = true ,
645
+ Name = "TestOutput" ,
646
+ Source = new VariableSource ( )
647
+ {
648
+ MobiFlightVariable = new MobiFlightVariable ( ) { Name = "TestVar" , Number = 123.45 }
649
+ } ,
650
+ Device = new OutputConfig . CustomDevice ( ) { CustomName = "TestDevice" } ,
651
+ DeviceType = "InputAction" // Special type that doesn't require physical devices
652
+ } ;
653
+
654
+ var project = new Project ( ) ;
655
+ project . ConfigFiles . Add ( new ConfigFile ( )
656
+ {
657
+ ConfigItems = { outputConfigItem }
658
+ } ) ;
659
+ _executionManager . Project = project ;
660
+
661
+ // Verify no controllers are connected
662
+ Assert . IsFalse ( _executionManager . ModulesAvailable ( ) , "No MobiFlight modules and/or Arcaze Boards should be connected" ) ;
663
+ Assert . IsFalse ( _executionManager . GetJoystickManager ( ) . JoysticksConnected ( ) , "No joysticks should be connected" ) ;
664
+ Assert . IsFalse ( _executionManager . GetMidiBoardManager ( ) . AreMidiBoardsConnected ( ) , "No midi controllers should be connected." ) ;
665
+
666
+ // Set up the variable so the config item has data to read
667
+ _executionManager . getMobiFlightModuleCache ( ) . SetMobiFlightVariable (
668
+ new MobiFlightVariable ( ) { Name = "TestVar" , Number = 123.45 } ) ;
669
+
670
+ // Get access to the updatedValues dictionary via reflection
671
+ var updatedValuesField = typeof ( ExecutionManager ) . GetField ( "updatedValues" ,
672
+ BindingFlags . NonPublic | BindingFlags . Instance ) ;
673
+ var updatedValues = ( Dictionary < string , IConfigItem > ) updatedValuesField . GetValue ( _executionManager ) ;
674
+
675
+ var initialUpdatedValuesCount = updatedValues . Count ;
676
+
677
+ // Act - Instead of relying on timer, directly call ExecuteConfig via reflection
678
+ _executionManager . Start ( ) ; // This sets up the execution manager state
679
+
680
+ // Use reflection to call the private ExecuteConfig method directly
681
+ var executeConfigMethod = typeof ( ExecutionManager ) . GetMethod ( "ExecuteConfig" ,
682
+ BindingFlags . NonPublic | BindingFlags . Instance ) ;
683
+ Assert . IsNotNull ( executeConfigMethod , "ExecuteConfig method should exist" ) ;
684
+
685
+ executeConfigMethod . Invoke ( _executionManager , null ) ;
686
+
687
+ // Assert - The config item should be processed and cloned into updatedValues
688
+ Assert . IsTrue ( updatedValues . ContainsKey ( outputConfigItem . GUID ) ,
689
+ "Config item should be cloned and added to updatedValues when processed" ) ;
690
+
691
+ var clonedConfigItem = updatedValues [ outputConfigItem . GUID ] as OutputConfigItem ;
692
+ Assert . IsNotNull ( clonedConfigItem , "Updated config item should be an OutputConfigItem" ) ;
693
+ Assert . AreEqual ( "123.45" , clonedConfigItem . Value ,
694
+ "Cloned config item should display the correct variable value" ) ;
695
+ Assert . AreEqual ( "123.45" , clonedConfigItem . RawValue ,
696
+ "Cloned config item should have the correct raw value" ) ;
697
+ }
636
698
}
637
699
}
0 commit comments