github.com/SAP/jenkins-library@v1.362.0/cmd/newmanExecute_test.go (about)

     1  //go:build unit
     2  // +build unit
     3  
     4  package cmd
     5  
     6  import (
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  	"testing"
    11  
    12  	sliceUtils "github.com/SAP/jenkins-library/pkg/piperutils"
    13  	"github.com/google/uuid"
    14  	"github.com/pkg/errors"
    15  	"github.com/stretchr/testify/assert"
    16  )
    17  
    18  type executedExecutables struct {
    19  	executable string
    20  	params     []string
    21  }
    22  
    23  type newmanExecuteMockUtils struct {
    24  	// *mock.ExecMockRunner
    25  	// *mock.FilesMock
    26  	errorOnGlob            bool
    27  	errorOnNewmanInstall   bool
    28  	errorOnRunShell        bool
    29  	errorOnNewmanExecution bool
    30  	errorOnLoggingNode     bool
    31  	errorOnLoggingNpm      bool
    32  	executedExecutables    []executedExecutables
    33  	filesToFind            []string
    34  	commandIndex           int
    35  }
    36  
    37  func newNewmanExecuteMockUtils() newmanExecuteMockUtils {
    38  	return newmanExecuteMockUtils{
    39  		filesToFind: []string{"localFile.json", "localFile2.json"},
    40  	}
    41  }
    42  
    43  func TestRunNewmanExecute(t *testing.T) {
    44  	t.Parallel()
    45  
    46  	allFineConfig := newmanExecuteOptions{
    47  		NewmanCollection:     "**.json",
    48  		NewmanEnvironment:    "env.json",
    49  		NewmanGlobals:        "globals.json",
    50  		NewmanInstallCommand: "npm install newman --global --quiet",
    51  		NewmanRunCommand:     "run {{.NewmanCollection}} --environment {{.Config.NewmanEnvironment}} --globals {{.Config.NewmanGlobals}} --reporters junit,html --reporter-junit-export target/newman/TEST-{{.CollectionDisplayName}}.xml --reporter-html-export target/newman/TEST-{{.CollectionDisplayName}}.html",
    52  	}
    53  
    54  	t.Run("happy path", func(t *testing.T) {
    55  		t.Parallel()
    56  		// init
    57  
    58  		utils := newNewmanExecuteMockUtils()
    59  
    60  		// test
    61  		err := runNewmanExecute(&allFineConfig, &utils)
    62  
    63  		// assert
    64  		assert.NoError(t, err)
    65  		assert.Contains(t, utils.executedExecutables, executedExecutables{executable: "node", params: []string{"--version"}})
    66  		assert.Contains(t, utils.executedExecutables, executedExecutables{executable: "npm", params: []string{"--version"}})
    67  		assert.Contains(t, utils.executedExecutables, executedExecutables{executable: "npm", params: []string{"install", "newman", "--global", "--quiet", "--prefix=~/.npm-global"}})
    68  		assert.Contains(t, utils.executedExecutables, executedExecutables{executable: filepath.FromSlash("/home/node/.npm-global/bin/newman"), params: []string{"run", "localFile.json", "--environment", "env.json", "--globals", "globals.json", "--reporters", "junit,html", "--reporter-junit-export", "target/newman/TEST-localFile.xml", "--reporter-html-export", "target/newman/TEST-localFile.html", "--suppress-exit-code"}})
    69  		assert.Contains(t, utils.executedExecutables, executedExecutables{executable: filepath.FromSlash("/home/node/.npm-global/bin/newman"), params: []string{"run", "localFile2.json", "--environment", "env.json", "--globals", "globals.json", "--reporters", "junit,html", "--reporter-junit-export", "target/newman/TEST-localFile2.xml", "--reporter-html-export", "target/newman/TEST-localFile2.html", "--suppress-exit-code"}})
    70  	})
    71  
    72  	t.Run("happy path with fail on error", func(t *testing.T) {
    73  		t.Parallel()
    74  		// init
    75  
    76  		utils := newNewmanExecuteMockUtils()
    77  		fineConfig := allFineConfig
    78  		fineConfig.FailOnError = true
    79  
    80  		// test
    81  		err := runNewmanExecute(&fineConfig, &utils)
    82  
    83  		// assert
    84  		assert.NoError(t, err)
    85  		assert.Contains(t, utils.executedExecutables, executedExecutables{executable: "node", params: []string{"--version"}})
    86  		assert.Contains(t, utils.executedExecutables, executedExecutables{executable: "npm", params: []string{"--version"}})
    87  		assert.Contains(t, utils.executedExecutables, executedExecutables{executable: "npm", params: []string{"install", "newman", "--global", "--quiet", "--prefix=~/.npm-global"}})
    88  		assert.Contains(t, utils.executedExecutables, executedExecutables{executable: filepath.FromSlash("/home/node/.npm-global/bin/newman"), params: []string{"run", "localFile.json", "--environment", "env.json", "--globals", "globals.json", "--reporters", "junit,html", "--reporter-junit-export", "target/newman/TEST-localFile.xml", "--reporter-html-export", "target/newman/TEST-localFile.html"}})
    89  		assert.Contains(t, utils.executedExecutables, executedExecutables{executable: filepath.FromSlash("/home/node/.npm-global/bin/newman"), params: []string{"run", "localFile2.json", "--environment", "env.json", "--globals", "globals.json", "--reporters", "junit,html", "--reporter-junit-export", "target/newman/TEST-localFile2.xml", "--reporter-html-export", "target/newman/TEST-localFile2.html"}})
    90  	})
    91  
    92  	t.Run("error on newman execution", func(t *testing.T) {
    93  		t.Parallel()
    94  		// init
    95  
    96  		utils := newNewmanExecuteMockUtils()
    97  		utils.errorOnNewmanExecution = true
    98  
    99  		// test
   100  		err := runNewmanExecute(&allFineConfig, &utils)
   101  
   102  		// assert
   103  		assert.EqualError(t, err, "The execution of the newman tests failed, see the log for details.: error on newman execution")
   104  	})
   105  
   106  	t.Run("error on newman installation", func(t *testing.T) {
   107  		t.Parallel()
   108  		// init
   109  
   110  		utils := newNewmanExecuteMockUtils()
   111  		utils.errorOnNewmanInstall = true
   112  
   113  		// test
   114  		err := runNewmanExecute(&allFineConfig, &utils)
   115  
   116  		// assert
   117  		assert.EqualError(t, err, "error installing newman: error on newman install")
   118  	})
   119  
   120  	t.Run("error on npm version logging", func(t *testing.T) {
   121  		t.Parallel()
   122  		// init
   123  
   124  		utils := newNewmanExecuteMockUtils()
   125  		utils.errorOnLoggingNpm = true
   126  
   127  		// test
   128  		err := runNewmanExecute(&allFineConfig, &utils)
   129  
   130  		// assert
   131  		assert.EqualError(t, err, "error logging npm version: error on RunExecutable")
   132  	})
   133  
   134  	t.Run("error on template resolution", func(t *testing.T) {
   135  		t.Parallel()
   136  		// init
   137  
   138  		utils := newNewmanExecuteMockUtils()
   139  		config := allFineConfig
   140  		config.NewmanRunCommand = "this is my erroneous command {{.collectionDisplayName}"
   141  
   142  		// test
   143  		err := runNewmanExecute(&config, &utils)
   144  
   145  		// assert
   146  		assert.EqualError(t, err, "could not parse newman command template: template: template:1: bad character U+007D '}'")
   147  	})
   148  
   149  	t.Run("error on file search", func(t *testing.T) {
   150  		t.Parallel()
   151  		// init
   152  
   153  		utils := newNewmanExecuteMockUtils()
   154  		utils.filesToFind = nil
   155  
   156  		// test
   157  		err := runNewmanExecute(&allFineConfig, &utils)
   158  
   159  		// assert
   160  		assert.EqualError(t, err, "no collection found with pattern '**.json'")
   161  	})
   162  
   163  	t.Run("no newman file", func(t *testing.T) {
   164  		t.Parallel()
   165  		// init
   166  
   167  		utils := newNewmanExecuteMockUtils()
   168  		utils.errorOnGlob = true
   169  
   170  		// test
   171  		err := runNewmanExecute(&allFineConfig, &utils)
   172  
   173  		// assert
   174  		assert.EqualError(t, err, "Could not execute global search for '**.json': error on Glob")
   175  	})
   176  }
   177  
   178  func TestDefineCollectionDisplayName(t *testing.T) {
   179  	t.Parallel()
   180  
   181  	t.Run("normal path", func(t *testing.T) {
   182  		t.Parallel()
   183  
   184  		path := filepath.Join("dir1", "dir2", "fancyFile.txt")
   185  		result := defineCollectionDisplayName(path)
   186  		assert.Equal(t, "dir1_dir2_fancyFile", result)
   187  	})
   188  
   189  	t.Run("directory", func(t *testing.T) {
   190  		t.Parallel()
   191  
   192  		path := filepath.Join("dir1", "dir2", "dir3")
   193  		result := defineCollectionDisplayName(path)
   194  		assert.Equal(t, "dir1_dir2_dir3", result)
   195  	})
   196  
   197  	t.Run("directory with dot prefix", func(t *testing.T) {
   198  		t.Parallel()
   199  
   200  		path := filepath.Join(".dir1", "dir2", "dir3", "file.json")
   201  		result := defineCollectionDisplayName(path)
   202  		assert.Equal(t, "dir1_dir2_dir3_file", result)
   203  	})
   204  
   205  	t.Run("empty path", func(t *testing.T) {
   206  		t.Parallel()
   207  
   208  		path := filepath.Join(".")
   209  		result := defineCollectionDisplayName(path)
   210  		assert.Equal(t, "", result)
   211  	})
   212  }
   213  
   214  func TestResolveTemplate(t *testing.T) {
   215  	t.Parallel()
   216  
   217  	t.Run("nothing to replace", func(t *testing.T) {
   218  		t.Parallel()
   219  
   220  		// config := newmanExecuteOptions{NewmanRunCommand: "this is my fancy command"}
   221  		config := newmanExecuteOptions{RunOptions: []string{"this", "is", "my", "fancy", "command"}}
   222  
   223  		cmd, err := resolveTemplate(&config, "collectionsDisplayName")
   224  		assert.NoError(t, err)
   225  		assert.Equal(t, []string{"this", "is", "my", "fancy", "command"}, cmd)
   226  	})
   227  
   228  	t.Run("replace display name", func(t *testing.T) {
   229  		t.Parallel()
   230  
   231  		config := newmanExecuteOptions{RunOptions: []string{"this", "is", "my", "fancy", "command", "{{.CollectionDisplayName}}"}}
   232  
   233  		cmd, err := resolveTemplate(&config, "theDisplayName")
   234  		assert.NoError(t, err)
   235  		assert.Equal(t, []string{"this", "is", "my", "fancy", "command", "theDisplayName"}, cmd)
   236  	})
   237  
   238  	t.Run("get environment variable", func(t *testing.T) {
   239  		t.Parallel()
   240  
   241  		temporaryEnvVarName := uuid.New().String()
   242  		os.Setenv(temporaryEnvVarName, "myEnvVar")
   243  		defer os.Unsetenv(temporaryEnvVarName)
   244  		config := newmanExecuteOptions{RunOptions: []string{"this", "is", "my", "fancy", "command", "with", "--env-var", "{{getenv \"" + temporaryEnvVarName + "\"}}"}}
   245  
   246  		cmd, err := resolveTemplate(&config, "collectionsDisplayName")
   247  		assert.NoError(t, err)
   248  		assert.Equal(t, []string{"this", "is", "my", "fancy", "command", "with", "--env-var", "myEnvVar"}, cmd)
   249  	})
   250  
   251  	t.Run("error when parameter cannot be resolved", func(t *testing.T) {
   252  		t.Parallel()
   253  
   254  		config := newmanExecuteOptions{RunOptions: []string{"this", "is", "my", "fancy", "command", "{{.collectionDisplayName}}"}}
   255  
   256  		_, err := resolveTemplate(&config, "theDisplayName")
   257  		assert.EqualError(t, err, "error on executing template: template: template:1:2: executing \"template\" at <.collectionDisplayName>: can't evaluate field collectionDisplayName in type cmd.TemplateConfig")
   258  	})
   259  
   260  	t.Run("error when template cannot be parsed", func(t *testing.T) {
   261  		t.Parallel()
   262  
   263  		config := newmanExecuteOptions{RunOptions: []string{"this", "is", "my", "fancy", "command", "{{.collectionDisplayName}"}}
   264  
   265  		_, err := resolveTemplate(&config, "theDisplayName")
   266  		assert.EqualError(t, err, "could not parse newman command template: template: template:1: bad character U+007D '}'")
   267  	})
   268  }
   269  
   270  func TestLogVersions(t *testing.T) {
   271  	t.Parallel()
   272  
   273  	t.Run("happy path", func(t *testing.T) {
   274  		utils := newNewmanExecuteMockUtils()
   275  
   276  		err := logVersions(&utils)
   277  		assert.NoError(t, err)
   278  		assert.Contains(t, utils.executedExecutables, executedExecutables{executable: "npm", params: []string{"--version"}})
   279  	})
   280  
   281  	t.Run("error in node execution", func(t *testing.T) {
   282  		utils := newNewmanExecuteMockUtils()
   283  		utils.errorOnLoggingNode = true
   284  
   285  		err := logVersions(&utils)
   286  		assert.EqualError(t, err, "error logging node version: error on RunExecutable")
   287  	})
   288  
   289  	t.Run("error in npm execution", func(t *testing.T) {
   290  		utils := newNewmanExecuteMockUtils()
   291  		utils.errorOnLoggingNpm = true
   292  
   293  		err := logVersions(&utils)
   294  		assert.EqualError(t, err, "error logging npm version: error on RunExecutable")
   295  		assert.Contains(t, utils.executedExecutables, executedExecutables{executable: "node", params: []string{"--version"}})
   296  	})
   297  }
   298  
   299  func (e *newmanExecuteMockUtils) Glob(string) (matches []string, err error) {
   300  	if e.errorOnGlob {
   301  		return nil, errors.New("error on Glob")
   302  	}
   303  
   304  	return e.filesToFind, nil
   305  }
   306  
   307  func (e *newmanExecuteMockUtils) RunExecutable(executable string, params ...string) error {
   308  	if e.errorOnRunShell {
   309  		return errors.New("error on RunExecutable")
   310  	}
   311  	if e.errorOnLoggingNode && executable == "node" && params[0] == "--version" {
   312  		return errors.New("error on RunExecutable")
   313  	}
   314  	if e.errorOnLoggingNpm && executable == "npm" && params[0] == "--version" {
   315  		return errors.New("error on RunExecutable")
   316  	}
   317  	if e.errorOnNewmanExecution && strings.Contains(executable, "newman") {
   318  		return errors.New("error on newman execution")
   319  	}
   320  	if e.errorOnNewmanInstall && sliceUtils.ContainsString(params, "install") {
   321  		return errors.New("error on newman install")
   322  	}
   323  
   324  	length := len(e.executedExecutables)
   325  	if length < e.commandIndex+1 {
   326  		e.executedExecutables = append(e.executedExecutables, executedExecutables{})
   327  		length++
   328  	}
   329  
   330  	e.executedExecutables[length-1].executable = executable
   331  	e.executedExecutables[length-1].params = params
   332  	e.commandIndex++
   333  
   334  	return nil
   335  }
   336  
   337  func (e *newmanExecuteMockUtils) Getenv(key string) string {
   338  	if key == "HOME" {
   339  		return "/home/node"
   340  	}
   341  	return ""
   342  }