@@ -572,3 +572,311 @@ fn test_fitness_info() {
572572 let err = get_fitness_info ( "unknown_function" ) ;
573573 assert ! ( err. is_err( ) ) ;
574574}
575+
576+ // ============================================================================
577+ // Evolution Strategy Extended Tests
578+ // ============================================================================
579+
580+ use fugue_evo_wasm:: ESSelection ;
581+
582+ #[ wasm_bindgen_test]
583+ fn test_evolution_strategy_mu_plus_lambda ( ) {
584+ let mut optimizer = EvolutionStrategyOptimizer :: new ( 3 ) ;
585+ optimizer. set_mu ( 5 ) ;
586+ optimizer. set_lambda ( 20 ) ;
587+ optimizer. set_selection_strategy ( ESSelection :: MuPlusLambda ) ;
588+ optimizer. set_initial_sigma ( 0.5 ) ;
589+ optimizer. set_self_adaptive ( true ) ;
590+ optimizer. set_population_size ( 20 ) ;
591+ optimizer. set_max_generations ( 30 ) ;
592+ optimizer. set_bounds ( -5.0 , 5.0 ) ;
593+ optimizer. set_seed ( 42 ) ;
594+ // Can't actually call optimize without a JS fitness function
595+ // Just verify configuration doesn't panic
596+ }
597+
598+ #[ wasm_bindgen_test]
599+ fn test_evolution_strategy_mu_comma_lambda ( ) {
600+ let mut optimizer = EvolutionStrategyOptimizer :: new ( 3 ) ;
601+ optimizer. set_mu ( 5 ) ;
602+ optimizer. set_lambda ( 30 ) ;
603+ optimizer. set_selection_strategy ( ESSelection :: MuCommaLambda ) ;
604+ optimizer. set_initial_sigma ( 1.0 ) ;
605+ optimizer. set_self_adaptive ( false ) ;
606+ optimizer. set_population_size ( 30 ) ;
607+ optimizer. set_max_generations ( 20 ) ;
608+ optimizer. set_bounds ( -10.0 , 10.0 ) ;
609+ optimizer. set_seed ( 123 ) ;
610+ // Configuration verified by not panicking
611+ }
612+
613+ // ============================================================================
614+ // BitStringResult Extended Tests
615+ // ============================================================================
616+
617+ #[ wasm_bindgen_test]
618+ fn test_bitstring_result_methods ( ) {
619+ let mut optimizer = BitStringOptimizer :: new ( 16 ) ;
620+ optimizer. set_population_size ( 30 ) ;
621+ optimizer. set_max_generations ( 50 ) ;
622+ optimizer. set_seed ( 42 ) ;
623+
624+ let result = optimizer. solve_one_max ( ) . expect ( "Should succeed" ) ;
625+
626+ // Test count_ones
627+ let ones_count = result. count_ones ( ) ;
628+ assert ! ( ones_count <= 16 ) ;
629+ assert ! ( ones_count > 0 ) ;
630+
631+ // Test best_genome_string
632+ let genome_str = result. best_genome_string ( ) ;
633+ assert_eq ! ( genome_str. len( ) , 16 ) ;
634+ assert ! ( genome_str. chars( ) . all( |c| c == '0' || c == '1' ) ) ;
635+
636+ // Test fitness_history
637+ let history = result. fitness_history ( ) ;
638+ assert ! ( !history. is_empty( ) ) ;
639+ }
640+
641+ // ============================================================================
642+ // MultiObjectiveResult Extended Tests
643+ // ============================================================================
644+
645+ #[ wasm_bindgen_test]
646+ fn test_multi_objective_result_methods ( ) {
647+ let mut optimizer = Nsga2Optimizer :: new ( 5 , 2 ) ;
648+ optimizer. set_population_size ( 30 ) ;
649+ optimizer. set_max_generations ( 20 ) ;
650+ optimizer. set_seed ( 42 ) ;
651+
652+ let result = optimizer
653+ . optimize_zdt ( ZdtProblem :: Zdt1 )
654+ . expect ( "Should succeed" ) ;
655+
656+ // Test front_size
657+ let front_size = result. front_size ( ) ;
658+ assert ! ( front_size > 0 ) ;
659+
660+ // Test generations and evaluations
661+ assert_eq ! ( result. generations( ) , 20 ) ;
662+ assert ! ( result. evaluations( ) > 0 ) ;
663+
664+ // Test get_solution
665+ if front_size > 0 {
666+ let solution = result. get_solution ( 0 ) . expect ( "Should get first solution" ) ;
667+ assert ! ( !solution. genome( ) . is_empty( ) ) ;
668+ assert ! ( !solution. objectives( ) . is_empty( ) ) ;
669+ }
670+
671+ // Test all_genomes and all_objectives
672+ let all_genomes = result. all_genomes ( ) ;
673+ let all_objectives = result. all_objectives ( ) ;
674+ assert ! ( !all_genomes. is_empty( ) ) ;
675+ assert ! ( !all_objectives. is_empty( ) ) ;
676+
677+ // Test to_json
678+ let json = result. to_json ( ) . expect ( "Should serialize to JSON" ) ;
679+ assert ! ( json. contains( "pareto_front" ) ) ;
680+ }
681+
682+ // ============================================================================
683+ // Additional Fitness Function Tests
684+ // ============================================================================
685+
686+ #[ wasm_bindgen_test]
687+ fn test_dixon_price_optimization ( ) {
688+ let mut optimizer = RealVectorOptimizer :: new ( 3 ) ;
689+ optimizer. set_population_size ( 30 ) ;
690+ optimizer. set_max_generations ( 50 ) ;
691+ optimizer. set_bounds ( -10.0 , 10.0 ) ;
692+ optimizer. set_fitness ( "dixon_price" ) ;
693+ optimizer. set_seed ( 42 ) ;
694+
695+ let result = optimizer
696+ . optimize ( )
697+ . expect ( "Dixon-Price optimization should succeed" ) ;
698+ assert ! ( result. best_fitness( ) >= 0.0 ) ;
699+ }
700+
701+ #[ wasm_bindgen_test]
702+ fn test_styblinski_tang_optimization ( ) {
703+ let mut optimizer = RealVectorOptimizer :: new ( 3 ) ;
704+ optimizer. set_population_size ( 30 ) ;
705+ optimizer. set_max_generations ( 50 ) ;
706+ optimizer. set_bounds ( -5.0 , 5.0 ) ;
707+ optimizer. set_fitness ( "styblinski_tang" ) ;
708+ optimizer. set_seed ( 42 ) ;
709+
710+ let result = optimizer
711+ . optimize ( )
712+ . expect ( "Styblinski-Tang optimization should succeed" ) ;
713+ // Result can be negative for Styblinski-Tang
714+ assert ! ( result. evaluations( ) > 0 ) ;
715+ }
716+
717+ // ============================================================================
718+ // Interactive Evolution Tests
719+ // ============================================================================
720+
721+ use fugue_evo_wasm:: { InteractiveOptimizer , StepResultType , WasmEvaluationMode } ;
722+
723+ #[ wasm_bindgen_test]
724+ fn test_interactive_optimizer_creation ( ) {
725+ let _optimizer = InteractiveOptimizer :: new ( 5 ) ;
726+ }
727+
728+ #[ wasm_bindgen_test]
729+ fn test_interactive_optimizer_with_config ( ) {
730+ let _optimizer = InteractiveOptimizer :: with_config (
731+ 5 , // dimension
732+ 20 , // population_size
733+ WasmEvaluationMode :: Rating , // evaluation_mode
734+ 5 , // batch_size
735+ 10 , // max_generations
736+ ) ;
737+ }
738+
739+ #[ wasm_bindgen_test]
740+ fn test_interactive_optimizer_with_extended_config ( ) {
741+ let _optimizer = InteractiveOptimizer :: with_extended_config (
742+ 5 , // dimension
743+ 20 , // population_size
744+ WasmEvaluationMode :: Pairwise , // evaluation_mode
745+ 5 , // batch_size
746+ 3 , // select_count
747+ 10 , // max_generations
748+ 2 , // elitism_count
749+ 0.8 , // min_coverage
750+ 0.9 , // crossover_probability
751+ 0.1 , // mutation_probability
752+ -5.0 , // lower_bound
753+ 5.0 , // upper_bound
754+ ) ;
755+ }
756+
757+ #[ wasm_bindgen_test]
758+ fn test_interactive_optimizer_step ( ) {
759+ let mut optimizer = InteractiveOptimizer :: with_config ( 3 , 10 , WasmEvaluationMode :: Rating , 3 , 5 ) ;
760+ optimizer. set_seed ( 42 ) ;
761+
762+ // First step should request evaluation
763+ let step_result = optimizer. step ( ) ;
764+ assert ! ( step_result. needs_evaluation( ) ) ;
765+ assert ! ( matches!(
766+ step_result. result_type( ) ,
767+ StepResultType :: NeedsEvaluation
768+ ) ) ;
769+
770+ // Verify we can get the request
771+ let request = step_result. get_request ( ) . expect ( "Should have request" ) ;
772+ assert ! ( request. candidate_count( ) > 0 ) ;
773+ }
774+
775+ #[ wasm_bindgen_test]
776+ fn test_interactive_optimizer_getters ( ) {
777+ let mut optimizer = InteractiveOptimizer :: with_config ( 3 , 10 , WasmEvaluationMode :: Rating , 3 , 5 ) ;
778+ optimizer. set_seed ( 42 ) ;
779+
780+ // Test initial state getters
781+ assert_eq ! ( optimizer. generation( ) , 0 ) ;
782+ assert_eq ! ( optimizer. population_size( ) , 10 ) ;
783+ assert ! ( optimizer. get_coverage( ) >= 0.0 ) ;
784+
785+ // Get population JSON
786+ let pop_json = optimizer
787+ . get_population_json ( )
788+ . expect ( "Should get population JSON" ) ;
789+ assert ! ( pop_json. contains( '[' ) ) ;
790+ }
791+
792+ #[ wasm_bindgen_test]
793+ fn test_interactive_optimizer_batch_selection_mode ( ) {
794+ let optimizer =
795+ InteractiveOptimizer :: with_config ( 3 , 10 , WasmEvaluationMode :: BatchSelection , 5 , 5 ) ;
796+
797+ assert_eq ! ( optimizer. population_size( ) , 10 ) ;
798+ }
799+
800+ // ============================================================================
801+ // Evaluation Request Tests
802+ // ============================================================================
803+
804+ #[ wasm_bindgen_test]
805+ fn test_evaluation_request_methods ( ) {
806+ let mut optimizer = InteractiveOptimizer :: with_config ( 3 , 10 , WasmEvaluationMode :: Rating , 3 , 5 ) ;
807+ optimizer. set_seed ( 42 ) ;
808+
809+ let step_result = optimizer. step ( ) ;
810+ let request = step_result. get_request ( ) . expect ( "Should have request" ) ;
811+
812+ // Test request type
813+ use fugue_evo_wasm:: RequestType ;
814+ assert ! ( matches!( request. request_type( ) , RequestType :: Rating ) ) ;
815+
816+ // Test candidate access
817+ let candidate_count = request. candidate_count ( ) ;
818+ assert ! ( candidate_count > 0 ) ;
819+
820+ // Test get candidate
821+ if candidate_count > 0 {
822+ let candidate = request
823+ . get_candidate ( 0 )
824+ . expect ( "Should get first candidate" ) ;
825+ assert ! ( candidate. genome( ) . len( ) == 3 ) ;
826+ assert ! ( !candidate. is_evaluated( ) ) ;
827+ assert_eq ! ( candidate. evaluation_count( ) , 0 ) ;
828+ }
829+
830+ // Test get candidate IDs
831+ let ids = request. get_candidate_ids ( ) ;
832+ assert_eq ! ( ids. len( ) , candidate_count) ;
833+
834+ // Test get candidates JSON
835+ let json = request
836+ . get_candidates_json ( )
837+ . expect ( "Should serialize candidates" ) ;
838+ assert ! ( json. contains( '[' ) ) ;
839+
840+ // Test scale bounds
841+ assert ! ( request. scale_min( ) <= request. scale_max( ) ) ;
842+
843+ // Test to_json
844+ let request_json = request. to_json ( ) . expect ( "Should serialize request" ) ;
845+ assert ! ( request_json. contains( "request_type" ) ) ;
846+ }
847+
848+ // ============================================================================
849+ // WasmCandidate Tests
850+ // ============================================================================
851+
852+ #[ wasm_bindgen_test]
853+ fn test_wasm_candidate_methods ( ) {
854+ let mut optimizer = InteractiveOptimizer :: with_config ( 3 , 10 , WasmEvaluationMode :: Rating , 3 , 5 ) ;
855+ optimizer. set_seed ( 42 ) ;
856+
857+ let step_result = optimizer. step ( ) ;
858+ let request = step_result. get_request ( ) . expect ( "Should have request" ) ;
859+ let candidate = request. get_candidate ( 0 ) . expect ( "Should get candidate" ) ;
860+
861+ // Test id
862+ let id = candidate. id ( ) ;
863+ assert ! ( id < 1000 ) ; // Reasonable ID
864+
865+ // Test genome
866+ let genome = candidate. genome ( ) ;
867+ assert_eq ! ( genome. len( ) , 3 ) ;
868+
869+ // Test fitness (should be None initially)
870+ assert ! ( candidate. fitness( ) . is_none( ) ) ;
871+
872+ // Test evaluation count
873+ assert_eq ! ( candidate. evaluation_count( ) , 0 ) ;
874+
875+ // Test is_evaluated
876+ assert ! ( !candidate. is_evaluated( ) ) ;
877+
878+ // Test to_json
879+ let json = candidate. to_json ( ) . expect ( "Should serialize candidate" ) ;
880+ assert ! ( json. contains( "id" ) ) ;
881+ assert ! ( json. contains( "genome" ) ) ;
882+ }
0 commit comments