import_test.go

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