bug_comment_test.go

  1package bugcmd
  2
  3import (
  4	"fmt"
  5	"os"
  6	"strings"
  7	"testing"
  8	"time"
  9
 10	"github.com/stretchr/testify/require"
 11
 12	"github.com/MichaelMure/git-bug/commands/bug/testenv"
 13	"github.com/MichaelMure/git-bug/commands/execenv"
 14)
 15
 16func TestBugComment(t *testing.T) {
 17	const golden = "testdata/comment/message-only"
 18
 19	env, bug := testenv.NewTestEnvAndBug(t)
 20
 21	require.NoError(t, runBugComment(env, []string{bug.Human()}))
 22
 23	requireCommentsEqual(t, golden, env)
 24}
 25
 26const gitDateFormat = "Mon Jan 2 15:04:05 2006 -0700"
 27
 28type parsedComment struct {
 29	author  string
 30	id      string
 31	date    time.Time
 32	message string
 33}
 34
 35type parseFunc func(*parsedComment, string)
 36
 37type commentParser struct {
 38	t        *testing.T
 39	fn       parseFunc
 40	comments []parsedComment
 41}
 42
 43func parseComments(t *testing.T, env *execenv.Env) []parsedComment {
 44	t.Helper()
 45
 46	parser := &commentParser{
 47		t:        t,
 48		comments: []parsedComment{},
 49	}
 50
 51	comment := &parsedComment{}
 52	parser.fn = parser.parseAuthor
 53
 54	for _, line := range strings.Split(env.Out.String(), "\n") {
 55		parser.fn(comment, line)
 56	}
 57
 58	parser.comments = append(parser.comments, *comment)
 59
 60	return parser.comments
 61}
 62
 63func (p *commentParser) parseAuthor(comment *parsedComment, line string) {
 64	p.t.Helper()
 65
 66	tkns := strings.Split(line, ": ")
 67	require.Len(p.t, tkns, 2)
 68	require.Equal(p.t, "Author", tkns[0])
 69
 70	comment.author = tkns[1]
 71	p.fn = p.parseID
 72}
 73
 74func (p *commentParser) parseID(comment *parsedComment, line string) {
 75	p.t.Helper()
 76
 77	tkns := strings.Split(line, ": ")
 78	require.Len(p.t, tkns, 2)
 79	require.Equal(p.t, "Id", tkns[0])
 80
 81	comment.id = tkns[1]
 82	p.fn = p.parseDate
 83}
 84
 85func (p *commentParser) parseDate(comment *parsedComment, line string) {
 86	p.t.Helper()
 87
 88	tkns := strings.Split(line, ": ")
 89	require.Len(p.t, tkns, 2)
 90	require.Equal(p.t, "Date", tkns[0])
 91
 92	date, err := time.Parse(gitDateFormat, tkns[1])
 93	require.NoError(p.t, err)
 94
 95	comment.date = date
 96	p.fn = p.parseMessage
 97}
 98
 99func (p *commentParser) parseMessage(comment *parsedComment, line string) {
100	p.t.Helper()
101
102	if strings.HasPrefix(line, "Author: ") {
103		p.comments = append(p.comments, *comment)
104		comment = &parsedComment{}
105		p.parseAuthor(comment, line)
106
107		return
108	}
109
110	require.True(p.t, line == "" || strings.HasPrefix(line, "    "))
111
112	comment.message = strings.Join([]string{comment.message, line}, "\n")
113}
114
115func normalizeParsedComments(t *testing.T, comments []parsedComment) []parsedComment {
116	t.Helper()
117
118	prefix := 0x1234567
119	date, err := time.Parse(gitDateFormat, "Fri Aug 19 07:00:00 2022 +1900")
120	require.NoError(t, err)
121
122	var out []parsedComment
123
124	for i, comment := range comments {
125		comment.id = fmt.Sprintf("%7x", prefix+i)
126		comment.date = date.Add(time.Duration(i) * time.Minute)
127		out = append(out, comment)
128	}
129
130	return out
131}
132
133func requireCommentsEqual(t *testing.T, golden string, env *execenv.Env) {
134	t.Helper()
135
136	const goldenFilePattern = "%s-%d-golden.txt"
137
138	comments := parseComments(t, env)
139	comments = normalizeParsedComments(t, comments)
140
141	if *cmdtest.Update {
142		t.Log("Got here")
143		for i, comment := range comments {
144			fileName := fmt.Sprintf(goldenFilePattern, golden, i)
145			require.NoError(t, os.WriteFile(fileName, []byte(comment.message), 0644))
146		}
147	}
148
149	prefix := 0x1234567
150	date, err := time.Parse(gitDateFormat, "Fri Aug 19 07:00:00 2022 +1900")
151	require.NoError(t, err)
152
153	for i, comment := range comments {
154		require.Equal(t, "John Doe", comment.author)
155		require.Equal(t, fmt.Sprintf("%7x", prefix+i), comment.id)
156		require.Equal(t, date.Add(time.Duration(i)*time.Minute), comment.date)
157
158		fileName := fmt.Sprintf(goldenFilePattern, golden, i)
159		exp, err := os.ReadFile(fileName)
160		require.NoError(t, err)
161		require.Equal(t, strings.ReplaceAll(string(exp), "\r", ""), strings.ReplaceAll(comment.message, "\r", ""))
162	}
163}