aboutsummaryrefslogtreecommitdiffstats
path: root/bridge/github/import_integration_test.go
diff options
context:
space:
mode:
authorrng-dynamics <73444470+rng-dynamics@users.noreply.github.com>2021-09-14 22:24:34 +0200
committerGitHub <noreply@github.com>2021-09-14 22:24:34 +0200
commitd546cdeee1a800d518e583c6a4727265723d096d (patch)
treefdaedfec4d47c1da9180c683140fb74e4778bc54 /bridge/github/import_integration_test.go
parent247e1a865db29a3189acfd89cde776a52a7ebaac (diff)
downloadgit-bug-d546cdeee1a800d518e583c6a4727265723d096d.tar.gz
Tests for the github bridge (#706)
Add integration test for github bridge
Diffstat (limited to 'bridge/github/import_integration_test.go')
-rw-r--r--bridge/github/import_integration_test.go384
1 files changed, 384 insertions, 0 deletions
diff --git a/bridge/github/import_integration_test.go b/bridge/github/import_integration_test.go
new file mode 100644
index 00000000..3349f3f5
--- /dev/null
+++ b/bridge/github/import_integration_test.go
@@ -0,0 +1,384 @@
+package github
+
+import (
+ "context"
+ "net/url"
+ "testing"
+ "time"
+
+ "github.com/MichaelMure/git-bug/bridge/github/mocks"
+ "github.com/MichaelMure/git-bug/bug"
+ "github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/repository"
+ "github.com/MichaelMure/git-bug/util/interrupt"
+ "github.com/pkg/errors"
+ "github.com/shurcooL/githubv4"
+ m "github.com/stretchr/testify/mock"
+ "github.com/stretchr/testify/require"
+)
+
+// using testify/mock and mockery
+
+var userName = githubv4.String("marcus")
+var userEmail = githubv4.String("marcus@rom.com")
+var unedited = githubv4.String("unedited")
+var edited = githubv4.String("edited")
+
+func TestGithubImporterIntegration(t *testing.T) {
+ // mock
+ clientMock := &mocks.Client{}
+ setupExpectations(t, clientMock)
+ importer := githubImporter{}
+ importer.client = &rateLimitHandlerClient{sc: clientMock}
+
+ // arrange
+ repo := repository.CreateGoGitTestRepo(false)
+ defer repository.CleanupTestRepos(repo)
+ backend, err := cache.NewRepoCache(repo)
+ require.NoError(t, err)
+ defer backend.Close()
+ interrupt.RegisterCleaner(backend.Close)
+ require.NoError(t, err)
+
+ // act
+ events, err := importer.ImportAll(context.Background(), backend, time.Time{})
+
+ // assert
+ require.NoError(t, err)
+ for e := range events {
+ require.NoError(t, e.Err)
+ }
+ require.Len(t, backend.AllBugsIds(), 5)
+ require.Len(t, backend.AllIdentityIds(), 2)
+
+ b1, err := backend.ResolveBugCreateMetadata(metaKeyGithubUrl, "https://github.com/marcus/to-himself/issues/1")
+ require.NoError(t, err)
+ ops1 := b1.Snapshot().Operations
+ require.Equal(t, "marcus", ops1[0].Author().Name())
+ require.Equal(t, "title 1", ops1[0].(*bug.CreateOperation).Title)
+ require.Equal(t, "body text 1", ops1[0].(*bug.CreateOperation).Message)
+
+ b3, err := backend.ResolveBugCreateMetadata(metaKeyGithubUrl, "https://github.com/marcus/to-himself/issues/3")
+ require.NoError(t, err)
+ ops3 := b3.Snapshot().Operations
+ require.Equal(t, "issue 3 comment 1", ops3[1].(*bug.AddCommentOperation).Message)
+ require.Equal(t, "issue 3 comment 2", ops3[2].(*bug.AddCommentOperation).Message)
+ require.Equal(t, []bug.Label{"bug"}, ops3[3].(*bug.LabelChangeOperation).Added)
+ require.Equal(t, "title 3, edit 1", ops3[4].(*bug.SetTitleOperation).Title)
+
+ b4, err := backend.ResolveBugCreateMetadata(metaKeyGithubUrl, "https://github.com/marcus/to-himself/issues/4")
+ require.NoError(t, err)
+ ops4 := b4.Snapshot().Operations
+ require.Equal(t, "edited", ops4[1].(*bug.EditCommentOperation).Message)
+
+}
+
+func setupExpectations(t *testing.T, mock *mocks.Client) {
+ rateLimitingError(mock)
+ expectIssueQuery1(mock)
+ expectIssueQuery2(mock)
+ expectIssueQuery3(mock)
+ expectUserQuery(t, mock)
+}
+
+func rateLimitingError(mock *mocks.Client) {
+ mock.On("Query", m.Anything, m.AnythingOfType("*github.issueQuery"), m.Anything).Return(errors.New("API rate limit exceeded")).Once()
+ mock.On("Query", m.Anything, m.AnythingOfType("*github.rateLimitQuery"), m.Anything).Return(nil).Run(
+ func(args m.Arguments) {
+ retVal := args.Get(1).(*rateLimitQuery)
+ retVal.RateLimit.ResetAt.Time = time.Now().Add(time.Millisecond * 200)
+ },
+ ).Once()
+}
+
+func expectIssueQuery1(mock *mocks.Client) {
+ mock.On("Query", m.Anything, m.AnythingOfType("*github.issueQuery"), m.Anything).Return(nil).Run(
+ func(args m.Arguments) {
+ retVal := args.Get(1).(*issueQuery)
+ retVal.Repository.Issues.Nodes = []issueNode{
+ {
+ issue: issue{
+ authorEvent: authorEvent{
+ Id: 1,
+ Author: &actor{
+ Typename: "User",
+ User: userActor{
+ Name: &userName,
+ Email: userEmail,
+ },
+ },
+ },
+ Title: "title 1",
+ Number: 1,
+ Body: "body text 1",
+ Url: githubv4.URI{
+ URL: &url.URL{
+ Scheme: "https",
+ Host: "github.com",
+ Path: "marcus/to-himself/issues/1",
+ },
+ },
+ },
+ UserContentEdits: userContentEditConnection{},
+ TimelineItems: timelineItemsConnection{},
+ },
+ {
+ issue: issue{
+ authorEvent: authorEvent{
+ Id: 2,
+ Author: &actor{
+ Typename: "User",
+ User: userActor{
+ Name: &userName,
+ Email: userEmail,
+ },
+ },
+ },
+ Title: "title 2",
+ Number: 2,
+ Body: "body text 2",
+ Url: githubv4.URI{
+ URL: &url.URL{
+ Scheme: "https",
+ Host: "github.com",
+ Path: "marcus/to-himself/issues/2",
+ },
+ },
+ },
+ UserContentEdits: userContentEditConnection{},
+ TimelineItems: timelineItemsConnection{},
+ },
+ }
+ retVal.Repository.Issues.PageInfo = pageInfo{
+ EndCursor: "end-cursor-1",
+ HasNextPage: true,
+ }
+ },
+ ).Once()
+}
+
+func expectIssueQuery2(mock *mocks.Client) {
+ mock.On("Query", m.Anything, m.AnythingOfType("*github.issueQuery"), m.Anything).Return(nil).Run(
+ func(args m.Arguments) {
+ retVal := args.Get(1).(*issueQuery)
+ retVal.Repository.Issues.Nodes = []issueNode{
+ {
+ issue: issue{
+ authorEvent: authorEvent{
+ Id: 3,
+ Author: &actor{
+ Typename: "User",
+ User: userActor{
+ Name: &userName,
+ Email: userEmail,
+ },
+ },
+ },
+ Title: "title 3",
+ Number: 3,
+ Body: "body text 3",
+ Url: githubv4.URI{
+ URL: &url.URL{
+ Scheme: "https",
+ Host: "github.com",
+ Path: "marcus/to-himself/issues/3",
+ },
+ },
+ },
+ UserContentEdits: userContentEditConnection{},
+ TimelineItems: timelineItemsConnection{
+ Nodes: []timelineItem{
+ {
+ Typename: "IssueComment",
+ IssueComment: issueComment{
+ authorEvent: authorEvent{
+ Id: 301,
+ Author: &actor{
+ Typename: "User",
+ User: userActor{
+ Name: &userName,
+ Email: userEmail,
+ },
+ },
+ },
+ Body: "issue 3 comment 1",
+ Url: githubv4.URI{
+ URL: &url.URL{
+ Scheme: "https",
+ Host: "github.com",
+ Path: "marcus/to-himself/issues/3#issuecomment-1",
+ },
+ },
+ UserContentEdits: userContentEditConnection{},
+ },
+ },
+ {
+ Typename: "IssueComment",
+ IssueComment: issueComment{
+ authorEvent: authorEvent{
+ Id: 302,
+ Author: &actor{
+ Typename: "User",
+ User: userActor{
+ Name: &userName,
+ Email: userEmail,
+ },
+ },
+ },
+ Body: "issue 3 comment 2",
+ Url: githubv4.URI{
+ URL: &url.URL{
+ Scheme: "https",
+ Host: "github.com",
+ Path: "marcus/to-himself/issues/3#issuecomment-2",
+ },
+ },
+ UserContentEdits: userContentEditConnection{},
+ },
+ },
+ {
+ Typename: "LabeledEvent",
+ LabeledEvent: labeledEvent{
+ actorEvent: actorEvent{
+ Id: 303,
+ Actor: &actor{
+ Typename: "User",
+ User: userActor{
+ Name: &userName,
+ Email: userEmail,
+ },
+ },
+ },
+ Label: label{
+ Name: "bug",
+ },
+ },
+ },
+ {
+ Typename: "RenamedTitleEvent",
+ RenamedTitleEvent: renamedTitleEvent{
+ actorEvent: actorEvent{
+ Id: 304,
+ Actor: &actor{
+ Typename: "User",
+ User: userActor{
+ Name: &userName,
+ Email: userEmail,
+ },
+ },
+ },
+ CurrentTitle: "title 3, edit 1",
+ },
+ },
+ },
+ PageInfo: pageInfo{},
+ },
+ },
+ {
+ issue: issue{
+ authorEvent: authorEvent{
+ Id: 4,
+ Author: &actor{
+ Typename: "User",
+ User: userActor{
+ Name: &userName,
+ Email: userEmail,
+ },
+ },
+ },
+ Title: "title 4",
+ Number: 4,
+ Body: unedited,
+ Url: githubv4.URI{
+ URL: &url.URL{
+ Scheme: "https",
+ Host: "github.com",
+ Path: "marcus/to-himself/issues/4",
+ },
+ },
+ },
+ UserContentEdits: userContentEditConnection{
+ Nodes: []userContentEdit{
+ // Github is weird: here the order is reversed chronological
+ {
+ Id: 402,
+ Editor: &actor{
+ Typename: "User",
+ User: userActor{
+ Name: &userName,
+ Email: userEmail,
+ },
+ },
+ Diff: &edited,
+ },
+ {
+ Id: 401,
+ Editor: &actor{
+ Typename: "User",
+ User: userActor{
+ Name: &userName,
+ Email: userEmail,
+ },
+ },
+ // Github is weird: whenever an issue has issue edits, then the first item
+ // (issue edit) holds the original (unedited) content and the second item
+ // (issue edit) holds the (first) edited content.
+ Diff: &unedited,
+ },
+ },
+ PageInfo: pageInfo{},
+ },
+ TimelineItems: timelineItemsConnection{},
+ },
+ }
+ retVal.Repository.Issues.PageInfo = pageInfo{
+ EndCursor: "end-cursor-2",
+ HasNextPage: true,
+ }
+ },
+ ).Once()
+}
+
+func expectIssueQuery3(mock *mocks.Client) {
+ mock.On("Query", m.Anything, m.AnythingOfType("*github.issueQuery"), m.Anything).Return(nil).Run(
+ func(args m.Arguments) {
+ retVal := args.Get(1).(*issueQuery)
+ retVal.Repository.Issues.Nodes = []issueNode{
+ {
+ issue: issue{
+ authorEvent: authorEvent{
+ Author: nil,
+ },
+ Title: "title 5",
+ Number: 5,
+ Body: "body text 5",
+ Url: githubv4.URI{
+ URL: &url.URL{
+ Scheme: "https",
+ Host: "github.com",
+ Path: "marcus/to-himself/issues/5",
+ },
+ },
+ },
+ UserContentEdits: userContentEditConnection{},
+ TimelineItems: timelineItemsConnection{},
+ },
+ }
+ retVal.Repository.Issues.PageInfo = pageInfo{}
+ },
+ ).Once()
+}
+
+func expectUserQuery(t *testing.T, mock *mocks.Client) {
+ mock.On("Query", m.Anything, m.AnythingOfType("*github.userQuery"), m.AnythingOfType("map[string]interface {}")).Return(nil).Run(
+ func(args m.Arguments) {
+ vars := args.Get(2).(map[string]interface{})
+ ghost := githubv4.String("ghost")
+ require.Equal(t, ghost, vars["login"])
+
+ retVal := args.Get(1).(*userQuery)
+ retVal.User.Name = &ghost
+ retVal.User.Login = "ghost-login"
+ },
+ ).Once()
+}