github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/documentation/generator/parameters_test.go (about)

     1  //go:build unit
     2  // +build unit
     3  
     4  package generator
     5  
     6  import (
     7  	"fmt"
     8  	"testing"
     9  
    10  	"github.com/SAP/jenkins-library/pkg/config"
    11  	"github.com/stretchr/testify/assert"
    12  )
    13  
    14  func TestCreateParameterOverview(t *testing.T) {
    15  
    16  	stepData := config.StepData{
    17  		Spec: config.StepSpec{
    18  			Inputs: config.StepInputs{
    19  				Resources: []config.StepResources{
    20  					{Name: "testStash", Type: "stash"},
    21  				},
    22  				Parameters: []config.StepParameters{
    23  					{Name: "param1"},
    24  					{Name: "param2", Mandatory: true},
    25  					{Name: "param3", MandatoryIf: []config.ParameterDependence{{Name: "param1", Value: "param3Necessary"}}},
    26  					{Name: "dockerImage", Default: "testImage"},
    27  					{Name: "stashContent", Default: "testStash"},
    28  				},
    29  			},
    30  		},
    31  	}
    32  	stepParameterNames = []string{"param1", "param2", "param3"}
    33  
    34  	t.Run("Test Step Section", func(t *testing.T) {
    35  
    36  		expected := `| Name | Mandatory | Additional information |
    37  | ---- | --------- | ---------------------- |
    38  | [param1](#param1) | no |  |
    39  | [param2](#param2) | **yes** |  |
    40  | [param3](#param3) | **(yes)** | mandatory in case of:<br />- ` + "[`param1`](#param1)=`param3Necessary`" + ` |
    41  
    42  `
    43  
    44  		assert.Equal(t, expected, createParameterOverview(&stepData, false))
    45  	})
    46  
    47  	t.Run("Test Execution Section", func(t *testing.T) {
    48  		expected := `| Name | Mandatory | Additional information |
    49  | ---- | --------- | ---------------------- |
    50  | [dockerImage](#dockerimage) | no |  |
    51  | [stashContent](#stashcontent) | no | [![Jenkins only](https://img.shields.io/badge/-Jenkins%20only-yellowgreen)](#) |
    52  
    53  `
    54  		assert.Equal(t, expected, createParameterOverview(&stepData, true))
    55  	})
    56  
    57  	stepParameterNames = []string{}
    58  }
    59  
    60  func TestParameterFurtherInfo(t *testing.T) {
    61  	tt := []struct {
    62  		paramName   string
    63  		stepParams  []string
    64  		stepData    *config.StepData
    65  		contains    string
    66  		notContains []string
    67  	}{
    68  		{paramName: "verbose", stepParams: []string{}, stepData: nil, contains: "activates debug output"},
    69  		{paramName: "script", stepParams: []string{}, stepData: nil, contains: "reference to Jenkins main pipeline script"},
    70  		{paramName: "noop", stepParams: []string{"noop"}, stepData: &config.StepData{Spec: config.StepSpec{Inputs: config.StepInputs{Parameters: []config.StepParameters{}}}}, contains: ""},
    71  		{
    72  			paramName: "testCredentialId",
    73  			stepData: &config.StepData{
    74  				Spec: config.StepSpec{
    75  					Inputs: config.StepInputs{
    76  						Secrets: []config.StepSecrets{{Name: "testCredentialId", Type: "jenkins"}},
    77  					},
    78  				},
    79  			},
    80  			notContains: []string{"deprecated"},
    81  			contains:    "id of credentials",
    82  		},
    83  		{
    84  			paramName:  "testSecret1",
    85  			stepParams: []string{"testSecret1"},
    86  			stepData: &config.StepData{
    87  				Spec: config.StepSpec{
    88  					Inputs: config.StepInputs{
    89  						Parameters: []config.StepParameters{
    90  							{Name: "testSecret1", Secret: true, ResourceRef: []config.ResourceReference{{Name: "mytestSecret", Type: "secret"}}},
    91  						},
    92  					},
    93  				},
    94  			},
    95  			notContains: []string{"deprecated"},
    96  			contains:    "credentials ([`mytestSecret`](#mytestsecret))",
    97  		},
    98  		{
    99  			paramName:  "testSecret1Deprecated",
   100  			stepParams: []string{"testSecret1Deprecated"},
   101  			stepData: &config.StepData{
   102  				Spec: config.StepSpec{
   103  					Inputs: config.StepInputs{
   104  						Parameters: []config.StepParameters{
   105  							{Name: "testSecret1Deprecated", Secret: true, ResourceRef: []config.ResourceReference{{Name: "mytestSecret", Type: "secret"}}, DeprecationMessage: "don't use"},
   106  						},
   107  					},
   108  				},
   109  			},
   110  			contains: "![deprecated](https://img.shields.io/badge/-deprecated-red)[![Secret](https://img.shields.io/badge/-Secret-yellowgreen)](#)",
   111  		},
   112  		{
   113  			paramName:  "testSecret2",
   114  			stepParams: []string{"testSecret2"},
   115  			stepData: &config.StepData{
   116  				Spec: config.StepSpec{
   117  					Inputs: config.StepInputs{
   118  						Parameters: []config.StepParameters{
   119  							{Name: "testSecret2"},
   120  						},
   121  					},
   122  				},
   123  			},
   124  			notContains: []string{"deprecated"},
   125  			contains:    "",
   126  		},
   127  		{
   128  			paramName:  "testDeprecated",
   129  			stepParams: []string{"testDeprecated"},
   130  			stepData: &config.StepData{
   131  				Spec: config.StepSpec{
   132  					Inputs: config.StepInputs{
   133  						Parameters: []config.StepParameters{
   134  							{Name: "testDeprecated", DeprecationMessage: "don't use"},
   135  						},
   136  					},
   137  				},
   138  			},
   139  			contains: "![deprecated](https://img.shields.io/badge/-deprecated-red)",
   140  		},
   141  	}
   142  
   143  	for _, test := range tt {
   144  		stepParameterNames = test.stepParams
   145  		res, err := parameterFurtherInfo(test.paramName, test.stepData, false)
   146  		assert.NoError(t, err)
   147  		stepParameterNames = []string{}
   148  		if len(test.contains) == 0 {
   149  			assert.Equalf(t, test.contains, res, fmt.Sprintf("param %v", test.paramName))
   150  		} else {
   151  			assert.Containsf(t, res, test.contains, fmt.Sprintf("param %v", test.paramName))
   152  		}
   153  		for _, notThere := range test.notContains {
   154  			assert.NotContainsf(t, res, notThere, fmt.Sprintf("param %v", test.paramName))
   155  		}
   156  	}
   157  }
   158  
   159  func TestCheckParameterInfo(t *testing.T) {
   160  	t.Parallel()
   161  	tt := []struct {
   162  		info                 string
   163  		stepParam            bool
   164  		executionEnvironment bool
   165  		expected             string
   166  		expectedErr          error
   167  	}{
   168  		{info: "step param", stepParam: true, executionEnvironment: false, expected: "step param", expectedErr: nil},
   169  		{info: "execution param", stepParam: false, executionEnvironment: true, expected: "execution param", expectedErr: nil},
   170  		{info: "step param in execution", stepParam: true, executionEnvironment: true, expected: "", expectedErr: fmt.Errorf("step parameter not relevant as execution environment parameter")},
   171  		{info: "execution param in step", stepParam: false, executionEnvironment: false, expected: "", expectedErr: fmt.Errorf("execution environment parameter not relevant as step parameter")},
   172  	}
   173  
   174  	for _, test := range tt {
   175  		result, err := checkParameterInfo(test.info, test.stepParam, test.executionEnvironment)
   176  		if test.expectedErr == nil {
   177  			assert.NoError(t, err)
   178  		} else {
   179  			assert.EqualError(t, err, fmt.Sprint(test.expectedErr))
   180  		}
   181  		assert.Equal(t, test.expected, result)
   182  	}
   183  
   184  }
   185  
   186  func TestCreateParameterDetails(t *testing.T) {
   187  	t.Run("default", func(t *testing.T) {
   188  		stepData := config.StepData{
   189  			Spec: config.StepSpec{
   190  				Inputs: config.StepInputs{
   191  					Parameters: []config.StepParameters{
   192  						{
   193  							Name:            "param1",
   194  							Aliases:         []config.Alias{{Name: "param1Alias"}, {Name: "paramAliasDeprecated", Deprecated: true}},
   195  							Mandatory:       true,
   196  							Default:         "param1Default",
   197  							LongDescription: "long description",
   198  							PossibleValues:  []interface{}{"val1", "val2"},
   199  							Scope:           []string{"STEPS"},
   200  							Secret:          true,
   201  							Type:            "string",
   202  						},
   203  					},
   204  				},
   205  			},
   206  		}
   207  
   208  		res := createParameterDetails(&stepData)
   209  
   210  		assert.Contains(t, res, "#### param1")
   211  		assert.Contains(t, res, "long description")
   212  		assert.Contains(t, res, "`param1Alias`")
   213  		assert.Contains(t, res, "`paramAliasDeprecated` (**deprecated**)")
   214  		assert.Contains(t, res, "string")
   215  		assert.Contains(t, res, "param1Default")
   216  		assert.Contains(t, res, "val1")
   217  		assert.Contains(t, res, "val2")
   218  		assert.Contains(t, res, "no")
   219  		assert.Contains(t, res, "**yes**")
   220  		assert.Contains(t, res, "steps")
   221  		assert.NotContains(t, res, "| Deprecated |")
   222  	})
   223  
   224  	t.Run("conditional mandatory parameters", func(t *testing.T) {
   225  		stepData := config.StepData{
   226  			Spec: config.StepSpec{
   227  				Inputs: config.StepInputs{
   228  					Parameters: []config.StepParameters{
   229  						{
   230  							Name:        "param2",
   231  							MandatoryIf: []config.ParameterDependence{{Name: "param1", Value: "param1Val"}},
   232  							Type:        "string",
   233  						},
   234  					},
   235  				},
   236  			},
   237  		}
   238  
   239  		res := createParameterDetails(&stepData)
   240  
   241  		assert.Contains(t, res, "mandatory in case of:<br />- [`param1`](#param1)=`param1Val`")
   242  	})
   243  
   244  	t.Run("deprecated parameters", func(t *testing.T) {
   245  		stepData := config.StepData{
   246  			Spec: config.StepSpec{
   247  				Inputs: config.StepInputs{
   248  					Parameters: []config.StepParameters{
   249  						{
   250  							Name:               "param2",
   251  							Type:               "string",
   252  							DeprecationMessage: "this is deprecated",
   253  						},
   254  					},
   255  				},
   256  			},
   257  		}
   258  
   259  		res := createParameterDetails(&stepData)
   260  
   261  		assert.Contains(t, res, "| Deprecated |")
   262  		assert.Contains(t, res, "this is deprecated")
   263  	})
   264  
   265  }
   266  
   267  func TestFormatDefault(t *testing.T) {
   268  	tt := []struct {
   269  		param      config.StepParameters
   270  		stepParams []string
   271  		expected   string
   272  		contains   []string
   273  	}{
   274  		{param: config.StepParameters{Name: "test1"}, stepParams: []string{"test1"}, expected: "`$PIPER_test1` (if set)"},
   275  		{param: config.StepParameters{Name: "jenkins1"}, stepParams: []string{}, expected: ""},
   276  		{
   277  			param:      config.StepParameters{Name: "test1", Default: []conditionDefault{{key: "key1", value: "val1", def: "def1"}, {key: "key2", value: "val2", def: "def2"}}},
   278  			stepParams: []string{"test1"},
   279  			contains:   []string{"key1=`val1`: `def1`", "key2=`val2`: `def2`"},
   280  		},
   281  		{
   282  			param:      config.StepParameters{Name: "test1", Default: []interface{}{conditionDefault{key: "key1", value: "val1", def: "def1"}, "def2"}},
   283  			stepParams: []string{"test1"},
   284  			contains:   []string{"key1=`val1`: `def1`", "- `def2`"},
   285  		},
   286  		{
   287  			param:      config.StepParameters{Name: "test1", Default: map[string]string{"key1": "def1", "key2": "def2"}},
   288  			stepParams: []string{"test1"},
   289  			contains:   []string{"`key1`: `def1`", "`key2`: `def2`"},
   290  		},
   291  		{param: config.StepParameters{Name: "test1", Default: ""}, stepParams: []string{"test1"}, expected: "`''`"},
   292  		{param: config.StepParameters{Name: "test1", Default: "def1"}, stepParams: []string{"test1"}, expected: "`def1`"},
   293  		{param: config.StepParameters{Name: "test1", Default: 1}, stepParams: []string{"test1"}, expected: "`1`"},
   294  	}
   295  
   296  	for _, test := range tt {
   297  		if len(test.contains) > 0 {
   298  			res := formatDefault(test.param, test.stepParams)
   299  			for _, check := range test.contains {
   300  				assert.Contains(t, res, check)
   301  			}
   302  
   303  		} else {
   304  			assert.Equal(t, test.expected, formatDefault(test.param, test.stepParams))
   305  		}
   306  
   307  	}
   308  }
   309  
   310  func TestAliasList(t *testing.T) {
   311  	tt := []struct {
   312  		aliases  []config.Alias
   313  		expected string
   314  		contains []string
   315  	}{
   316  		{aliases: []config.Alias{}, expected: "-"},
   317  		{aliases: []config.Alias{{Name: "alias1"}}, expected: "`alias1`"},
   318  		{aliases: []config.Alias{{Name: "alias1", Deprecated: true}}, expected: "`alias1` (**deprecated**)"},
   319  		{aliases: []config.Alias{{Name: "alias1"}, {Name: "alias2", Deprecated: true}}, contains: []string{"- `alias1`", "- `alias2` (**deprecated**)"}},
   320  	}
   321  
   322  	for _, test := range tt {
   323  		if len(test.contains) > 0 {
   324  			res := aliasList(test.aliases)
   325  			for _, check := range test.contains {
   326  				assert.Contains(t, res, check)
   327  			}
   328  		} else {
   329  			assert.Equal(t, test.expected, aliasList(test.aliases))
   330  		}
   331  	}
   332  }
   333  
   334  func TestPossibleValueList(t *testing.T) {
   335  	tt := []struct {
   336  		possibleValues []interface{}
   337  		expected       string
   338  		contains       []string
   339  	}{
   340  		{possibleValues: []interface{}{}, expected: ""},
   341  		{possibleValues: []interface{}{"poss1", 0}, contains: []string{"- `poss1`", "- `0`"}},
   342  	}
   343  
   344  	for _, test := range tt {
   345  		if len(test.contains) > 0 {
   346  			res := possibleValueList(test.possibleValues)
   347  			for _, check := range test.contains {
   348  				assert.Contains(t, res, check)
   349  			}
   350  		} else {
   351  			assert.Equal(t, test.expected, possibleValueList(test.possibleValues))
   352  		}
   353  	}
   354  }
   355  
   356  func TestScopeDetails(t *testing.T) {
   357  	tt := []struct {
   358  		scope    []string
   359  		contains []string
   360  	}{
   361  		{scope: []string{"PARAMETERS", "GENERAL", "STEPS", "STAGES"}, contains: []string{"<li>&#9746; parameter</li>", "<li>&#9746; general</li>", "<li>&#9746; steps</li>", "<li>&#9746; stages</li>"}},
   362  		{scope: []string{}, contains: []string{"<li>&#9744; parameter</li>", "<li>&#9744; general</li>", "<li>&#9744; steps</li>", "<li>&#9744; stages</li>"}},
   363  	}
   364  
   365  	for _, test := range tt {
   366  		res := scopeDetails(test.scope)
   367  
   368  		for _, c := range test.contains {
   369  			assert.Contains(t, res, c)
   370  		}
   371  	}
   372  
   373  }
   374  
   375  func TestResourceReferenceDetails(t *testing.T) {
   376  	tt := []struct {
   377  		resourceRef []config.ResourceReference
   378  		expected    string
   379  		contains    []string
   380  	}{
   381  		{resourceRef: []config.ResourceReference{}, expected: "none"},
   382  		{
   383  			resourceRef: []config.ResourceReference{
   384  				{Name: "commonPipelineEnvironment", Aliases: []config.Alias{}, Type: "", Param: "testParam"},
   385  			},
   386  			expected: "_commonPipelineEnvironment_:<br />&nbsp;&nbsp;reference to: `testParam`<br />",
   387  		},
   388  		{
   389  			resourceRef: []config.ResourceReference{
   390  				{Name: "testCredentialId", Aliases: []config.Alias{}, Type: "secret", Param: "password"},
   391  			},
   392  			expected: "Jenkins credential id:<br />&nbsp;&nbsp;id: [`testCredentialId`](#testcredentialid)<br />&nbsp;&nbsp;reference to: `password`<br />",
   393  		},
   394  		{
   395  			resourceRef: []config.ResourceReference{
   396  				{Name: "testCredentialId", Aliases: []config.Alias{{Name: "alias1"}, {Name: "alias2", Deprecated: true}}, Type: "secret", Param: "password"},
   397  			},
   398  			contains: []string{"&nbsp;&nbsp;aliases:<br />", "&nbsp;&nbsp;- `alias1`<br />", "&nbsp;&nbsp;- `alias2` (**Deprecated**)<br />"},
   399  		},
   400  	}
   401  
   402  	for _, test := range tt {
   403  		if len(test.contains) > 0 {
   404  			res := resourceReferenceDetails(test.resourceRef)
   405  			for _, check := range test.contains {
   406  				assert.Contains(t, res, check)
   407  			}
   408  		} else {
   409  			assert.Equal(t, test.expected, resourceReferenceDetails(test.resourceRef))
   410  		}
   411  	}
   412  }
   413  
   414  func TestSortStepParameters(t *testing.T) {
   415  	stepData := config.StepData{
   416  		Spec: config.StepSpec{
   417  			Inputs: config.StepInputs{
   418  				Parameters: []config.StepParameters{
   419  					{Name: "ab1", Mandatory: false},
   420  					{Name: "ab3", Mandatory: true},
   421  					{Name: "ab5", Mandatory: false},
   422  					{Name: "ab6", Mandatory: true},
   423  					{Name: "ab4", Mandatory: false},
   424  					{Name: "ab2", Mandatory: true},
   425  					{Name: "ab7", MandatoryIf: []config.ParameterDependence{{Name: "ab1", Value: "ab1Val1"}}},
   426  				},
   427  			},
   428  		},
   429  	}
   430  
   431  	t.Run("ignore mandatory", func(t *testing.T) {
   432  		sortStepParameters(&stepData, false)
   433  
   434  		assert.Equal(t, "ab1", stepData.Spec.Inputs.Parameters[0].Name)
   435  		assert.Equal(t, "ab2", stepData.Spec.Inputs.Parameters[1].Name)
   436  		assert.Equal(t, "ab3", stepData.Spec.Inputs.Parameters[2].Name)
   437  		assert.Equal(t, "ab4", stepData.Spec.Inputs.Parameters[3].Name)
   438  		assert.Equal(t, "ab5", stepData.Spec.Inputs.Parameters[4].Name)
   439  		assert.Equal(t, "ab6", stepData.Spec.Inputs.Parameters[5].Name)
   440  		assert.Equal(t, "ab7", stepData.Spec.Inputs.Parameters[6].Name)
   441  	})
   442  
   443  	t.Run("consider mandatory", func(t *testing.T) {
   444  		sortStepParameters(&stepData, true)
   445  
   446  		assert.Equal(t, "ab2", stepData.Spec.Inputs.Parameters[0].Name)
   447  		assert.Equal(t, "ab3", stepData.Spec.Inputs.Parameters[1].Name)
   448  		assert.Equal(t, "ab6", stepData.Spec.Inputs.Parameters[2].Name)
   449  		assert.Equal(t, "ab7", stepData.Spec.Inputs.Parameters[3].Name)
   450  		assert.Equal(t, "ab1", stepData.Spec.Inputs.Parameters[4].Name)
   451  		assert.Equal(t, "ab4", stepData.Spec.Inputs.Parameters[5].Name)
   452  		assert.Equal(t, "ab5", stepData.Spec.Inputs.Parameters[6].Name)
   453  	})
   454  }