refactor(778): test only command implementations

Steve Moyer created

Change summary

commands/add_test.go                  | 19 ++++----
commands/env.go                       | 31 +------------
commands/env_test.go                  | 61 ----------------------------
commands/env_testing.go               | 62 +++++++++++++++++++++++++++++
commands/rm_test.go                   | 18 ++++---
commands/root_test.go                 | 35 ----------------
commands/testdata/root_out_golden.txt | 38 -----------------
commands/user_create_test.go          | 21 ++++-----
8 files changed, 94 insertions(+), 191 deletions(-)

Detailed changes

commands/add_test.go 🔗

@@ -1,4 +1,4 @@
-package commands_test
+package commands
 
 import (
 	"strings"
@@ -11,15 +11,14 @@ func newTestEnvUserAndBug(t *testing.T) (*testEnv, string, string) {
 	t.Helper()
 
 	testEnv, userID := newTestEnvAndUser(t)
-
-	testEnv.cmd.SetArgs([]string{
-		"add",
-		"--non-interactive",
-		"-t 'this is a bug title'",
-		"-m 'this is a bug message'",
-	})
-
-	testEnv.Execute(t)
+	opts := addOptions{
+		title:          "this is a bug title",
+		message:        "this is a bug message",
+		messageFile:    "",
+		nonInteractive: true,
+	}
+
+	require.NoError(t, runAdd(testEnv.env, opts))
 	require.Regexp(t, "^[0-9A-Fa-f]{7} created\n$", testEnv.out)
 	bugID := strings.Split(testEnv.out.String(), " ")[0]
 	testEnv.out.Reset()

commands/env.go 🔗

@@ -14,7 +14,7 @@ import (
 	"github.com/MichaelMure/git-bug/util/interrupt"
 )
 
-const GitBugNamespace = "git-bug"
+const gitBugNamespace = "git-bug"
 
 // Env is the environment of a command
 type Env struct {
@@ -48,35 +48,15 @@ func (o out) Println(a ...interface{}) {
 	_, _ = fmt.Fprintln(o, a...)
 }
 
-// getCWD returns the current working directory.  Normal operation simply
-// returns the working directory reported by the OS (as an OS-compatible
-// filepath.)  During tests, temporary repositories are created outside
-// the test execution's CWD.  In this case, it's possible to provide an
-// alternate CWD filepath by adding a value to the command's context
-// with the key "cwd".
-func getCWD(cmd *cobra.Command) (string, error) {
-	cwd, ok := cmd.Context().Value("cwd").(string)
-	if cwd != "" && ok {
-		return cwd, nil
-	}
-
-	cwd, err := os.Getwd()
-	if err != nil {
-		return "", fmt.Errorf("unable to get the current working directory: %q", err)
-	}
-
-	return cwd, nil
-}
-
 // loadRepo is a pre-run function that load the repository for use in a command
 func loadRepo(env *Env) func(*cobra.Command, []string) error {
 	return func(cmd *cobra.Command, args []string) error {
-		cwd, err := getCWD(cmd)
+		cwd, err := os.Getwd()
 		if err != nil {
-			return err
+			return fmt.Errorf("unable to get the current working directory: %q", err)
 		}
 
-		env.repo, err = repository.OpenGoGitRepo(cwd, GitBugNamespace, []repository.ClockLoader{bug.ClockLoader})
+		env.repo, err = repository.OpenGoGitRepo(cwd, gitBugNamespace, []repository.ClockLoader{bug.ClockLoader})
 		if err == repository.ErrNotARepo {
 			return fmt.Errorf("%s must be run from within a git repo", rootCommandName)
 		}
@@ -163,9 +143,6 @@ func loadBackendEnsureUser(env *Env) func(*cobra.Command, []string) error {
 // This wrapper style is necessary because a Cobra PostE function does not run if RunE return an error.
 func closeBackend(env *Env, runE func(cmd *cobra.Command, args []string) error) func(*cobra.Command, []string) error {
 	return func(cmd *cobra.Command, args []string) error {
-		env.err = out{Writer: cmd.ErrOrStderr()}
-		env.out = out{Writer: cmd.OutOrStdout()}
-
 		errRun := runE(cmd, args)
 
 		if env.backend == nil {

commands/env_test.go 🔗

@@ -1,61 +0,0 @@
-package commands_test
-
-import (
-	"bytes"
-	"context"
-	"flag"
-	"io/ioutil"
-	"os"
-	"testing"
-
-	"github.com/spf13/cobra"
-	"github.com/stretchr/testify/require"
-
-	"github.com/MichaelMure/git-bug/commands"
-	"github.com/MichaelMure/git-bug/repository"
-)
-
-var update = flag.Bool("update", false, "pass -update to the test runner to update golden files")
-
-type testEnv struct {
-	cwd  string
-	repo *repository.GoGitRepo
-	cmd  *cobra.Command
-	out  *bytes.Buffer
-}
-
-func newTestEnv(t *testing.T) *testEnv {
-	t.Helper()
-
-	cwd, err := ioutil.TempDir("", "")
-	require.NoError(t, err)
-	t.Cleanup(func() {
-		require.NoError(t, os.RemoveAll(cwd))
-	})
-
-	repo, err := repository.InitGoGitRepo(cwd, commands.GitBugNamespace)
-	require.NoError(t, err)
-	t.Cleanup(func() {
-		require.NoError(t, repo.Close())
-	})
-
-	out := new(bytes.Buffer)
-	cmd := commands.NewRootCommand()
-	cmd.SetArgs([]string{})
-	cmd.SetErr(out)
-	cmd.SetOut(out)
-
-	return &testEnv{
-		cwd:  cwd,
-		repo: repo,
-		cmd:  cmd,
-		out:  out,
-	}
-}
-
-func (e *testEnv) Execute(t *testing.T) {
-	t.Helper()
-
-	ctx := context.WithValue(context.Background(), "cwd", e.cwd)
-	require.NoError(t, e.cmd.ExecuteContext(ctx))
-}

commands/env_testing.go 🔗

@@ -0,0 +1,62 @@
+package commands
+
+import (
+	"bytes"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+
+	"github.com/MichaelMure/git-bug/cache"
+	"github.com/MichaelMure/git-bug/repository"
+	"github.com/MichaelMure/git-bug/util/interrupt"
+)
+
+type testEnv struct {
+	env *Env
+	cwd string
+	out *bytes.Buffer
+}
+
+func newTestEnv(t *testing.T) *testEnv {
+	t.Helper()
+
+	cwd := t.TempDir()
+
+	repo, err := repository.InitGoGitRepo(cwd, gitBugNamespace)
+	require.NoError(t, err)
+	t.Cleanup(func() {
+		require.NoError(t, repo.Close())
+	})
+
+	buf := new(bytes.Buffer)
+
+	backend, err := cache.NewRepoCache(repo)
+	require.NoError(t, err)
+
+	testEnv := &testEnv{
+		env: &Env{
+			repo:    repo,
+			backend: backend,
+			out:     out{Writer: buf},
+			err:     out{Writer: buf},
+		},
+		cwd: cwd,
+		out: buf,
+	}
+
+	cleaner := func(env *Env) interrupt.CleanerFunc {
+		return func() error {
+			if env.backend != nil {
+				err := env.backend.Close()
+				env.backend = nil
+				return err
+			}
+			return nil
+		}
+	}
+
+	// Cleanup properly on interrupt
+	interrupt.RegisterCleaner(cleaner(testEnv.env))
+
+	return testEnv
+}

commands/rm_test.go 🔗

@@ -1,15 +1,17 @@
-package commands_test
+package commands
 
-import "testing"
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
 
 func TestRm(t *testing.T) {
 	testEnv, _, bugID := newTestEnvUserAndBug(t)
 
-	testEnv.cmd.SetArgs([]string{
-		"rm",
-		bugID,
-	})
+	exp := "bug " + bugID + " removed\n"
 
-	testEnv.Execute(t)
-	// TODO: add assertions after #778 is diagnosed and fixed
+	require.NoError(t, runRm(testEnv.env, []string{bugID}))
+	require.Equal(t, exp, testEnv.out.String())
+	testEnv.out.Reset()
 }

commands/root_test.go 🔗

@@ -1,35 +0,0 @@
-//go:build !windows
-// +build !windows
-
-package commands_test
-
-import (
-	"io/ioutil"
-	"path/filepath"
-	"testing"
-
-	"github.com/stretchr/testify/require"
-)
-
-func requireGoldenFileEqual(t *testing.T, path string, act []byte) {
-	t.Helper()
-
-	path = filepath.Join("testdata", path)
-
-	if *update {
-		require.NoError(t, ioutil.WriteFile(path, act, 0644))
-	}
-
-	exp, err := ioutil.ReadFile(path)
-	require.NoError(t, err)
-	require.Equal(t, string(exp), string(act))
-}
-
-func TestNewRootCommand(t *testing.T) {
-	t.Skip()
-
-	testEnv := newTestEnv(t)
-	testEnv.Execute(t)
-
-	requireGoldenFileEqual(t, "root_out_golden.txt", testEnv.out.Bytes())
-}

commands/testdata/root_out_golden.txt 🔗

@@ -1,38 +0,0 @@
-git-bug is a bug tracker embedded in git.
-
-git-bug use git objects to store the bug tracking separated from the files
-history. As bugs are regular git objects, they can be pushed and pulled from/to
-the same git remote you are already using to collaborate with other people.
-
-Usage:
-  git-bug [flags]
-  git-bug [command]
-
-Available Commands:
-  add         Create a new bug.
-  bridge      Configure and use bridges to other bug trackers.
-  commands    Display available commands.
-  comment     Display or add comments to a bug.
-  completion  Generate the autocompletion script for the specified shell
-  deselect    Clear the implicitly selected bug.
-  help        Help about any command
-  label       Display, add or remove labels to/from a bug.
-  ls          List bugs.
-  ls-id       List bug identifiers.
-  ls-label    List valid labels.
-  pull        Pull bugs update from a git remote.
-  push        Push bugs update to a git remote.
-  rm          Remove an existing bug.
-  select      Select a bug for implicit use in future commands.
-  show        Display the details of a bug.
-  status      Display or change a bug status.
-  termui      Launch the terminal UI.
-  title       Display or change a title of a bug.
-  user        Display or change the user identity.
-  version     Show git-bug version information.
-  webui       Launch the web UI.
-
-Flags:
-  -h, --help   help for git-bug
-
-Use "git-bug [command] --help" for more information about a command.

commands/user_create_test.go 🔗

@@ -1,4 +1,4 @@
-package commands_test
+package commands
 
 import (
 	"path/filepath"
@@ -13,16 +13,15 @@ func newTestEnvAndUser(t *testing.T) (*testEnv, string) {
 
 	testEnv := newTestEnv(t)
 
-	testEnv.cmd.SetArgs(
-		[]string{
-			"user",
-			"create",
-			"--non-interactive",
-			"-n John Doe",
-			"-e jdoe@example.com",
-		})
+	opts := createUserOptions{
+		name:           "John Doe",
+		email:          "jdoe@example.com",
+		avatarURL:      "",
+		nonInteractive: true,
+	}
+
+	require.NoError(t, runUserCreate(testEnv.env, opts))
 
-	testEnv.Execute(t)
 	userID := strings.TrimSpace(testEnv.out.String())
 	testEnv.out.Reset()
 
@@ -32,8 +31,6 @@ func newTestEnvAndUser(t *testing.T) (*testEnv, string) {
 func TestUserCreateCommand(t *testing.T) {
 	testEnv, userID := newTestEnvAndUser(t)
 
-	t.Log("CWD:", testEnv.cwd)
-
 	require.FileExists(t, filepath.Join(testEnv.cwd, ".git", "refs", "identities", userID))
 	require.FileExists(t, filepath.Join(testEnv.cwd, ".git", "git-bug", "identity-cache"))
 }