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}