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