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