1package github
2
3import (
4 "context"
5 "fmt"
6 "os"
7 "testing"
8 "time"
9
10 "github.com/stretchr/testify/require"
11
12 "github.com/MichaelMure/git-bug/bridge/core"
13 "github.com/MichaelMure/git-bug/bridge/core/auth"
14 "github.com/MichaelMure/git-bug/bug"
15 "github.com/MichaelMure/git-bug/cache"
16 "github.com/MichaelMure/git-bug/identity"
17 "github.com/MichaelMure/git-bug/repository"
18 "github.com/MichaelMure/git-bug/util/interrupt"
19)
20
21func TestGithubImporter(t *testing.T) {
22 envToken := os.Getenv("GITHUB_TOKEN_PRIVATE")
23 if envToken == "" {
24 t.Skip("Env var GITHUB_TOKEN_PRIVATE missing")
25 }
26
27 repo := repository.CreateGoGitTestRepo(t, false)
28
29 backend, err := cache.NewRepoCache(repo)
30 require.NoError(t, err)
31
32 defer backend.Close()
33 interrupt.RegisterCleaner(backend.Close)
34
35 author, err := identity.NewIdentity(repo, "Michael Muré", "batolettre@gmail.com")
36 require.NoError(t, err)
37
38 tests := []struct {
39 name string
40 url string
41 bug *bug.Snapshot
42 }{
43 {
44 name: "simple issue",
45 url: "https://github.com/MichaelMure/git-bug-test-github-bridge/issues/1",
46 bug: &bug.Snapshot{
47 Operations: []bug.Operation{
48 bug.NewCreateOp(author, 0, "simple issue", "initial comment", nil),
49 bug.NewAddCommentOp(author, 0, "first comment", nil),
50 bug.NewAddCommentOp(author, 0, "second comment", nil),
51 },
52 },
53 },
54 {
55 name: "empty issue",
56 url: "https://github.com/MichaelMure/git-bug-test-github-bridge/issues/2",
57 bug: &bug.Snapshot{
58 Operations: []bug.Operation{
59 bug.NewCreateOp(author, 0, "empty issue", "", nil),
60 },
61 },
62 },
63 {
64 name: "complex issue",
65 url: "https://github.com/MichaelMure/git-bug-test-github-bridge/issues/3",
66 bug: &bug.Snapshot{
67 Operations: []bug.Operation{
68 bug.NewCreateOp(author, 0, "complex issue", "initial comment", nil),
69 bug.NewLabelChangeOperation(author, 0, []bug.Label{"bug"}, []bug.Label{}),
70 bug.NewLabelChangeOperation(author, 0, []bug.Label{"duplicate"}, []bug.Label{}),
71 bug.NewLabelChangeOperation(author, 0, []bug.Label{}, []bug.Label{"duplicate"}),
72 bug.NewAddCommentOp(author, 0, "### header\n\n**bold**\n\n_italic_\n\n> with quote\n\n`inline code`\n\n```\nmultiline code\n```\n\n- bulleted\n- list\n\n1. numbered\n1. list\n\n- [ ] task\n- [x] list\n\n@MichaelMure mention\n\n#2 reference issue\n#3 auto-reference issue\n\n", nil),
73 bug.NewSetTitleOp(author, 0, "complex issue edited", "complex issue"),
74 bug.NewSetTitleOp(author, 0, "complex issue", "complex issue edited"),
75 bug.NewSetStatusOp(author, 0, bug.ClosedStatus),
76 bug.NewSetStatusOp(author, 0, bug.OpenStatus),
77 },
78 },
79 },
80 {
81 name: "editions",
82 url: "https://github.com/MichaelMure/git-bug-test-github-bridge/issues/4",
83 bug: &bug.Snapshot{
84 Operations: []bug.Operation{
85 bug.NewCreateOp(author, 0, "editions", "initial comment edited", nil),
86 bug.NewEditCommentOp(author, 0, "", "erased then edited again", nil),
87 bug.NewAddCommentOp(author, 0, "first comment", nil),
88 bug.NewEditCommentOp(author, 0, "", "first comment edited", nil),
89 },
90 },
91 },
92 {
93 name: "comment deletion",
94 url: "https://github.com/MichaelMure/git-bug-test-github-bridge/issues/5",
95 bug: &bug.Snapshot{
96 Operations: []bug.Operation{
97 bug.NewCreateOp(author, 0, "comment deletion", "", nil),
98 },
99 },
100 },
101 {
102 name: "edition deletion",
103 url: "https://github.com/MichaelMure/git-bug-test-github-bridge/issues/6",
104 bug: &bug.Snapshot{
105 Operations: []bug.Operation{
106 bug.NewCreateOp(author, 0, "edition deletion", "initial comment", nil),
107 bug.NewEditCommentOp(author, 0, "", "initial comment edited again", nil),
108 bug.NewAddCommentOp(author, 0, "first comment", nil),
109 bug.NewEditCommentOp(author, 0, "", "first comment edited again", nil),
110 },
111 },
112 },
113 {
114 name: "hidden comment",
115 url: "https://github.com/MichaelMure/git-bug-test-github-bridge/issues/7",
116 bug: &bug.Snapshot{
117 Operations: []bug.Operation{
118 bug.NewCreateOp(author, 0, "hidden comment", "initial comment", nil),
119 bug.NewAddCommentOp(author, 0, "first comment", nil),
120 },
121 },
122 },
123 {
124 name: "transfered issue",
125 url: "https://github.com/MichaelMure/git-bug-test-github-bridge/issues/8",
126 bug: &bug.Snapshot{
127 Operations: []bug.Operation{
128 bug.NewCreateOp(author, 0, "transfered issue", "", nil),
129 },
130 },
131 },
132 {
133 name: "unicode control characters",
134 url: "https://github.com/MichaelMure/git-bug-test-github-bridge/issues/10",
135 bug: &bug.Snapshot{
136 Operations: []bug.Operation{
137 bug.NewCreateOp(author, 0, "unicode control characters", "u0000: \nu0001: \nu0002: \nu0003: \nu0004: \nu0005: \nu0006: \nu0007: \nu0008: \nu0009: \t\nu0010: \nu0011: \nu0012: \nu0013: \nu0014: \nu0015: \nu0016: \nu0017: \nu0018: \nu0019:", nil),
138 },
139 },
140 },
141 }
142
143 login := "test-identity"
144 author.SetMetadata(metaKeyGithubLogin, login)
145
146 token := auth.NewToken(target, envToken)
147 token.SetMetadata(auth.MetaKeyLogin, login)
148 err = auth.Store(repo, token)
149 require.NoError(t, err)
150
151 ctx := context.Background()
152
153 importer := &githubImporter{}
154 err = importer.Init(ctx, backend, core.Configuration{
155 confKeyOwner: "MichaelMure",
156 confKeyProject: "git-bug-test-github-bridge",
157 confKeyDefaultLogin: login,
158 })
159 require.NoError(t, err)
160
161 start := time.Now()
162
163 events, err := importer.ImportAll(ctx, backend, time.Time{})
164 require.NoError(t, err)
165
166 for result := range events {
167 require.NoError(t, result.Err)
168 }
169
170 fmt.Printf("test repository imported in %f seconds\n", time.Since(start).Seconds())
171
172 require.Len(t, backend.AllBugsIds(), len(tests))
173
174 for _, tt := range tests {
175 t.Run(tt.name, func(t *testing.T) {
176 b, err := backend.ResolveBugCreateMetadata(metaKeyGithubUrl, tt.url)
177 require.NoError(t, err)
178
179 ops := b.Snapshot().Operations
180 require.Len(t, tt.bug.Operations, len(b.Snapshot().Operations))
181
182 for i, op := range tt.bug.Operations {
183 require.IsType(t, ops[i], op)
184 require.Equal(t, op.Author().Name(), ops[i].Author().Name())
185
186 switch op := op.(type) {
187 case *bug.CreateOperation:
188 require.Equal(t, op.Title, ops[i].(*bug.CreateOperation).Title)
189 require.Equal(t, op.Message, ops[i].(*bug.CreateOperation).Message)
190 case *bug.SetStatusOperation:
191 require.Equal(t, op.Status, ops[i].(*bug.SetStatusOperation).Status)
192 case *bug.SetTitleOperation:
193 require.Equal(t, op.Was, ops[i].(*bug.SetTitleOperation).Was)
194 require.Equal(t, op.Title, ops[i].(*bug.SetTitleOperation).Title)
195 case *bug.LabelChangeOperation:
196 require.ElementsMatch(t, op.Added, ops[i].(*bug.LabelChangeOperation).Added)
197 require.ElementsMatch(t, op.Removed, ops[i].(*bug.LabelChangeOperation).Removed)
198 case *bug.AddCommentOperation:
199 require.Equal(t, op.Message, ops[i].(*bug.AddCommentOperation).Message)
200 case *bug.EditCommentOperation:
201 require.Equal(t, op.Message, ops[i].(*bug.EditCommentOperation).Message)
202
203 default:
204 panic("unknown operation type")
205 }
206 }
207 })
208 }
209}