github.com/jaylevin/jenkins-library@v1.230.4/pkg/config/evaluation_test.go (about) 1 package config 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "strings" 11 "testing" 12 13 "github.com/SAP/jenkins-library/pkg/mock" 14 "github.com/stretchr/testify/assert" 15 ) 16 17 func evaluateConditionsGlobMock(pattern string) ([]string, error) { 18 matches := []string{} 19 switch pattern { 20 case "**/conf.js": 21 matches = append(matches, "conf.js") 22 case "**/package.json": 23 matches = append(matches, "package.json", "package/node_modules/lib/package.json", "node_modules/package.json", "test/package.json") 24 25 } 26 return matches, nil 27 } 28 29 func evaluateConditionsOpenFileMock(name string, _ map[string]string) (io.ReadCloser, error) { 30 var fileContent io.ReadCloser 31 switch name { 32 case "package.json": 33 fileContent = ioutil.NopCloser(strings.NewReader(` 34 { 35 "scripts": { 36 "npmScript": "echo test", 37 "npmScript2": "echo test" 38 } 39 } 40 `)) 41 case "_package.json": 42 fileContent = ioutil.NopCloser(strings.NewReader("wrong json format")) 43 case "test/package.json": 44 fileContent = ioutil.NopCloser(strings.NewReader("{}")) 45 } 46 return fileContent, nil 47 } 48 49 func TestEvaluateConditionsV1(t *testing.T) { 50 filesMock := mock.FilesMock{} 51 52 runConfig := RunConfigV1{ 53 PipelineConfig: PipelineDefinitionV1{ 54 Spec: Spec{ 55 Stages: []Stage{ 56 { 57 Name: "stage1", 58 DisplayName: "Test Stage 1", 59 Steps: []Step{ 60 { 61 Name: "step1_1", 62 Conditions: []StepCondition{}, 63 Orchestrators: []string{"Jenkins"}, 64 }, 65 { 66 Name: "step1_2", 67 Conditions: []StepCondition{ 68 {ConfigKey: "testKey"}, 69 }, 70 }, 71 { 72 Name: "step1_3", 73 Conditions: []StepCondition{}, 74 }, 75 }, 76 }, 77 { 78 Name: "stage2", 79 DisplayName: "Test Stage 2", 80 Steps: []Step{ 81 { 82 Name: "step2_1", 83 Conditions: []StepCondition{ 84 {ConfigKey: "testKeyNotExisting"}, 85 {ConfigKey: "testKey"}, 86 }, 87 }, 88 { 89 Name: "step2_2", 90 }, 91 }, 92 }, 93 { 94 Name: "stage3", 95 DisplayName: "Test Stage 3", 96 Steps: []Step{ 97 { 98 Name: "step3_1", 99 Conditions: []StepCondition{ 100 {ConfigKey: "testKeyNotExisting"}, 101 {ConfigKey: "testKey"}, 102 }, 103 }, 104 }, 105 }, 106 }, 107 }, 108 }, 109 } 110 config := Config{Stages: map[string]map[string]interface{}{ 111 "Test Stage 1": {"step1_3": false, "testKey": "testVal"}, 112 "Test Stage 2": {"testKey": "testVal"}, 113 }} 114 115 expectedSteps := map[string]map[string]bool{ 116 "Test Stage 1": { 117 "step1_2": true, 118 "step1_3": false, 119 }, 120 "Test Stage 2": { 121 "step2_1": true, 122 "step2_2": true, 123 }, 124 "Test Stage 3": { 125 "step3_1": false, 126 }, 127 } 128 129 expectedStages := map[string]bool{ 130 "Test Stage 1": true, 131 "Test Stage 2": true, 132 "Test Stage 3": false, 133 } 134 135 err := runConfig.evaluateConditionsV1(&config, nil, nil, nil, nil, &filesMock, ".pipeline") 136 assert.NoError(t, err) 137 assert.Equal(t, expectedSteps, runConfig.RunSteps) 138 assert.Equal(t, expectedStages, runConfig.RunStages) 139 140 } 141 142 func TestNotActiveEvaluateConditionsV1(t *testing.T) { 143 filesMock := mock.FilesMock{} 144 145 runConfig := RunConfigV1{ 146 PipelineConfig: PipelineDefinitionV1{ 147 Spec: Spec{ 148 Stages: []Stage{ 149 { 150 Name: "stage1", 151 DisplayName: "Test Stage 1", 152 Steps: []Step{ 153 { 154 Name: "step1_1", 155 Conditions: []StepCondition{}, 156 Orchestrators: []string{"Jenkins"}, 157 }, 158 { 159 Name: "step1_2", 160 Conditions: []StepCondition{ 161 {ConfigKey: "testKey"}, 162 }, 163 NotActiveConditions: []StepCondition{ 164 {ConfigKey: "testKeyNotExisting"}, 165 }, 166 }, 167 { 168 Name: "step1_3", 169 Conditions: []StepCondition{}, 170 NotActiveConditions: []StepCondition{ 171 {ConfigKey: "testKeyNotExisting"}, 172 {ConfigKey: "testKey"}, 173 }, 174 }, 175 }, 176 }, 177 { 178 Name: "stage2", 179 DisplayName: "Test Stage 2", 180 Steps: []Step{ 181 { 182 Name: "step2_1", 183 Conditions: []StepCondition{ 184 {ConfigKey: "testKeyNotExisting"}, 185 {ConfigKey: "testKey"}, 186 }, 187 }, 188 }, 189 }, 190 { 191 Name: "stage3", 192 DisplayName: "Test Stage 3", 193 Steps: []Step{ 194 { 195 Name: "step3_1", 196 NotActiveConditions: []StepCondition{ 197 {ConfigKey: "testKey"}, 198 }, 199 }, 200 }, 201 }, 202 }, 203 }, 204 }, 205 } 206 config := Config{Stages: map[string]map[string]interface{}{ 207 "Test Stage 1": {"testKey": "testVal"}, 208 "Test Stage 2": {"testKey": "testVal"}, 209 "Test Stage 3": {"testKey": "testVal"}, 210 }} 211 212 expectedSteps := map[string]map[string]bool{ 213 "Test Stage 1": { 214 "step1_2": true, 215 "step1_3": false, 216 }, 217 "Test Stage 2": { 218 "step2_1": true, 219 }, 220 "Test Stage 3": { 221 "step3_1": false, 222 }, 223 } 224 225 expectedStages := map[string]bool{ 226 "Test Stage 1": true, 227 "Test Stage 2": true, 228 "Test Stage 3": false, 229 } 230 231 err := runConfig.evaluateConditionsV1(&config, nil, nil, nil, nil, &filesMock, ".pipeline") 232 assert.NoError(t, err) 233 assert.Equal(t, expectedSteps, runConfig.RunSteps) 234 assert.Equal(t, expectedStages, runConfig.RunStages) 235 236 } 237 238 func TestEvaluateV1(t *testing.T) { 239 tt := []struct { 240 name string 241 config StepConfig 242 stepCondition StepCondition 243 expected bool 244 expectedError error 245 }{ 246 { 247 name: "Config condition - true", 248 config: StepConfig{Config: map[string]interface{}{ 249 "deployTool": "helm3", 250 }}, 251 stepCondition: StepCondition{Config: map[string][]interface{}{"deployTool": {"helm", "helm3", "kubectl"}}}, 252 expected: true, 253 }, 254 { 255 name: "Config condition - false", 256 config: StepConfig{Config: map[string]interface{}{ 257 "deployTool": "notsupported", 258 }}, 259 stepCondition: StepCondition{Config: map[string][]interface{}{"deployTool": {"helm", "helm3", "kubectl"}}}, 260 expected: false, 261 }, 262 { 263 name: "Config condition - integer - true", 264 config: StepConfig{Config: map[string]interface{}{ 265 "executors": 1, 266 }}, 267 stepCondition: StepCondition{Config: map[string][]interface{}{"executors": {1}}}, 268 expected: true, 269 }, 270 { 271 name: "Config condition - wrong condition definition", 272 config: StepConfig{Config: map[string]interface{}{ 273 "deployTool": "helm3", 274 }}, 275 stepCondition: StepCondition{Config: map[string][]interface{}{"deployTool": {"helm", "helm3", "kubectl"}, "deployTool2": {"myTool"}}}, 276 expectedError: fmt.Errorf("only one config key allowed per condition but 2 provided"), 277 }, 278 { 279 name: "ConfigKey condition - true", 280 config: StepConfig{Config: map[string]interface{}{ 281 "dockerRegistryUrl": "https://my.docker.registry.url", 282 }}, 283 stepCondition: StepCondition{ConfigKey: "dockerRegistryUrl"}, 284 expected: true, 285 }, 286 { 287 name: "ConfigKey condition - false", 288 config: StepConfig{Config: map[string]interface{}{}}, 289 stepCondition: StepCondition{ConfigKey: "dockerRegistryUrl"}, 290 expected: false, 291 }, 292 { 293 name: "FilePattern condition - true", 294 config: StepConfig{Config: map[string]interface{}{}}, 295 stepCondition: StepCondition{FilePattern: "**/conf.js"}, 296 expected: true, 297 }, 298 { 299 name: "FilePattern condition - false", 300 config: StepConfig{Config: map[string]interface{}{}}, 301 stepCondition: StepCondition{FilePattern: "**/confx.js"}, 302 expected: false, 303 }, 304 { 305 name: "FilePatternFromConfig condition - true", 306 config: StepConfig{Config: map[string]interface{}{ 307 "newmanCollection": "**/*.postman_collection.json", 308 }}, 309 stepCondition: StepCondition{FilePatternFromConfig: "newmanCollection"}, 310 expected: true, 311 }, 312 { 313 name: "FilePatternFromConfig condition - false", 314 config: StepConfig{Config: map[string]interface{}{ 315 "newmanCollection": "**/*.postmanx_collection.json", 316 }}, 317 stepCondition: StepCondition{FilePatternFromConfig: "newmanCollection"}, 318 expected: false, 319 }, 320 { 321 name: "FilePatternFromConfig condition - false, empty value", 322 config: StepConfig{Config: map[string]interface{}{ 323 "newmanCollection": "", 324 }}, 325 stepCondition: StepCondition{FilePatternFromConfig: "newmanCollection"}, 326 expected: false, 327 }, 328 { 329 name: "NpmScript condition - true", 330 config: StepConfig{Config: map[string]interface{}{}}, 331 stepCondition: StepCondition{NpmScript: "testScript"}, 332 expected: true, 333 }, 334 { 335 name: "NpmScript condition - true", 336 config: StepConfig{Config: map[string]interface{}{}}, 337 stepCondition: StepCondition{NpmScript: "missingScript"}, 338 expected: false, 339 }, 340 { 341 name: "Inactive condition - false", 342 config: StepConfig{Config: map[string]interface{}{}}, 343 stepCondition: StepCondition{Inactive: true}, 344 expected: false, 345 }, 346 { 347 name: "Inactive condition - true", 348 config: StepConfig{Config: map[string]interface{}{}}, 349 stepCondition: StepCondition{Inactive: false}, 350 expected: true, 351 }, 352 { 353 name: "CommonPipelineEnvironment - true", 354 config: StepConfig{Config: map[string]interface{}{}}, 355 stepCondition: StepCondition{CommonPipelineEnvironment: map[string]interface{}{"myCpeTrueFile": "myTrueValue"}}, 356 expected: true, 357 }, 358 { 359 name: "CommonPipelineEnvironment - false", 360 config: StepConfig{Config: map[string]interface{}{}}, 361 stepCondition: StepCondition{CommonPipelineEnvironment: map[string]interface{}{"myCpeTrueFile": "notMyTrueValue"}}, 362 expected: false, 363 }, 364 { 365 name: "No condition - true", 366 config: StepConfig{Config: map[string]interface{}{}}, 367 expected: true, 368 }, 369 } 370 371 packageJson := `{ 372 "scripts": { 373 "testScript": "whatever" 374 } 375 }` 376 377 filesMock := mock.FilesMock{} 378 filesMock.AddFile("conf.js", []byte("//test")) 379 filesMock.AddFile("my.postman_collection.json", []byte("{}")) 380 filesMock.AddFile("package.json", []byte(packageJson)) 381 382 dir, err := ioutil.TempDir("", "") 383 if err != nil { 384 t.Fatal("Failed to create temporary directory") 385 } 386 // clean up tmp dir 387 defer os.RemoveAll(dir) 388 389 cpeDir := filepath.Join(dir, "commonPipelineEnvironment") 390 err = os.MkdirAll(cpeDir, 0700) 391 if err != nil { 392 t.Fatal("Failed to create sub directory") 393 } 394 ioutil.WriteFile(filepath.Join(cpeDir, "myCpeTrueFile"), []byte("myTrueValue"), 0700) 395 396 for _, test := range tt { 397 t.Run(test.name, func(t *testing.T) { 398 active, err := test.stepCondition.evaluateV1(test.config, &filesMock, "dummy", dir) 399 if test.expectedError == nil { 400 assert.NoError(t, err) 401 } else { 402 assert.EqualError(t, err, fmt.Sprint(test.expectedError)) 403 } 404 assert.Equal(t, test.expected, active) 405 }) 406 } 407 } 408 409 func TestEvaluateConditions(t *testing.T) { 410 tests := []struct { 411 name string 412 customConfig *Config 413 stageConfig io.ReadCloser 414 runStepsExpected map[string]map[string]bool 415 globFunc func(pattern string) ([]string, error) 416 wantErr bool 417 }{ 418 { 419 name: "test config condition - success", 420 customConfig: &Config{ 421 General: map[string]interface{}{ 422 "testGeneral": "myVal1", 423 }, 424 Stages: map[string]map[string]interface{}{ 425 "testStage2": { 426 "testStage": "myVal2", 427 }, 428 }, 429 Steps: map[string]map[string]interface{}{ 430 "thirdStep": { 431 "testStep1": "myVal3", 432 }, 433 }, 434 }, 435 stageConfig: ioutil.NopCloser(strings.NewReader(` 436 stages: 437 testStage1: 438 stepConditions: 439 firstStep: 440 config: testGeneral 441 testStage2: 442 stepConditions: 443 secondStep: 444 config: testStage 445 testStage3: 446 stepConditions: 447 thirdStep: 448 config: testStep1 449 forthStep: 450 config: testStep2 451 `)), 452 runStepsExpected: map[string]map[string]bool{ 453 "testStage1": {"firstStep": true}, 454 "testStage2": {"secondStep": true}, 455 "testStage3": { 456 "thirdStep": true, 457 "forthStep": false, 458 }, 459 }, 460 wantErr: false, 461 }, 462 { 463 name: "test config condition - wrong usage with list", 464 customConfig: &Config{ 465 General: map[string]interface{}{}, 466 Stages: map[string]map[string]interface{}{}, 467 Steps: map[string]map[string]interface{}{}, 468 }, 469 stageConfig: ioutil.NopCloser(strings.NewReader(` 470 stages: 471 testStage1: 472 stepConditions: 473 firstStep: 474 config: 475 - testGeneral 476 `)), 477 runStepsExpected: map[string]map[string]bool{}, 478 wantErr: true, 479 }, 480 { 481 name: "test config value condition - success", 482 customConfig: &Config{ 483 General: map[string]interface{}{ 484 "testGeneral": "myVal1", 485 }, 486 Stages: map[string]map[string]interface{}{}, 487 Steps: map[string]map[string]interface{}{ 488 "thirdStep": { 489 "testStep": "myVal3", 490 }, 491 }, 492 }, 493 stageConfig: ioutil.NopCloser(strings.NewReader(` 494 stages: 495 testStage1: 496 stepConditions: 497 firstStep: 498 config: 499 testGeneral: 500 - myValx 501 - myVal1 502 testStage2: 503 stepConditions: 504 secondStep: 505 config: 506 testStage: 507 - maValXyz 508 testStage3: 509 stepConditions: 510 thirdStep: 511 config: 512 testStep: 513 - myVal3 514 `)), 515 runStepsExpected: map[string]map[string]bool{ 516 "testStage1": {"firstStep": true}, 517 "testStage2": {"secondStep": false}, 518 "testStage3": {"thirdStep": true}, 519 }, 520 wantErr: false, 521 }, 522 { 523 name: "test configKey condition - success", 524 customConfig: &Config{ 525 General: map[string]interface{}{ 526 "myKey1_1": "myVal1_1", 527 }, 528 Stages: map[string]map[string]interface{}{}, 529 Steps: map[string]map[string]interface{}{ 530 "thirdStep": { 531 "myKey3_1": "myVal3_1", 532 }, 533 }, 534 }, 535 stageConfig: ioutil.NopCloser(strings.NewReader(` 536 stages: 537 testStage1: 538 stepConditions: 539 firstStep: 540 configKeys: 541 - myKey1_1 542 - myKey1_2 543 testStage2: 544 stepConditions: 545 secondStep: 546 configKeys: 547 - myKey2_1 548 testStage3: 549 stepConditions: 550 thirdStep: 551 configKeys: 552 - myKey3_1 553 `)), 554 runStepsExpected: map[string]map[string]bool{ 555 "testStage1": {"firstStep": true}, 556 "testStage2": {"secondStep": false}, 557 "testStage3": {"thirdStep": true}, 558 }, 559 wantErr: false, 560 }, 561 { 562 name: "test configKey condition - not list", 563 customConfig: &Config{ 564 General: map[string]interface{}{ 565 "myKey1_1": "myVal1_1", 566 }, 567 Stages: map[string]map[string]interface{}{}, 568 Steps: map[string]map[string]interface{}{}, 569 }, 570 stageConfig: ioutil.NopCloser(strings.NewReader(` 571 stages: 572 testStage1: 573 stepConditions: 574 firstStep: 575 configKeys: myKey1_1 576 `)), 577 wantErr: true, 578 }, 579 { 580 name: "test configKey condition - success", 581 customConfig: &Config{ 582 General: map[string]interface{}{ 583 "myKey1_1": "myVal1_1", 584 }, 585 Stages: map[string]map[string]interface{}{}, 586 Steps: map[string]map[string]interface{}{ 587 "thirdStep": { 588 "myKey3_1": "myVal3_1", 589 }, 590 }, 591 }, 592 stageConfig: ioutil.NopCloser(strings.NewReader(` 593 stages: 594 testStage1: 595 stepConditions: 596 firstStep: 597 configKeys: 598 - myKey1_1 599 - myKey1_2 600 testStage2: 601 stepConditions: 602 secondStep: 603 configKeys: 604 - myKey2_1 605 testStage3: 606 stepConditions: 607 thirdStep: 608 configKeys: 609 - myKey3_1 610 `)), 611 runStepsExpected: map[string]map[string]bool{ 612 "testStage1": {"firstStep": true}, 613 "testStage2": {"secondStep": false}, 614 "testStage3": {"thirdStep": true}, 615 }, 616 wantErr: false, 617 }, 618 { 619 name: "test filePattern condition - success", 620 globFunc: evaluateConditionsGlobMock, 621 customConfig: &Config{ 622 General: map[string]interface{}{}, 623 Stages: map[string]map[string]interface{}{}, 624 Steps: map[string]map[string]interface{}{}, 625 }, 626 stageConfig: ioutil.NopCloser(strings.NewReader(` 627 stages: 628 testStage1: 629 stepConditions: 630 firstStep: 631 filePattern: '**/conf.js' 632 secondStep: 633 filePattern: '**/conf.jsx' 634 `)), 635 runStepsExpected: map[string]map[string]bool{ 636 "testStage1": { 637 "firstStep": true, 638 "secondStep": false, 639 }, 640 }, 641 wantErr: false, 642 }, 643 { 644 name: "test filePattern condition - error while searching files by pattern", 645 customConfig: &Config{ 646 General: map[string]interface{}{}, 647 Stages: map[string]map[string]interface{}{}, 648 Steps: map[string]map[string]interface{}{}, 649 }, 650 stageConfig: ioutil.NopCloser(strings.NewReader(` 651 stages: 652 testStage1: 653 stepConditions: 654 firstStep: 655 filePattern: '**/conf.js' 656 `)), 657 runStepsExpected: map[string]map[string]bool{}, 658 globFunc: func(pattern string) ([]string, error) { 659 return nil, errors.New("failed to check if file exists") 660 }, 661 wantErr: true, 662 }, 663 { 664 name: "test filePattern condition with list - success", 665 globFunc: evaluateConditionsGlobMock, 666 customConfig: &Config{ 667 General: map[string]interface{}{}, 668 Stages: map[string]map[string]interface{}{}, 669 Steps: map[string]map[string]interface{}{}, 670 }, 671 stageConfig: ioutil.NopCloser(strings.NewReader(` 672 stages: 673 testStage1: 674 stepConditions: 675 firstStep: 676 filePattern: 677 - '**/conf.js' 678 - 'myCollection.json' 679 secondStep: 680 filePattern: 681 - '**/conf.jsx' 682 `)), 683 runStepsExpected: map[string]map[string]bool{ 684 "testStage1": { 685 "firstStep": true, 686 "secondStep": false, 687 }, 688 }, 689 wantErr: false, 690 }, 691 { 692 name: "test filePattern condition with list - error while searching files by pattern", 693 customConfig: &Config{ 694 General: map[string]interface{}{}, 695 Stages: map[string]map[string]interface{}{}, 696 Steps: map[string]map[string]interface{}{}, 697 }, 698 stageConfig: ioutil.NopCloser(strings.NewReader(` 699 stages: 700 testStage1: 701 stepConditions: 702 firstStep: 703 filePattern: 704 - '**/conf.js' 705 - 'myCollection.json' 706 `)), 707 runStepsExpected: map[string]map[string]bool{}, 708 globFunc: func(pattern string) ([]string, error) { 709 return nil, errors.New("failed to check if file exists") 710 }, 711 wantErr: true, 712 }, 713 { 714 name: "test filePatternFromConfig condition - success", 715 globFunc: evaluateConditionsGlobMock, 716 customConfig: &Config{ 717 General: map[string]interface{}{}, 718 Stages: map[string]map[string]interface{}{}, 719 Steps: map[string]map[string]interface{}{ 720 "firstStep": { 721 "myVal1": "**/conf.js", 722 }, 723 "thirdStep": { 724 "myVal3": "**/conf.jsx", 725 }, 726 }, 727 }, 728 stageConfig: ioutil.NopCloser(strings.NewReader(` 729 stages: 730 testStage1: 731 stepConditions: 732 firstStep: 733 filePatternFromConfig: myVal1 734 secondStep: 735 filePatternFromConfig: myVal2 736 thirdStep: 737 filePatternFromConfig: myVal3 738 `)), 739 runStepsExpected: map[string]map[string]bool{ 740 "testStage1": { 741 "firstStep": true, 742 "secondStep": false, 743 "thirdStep": false, 744 }, 745 }, 746 wantErr: false, 747 }, 748 { 749 name: "test filePatternFromConfig condition - error while searching files by pattern", 750 customConfig: &Config{ 751 General: map[string]interface{}{}, 752 Stages: map[string]map[string]interface{}{}, 753 Steps: map[string]map[string]interface{}{ 754 "firstStep": { 755 "myVal1": "**/conf.js", 756 }, 757 }, 758 }, 759 stageConfig: ioutil.NopCloser(strings.NewReader(` 760 stages: 761 testStage1: 762 stepConditions: 763 firstStep: 764 filePatternFromConfig: myVal1 765 `)), 766 runStepsExpected: map[string]map[string]bool{}, 767 globFunc: func(pattern string) ([]string, error) { 768 return nil, errors.New("failed to check if file exists") 769 }, 770 wantErr: true, 771 }, 772 { 773 name: "test npmScripts condition - success", 774 globFunc: evaluateConditionsGlobMock, 775 customConfig: &Config{ 776 General: map[string]interface{}{}, 777 Stages: map[string]map[string]interface{}{}, 778 Steps: map[string]map[string]interface{}{}, 779 }, 780 stageConfig: ioutil.NopCloser(strings.NewReader(` 781 stages: 782 testStage1: 783 stepConditions: 784 firstStep: 785 npmScripts: 'npmScript' 786 secondStep: 787 npmScripts: 'npmScript1' 788 `)), 789 runStepsExpected: map[string]map[string]bool{ 790 "testStage1": { 791 "firstStep": true, 792 "secondStep": false, 793 }, 794 }, 795 wantErr: false, 796 }, 797 { 798 name: "test npmScripts condition with list - success", 799 globFunc: evaluateConditionsGlobMock, 800 customConfig: &Config{ 801 General: map[string]interface{}{}, 802 Stages: map[string]map[string]interface{}{}, 803 Steps: map[string]map[string]interface{}{}, 804 }, 805 stageConfig: ioutil.NopCloser(strings.NewReader(` 806 stages: 807 testStage1: 808 stepConditions: 809 firstStep: 810 npmScripts: 811 - 'npmScript' 812 - 'npmScript2' 813 secondStep: 814 npmScripts: 815 - 'npmScript3' 816 - 'npmScript4' 817 `)), 818 runStepsExpected: map[string]map[string]bool{ 819 "testStage1": { 820 "firstStep": true, 821 "secondStep": false, 822 }, 823 }, 824 wantErr: false, 825 }, 826 { 827 name: "test npmScripts condition - json with wrong format", 828 customConfig: &Config{ 829 General: map[string]interface{}{}, 830 Stages: map[string]map[string]interface{}{}, 831 Steps: map[string]map[string]interface{}{}, 832 }, 833 stageConfig: ioutil.NopCloser(strings.NewReader(` 834 stages: 835 testStage1: 836 stepConditions: 837 firstStep: 838 npmScripts: 839 - 'npmScript3' 840 `)), 841 runStepsExpected: map[string]map[string]bool{}, 842 globFunc: func(pattern string) ([]string, error) { 843 return []string{"_package.json"}, nil 844 }, 845 wantErr: true, 846 }, 847 { 848 name: "test npmScripts condition - error while searching package.json", 849 customConfig: &Config{ 850 General: map[string]interface{}{}, 851 Stages: map[string]map[string]interface{}{}, 852 Steps: map[string]map[string]interface{}{}, 853 }, 854 stageConfig: ioutil.NopCloser(strings.NewReader(` 855 stages: 856 testStage1: 857 stepConditions: 858 firstStep: 859 npmScripts: 860 - 'npmScript3' 861 `)), 862 runStepsExpected: map[string]map[string]bool{}, 863 globFunc: func(pattern string) ([]string, error) { 864 return nil, errors.New("failed to check if file exists") 865 }, 866 wantErr: true, 867 }, 868 { 869 name: "test explicit activation / de-activation of step", 870 customConfig: &Config{ 871 Stages: map[string]map[string]interface{}{ 872 "testStage1": { 873 "firstStep": true, 874 "fisecondStep": false, 875 }, 876 }, 877 }, 878 stageConfig: ioutil.NopCloser(strings.NewReader(` 879 stages: 880 testStage1: 881 stepConditions: 882 firstStep: 883 config: testGeneral 884 secondStep: 885 config: testStage 886 `)), 887 runStepsExpected: map[string]map[string]bool{ 888 "testStage1": { 889 "firstStep": true, 890 "secondStep": false, 891 }, 892 }, 893 }, 894 } 895 for _, tt := range tests { 896 t.Run(tt.name, func(t *testing.T) { 897 runConfig := RunConfig{ 898 StageConfigFile: tt.stageConfig, 899 RunSteps: map[string]map[string]bool{}, 900 OpenFile: evaluateConditionsOpenFileMock, 901 } 902 err := runConfig.loadConditions() 903 assert.NoError(t, err) 904 err = runConfig.evaluateConditions(tt.customConfig, nil, nil, nil, nil, tt.globFunc) 905 if tt.wantErr { 906 assert.Error(t, err) 907 } else { 908 assert.NoError(t, err) 909 assert.Equal(t, tt.runStepsExpected, runConfig.RunSteps) 910 } 911 }) 912 } 913 }