@@ -825,3 +825,204 @@ func TestGeneratePipelineWithSecretsInGroup(t *testing.T) {
825825 assert .Contains (t , string (got ), "- PROD_DB_HOST" )
826826 assert .Contains (t , string (got ), "- PROD_DB_PASS" )
827827}
828+
829+ func TestFilterValidSteps_AllValid (t * testing.T ) {
830+ steps := []Step {
831+ {Command : "echo valid 1" },
832+ {Trigger : "valid-trigger" },
833+ {Commands : []string {"echo valid 2" }},
834+ }
835+
836+ valid , invalid := filterValidSteps (steps )
837+
838+ assert .Len (t , valid , 3 )
839+ assert .Len (t , invalid , 0 )
840+ }
841+
842+ func TestFilterValidSteps_AllInvalid (t * testing.T ) {
843+ steps := []Step {
844+ {},
845+ {Label : "no command" },
846+ {Env : map [string ]string {"KEY" : "value" }},
847+ }
848+
849+ valid , invalid := filterValidSteps (steps )
850+
851+ assert .Len (t , valid , 0 )
852+ assert .Len (t , invalid , 3 )
853+ }
854+
855+ func TestFilterValidSteps_MixedValidInvalid (t * testing.T ) {
856+ steps := []Step {
857+ {Command : "echo valid" },
858+ {},
859+ {Trigger : "valid-trigger" },
860+ {Label : "invalid - no command/trigger" },
861+ {Commands : []string {"echo also valid" }},
862+ }
863+
864+ valid , invalid := filterValidSteps (steps )
865+
866+ assert .Len (t , valid , 3 )
867+ assert .Len (t , invalid , 2 )
868+ assert .Equal (t , "echo valid" , valid [0 ].Command )
869+ assert .Equal (t , "valid-trigger" , valid [1 ].Trigger )
870+ assert .NotNil (t , valid [2 ].Commands )
871+ }
872+
873+ func TestFilterValidSteps_GroupSteps (t * testing.T ) {
874+ steps := []Step {
875+ {
876+ Group : "valid-group" ,
877+ Steps : []Step {
878+ {Command : "echo test" },
879+ },
880+ },
881+ {
882+ Group : "empty-group" ,
883+ Steps : []Step {},
884+ },
885+ {
886+ Group : "invalid-nested-group" ,
887+ Steps : []Step {
888+ {Label : "no command" },
889+ },
890+ },
891+ }
892+
893+ valid , invalid := filterValidSteps (steps )
894+
895+ assert .Len (t , valid , 1 )
896+ assert .Len (t , invalid , 2 )
897+ assert .Equal (t , "valid-group" , valid [0 ].Group )
898+ }
899+
900+ func TestStepsToTrigger_Issue83 (t * testing.T ) {
901+ // Integration test for issue #83 - empty step configuration
902+ watch := []WatchConfig {
903+ {
904+ Paths : []string {"some-path/**" },
905+ Step : Step {}, // Empty step - should be filtered
906+ },
907+ {
908+ Paths : []string {"other-path/**" },
909+ Step : Step {Command : "echo valid" },
910+ },
911+ }
912+
913+ changedFiles := []string {
914+ "some-path/file.txt" ,
915+ "other-path/file.txt" ,
916+ }
917+
918+ steps , err := stepsToTrigger (changedFiles , watch )
919+
920+ assert .NoError (t , err )
921+ assert .Len (t , steps , 1 )
922+ assert .Equal (t , "echo valid" , steps [0 ].Command )
923+ }
924+
925+ func TestStepsToTrigger_DefaultWithEmptyStep (t * testing.T ) {
926+ // Test that empty default step is filtered
927+ watch := []WatchConfig {
928+ {
929+ Paths : []string {"app/" },
930+ Step : Step {Command : "echo app" },
931+ },
932+ {
933+ Default : struct {}{},
934+ Step : Step {}, // Empty default - should be filtered
935+ },
936+ }
937+
938+ changedFiles := []string {"unmatched/file.txt" }
939+
940+ steps , err := stepsToTrigger (changedFiles , watch )
941+
942+ assert .NoError (t , err )
943+ assert .Len (t , steps , 0 )
944+ }
945+
946+ func TestStepsToTrigger_AllStepsInvalid (t * testing.T ) {
947+ // Test that when all matched steps are invalid, empty array is returned
948+ watch := []WatchConfig {
949+ {
950+ Paths : []string {"path1/" },
951+ Step : Step {},
952+ },
953+ {
954+ Paths : []string {"path2/" },
955+ Step : Step {Label : "no command" },
956+ },
957+ }
958+
959+ changedFiles := []string {"path1/file.txt" , "path2/file.txt" }
960+
961+ steps , err := stepsToTrigger (changedFiles , watch )
962+
963+ assert .NoError (t , err )
964+ assert .Len (t , steps , 0 )
965+ }
966+
967+ func TestStepsToTrigger_EmptyGroupInConfig (t * testing.T ) {
968+ // Test that empty group steps are filtered
969+ watch := []WatchConfig {
970+ {
971+ Paths : []string {"services/" },
972+ Step : Step {
973+ Group : "deploy" ,
974+ Steps : []Step {}, // Empty group
975+ },
976+ },
977+ }
978+
979+ changedFiles := []string {"services/main.go" }
980+
981+ steps , err := stepsToTrigger (changedFiles , watch )
982+
983+ assert .NoError (t , err )
984+ assert .Len (t , steps , 0 )
985+ }
986+
987+ func TestStepsToTrigger_ValidAndInvalidStepsMixed (t * testing.T ) {
988+ // Test that valid steps are kept while invalid are filtered
989+ watch := []WatchConfig {
990+ {
991+ Paths : []string {"app/" },
992+ Step : Step {Command : "echo valid app" },
993+ },
994+ {
995+ Paths : []string {"tests/" },
996+ Step : Step {}, // Invalid
997+ },
998+ {
999+ Paths : []string {"deploy/" },
1000+ Step : Step {Trigger : "deploy-pipeline" },
1001+ },
1002+ }
1003+
1004+ changedFiles := []string {
1005+ "app/main.go" ,
1006+ "tests/test.go" ,
1007+ "deploy/script.sh" ,
1008+ }
1009+
1010+ steps , err := stepsToTrigger (changedFiles , watch )
1011+
1012+ assert .NoError (t , err )
1013+ assert .Len (t , steps , 2 )
1014+
1015+ // Verify we got the valid steps
1016+ hasAppStep := false
1017+ hasDeployStep := false
1018+ for _ , step := range steps {
1019+ if step .Command == "echo valid app" {
1020+ hasAppStep = true
1021+ }
1022+ if step .Trigger == "deploy-pipeline" {
1023+ hasDeployStep = true
1024+ }
1025+ }
1026+ assert .True (t , hasAppStep )
1027+ assert .True (t , hasDeployStep )
1028+ }
0 commit comments