Merge pull request #855 from MichaelMure/fix-850-ineffective-comment-edit

Steve Moyer created

test(850): add tests for `git-bug comment edit` has no effect

Change summary

README.md                                           |   7 
commands/comment_add_test.go                        |  33 +++
commands/comment_edit_test.go                       |  21 +
commands/comment_test.go                            | 160 +++++++++++++++
commands/golden_test.go                             |   5 
commands/ls_test.go                                 |   1 
commands/testdata/comment/add-0-golden.txt          |   3 
commands/testdata/comment/add-1-golden.txt          |   6 
commands/testdata/comment/edit-0-golden.txt         |   3 
commands/testdata/comment/edit-1-golden.txt         |   6 
commands/testdata/comment/message-only-0-golden.txt |   3 
11 files changed, 247 insertions(+), 1 deletion(-)

Detailed changes

README.md 🔗

@@ -298,6 +298,13 @@ You can now run `make` to build the project, or `make install` to install the bi
 
 To work on the web UI, have a look at [the dedicated Readme.](webui/Readme.md)
 
+Some tests for the CLI use golden files, if the output of CLI commands is
+changed, run the following command, then inspect the changed files in
+`commands/testdata/...` to make sure the output text is as expected:
+
+```shell
+go test ./commands -update
+```
 
 ## Contributors :heart:
 

commands/comment_add_test.go 🔗

@@ -0,0 +1,33 @@
+package commands
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func newTestEnvAndBugWithComment(t *testing.T) (*testEnv, string, string) {
+	t.Helper()
+
+	env, bugID := newTestEnvAndBug(t)
+
+	opts := commentAddOptions{
+		message: "this is a bug comment",
+	}
+	require.NoError(t, runCommentAdd(env.env, opts, []string{bugID}))
+	require.NoError(t, runComment(env.env, []string{bugID}))
+	comments := parseComments(t, env)
+	require.Len(t, comments, 2)
+
+	env.out.Reset()
+
+	return env, bugID, comments[1].id
+}
+
+func TestCommentAdd(t *testing.T) {
+	const golden = "testdata/comment/add"
+
+	env, bugID, _ := newTestEnvAndBugWithComment(t)
+	require.NoError(t, runComment(env.env, []string{bugID}))
+	requireCommentsEqual(t, golden, env)
+}

commands/comment_edit_test.go 🔗

@@ -0,0 +1,21 @@
+package commands
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestCommentEdit(t *testing.T) {
+	const golden = "testdata/comment/edit"
+
+	env, bugID, commentID := newTestEnvAndBugWithComment(t)
+
+	opts := commentEditOptions{
+		message: "this is an altered bug comment",
+	}
+	require.NoError(t, runCommentEdit(env.env, opts, []string{commentID}))
+
+	require.NoError(t, runComment(env.env, []string{bugID}))
+	requireCommentsEqual(t, golden, env)
+}

commands/comment_test.go 🔗

@@ -0,0 +1,160 @@
+package commands
+
+import (
+	"fmt"
+	"io/ioutil"
+	"strings"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestComment(t *testing.T) {
+	const golden = "testdata/comment/message-only"
+
+	env, bug := newTestEnvAndBug(t)
+
+	require.NoError(t, runComment(env.env, []string{bug}))
+
+	requireCommentsEqual(t, golden, env)
+}
+
+const gitDateFormat = "Mon Jan 2 15:04:05 2006 -0700"
+
+type parsedComment struct {
+	author  string
+	id      string
+	date    time.Time
+	message string
+}
+
+type parseFunc func(*parsedComment, string)
+
+type commentParser struct {
+	t        *testing.T
+	fn       parseFunc
+	comments []parsedComment
+}
+
+func parseComments(t *testing.T, env *testEnv) []parsedComment {
+	t.Helper()
+
+	parser := &commentParser{
+		t:        t,
+		comments: []parsedComment{},
+	}
+
+	comment := &parsedComment{}
+	parser.fn = parser.parseAuthor
+
+	for _, line := range strings.Split(env.out.String(), "\n") {
+		parser.fn(comment, line)
+	}
+
+	parser.comments = append(parser.comments, *comment)
+
+	return parser.comments
+}
+
+func (p *commentParser) parseAuthor(comment *parsedComment, line string) {
+	p.t.Helper()
+
+	tkns := strings.Split(line, ": ")
+	require.Len(p.t, tkns, 2)
+	require.Equal(p.t, "Author", tkns[0])
+
+	comment.author = tkns[1]
+	p.fn = p.parseID
+}
+
+func (p *commentParser) parseID(comment *parsedComment, line string) {
+	p.t.Helper()
+
+	tkns := strings.Split(line, ": ")
+	require.Len(p.t, tkns, 2)
+	require.Equal(p.t, "Id", tkns[0])
+
+	comment.id = tkns[1]
+	p.fn = p.parseDate
+}
+
+func (p *commentParser) parseDate(comment *parsedComment, line string) {
+	p.t.Helper()
+
+	tkns := strings.Split(line, ": ")
+	require.Len(p.t, tkns, 2)
+	require.Equal(p.t, "Date", tkns[0])
+
+	date, err := time.Parse(gitDateFormat, tkns[1])
+	require.NoError(p.t, err)
+
+	comment.date = date
+	p.fn = p.parseMessage
+}
+
+func (p *commentParser) parseMessage(comment *parsedComment, line string) {
+	p.t.Helper()
+
+	if strings.HasPrefix(line, "Author: ") {
+		p.comments = append(p.comments, *comment)
+		comment = &parsedComment{}
+		p.parseAuthor(comment, line)
+
+		return
+	}
+
+	require.True(p.t, line == "" || strings.HasPrefix(line, "    "))
+
+	comment.message = strings.Join([]string{comment.message, line}, "\n")
+}
+
+func normalizeParsedComments(t *testing.T, comments []parsedComment) []parsedComment {
+	t.Helper()
+
+	prefix := 0x1234567
+	date, err := time.Parse(gitDateFormat, "Fri Aug 19 07:00:00 2022 +1900")
+	require.NoError(t, err)
+
+	out := []parsedComment{}
+
+	for i, comment := range comments {
+		comment.id = fmt.Sprintf("%7x", prefix+i)
+		comment.date = date.Add(time.Duration(i) * time.Minute)
+		out = append(out, comment)
+	}
+
+	return out
+}
+
+func requireCommentsEqual(t *testing.T, golden string, env *testEnv) {
+	t.Helper()
+
+	const goldenFilePatter = "%s-%d-golden.txt"
+
+	comments := parseComments(t, env)
+	comments = normalizeParsedComments(t, comments)
+
+	if *update {
+		t.Log("Got here")
+		for i, comment := range comments {
+			fileName := fmt.Sprintf(goldenFilePatter, golden, i)
+			require.NoError(t, ioutil.WriteFile(fileName, []byte(comment.message), 0644))
+		}
+	}
+
+	prefix := 0x1234567
+	date, err := time.Parse(gitDateFormat, "Fri Aug 19 07:00:00 2022 +1900")
+	require.NoError(t, err)
+
+	for i, comment := range comments {
+		require.Equal(t, "John Doe", comment.author)
+		require.Equal(t, fmt.Sprintf("%7x", prefix+i), comment.id)
+		require.Equal(t, date.Add(time.Duration(i)*time.Minute), comment.date)
+
+		fileName := fmt.Sprintf(goldenFilePatter, golden, i)
+		exp, err := ioutil.ReadFile(fileName)
+		require.NoError(t, err)
+		require.Equal(t, strings.ReplaceAll(string(exp), "\r", ""), strings.ReplaceAll(comment.message, "\r", ""))
+	}
+}

commands/golden_test.go 🔗

@@ -0,0 +1,5 @@
+package commands
+
+import "flag"
+
+var update = flag.Bool("update", false, "update golden files")

commands/ls_test.go 🔗

@@ -77,7 +77,6 @@ $`
 			env, _ := newTestEnvAndBug(t)
 
 			require.NoError(t, runLs(env.env, opts, []string{}))
-			t.Log(env.out.String())
 			require.Regexp(t, testcase.exp, env.out.String())
 		})
 	}