diff --git a/cmd/config/io.go b/cmd/config/io.go index b609e5c8..188c75e8 100644 --- a/cmd/config/io.go +++ b/cmd/config/io.go @@ -4,42 +4,68 @@ import ( "errors" "io/ioutil" "os" + "path/filepath" + "github.com/spf13/viper" "gopkg.in/yaml.v3" ) // ReadFile returns OneBuildConfiguration file content as string. func ReadFile() (string, error) { - if _, err := os.Stat(OneBuildConfigFileName); os.IsNotExist(err) { - return "", errors.New("no '" + OneBuildConfigFileName + "' file found in current directory") + oneBuildConfigFile := getConfigFile() + if _, err := os.Stat(oneBuildConfigFile); os.IsNotExist(err) { + return "", errors.New("no '" + oneBuildConfigFile + "' file found") } - yamlFile, err := ioutil.ReadFile(OneBuildConfigFileName) + yamlFile, err := ioutil.ReadFile(oneBuildConfigFile) if err != nil { - return "", errors.New("error in reading '" + OneBuildConfigFileName + "' configuration file") + return "", errors.New("error in reading '" + oneBuildConfigFile + "' configuration file") } return string(yamlFile), nil } // IsConfigFilePresent return whether the config file present or not func IsConfigFilePresent() bool { - if _, err := os.Stat(OneBuildConfigFileName); err == nil { + oneBuildConfigFile := getConfigFile() + if _, err := os.Stat(oneBuildConfigFile); err == nil { return true } else if os.IsNotExist(err) { return false - } else { - return true } + return false } // WriteConfigFile writes config to the file // If there is an error, it will be of type *Error. func WriteConfigFile(configuration OneBuildConfiguration) error { + oneBuildConfigFile := getConfigFile() yamlData, _ := yaml.Marshal(&configuration) content := string(yamlData) - return ioutil.WriteFile(OneBuildConfigFileName, []byte(content), 0777) + return ioutil.WriteFile(oneBuildConfigFile, []byte(content), 0750) } // DeleteConfigFile deletes the config file func DeleteConfigFile() error { - return os.Remove(OneBuildConfigFileName) + oneBuildConfigFile := getConfigFile() + return os.Remove(oneBuildConfigFile) +} + +// GetAbsoluteDirPathOfConfigFile gets the base directory from the configuration file location +func GetAbsoluteDirPathOfConfigFile() (string, error) { + oneBuildConfigFile := getConfigFile() + abs, err := filepath.Abs(oneBuildConfigFile) + if err != nil { + return "", errors.New("error in resolving file path for '" + oneBuildConfigFile + "' configuration file.") + } + baseDirFromAbs := filepath.Dir(abs) + return baseDirFromAbs, nil +} + +// getConfigFile returns the 1build configuration file from root file flag or global file variable +func getConfigFile() string { + fileFlag := viper.GetString("file") + if fileFlag == "" { + return OneBuildConfigFileName + } + + return fileFlag } diff --git a/cmd/delete.go b/cmd/del/delete.go similarity index 86% rename from cmd/delete.go rename to cmd/del/delete.go index 034c82bd..592f20ea 100644 --- a/cmd/delete.go +++ b/cmd/del/delete.go @@ -1,4 +1,4 @@ -package cmd +package del import ( "bufio" @@ -13,7 +13,8 @@ import ( var shouldDelete bool -var deleteCmd = &cobra.Command{ +// Cmd cobra command for delete one build configuration +var Cmd = &cobra.Command{ Use: "delete", Short: "Deletes project configuration", Long: `Deletes project configuration @@ -49,6 +50,5 @@ For example: } func init() { - rootCmd.AddCommand(deleteCmd) - deleteCmd.Flags().BoolVarP(&shouldDelete, "force", "f", false, "Forcibly delete configuration file") + Cmd.Flags().BoolVar(&shouldDelete, "force", false, "Forcibly del configuration file") } diff --git a/cmd/exec/exec.go b/cmd/exec/exec.go index d807f663..286d659a 100644 --- a/cmd/exec/exec.go +++ b/cmd/exec/exec.go @@ -67,9 +67,9 @@ func executeAndStopIfFailed(command *models.CommandContext, executeStart time.Ti } -func buildExecutionPlan(onebuildConfig config.OneBuildConfiguration, commands ...string) models.OneBuildExecutionPlan { +func buildExecutionPlan(config config.OneBuildConfiguration, commands ...string) models.OneBuildExecutionPlan { - before := onebuildConfig.Before + before := config.Before var executionPlan models.OneBuildExecutionPlan if before != "" { executionPlan.Before = &models.CommandContext{ @@ -77,18 +77,18 @@ func buildExecutionPlan(onebuildConfig config.OneBuildConfiguration, commands .. } for _, name := range commands { - executionCommand := onebuildConfig.GetCommand(name) + executionCommand := config.GetCommand(name) if executionCommand == "" { utils.CPrintln("\nError building execution plan. Command \""+name+"\" not found.", utils.Style{Color: utils.RED, Bold: true}) - onebuildConfig.Print() + config.Print() utils.ExitWithCode("127") } executionPlan.Commands = append(executionPlan.Commands, &models.CommandContext{ Name: name, Command: executionCommand, CommandSession: bashCommand(sh.NewSession(), executionCommand)}) } - after := onebuildConfig.After + after := config.After if after != "" { executionPlan.After = &models.CommandContext{ Name: "after", Command: after, CommandSession: bashCommand(sh.NewSession(), after)} @@ -98,6 +98,8 @@ func buildExecutionPlan(onebuildConfig config.OneBuildConfiguration, commands .. } func bashCommand(s *sh.Session, command string) *sh.Session { + configFileAbsoluteDir, _ := config.GetAbsoluteDirPathOfConfigFile() + s.SetDir(configFileAbsoluteDir) return s.Command("bash", "-c", command) } diff --git a/cmd/init.go b/cmd/initialize/init.go similarity index 78% rename from cmd/init.go rename to cmd/initialize/init.go index b7eccc7d..65c493e4 100644 --- a/cmd/init.go +++ b/cmd/initialize/init.go @@ -1,4 +1,4 @@ -package cmd +package initialize import ( "fmt" @@ -7,7 +7,8 @@ import ( "github.com/spf13/cobra" ) -var initCmd = &cobra.Command{ +// Cmd cobra command for initializing one build configuration +var Cmd = &cobra.Command{ Use: "init", Short: "Create default project configuration", Long: `Create default project configuration @@ -16,8 +17,8 @@ var initCmd = &cobra.Command{ For example: - 1build init --name project - 1build init --name "My favorite project"`, + 1build initialize --name project + 1build initialize --name "My favorite project"`, PreRun: func(cmd *cobra.Command, args []string) { if config.IsConfigFilePresent() { fmt.Println("'" + config.OneBuildConfigFileName + "' configuration file already exists.") @@ -43,8 +44,6 @@ For example: } func init() { - rootCmd.AddCommand(initCmd) - - initCmd.Flags().StringP("name", "n", "", "Project name") - _ = initCmd.MarkFlagRequired("name") + Cmd.Flags().StringP("name", "n", "", "Project name") + _ = Cmd.MarkFlagRequired("name") } diff --git a/cmd/list.go b/cmd/list/list.go similarity index 82% rename from cmd/list.go rename to cmd/list/list.go index c4b52047..06755669 100644 --- a/cmd/list.go +++ b/cmd/list/list.go @@ -1,4 +1,4 @@ -package cmd +package list import ( "fmt" @@ -6,7 +6,8 @@ import ( "github.com/spf13/cobra" ) -var listCmd = &cobra.Command{ +// Cmd cobra command for listing one build configuration +var Cmd = &cobra.Command{ Use: "list", Short: "Show all available commands from the current project configuration", Long: "Show all available commands from the current project configuration", @@ -19,7 +20,3 @@ var listCmd = &cobra.Command{ oneBuildConfig.Print() }, } - -func init() { - rootCmd.AddCommand(listCmd) -} diff --git a/cmd/root.go b/cmd/root.go index 742805af..d768df71 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,21 +2,27 @@ package cmd import ( "fmt" + "github.com/gopinath-langote/1build/cmd/del" + "github.com/gopinath-langote/1build/cmd/initialize" + "github.com/gopinath-langote/1build/cmd/list" + "github.com/gopinath-langote/1build/cmd/set" + "github.com/gopinath-langote/1build/cmd/unset" - parse "github.com/gopinath-langote/1build/cmd/config" + configuration "github.com/gopinath-langote/1build/cmd/config" "github.com/gopinath-langote/1build/cmd/exec" "github.com/gopinath-langote/1build/cmd/utils" "github.com/spf13/cobra" "github.com/spf13/viper" ) -var rootCmd = &cobra.Command{ +// Cmd cobra for root level +var Cmd = &cobra.Command{ Use: "1build", Version: "1.4.0", Short: "Frictionless way of managing project-specific commands", Args: cobra.MinimumNArgs(0), PreRun: func(cmd *cobra.Command, args []string) { - _, err := parse.LoadOneBuildConfiguration() + _, err := configuration.LoadOneBuildConfiguration() if err != nil { fmt.Println(err) utils.ExitError() @@ -24,7 +30,7 @@ var rootCmd = &cobra.Command{ }, Run: func(cmd *cobra.Command, args []string) { if len(args) < 1 { - listCmd.Run(cmd, args) + list.Cmd.Run(cmd, args) } else { exec.ExecutePlan(args...) } @@ -33,15 +39,23 @@ var rootCmd = &cobra.Command{ // Execute entry-point for cobra app func Execute() { - if err := rootCmd.Execute(); err != nil { + if err := Cmd.Execute(); err != nil { fmt.Println(err) utils.ExitError() } } func init() { - rootCmd.SetHelpCommand(&cobra.Command{Use: "no-help", Hidden: true}) - rootCmd.PersistentFlags().BoolP("quiet", "q", false, + Cmd.SetHelpCommand(&cobra.Command{Use: "no-help", Hidden: true}) + Cmd.PersistentFlags().BoolP("quiet", "q", false, "Hide output log of command & only show SUCCESS/FAILURE result") - _ = viper.BindPFlags(rootCmd.PersistentFlags()) + Cmd.PersistentFlags(). + StringP("file", "f", configuration.OneBuildConfigFileName, "The file path for 1build configuration file.") + _ = viper.BindPFlags(Cmd.PersistentFlags()) + + Cmd.AddCommand(list.Cmd) + Cmd.AddCommand(del.Cmd) + Cmd.AddCommand(initialize.Cmd) + Cmd.AddCommand(set.Cmd) + Cmd.AddCommand(unset.Cmd) } diff --git a/cmd/set.go b/cmd/set/set.go similarity index 90% rename from cmd/set.go rename to cmd/set/set.go index b0180aeb..8e8f2edb 100644 --- a/cmd/set.go +++ b/cmd/set/set.go @@ -1,4 +1,4 @@ -package cmd +package set import ( "fmt" @@ -10,7 +10,8 @@ import ( "github.com/spf13/cobra" ) -var setCmd = &cobra.Command{ +// Cmd cobra command for setting one build configuration command +var Cmd = &cobra.Command{ Use: "set", Short: "Set new or update the existing command in the current project configuration", Long: `Set new or update the existing command in the current project configuration @@ -86,7 +87,7 @@ func setCommand(configuration config.OneBuildConfiguration, name string, value s command := map[string]string{} command[name] = value - index := indexOfCommandIfPresent(configuration, name) + index := IndexOfCommandIfPresent(configuration, name) if index == -1 { strings := append(configuration.Commands, command) configuration.Commands = strings @@ -96,7 +97,8 @@ func setCommand(configuration config.OneBuildConfiguration, name string, value s return configuration } -func indexOfCommandIfPresent(configuration config.OneBuildConfiguration, commandName string) int { +// IndexOfCommandIfPresent returns index in configuration for command if exists +func IndexOfCommandIfPresent(configuration config.OneBuildConfiguration, commandName string) int { return utils.SliceIndex(len(configuration.Commands), func(i int) bool { i2 := configuration.Commands[i] for k := range i2 { @@ -107,7 +109,3 @@ func indexOfCommandIfPresent(configuration config.OneBuildConfiguration, command return false }) } - -func init() { - rootCmd.AddCommand(setCmd) -} diff --git a/cmd/unset.go b/cmd/unset/unset.go similarity index 93% rename from cmd/unset.go rename to cmd/unset/unset.go index 2e60747f..d3d39399 100644 --- a/cmd/unset.go +++ b/cmd/unset/unset.go @@ -1,7 +1,8 @@ -package cmd +package unset import ( "fmt" + "github.com/gopinath-langote/1build/cmd/set" "regexp" "strings" @@ -11,7 +12,8 @@ import ( "github.com/spf13/cobra" ) -var unsetCmd = &cobra.Command{ +// Cmd cobra command for unsetting one build configuration command +var Cmd = &cobra.Command{ Use: "unset", Short: "Remove one or more existing command(s) in the current project configuration", Long: `Remove one or more existing command(s) in the current project configuration @@ -88,7 +90,7 @@ func findIndex(configuration config.OneBuildConfiguration, name string) int { case config.BeforeCommand, config.AfterCommand: return callbackExistence(configuration, name) default: - return indexOfCommandIfPresent(configuration, name) + return set.IndexOfCommandIfPresent(configuration, name) } } @@ -115,6 +117,3 @@ func removeCommand(configuration config.OneBuildConfiguration, name string, inde return configuration } -func init() { - rootCmd.AddCommand(unsetCmd) -} diff --git a/testing/cli_test.go b/testing/cli_test.go index 62c5ad0e..ea9f9038 100644 --- a/testing/cli_test.go +++ b/testing/cli_test.go @@ -25,7 +25,11 @@ func TestAll(t *testing.T) { if tt.Setup != nil { _ = tt.Setup(testResourceDirectory) } - cmd := exec.Command(binaryPath, tt.CmdArgs...) + var args []string + if tt.CmdArgs != nil { + args = tt.CmdArgs(testResourceDirectory) + } + cmd := exec.Command(binaryPath, args...) cmd.Dir = testResourceDirectory out, _ := cmd.Output() _ = tt.Assertion(testResourceDirectory, string(out), t) diff --git a/testing/fixtures/command_delete_fixtures.go b/testing/fixtures/command_delete_fixtures.go index 1bed0900..3c1a68df 100644 --- a/testing/fixtures/command_delete_fixtures.go +++ b/testing/fixtures/command_delete_fixtures.go @@ -13,6 +13,7 @@ func featureDeleteTestData() []Test { feature := "delete" return []Test{ shouldDeleteConfigFile(feature), + shouldDeleteConfigSpecifiedFile(feature), shouldFailIfFileDoesntExists(feature, ""), shouldFailIfFileDoesntExists(feature, "--force"), } @@ -22,7 +23,7 @@ func shouldDeleteConfigFile(feature string) Test { return Test{ Feature: feature, Name: "shouldDeleteConfigFile", - CmdArgs: []string{"delete", "--force"}, + CmdArgs: Args("delete", "--force"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, "project: Sample Project\ncommands:\n") }, @@ -32,12 +33,30 @@ func shouldDeleteConfigFile(feature string) Test { } } +func shouldDeleteConfigSpecifiedFile(feature string) Test { + return Test{ + Feature: feature, + Name: "shouldDeleteConfigSpecifiedFile", + CmdArgs: func(dir string) []string { + return []string{"delete", "-f", dir + "/custom-directory/some-file.yaml", "--force"} + }, + Setup: func(dir string) error { + _ = os.MkdirAll(dir+"/custom-directory", 0750) + return utils.CreateConfigFileWithName( + dir+"/custom-directory", "some-file.yaml", "project: Sample Project\ncommands:\n") + }, + Assertion: func(dir string, actualOutput string, t *testing.T) bool { + return assertFileNotExists(t, dir+"/custom-directory/some-file.yaml") + }, + } +} + func shouldFailIfFileDoesntExists(feature string, arg string) Test { expectedOutput := "No configuration file found!" return Test{ Feature: feature, Name: "shouldFailIfFileDoesntExists", - CmdArgs: []string{"delete", arg}, + CmdArgs: Args("delete", arg), Assertion: func(dir string, actualOutput string, t *testing.T) bool { return assert.Contains(t, actualOutput, expectedOutput) }, diff --git a/testing/fixtures/command_init_fixtures.go b/testing/fixtures/command_init_fixtures.go index 10ed1b25..1cfe5e56 100644 --- a/testing/fixtures/command_init_fixtures.go +++ b/testing/fixtures/command_init_fixtures.go @@ -2,6 +2,7 @@ package fixtures import ( "io/ioutil" + "os" "testing" "github.com/gopinath-langote/1build/testing/def" @@ -13,6 +14,7 @@ func featureInitTestsData() []Test { feature := "init" return []Test{ shouldInitialiseNewProject(feature), + shouldInitialiseNewProjectInSpecifiedFile(feature), shouldFailIfFileAlreadyExists(feature), } } @@ -25,7 +27,7 @@ commands: return Test{ Feature: feature, Name: "shouldInitialiseNewProject", - CmdArgs: []string{"init", "--name", "trial"}, + CmdArgs: Args("init", "--name", "trial"), Assertion: func(dir string, actualOutput string, t *testing.T) bool { filePath := dir + "/" + def.ConfigFileName assert.FileExists(t, dir+"/"+def.ConfigFileName) @@ -35,6 +37,29 @@ commands: } } +func shouldInitialiseNewProjectInSpecifiedFile(feature string) Test { + expectedOutput := `project: trial +commands: + - build: echo 'Running build' +` + return Test{ + Feature: feature, + Name: "shouldInitialiseNewProjectInSpecifiedFile", + CmdArgs: func(dir string) []string { + return []string{"init", "--name", "trial", "-f", dir + "/some-dir/some-config.yaml"} + }, + Setup: func(dir string) error { + return os.MkdirAll(dir+"/some-dir/", 0750) + }, + Assertion: func(dir string, actualOutput string, t *testing.T) bool { + filePath := dir + "/some-dir/some-config.yaml" + assert.FileExists(t, filePath) + content, _ := ioutil.ReadFile(filePath) + return assert.Contains(t, string(content), expectedOutput) + }, + } +} + func shouldFailIfFileAlreadyExists(feature string) Test { defaultFileContent := ` project: Sample Project @@ -46,7 +71,7 @@ commands: return Test{ Feature: feature, Name: "shouldFailIfFileAlreadyExists", - CmdArgs: []string{"init", "--name", "trial"}, + CmdArgs: Args("init", "--name", "trial"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, diff --git a/testing/fixtures/command_list_fixtures.go b/testing/fixtures/command_list_fixtures.go index aaabc678..0c9c7c2c 100644 --- a/testing/fixtures/command_list_fixtures.go +++ b/testing/fixtures/command_list_fixtures.go @@ -3,6 +3,7 @@ package fixtures import ( "github.com/gopinath-langote/1build/testing/utils" "github.com/stretchr/testify/assert" + "os" "testing" ) @@ -10,6 +11,8 @@ func featureListTestData() []Test { var feature = "list" return []Test{ shouldShowListOfCommands(feature), + shouldShowListOfCommandsFromSpecifiedConfigFile(feature), + shouldShowListOfCommandsFromSpecifiedConfigFileWithFullFlagName(feature), shouldNotShowAnyCommandsIfNoCommandsFound(feature), shouldShowCommandsWithBeforeAndAfterIfPresent(feature), } @@ -32,7 +35,7 @@ commands: return Test{ Feature: feature, Name: "shouldShowListOfCommands", - CmdArgs: []string{"list"}, + CmdArgs: Args("list"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -42,6 +45,64 @@ commands: } } +func shouldShowListOfCommandsFromSpecifiedConfigFile(feature string) Test { + commandListMessage := utils.PlainBanner() + ` +project: Sample Project +commands: +build | npm run build +` + utils.PlainBanner() + defaultFileContent := ` +project: Sample Project +commands: + - build: npm run build +` + return Test{ + Feature: feature, + Name: "shouldShowListOfCommandsFromSpecifiedConfigFile", + CmdArgs: func(dir string) []string { + strings := []string{"list", "-f", dir + "/custom-directory/some-config.yaml"} + return strings + }, + Setup: func(dir string) error { + _ = os.MkdirAll(dir+"/custom-directory", 0750) + err := utils.CreateConfigFileWithName(dir+"/custom-directory", "some-config.yaml", defaultFileContent) + return err + }, + Assertion: func(dir string, actualOutput string, t *testing.T) bool { + return assert.Contains(t, actualOutput, commandListMessage) + }, + } +} + +func shouldShowListOfCommandsFromSpecifiedConfigFileWithFullFlagName(feature string) Test { + commandListMessage := utils.PlainBanner() + ` +project: Sample Project +commands: +build | npm run build +` + utils.PlainBanner() + defaultFileContent := ` +project: Sample Project +commands: + - build: npm run build +` + return Test{ + Feature: feature, + Name: "shouldShowListOfCommandsFromSpecifiedConfigFileWithFullFlagName", + CmdArgs: func(dir string) []string { + strings := []string{"list", "--file", dir + "/custom-directory/some-config.yaml"} + return strings + }, + Setup: func(dir string) error { + _ = os.MkdirAll(dir+"/custom-directory", 0750) + err := utils.CreateConfigFileWithName(dir+"/custom-directory", "some-config.yaml", defaultFileContent) + return err + }, + Assertion: func(dir string, actualOutput string, t *testing.T) bool { + return assert.Contains(t, actualOutput, commandListMessage) + }, + } +} + func shouldNotShowAnyCommandsIfNoCommandsFound(feature string) Test { emptyCommandListMessage := utils.PlainBanner() + ` project: Sample Project @@ -50,7 +111,6 @@ commands: return Test{ Feature: feature, Name: "shouldNotShowAnyCommandsIfNoCommandsFound", - CmdArgs: []string{}, Setup: func(dir string) error { return utils.CreateConfigFile(dir, "project: Sample Project\ncommands:\n") }, @@ -79,7 +139,7 @@ commands: return Test{ Feature: feature, Name: "shouldShowCommandsWithBeforeAndAfterIfPresent", - CmdArgs: []string{"list"}, + CmdArgs: Args("list"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, diff --git a/testing/fixtures/command_root_fixtures.go b/testing/fixtures/command_root_fixtures.go index a17efe54..29b64876 100644 --- a/testing/fixtures/command_root_fixtures.go +++ b/testing/fixtures/command_root_fixtures.go @@ -21,9 +21,8 @@ func shouldFailIfYamlFileIsNotPresent(feature string) Test { return Test{ Feature: feature, Name: "shouldFailIfYamlFileIsNotPresent", - CmdArgs: []string{}, Assertion: func(dir string, actualOutput string, t *testing.T) bool { - return assert.Contains(t, actualOutput, "no '"+def.ConfigFileName+"' file found in current directory") + return assert.Contains(t, actualOutput, "no '"+def.ConfigFileName+"' file found") }, } } @@ -43,7 +42,6 @@ commands: return Test{ Feature: feature, Name: "shouldFailIfYamlFileIsNotInCorrectYamlFormat", - CmdArgs: []string{}, Setup: func(dir string) error { return utils.CreateConfigFile(dir, "invalid yaml file") }, @@ -71,7 +69,6 @@ commands: return Test{ Feature: feature, Name: "shouldShowListOfCommandsIfNoCommandSpecified", - CmdArgs: []string{}, Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, diff --git a/testing/fixtures/command_set_fixtures.go b/testing/fixtures/command_set_fixtures.go index f2662aca..7750ae3a 100644 --- a/testing/fixtures/command_set_fixtures.go +++ b/testing/fixtures/command_set_fixtures.go @@ -5,6 +5,7 @@ import ( "github.com/gopinath-langote/1build/testing/utils" "github.com/stretchr/testify/assert" "io/ioutil" + "os" "testing" ) @@ -13,6 +14,7 @@ func featureSetTestsData() []Test { return []Test{ shouldSetNewCommand(feature), + shouldSetNewCommandInSpecifiedFile(feature), shouldUpdateExistingCommand(feature), shouldFailWhenConfigurationFileIsNotFound(feature), shouldFailWhenConfigurationFileIsInInvalidFormat(feature), @@ -38,7 +40,7 @@ commands: return Test{ Feature: feature, Name: "shouldSetNewCommand", - CmdArgs: []string{"set", "Test", "go Test"}, + CmdArgs: Args("set", "Test", "go Test"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -51,6 +53,39 @@ commands: } } +func shouldSetNewCommandInSpecifiedFile(feature string) Test { + + defaultFileContent := ` +project: Sample Project +commands: + - build: go build +` + + expectedOutput := `project: Sample Project +commands: + - build: go build + - Test: go Test +` + + return Test{ + Feature: feature, + Name: "shouldSetNewCommandInSpecifiedFile", + CmdArgs: func(dir string) []string { + return []string{"set", "Test", "go Test", "-f", dir + "/some-dir/some-config.yaml"} + }, + Setup: func(dir string) error { + _ = os.MkdirAll(dir+"/some-dir", 0750) + return utils.CreateConfigFileWithName(dir+"/some-dir", "some-config.yaml", defaultFileContent) + }, + Assertion: func(dir string, actualOutput string, t *testing.T) bool { + filePath := dir + "/some-dir/some-config.yaml" + assert.FileExists(t, filePath) + content, _ := ioutil.ReadFile(filePath) + return assert.Contains(t, string(content), expectedOutput) + }, + } +} + func shouldUpdateExistingCommand(feature string) Test { defaultFileContent := ` @@ -67,7 +102,7 @@ commands: return Test{ Feature: feature, Name: "shouldUpdateExistingCommand", - CmdArgs: []string{"set", "build", "go build -o"}, + CmdArgs: Args("set", "build", "go build -o"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -84,9 +119,9 @@ func shouldFailWhenConfigurationFileIsNotFound(feature string) Test { return Test{ Feature: feature, Name: "shouldFailWhenConfigurationFileIsNotFound", - CmdArgs: []string{"set", "build", "go build -o"}, + CmdArgs: Args("set", "build", "go build -o"), Assertion: func(dir string, actualOutput string, t *testing.T) bool { - return assert.Contains(t, actualOutput, "no '"+def.ConfigFileName+"' file found in current directory") + return assert.Contains(t, actualOutput, "no '"+def.ConfigFileName+"' file found") }, } } @@ -95,7 +130,7 @@ func shouldFailWhenConfigurationFileIsInInvalidFormat(feature string) Test { return Test{ Feature: feature, Name: "shouldFailWhenConfigurationFileIsInInvalidFormat", - CmdArgs: []string{"set", "build", "go build"}, + CmdArgs: Args("set", "build", "go build"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, "invalid config content") }, @@ -122,7 +157,7 @@ commands: return Test{ Feature: feature, Name: "shouldSetBeforeCommand", - CmdArgs: []string{"set", "after", "yo"}, + CmdArgs: Args("set", "after", "yo"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -152,7 +187,7 @@ commands: return Test{ Feature: feature, Name: "shouldSetBeforeCommand", - CmdArgs: []string{"set", "after", "yo"}, + CmdArgs: Args("set", "after", "yo"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, diff --git a/testing/fixtures/command_unset_fixtures.go b/testing/fixtures/command_unset_fixtures.go index 6d49ae25..c3a268ce 100644 --- a/testing/fixtures/command_unset_fixtures.go +++ b/testing/fixtures/command_unset_fixtures.go @@ -2,6 +2,7 @@ package fixtures import ( "io/ioutil" + "os" "testing" "github.com/gopinath-langote/1build/testing/def" @@ -14,6 +15,7 @@ func featureUnsetTestsData() []Test { return []Test{ shouldUnsetTheExistingCommand(feature), + shouldUnsetTheExistingCommandFromSpecifiedFile(feature), unsetShouldFailWhenConfigurationFileIsNotFound(feature), unsetShouldFailWhenConfigurationFileIsInInvalidFormat(feature), unsetShouldFailWhenCommandIsNotFound(feature), @@ -45,7 +47,7 @@ commands: [] return Test{ Feature: feature, Name: "shouldUnsetTheExistingCommand", - CmdArgs: []string{"unset", "build"}, + CmdArgs: Args("unset", "build"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -58,6 +60,37 @@ commands: [] } } +func shouldUnsetTheExistingCommandFromSpecifiedFile(feature string) Test { + + defaultFileContent := ` +project: Sample Project +commands: + - build: go build +` + + expectedOutput := `project: Sample Project +commands: [] +` + + return Test{ + Feature: feature, + Name: "shouldUnsetTheExistingCommandFromSpecifiedFile", + CmdArgs: func(dir string) []string { + return []string{"unset", "build", "-f", dir + "/some-dir/some-config.yaml"} + }, + Setup: func(dir string) error { + _ = os.MkdirAll(dir+"/some-dir", 0750) + return utils.CreateConfigFileWithName(dir+"/some-dir", "some-config.yaml", defaultFileContent) + }, + Assertion: func(dir string, actualOutput string, t *testing.T) bool { + filePath := dir + "/some-dir/some-config.yaml" + assert.FileExists(t, filePath) + content, _ := ioutil.ReadFile(filePath) + return assert.Exactly(t, expectedOutput, string(content)) + }, + } +} + func unsetShouldFailWhenCommandIsNotFound(feature string) Test { defaultFileContent := ` @@ -69,7 +102,7 @@ commands: return Test{ Feature: feature, Name: "unsetShouldFailWhenCommandIsNotFound", - CmdArgs: []string{"unset", "Test"}, + CmdArgs: Args("unset", "Test"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -83,9 +116,9 @@ func unsetShouldFailWhenConfigurationFileIsNotFound(feature string) Test { return Test{ Feature: feature, Name: "unsetShouldFailWhenConfigurationFileIsNotFound", - CmdArgs: []string{"unset", "build"}, + CmdArgs: Args("unset", "build"), Assertion: func(dir string, actualOutput string, t *testing.T) bool { - return assert.Contains(t, actualOutput, "no '"+def.ConfigFileName+"' file found in current directory") + return assert.Contains(t, actualOutput, "no '"+def.ConfigFileName+"' file found") }, } } @@ -94,7 +127,7 @@ func unsetShouldFailWhenConfigurationFileIsInInvalidFormat(feature string) Test return Test{ Feature: feature, Name: "unsetShouldFailWhenConfigurationFileIsInInvalidFormat", - CmdArgs: []string{"unset", "build"}, + CmdArgs: Args("unset", "build"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, "invalid config content") }, @@ -122,7 +155,7 @@ commands: [] return Test{ Feature: feature, Name: "shouldUnsetMultipleCommands", - CmdArgs: []string{"unset", "build", "test", "before", "after"}, + CmdArgs: Args("unset", "build", "test", "before", "after"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -151,7 +184,7 @@ commands: [] return Test{ Feature: feature, Name: "shouldUnsetMultipleCommandsEvenWhenCommandIsNotFound1", - CmdArgs: []string{"unset", "build", "test", "missingCmd"}, + CmdArgs: Args("unset", "build", "test", "missingCmd"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -186,7 +219,7 @@ commands: return Test{ Feature: feature, Name: "shouldUnsetMultipleCommandsEvenWhenCommandIsNotFound2", - CmdArgs: []string{"unset", "build", "missingCmd", "test", "missingCmd2"}, + CmdArgs: Args("unset", "build", "missingCmd", "test", "missingCmd2"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -218,7 +251,7 @@ commands: [] return Test{ Feature: feature, Name: "shouldUnsetMultipleCommandsEvenWhenCommandIsNotFound3", - CmdArgs: []string{"unset", "before", "after", "missingCmd"}, + CmdArgs: Args("unset", "before", "after", "missingCmd"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -250,7 +283,7 @@ commands: [] return Test{ Feature: feature, Name: "shouldUnsetBeforeAndAfterCommand", - CmdArgs: []string{"unset", "before"}, + CmdArgs: Args("unset", "before"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -278,7 +311,7 @@ commands: [] return Test{ Feature: feature, Name: "shouldUnsetTheAfterCommand", - CmdArgs: []string{"unset", "after"}, + CmdArgs: Args("unset", "after"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -302,7 +335,7 @@ commands: return Test{ Feature: feature, Name: "unsetBeforeShouldFailWhenBeforeIsNotFound", - CmdArgs: []string{"unset", "before"}, + CmdArgs: Args("unset", "before"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -323,7 +356,7 @@ commands: return Test{ Feature: feature, Name: "unsetAfterShouldFailWhenAfterIsNotFound", - CmdArgs: []string{"unset", "after"}, + CmdArgs: Args("unset", "after"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -345,7 +378,7 @@ commands: return Test{ Feature: feature, Name: "unsetSingleCommandShouldFailWhenInvalidCommandNameIsEntered", - CmdArgs: []string{"unset", invalidName}, + CmdArgs: Args("unset", invalidName), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, @@ -367,7 +400,7 @@ commands: return Test{ Feature: feature, Name: "unsetSingleCommandShouldFailWhenInvalidCommandNameIsEntered", - CmdArgs: []string{"unset", "build", invalidName}, + CmdArgs: Args("unset", "build", invalidName), Setup: func(dir string) error { return utils.CreateConfigFile(dir, defaultFileContent) }, diff --git a/testing/fixtures/execute_cmd_fixtures.go b/testing/fixtures/execute_cmd_fixtures.go index d938a831..a541b2c1 100644 --- a/testing/fixtures/execute_cmd_fixtures.go +++ b/testing/fixtures/execute_cmd_fixtures.go @@ -1,6 +1,7 @@ package fixtures import ( + "os" "testing" "github.com/gopinath-langote/1build/testing/utils" @@ -11,6 +12,7 @@ func featureExecuteCmdTestData() []Test { return []Test{ shouldExecuteAvailableCommand(feature), + shouldExecuteAvailableCommandFromSpecifiedFile(feature), shouldShowErrorIfCommandNotFound(feature), shouldExecuteBeforeCommand(feature), shouldExecuteAfterCommand(feature), @@ -40,7 +42,7 @@ building project return Test{ Feature: feature, Name: "shouldExecuteAvailableCommand", - CmdArgs: []string{"build"}, + CmdArgs: Args("build"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, @@ -51,6 +53,40 @@ building project } } +func shouldExecuteAvailableCommandFromSpecifiedFile(feature string) Test { + fileContent := ` +project: Sample Project +commands: + - build: echo building project +` + expectedOutput := ` +----- --------------------- +Phase Command +----- --------------------- +build echo building project + + +-------------------------------[ ` + "build" + ` ]-------------------------------- +building project + +` + return Test{ + Feature: feature, + Name: "shouldExecuteAvailableCommandFromSpecifiedFile", + CmdArgs: func(dir string) []string { + return []string{"build", "-f", dir + "/some-dir/some-config.yaml"} + }, + Setup: func(dir string) error { + _ = os.MkdirAll(dir+"/some-dir/", 0750) + return utils.CreateConfigFileWithName(dir+"/some-dir", "some-config.yaml", fileContent) + }, + Assertion: func(dir string, actualOutput string, t *testing.T) bool { + return utils.AssertContains(t, actualOutput, expectedOutput) && + assertSuccessBanner(t, actualOutput) + }, + } +} + func shouldShowErrorIfCommandNotFound(feature string) Test { fileContent := ` project: Sample Project @@ -68,7 +104,7 @@ build | echo building project return Test{ Feature: feature, Name: "shouldShowErrorIfCommandNotFound", - CmdArgs: []string{"random"}, + CmdArgs: Args("random"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, @@ -102,7 +138,7 @@ building project return Test{ Feature: feature, Name: "shouldExecuteBeforeCommand", - CmdArgs: []string{"build"}, + CmdArgs: Args("build"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, @@ -137,7 +173,7 @@ running post-command return Test{ Feature: feature, Name: "shouldExecuteAfterCommand", - CmdArgs: []string{"build"}, + CmdArgs: Args("build"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, @@ -176,7 +212,7 @@ running post-command return Test{ Feature: feature, Name: "shouldExecuteBeforeAndAfterCommand", - CmdArgs: []string{"build"}, + CmdArgs: Args("build"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, @@ -209,7 +245,7 @@ after echo running post-command return Test{ Feature: feature, Name: "shouldStopExecutionIfBeforeCommandFailed", - CmdArgs: []string{"build"}, + CmdArgs: Args("build"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, @@ -246,7 +282,7 @@ running pre-command return Test{ Feature: feature, Name: "shouldStopExecutionIfCommandFailed", - CmdArgs: []string{"build"}, + CmdArgs: Args("build"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, diff --git a/testing/fixtures/fixures.go b/testing/fixtures/fixures.go index c0535f99..d3c7d1c4 100644 --- a/testing/fixtures/fixures.go +++ b/testing/fixtures/fixures.go @@ -2,6 +2,7 @@ package fixtures import "testing" +type cmdArgs func(dir string) []string type setup func(dir string) error type assertion func(dir string, actualOutput string, t *testing.T) bool type teardown func(dir string) error @@ -10,7 +11,7 @@ type teardown func(dir string) error type Test struct { Feature string Name string - CmdArgs []string + CmdArgs cmdArgs Setup setup Assertion assertion Teardown teardown @@ -39,3 +40,10 @@ func GetFixtures() []Test { } return r1 } + +// Args returns argument function +func Args(args ...string) func(dir string) []string { + return func(dir string) []string { + return args + } +} diff --git a/testing/fixtures/flag_fixtures.go b/testing/fixtures/flag_fixtures.go index 17b828d9..c5bb762f 100644 --- a/testing/fixtures/flag_fixtures.go +++ b/testing/fixtures/flag_fixtures.go @@ -37,7 +37,7 @@ build echo building project return Test{ Feature: feature, Name: "shouldExecuteCommandWithquietFlag", - CmdArgs: []string{"build", "--quiet"}, + CmdArgs: Args("build", "--quiet"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, @@ -70,7 +70,7 @@ build echo building project return Test{ Feature: feature, Name: "shouldExecuteBeforeCommandWithquietFlag", - CmdArgs: []string{"build", "--quiet"}, + CmdArgs: Args("build", "--quiet"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, @@ -103,7 +103,7 @@ after echo running post-command return Test{ Feature: feature, Name: "shouldExecuteAfterCommandWithquietFlag", - CmdArgs: []string{"build", "--quiet"}, + CmdArgs: Args("build", "--quiet"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, @@ -139,7 +139,7 @@ after echo running post-command return Test{ Feature: feature, Name: "shouldExecuteBeforeAndAfterCommandWithquietFlag", - CmdArgs: []string{"build", "--quiet"}, + CmdArgs: Args("build", "--quiet"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, @@ -174,7 +174,7 @@ after echo running post-command return Test{ Feature: feature, Name: "shouldStopExecutionIfBeforeCommandFailedWithquietFlag", - CmdArgs: []string{"build", "--quiet"}, + CmdArgs: Args("build", "--quiet"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, @@ -211,7 +211,7 @@ after echo running post-command return Test{ Feature: feature, Name: "shouldStopExecutionIfCommandFailedWithquietFlag", - CmdArgs: []string{"build", "--quiet"}, + CmdArgs: Args("build", "--quiet"), Setup: func(dir string) error { return utils.CreateConfigFile(dir, fileContent) }, diff --git a/testing/fixtures/flag_version_fixtures.go b/testing/fixtures/flag_version_fixtures.go index bce052fe..c4959904 100644 --- a/testing/fixtures/flag_version_fixtures.go +++ b/testing/fixtures/flag_version_fixtures.go @@ -16,7 +16,7 @@ func shouldPrintCurrentVersion(feature string) Test { return Test{ Feature: feature, Name: "shouldPrintCurrentVersion", - CmdArgs: []string{"--version"}, + CmdArgs: Args("--version"), Assertion: func(dir string, actualOutput string, t *testing.T) bool { return assert.Contains(t, actualOutput, "1build version 1.4.0") }, diff --git a/testing/utils/test_utils.go b/testing/utils/test_utils.go index 7e8a5b43..ef2eac48 100644 --- a/testing/utils/test_utils.go +++ b/testing/utils/test_utils.go @@ -17,7 +17,12 @@ var regex = regexp.MustCompile(ansi) // CreateConfigFile creates a config file func CreateConfigFile(dir string, content string) error { - return ioutil.WriteFile(dir+"/"+def.ConfigFileName, []byte(content), 0777) + return ioutil.WriteFile(dir+"/"+def.ConfigFileName, []byte(content), 0750) +} + +// CreateConfigFileWithName creates a config file with specified name +func CreateConfigFileWithName(dir string, fileName string, content string) error { + return ioutil.WriteFile(dir+"/"+fileName, []byte(content), 0750) } // CreateTempDir created temporary directory @@ -25,6 +30,11 @@ func CreateTempDir() (string, error) { return ioutil.TempDir("", "onebuild_test") } +// CreateCustomTestResourceSubDir created temporary directory +func CreateCustomTestResourceSubDir(testDir string, subDirectoryName string) error { + return os.MkdirAll(testDir+"/"+subDirectoryName, 0750) +} + // RemoveAllFilesFromDir Cleans up the directory func RemoveAllFilesFromDir(dir string) { _ = os.RemoveAll(dir) @@ -34,7 +44,7 @@ func RemoveAllFilesFromDir(dir string) { func RecreateTestResourceDirectory(dir string) string { restResourceDirectory := dir + "/resources" RemoveAllFilesFromDir(restResourceDirectory) - _ = os.Mkdir(restResourceDirectory, 0777) + _ = os.Mkdir(restResourceDirectory, 0750) return restResourceDirectory }