From 46de48226288a0b442af23d2041d7893aaacd26a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orlando=20Tom=C3=A1s?= Date: Mon, 6 Jan 2025 10:59:32 +0100 Subject: [PATCH] add unit test for create command --- cmd/create_command.go | 15 +++---- cmd/create_command_test.go | 84 ++++++++++++++++++++++++++++++++++++++ cmd/main.go | 5 ++- 3 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 cmd/create_command_test.go diff --git a/cmd/create_command.go b/cmd/create_command.go index 95c8806..3f29205 100644 --- a/cmd/create_command.go +++ b/cmd/create_command.go @@ -4,6 +4,7 @@ import ( "encoding/json" "flag" "fmt" + "io" "os" "strings" "time" @@ -22,7 +23,7 @@ const ( JSON ) -func RunCreateShiftPlan(arguments []string) error { +func RunCreateShiftPlan(writer io.Writer, arguments []string) error { enums := map[string]Format{"CVS": CVS, "Table": Table, "json": JSON} exporters := map[Format]func() apis.Exporter{ Table: func() apis.Exporter { @@ -55,12 +56,12 @@ func RunCreateShiftPlan(arguments []string) error { createCommand.StringVar(primaryRules, "primary-rules", "vacation", "Rule to decide which employee should be on-call for the next shift") createCommand.StringVar(secondaryRules, "secondary-rules", "vacation", "Rule to decide which employee should be on-call for the next shift") createCommand.Usage = func() { - fmt.Fprintf(os.Stdout, "Create on-call schedule\n") - fmt.Fprintf(os.Stdout, "\nUsage\n") - fmt.Fprintf(os.Stdout, " %s create [flags]\n", os.Args[0]) - fmt.Fprintf(os.Stdout, "\nFlags:\n") + fmt.Fprintf(writer, "Create on-call schedule\n") + fmt.Fprintf(writer, "\nUsage\n") + fmt.Fprintf(writer, " %s create [flags]\n", os.Args[0]) + fmt.Fprintf(writer, "\nFlags:\n") flag.PrintDefaults() - fmt.Fprintf(os.Stdout, "\nUse \"%s create -h\" for more information about a command\n", os.Args[0]) + fmt.Fprintf(writer, "\nUse \"%s create -h\" for more information about a command\n", os.Args[0]) } if err := createCommand.Parse(arguments); err != nil { @@ -101,7 +102,7 @@ func RunCreateShiftPlan(arguments []string) error { return fmt.Errorf("can not create on-call schedule: %w", err) } - if err := exporters[outputFormat]().Write(plan, os.Stdout); err != nil { + if err := exporters[outputFormat]().Write(plan, writer); err != nil { return fmt.Errorf("unexpecting error: %w", err) } diff --git a/cmd/create_command_test.go b/cmd/create_command_test.go new file mode 100644 index 0000000..bf6c54a --- /dev/null +++ b/cmd/create_command_test.go @@ -0,0 +1,84 @@ +package main + +import ( + "bytes" + "os" + "path/filepath" + "strings" + "testing" +) + +func TestRunCreateShiftPlan(t *testing.T) { + dir := t.TempDir() + tempFilePath := filepath.Join(dir, "team.json") + content := `{"employees": [{"id": "joe@example.com", "name": "Joe"}, {"id": "jan@example.com", "name": "Jan"}]}` + if err := os.WriteFile(tempFilePath, []byte(content), 0o600); err != nil { + t.FailNow() + } + + type args struct { + arguments []string + } + tests := []struct { + name string + args args + wantWriter string + wantErrMsg string + }{ + { + name: "Print Usage when required flags are missing", + wantWriter: "Usage", + wantErrMsg: "missing required flag: start,end,team-file", + }, + { + name: "Print Usage when use help flag", + args: args{ + arguments: []string{ + "-h", + }, + }, + wantWriter: "Usage", + wantErrMsg: "", + }, + { + name: "Print an on-call schedule in JSON format", + args: args{ + arguments: []string{ + "--start", "2024-01-01 00:00:00", + "--end", "2024-01-08 00:00:00", + "--team-file", tempFilePath, + "--output", "json", + }, + }, + wantWriter: `[{"start":"2024-01-01T00:00:00Z","end":"2024-01-08T00:00:00Z","primary":"joe@example.com","secondary":"jan@example.com"}]`, + wantErrMsg: "", + }, + { + name: "Print an error if shift plan cannot be created if rules are too restricted", + args: args{ + arguments: []string{ + "--start", "2024-01-01 00:00:00", + "--end", "2024-01-15 00:00:00", + "--team-file", tempFilePath, + "--primary-rules", "minimumfourshiftgap", + "--output", "json", + }, + }, + wantWriter: "", + wantErrMsg: "can not create on-call schedule: could not find available duty between 2024-01-08 00:00:00 +0000 UTC and 2024-01-15 00:00:00 +0000 UTC", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + writer := &bytes.Buffer{} + err := RunCreateShiftPlan(writer, tt.args.arguments) + if (err != nil) && tt.wantErrMsg != err.Error() { + t.Errorf("RunCreateShiftPlan() error = %v, wantErr %v", err, tt.wantErrMsg) + return + } + if gotWriter := writer.String(); !strings.Contains(gotWriter, tt.wantWriter) { + t.Errorf("RunCreateShiftPlan() gotWriter = %v, want %v", gotWriter, tt.wantWriter) + } + }) + } +} diff --git a/cmd/main.go b/cmd/main.go index c4488e0..c772304 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -4,6 +4,7 @@ import ( "errors" "flag" "fmt" + "io" "os" "slices" ) @@ -13,7 +14,7 @@ var ErrCommandNotFound = errors.New("command not found") type command struct { name string description string - run func([]string) error + run func(io.Writer, []string) error } func main() { @@ -67,7 +68,7 @@ func runCommand(cmd string, commands []command) error { return fmt.Errorf("%w: %s", ErrCommandNotFound, cmd) } - if err := commands[cmdIdx].run(os.Args[2:]); err != nil { + if err := commands[cmdIdx].run(os.Stdout, os.Args[2:]); err != nil { return fmt.Errorf("\n\n%w", err) }