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}