You've already forked sap-jenkins-library
mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-07-01 00:54:55 +02:00
Refactor pkg/npm and npmExecuteScripts (#1684)
This change refactors the npm pkg and npmExecuteScripts implementations to be reusable for future steps, e.g., npmExecuteLint. In addition, it fixes few small bugs related to unit test execution on Windows and the fileUtils mocking implementation. Co-authored-by: Daniel Kurzynski <daniel.kurzynski@sap.com> Co-authored-by: Stephan Aßmus <stephan.assmus@sap.com>
This commit is contained in:
@ -1,161 +1,140 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/SAP/jenkins-library/pkg/mock"
|
||||
"github.com/bmatcuk/doublestar"
|
||||
"github.com/SAP/jenkins-library/pkg/npm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type npmExecuteScriptsMockUtilsBundle struct {
|
||||
execRunner mock.ExecMockRunner
|
||||
files map[string][]byte
|
||||
type npmMockUtilsBundle struct {
|
||||
*mock.FilesMock
|
||||
execRunner *mock.ExecMockRunner
|
||||
}
|
||||
|
||||
func (u *npmExecuteScriptsMockUtilsBundle) fileExists(path string) (bool, error) {
|
||||
_, exists := u.files[path]
|
||||
return exists, nil
|
||||
func (u *npmMockUtilsBundle) GetExecRunner() npm.ExecRunner {
|
||||
return u.execRunner
|
||||
}
|
||||
|
||||
// duplicated from nexusUpload_test.go for now, refactor later?
|
||||
func (u *npmExecuteScriptsMockUtilsBundle) glob(pattern string) ([]string, error) {
|
||||
var matches []string
|
||||
for path := range u.files {
|
||||
matched, _ := doublestar.Match(pattern, path)
|
||||
if matched {
|
||||
matches = append(matches, path)
|
||||
func newNpmMockUtilsBundle() npmMockUtilsBundle {
|
||||
utils := npmMockUtilsBundle{FilesMock: &mock.FilesMock{}, execRunner: &mock.ExecMockRunner{}}
|
||||
return utils
|
||||
}
|
||||
|
||||
type npmExecutorMock struct {
|
||||
utils npmMockUtilsBundle
|
||||
config npmExecuteScriptsOptions
|
||||
}
|
||||
|
||||
func (n *npmExecutorMock) FindPackageJSONFiles() []string {
|
||||
packages, _ := n.utils.Glob("**/package.json")
|
||||
return packages
|
||||
}
|
||||
|
||||
func (n *npmExecutorMock) FindPackageJSONFilesWithScript(packageJSONFiles []string, script string) ([]string, error) {
|
||||
return packageJSONFiles, nil
|
||||
}
|
||||
|
||||
func (n *npmExecutorMock) RunScriptsInAllPackages(runScripts []string, runOptions []string, virtualFrameBuffer bool) error {
|
||||
if len(runScripts) != len(n.config.RunScripts) {
|
||||
return fmt.Errorf("RunScriptsInAllPackages was called with a different list of runScripts than config.RunScripts")
|
||||
}
|
||||
for i, script := range runScripts {
|
||||
if script != n.config.RunScripts[i] {
|
||||
return fmt.Errorf("RunScriptsInAllPackages was called with a different list of runScripts than config.RunScripts")
|
||||
}
|
||||
}
|
||||
// The order in m.files is not deterministic, this would result in flaky tests.
|
||||
sort.Strings(matches)
|
||||
return matches, nil
|
||||
}
|
||||
|
||||
func (u *npmExecuteScriptsMockUtilsBundle) getwd() (dir string, err error) {
|
||||
return "/project", nil
|
||||
}
|
||||
if len(runOptions) != 0 {
|
||||
return fmt.Errorf("RunScriptsInAllPackages was unexpectedly called with a list of runOptions")
|
||||
}
|
||||
|
||||
if virtualFrameBuffer != n.config.VirtualFrameBuffer {
|
||||
return fmt.Errorf("RunScriptsInAllPackages was called with a different value of virtualFrameBuffer than config.virtualFrameBuffer")
|
||||
}
|
||||
|
||||
func (u *npmExecuteScriptsMockUtilsBundle) chdir(dir string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *npmExecuteScriptsMockUtilsBundle) getExecRunner() execRunner {
|
||||
return &u.execRunner
|
||||
func (n *npmExecutorMock) InstallAllDependencies(packageJSONFiles []string) error {
|
||||
allPackages := n.FindPackageJSONFiles()
|
||||
if len(packageJSONFiles) != len(allPackages) {
|
||||
return fmt.Errorf("packageJSONFiles != n.FindPackageJSONFiles()")
|
||||
}
|
||||
for i, packageJSON := range packageJSONFiles {
|
||||
if packageJSON != allPackages[i] {
|
||||
return fmt.Errorf("InstallAllDependencies was called with a different list of package.json files than result of n.FindPackageJSONFiles()")
|
||||
}
|
||||
}
|
||||
|
||||
if !n.config.Install {
|
||||
return fmt.Errorf("InstallAllDependencies was called but config.Install was false")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *npmExecutorMock) SetNpmRegistries() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestNpmExecuteScripts(t *testing.T) {
|
||||
t.Run("Call without install and run-scripts", func(t *testing.T) {
|
||||
utils := newNpmExecuteScriptsMockUtilsBundle()
|
||||
utils.files["package.json"] = []byte(`abc`)
|
||||
utils.files["package-lock.json"] = []byte(`abc`)
|
||||
options := npmExecuteScriptsOptions{}
|
||||
t.Run("Call with install", func(t *testing.T) {
|
||||
config := npmExecuteScriptsOptions{Install: true, RunScripts: []string{"ci-build", "ci-test"}}
|
||||
utils := newNpmMockUtilsBundle()
|
||||
utils.AddFile("package.json", []byte("{\"name\": \"Test\" }"))
|
||||
utils.AddFile("src/package.json", []byte("{\"name\": \"Test\" }"))
|
||||
|
||||
err := runNpmExecuteScripts(&utils, &options)
|
||||
npmExecutor := npmExecutorMock{utils: utils, config: config}
|
||||
err := runNpmExecuteScripts(&npmExecutor, &config)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 2, len(utils.execRunner.Calls))
|
||||
})
|
||||
|
||||
t.Run("Project with package lock", func(t *testing.T) {
|
||||
utils := newNpmExecuteScriptsMockUtilsBundle()
|
||||
utils.files["package.json"] = []byte(`abc`)
|
||||
utils.files["foo/bar/node_modules/package.json"] = []byte(`abc`) // is filtered out
|
||||
utils.files["gen/bar/package.json"] = []byte(`abc`) // is filtered out
|
||||
utils.files["foo/gen/package.json"] = []byte(`abc`) // is filtered out
|
||||
utils.files["package-lock.json"] = []byte(`abc`)
|
||||
options := npmExecuteScriptsOptions{}
|
||||
options.Install = true
|
||||
options.RunScripts = []string{"foo", "bar"}
|
||||
options.DefaultNpmRegistry = "foo.bar"
|
||||
t.Run("Call without install", func(t *testing.T) {
|
||||
config := npmExecuteScriptsOptions{Install: true, RunScripts: []string{"ci-build", "ci-test"}}
|
||||
utils := newNpmMockUtilsBundle()
|
||||
utils.AddFile("package.json", []byte("{\"name\": \"Test\" }"))
|
||||
utils.AddFile("src/package.json", []byte("{\"name\": \"Test\" }"))
|
||||
|
||||
err := runNpmExecuteScripts(&utils, &options)
|
||||
npmExecutor := npmExecutorMock{utils: utils, config: config}
|
||||
err := runNpmExecuteScripts(&npmExecutor, &config)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"ci"}}, utils.execRunner.Calls[2])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run-script", "foo", "--if-present"}}, utils.execRunner.Calls[3])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run-script", "bar", "--if-present"}}, utils.execRunner.Calls[4])
|
||||
assert.Equal(t, 5, len(utils.execRunner.Calls))
|
||||
})
|
||||
|
||||
t.Run("Project with two package json files", func(t *testing.T) {
|
||||
utils := newNpmExecuteScriptsMockUtilsBundle()
|
||||
utils.files["package.json"] = []byte(`abc`)
|
||||
utils.files["foo/bar/package.json"] = []byte(`abc`)
|
||||
utils.files["package-lock.json"] = []byte(`abc`)
|
||||
options := npmExecuteScriptsOptions{}
|
||||
options.Install = true
|
||||
options.RunScripts = []string{"foo", "bar"}
|
||||
t.Run("Call with virtualFrameBuffer", func(t *testing.T) {
|
||||
config := npmExecuteScriptsOptions{Install: true, RunScripts: []string{"ci-build", "ci-test"}, VirtualFrameBuffer: true}
|
||||
utils := newNpmMockUtilsBundle()
|
||||
utils.AddFile("package.json", []byte("{\"name\": \"Test\" }"))
|
||||
utils.AddFile("src/package.json", []byte("{\"name\": \"Test\" }"))
|
||||
|
||||
err := runNpmExecuteScripts(&utils, &options)
|
||||
npmExecutor := npmExecutorMock{utils: utils, config: config}
|
||||
err := runNpmExecuteScripts(&npmExecutor, &config)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"ci"}}, utils.execRunner.Calls[2])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run-script", "foo", "--if-present"}}, utils.execRunner.Calls[3])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run-script", "bar", "--if-present"}}, utils.execRunner.Calls[4])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"ci"}}, utils.execRunner.Calls[7])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run-script", "foo", "--if-present"}}, utils.execRunner.Calls[8])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run-script", "bar", "--if-present"}}, utils.execRunner.Calls[9])
|
||||
assert.Equal(t, 10, len(utils.execRunner.Calls))
|
||||
})
|
||||
|
||||
t.Run("Project with yarn lock", func(t *testing.T) {
|
||||
utils := newNpmExecuteScriptsMockUtilsBundle()
|
||||
utils.files["package.json"] = []byte(`abc`)
|
||||
utils.files["yarn.lock"] = []byte(`abc`)
|
||||
options := npmExecuteScriptsOptions{}
|
||||
options.Install = true
|
||||
options.RunScripts = []string{"foo", "bar"}
|
||||
t.Run("Test integration with npm pkg", func(t *testing.T) {
|
||||
config := npmExecuteScriptsOptions{Install: true, RunScripts: []string{"ci-build"}}
|
||||
|
||||
err := runNpmExecuteScripts(&utils, &options)
|
||||
options := npm.ExecutorOptions{SapNpmRegistry: config.SapNpmRegistry, DefaultNpmRegistry: config.DefaultNpmRegistry}
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, mock.ExecCall{Exec: "yarn", Params: []string{"install", "--frozen-lockfile"}}, utils.execRunner.Calls[2])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run-script", "foo", "--if-present"}}, utils.execRunner.Calls[3])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run-script", "bar", "--if-present"}}, utils.execRunner.Calls[4])
|
||||
})
|
||||
utils := newNpmMockUtilsBundle()
|
||||
utils.AddFile("package.json", []byte("{\"scripts\": { \"ci-build\": \"\" } }"))
|
||||
utils.AddFile("package-lock.json", []byte(""))
|
||||
|
||||
t.Run("Project without lock file", func(t *testing.T) {
|
||||
utils := newNpmExecuteScriptsMockUtilsBundle()
|
||||
utils.files["package.json"] = []byte(`abc`)
|
||||
options := npmExecuteScriptsOptions{}
|
||||
options.Install = true
|
||||
options.RunScripts = []string{"foo", "bar"}
|
||||
npmExecutor := npm.Execute{Utils: &utils, Options: options}
|
||||
|
||||
err := runNpmExecuteScripts(&utils, &options)
|
||||
err := runNpmExecuteScripts(&npmExecutor, &config)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"install"}}, utils.execRunner.Calls[2])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run-script", "foo", "--if-present"}}, utils.execRunner.Calls[3])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run-script", "bar", "--if-present"}}, utils.execRunner.Calls[4])
|
||||
})
|
||||
|
||||
t.Run("Call run-scripts with virtual frame buffer", func(t *testing.T) {
|
||||
utils := newNpmExecuteScriptsMockUtilsBundle()
|
||||
utils.files["package.json"] = []byte("{\"scripts\": { \"foo\": \"\" } }")
|
||||
options := npmExecuteScriptsOptions{}
|
||||
options.Install = false
|
||||
options.RunScripts = []string{"foo"}
|
||||
options.VirtualFrameBuffer = true
|
||||
|
||||
err := runNpmExecuteScripts(&utils, &options)
|
||||
|
||||
assert.Contains(t, utils.execRunner.Env, "DISPLAY=:99")
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, utils.execRunner.Calls, 4) {
|
||||
xvfbCall := utils.execRunner.Calls[0]
|
||||
assert.Equal(t, "Xvfb", xvfbCall.Exec)
|
||||
assert.Equal(t, []string{"-ac", ":99", "-screen", "0", "1280x1024x16"}, xvfbCall.Params)
|
||||
assert.True(t, xvfbCall.Async)
|
||||
assert.True(t, xvfbCall.Execution.Killed)
|
||||
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run-script", "foo", "--if-present"}}, utils.execRunner.Calls[3])
|
||||
if assert.NoError(t, err) {
|
||||
if assert.Equal(t, 6, len(utils.execRunner.Calls)) {
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"config", "get", "registry"}}, utils.execRunner.Calls[0])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"config", "get", "@sap:registry"}}, utils.execRunner.Calls[1])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"ci"}}, utils.execRunner.Calls[2])
|
||||
assert.Equal(t, mock.ExecCall{Exec: "npm", Params: []string{"run", "ci-build"}}, utils.execRunner.Calls[5])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func newNpmExecuteScriptsMockUtilsBundle() npmExecuteScriptsMockUtilsBundle {
|
||||
utils := npmExecuteScriptsMockUtilsBundle{}
|
||||
utils.files = map[string][]byte{}
|
||||
return utils
|
||||
}
|
||||
|
Reference in New Issue
Block a user