@@ -522,3 +522,151 @@ func TestAccPortScorecardUpdateIdentifier(t *testing.T) {
522522 },
523523 })
524524}
525+
526+ func TestAccPortScorecardRuleOrderPreservation (t * testing.T ) {
527+ blueprintIdentifier := utils .GenID ()
528+ scorecardIdentifier := utils .GenID ()
529+
530+ // Create scorecard with rules in a specific non-alphabetical order
531+ // Order: "zebra" (Z), "alpha" (A), "beta" (B)
532+ // This tests that order is preserved even if API returns them alphabetically
533+ var testAccConfigCreate = testAccCreateBlueprintConfig (blueprintIdentifier ) + fmt .Sprintf (`
534+ resource "port_scorecard" "test" {
535+ identifier = "%s"
536+ title = "Rule Order Test"
537+ blueprint = "%s"
538+ rules = [
539+ {
540+ identifier = "zebra"
541+ title = "Zebra Rule"
542+ level = "Gold"
543+ query = {
544+ combinator = "and"
545+ conditions = [jsonencode({
546+ property = "$team"
547+ operator = "isNotEmpty"
548+ })]
549+ }
550+ },
551+ {
552+ identifier = "alpha"
553+ title = "Alpha Rule"
554+ level = "Silver"
555+ query = {
556+ combinator = "and"
557+ conditions = [jsonencode({
558+ property = "author"
559+ operator = "isNotEmpty"
560+ })]
561+ }
562+ },
563+ {
564+ identifier = "beta"
565+ title = "Beta Rule"
566+ level = "Bronze"
567+ query = {
568+ combinator = "and"
569+ conditions = [jsonencode({
570+ property = "url"
571+ operator = "isNotEmpty"
572+ })]
573+ }
574+ }
575+ ]
576+ depends_on = [
577+ port_blueprint.microservice
578+ ]
579+ }` , scorecardIdentifier , blueprintIdentifier )
580+
581+ // Update config - only change title to trigger refresh, rules remain the same
582+ var testAccConfigUpdate = testAccCreateBlueprintConfig (blueprintIdentifier ) + fmt .Sprintf (`
583+ resource "port_scorecard" "test" {
584+ identifier = "%s"
585+ title = "Rule Order Test Updated"
586+ blueprint = "%s"
587+ rules = [
588+ {
589+ identifier = "zebra"
590+ title = "Zebra Rule"
591+ level = "Gold"
592+ query = {
593+ combinator = "and"
594+ conditions = [jsonencode({
595+ property = "$team"
596+ operator = "isNotEmpty"
597+ })]
598+ }
599+ },
600+ {
601+ identifier = "alpha"
602+ title = "Alpha Rule"
603+ level = "Silver"
604+ query = {
605+ combinator = "and"
606+ conditions = [jsonencode({
607+ property = "author"
608+ operator = "isNotEmpty"
609+ })]
610+ }
611+ },
612+ {
613+ identifier = "beta"
614+ title = "Beta Rule"
615+ level = "Bronze"
616+ query = {
617+ combinator = "and"
618+ conditions = [jsonencode({
619+ property = "url"
620+ operator = "isNotEmpty"
621+ })]
622+ }
623+ }
624+ ]
625+ depends_on = [
626+ port_blueprint.microservice
627+ ]
628+ }` , scorecardIdentifier , blueprintIdentifier )
629+
630+ resource .Test (t , resource.TestCase {
631+ PreCheck : func () { acctest .TestAccPreCheck (t ) },
632+ ProtoV6ProviderFactories : acctest .TestAccProtoV6ProviderFactories ,
633+ Steps : []resource.TestStep {
634+ {
635+ Config : acctest .ProviderConfig + testAccConfigCreate ,
636+ Check : resource .ComposeTestCheckFunc (
637+ resource .TestCheckResourceAttr ("port_scorecard.test" , "title" , "Rule Order Test" ),
638+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.#" , "3" ),
639+ // Verify rules are in the original order (zebra, alpha, beta)
640+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.0.identifier" , "zebra" ),
641+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.0.title" , "Zebra Rule" ),
642+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.0.level" , "Gold" ),
643+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.1.identifier" , "alpha" ),
644+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.1.title" , "Alpha Rule" ),
645+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.1.level" , "Silver" ),
646+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.2.identifier" , "beta" ),
647+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.2.title" , "Beta Rule" ),
648+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.2.level" , "Bronze" ),
649+ ),
650+ },
651+ {
652+ Config : acctest .ProviderConfig + testAccConfigUpdate ,
653+ Check : resource .ComposeTestCheckFunc (
654+ resource .TestCheckResourceAttr ("port_scorecard.test" , "title" , "Rule Order Test Updated" ),
655+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.#" , "3" ),
656+ // Verify rules are STILL in the original order after refresh (zebra, alpha, beta)
657+ // This ensures that even if API returns them in a different order,
658+ // the original state order is preserved
659+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.0.identifier" , "zebra" ),
660+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.0.title" , "Zebra Rule" ),
661+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.0.level" , "Gold" ),
662+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.1.identifier" , "alpha" ),
663+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.1.title" , "Alpha Rule" ),
664+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.1.level" , "Silver" ),
665+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.2.identifier" , "beta" ),
666+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.2.title" , "Beta Rule" ),
667+ resource .TestCheckResourceAttr ("port_scorecard.test" , "rules.2.level" , "Bronze" ),
668+ ),
669+ },
670+ },
671+ })
672+ }
0 commit comments