github.com/andrewhsu/cli/v2@v2.0.1-0.20210910131313-d4b4061f5b89/pkg/cmd/pr/shared/finder_test.go (about) 1 package shared 2 3 import ( 4 "errors" 5 "net/http" 6 "net/url" 7 "testing" 8 9 "github.com/andrewhsu/cli/v2/context" 10 "github.com/andrewhsu/cli/v2/git" 11 "github.com/andrewhsu/cli/v2/internal/ghrepo" 12 "github.com/andrewhsu/cli/v2/pkg/httpmock" 13 ) 14 15 func TestFind(t *testing.T) { 16 type args struct { 17 baseRepoFn func() (ghrepo.Interface, error) 18 branchFn func() (string, error) 19 branchConfig func(string) git.BranchConfig 20 remotesFn func() (context.Remotes, error) 21 selector string 22 fields []string 23 baseBranch string 24 } 25 tests := []struct { 26 name string 27 args args 28 httpStub func(*httpmock.Registry) 29 wantPR int 30 wantRepo string 31 wantErr bool 32 }{ 33 { 34 name: "number argument", 35 args: args{ 36 selector: "13", 37 fields: []string{"id", "number"}, 38 baseRepoFn: func() (ghrepo.Interface, error) { 39 return ghrepo.FromFullName("OWNER/REPO") 40 }, 41 }, 42 httpStub: func(r *httpmock.Registry) { 43 r.Register( 44 httpmock.GraphQL(`query PullRequestByNumber\b`), 45 httpmock.StringResponse(`{"data":{"repository":{ 46 "pullRequest":{"number":13} 47 }}}`)) 48 }, 49 wantPR: 13, 50 wantRepo: "https://github.com/OWNER/REPO", 51 }, 52 { 53 name: "baseRepo is error", 54 args: args{ 55 selector: "13", 56 fields: []string{"id", "number"}, 57 baseRepoFn: func() (ghrepo.Interface, error) { 58 return nil, errors.New("baseRepoErr") 59 }, 60 }, 61 wantErr: true, 62 }, 63 { 64 name: "blank fields is error", 65 args: args{ 66 selector: "13", 67 fields: []string{}, 68 }, 69 wantErr: true, 70 }, 71 { 72 name: "number only", 73 args: args{ 74 selector: "13", 75 fields: []string{"number"}, 76 baseRepoFn: func() (ghrepo.Interface, error) { 77 return ghrepo.FromFullName("OWNER/REPO") 78 }, 79 }, 80 httpStub: nil, 81 wantPR: 13, 82 wantRepo: "https://github.com/OWNER/REPO", 83 }, 84 { 85 name: "number with hash argument", 86 args: args{ 87 selector: "#13", 88 fields: []string{"id", "number"}, 89 baseRepoFn: func() (ghrepo.Interface, error) { 90 return ghrepo.FromFullName("OWNER/REPO") 91 }, 92 }, 93 httpStub: func(r *httpmock.Registry) { 94 r.Register( 95 httpmock.GraphQL(`query PullRequestByNumber\b`), 96 httpmock.StringResponse(`{"data":{"repository":{ 97 "pullRequest":{"number":13} 98 }}}`)) 99 }, 100 wantPR: 13, 101 wantRepo: "https://github.com/OWNER/REPO", 102 }, 103 { 104 name: "URL argument", 105 args: args{ 106 selector: "https://example.org/OWNER/REPO/pull/13/files", 107 fields: []string{"id", "number"}, 108 baseRepoFn: nil, 109 }, 110 httpStub: func(r *httpmock.Registry) { 111 r.Register( 112 httpmock.GraphQL(`query PullRequestByNumber\b`), 113 httpmock.StringResponse(`{"data":{"repository":{ 114 "pullRequest":{"number":13} 115 }}}`)) 116 }, 117 wantPR: 13, 118 wantRepo: "https://example.org/OWNER/REPO", 119 }, 120 { 121 name: "branch argument", 122 args: args{ 123 selector: "blueberries", 124 fields: []string{"id", "number"}, 125 baseRepoFn: func() (ghrepo.Interface, error) { 126 return ghrepo.FromFullName("OWNER/REPO") 127 }, 128 }, 129 httpStub: func(r *httpmock.Registry) { 130 r.Register( 131 httpmock.GraphQL(`query PullRequestForBranch\b`), 132 httpmock.StringResponse(`{"data":{"repository":{ 133 "pullRequests":{"nodes":[ 134 { 135 "number": 14, 136 "state": "CLOSED", 137 "baseRefName": "main", 138 "headRefName": "blueberries", 139 "isCrossRepository": false, 140 "headRepositoryOwner": {"login":"OWNER"} 141 }, 142 { 143 "number": 13, 144 "state": "OPEN", 145 "baseRefName": "main", 146 "headRefName": "blueberries", 147 "isCrossRepository": false, 148 "headRepositoryOwner": {"login":"OWNER"} 149 } 150 ]} 151 }}}`)) 152 }, 153 wantPR: 13, 154 wantRepo: "https://github.com/OWNER/REPO", 155 }, 156 { 157 name: "branch argument with base branch", 158 args: args{ 159 selector: "blueberries", 160 baseBranch: "main", 161 fields: []string{"id", "number"}, 162 baseRepoFn: func() (ghrepo.Interface, error) { 163 return ghrepo.FromFullName("OWNER/REPO") 164 }, 165 }, 166 httpStub: func(r *httpmock.Registry) { 167 r.Register( 168 httpmock.GraphQL(`query PullRequestForBranch\b`), 169 httpmock.StringResponse(`{"data":{"repository":{ 170 "pullRequests":{"nodes":[ 171 { 172 "number": 14, 173 "state": "OPEN", 174 "baseRefName": "dev", 175 "headRefName": "blueberries", 176 "isCrossRepository": false, 177 "headRepositoryOwner": {"login":"OWNER"} 178 }, 179 { 180 "number": 13, 181 "state": "OPEN", 182 "baseRefName": "main", 183 "headRefName": "blueberries", 184 "isCrossRepository": false, 185 "headRepositoryOwner": {"login":"OWNER"} 186 } 187 ]} 188 }}}`)) 189 }, 190 wantPR: 13, 191 wantRepo: "https://github.com/OWNER/REPO", 192 }, 193 { 194 name: "no argument reads current branch", 195 args: args{ 196 selector: "", 197 fields: []string{"id", "number"}, 198 baseRepoFn: func() (ghrepo.Interface, error) { 199 return ghrepo.FromFullName("OWNER/REPO") 200 }, 201 branchFn: func() (string, error) { 202 return "blueberries", nil 203 }, 204 branchConfig: func(branch string) (c git.BranchConfig) { 205 return 206 }, 207 }, 208 httpStub: func(r *httpmock.Registry) { 209 r.Register( 210 httpmock.GraphQL(`query PullRequestForBranch\b`), 211 httpmock.StringResponse(`{"data":{"repository":{ 212 "pullRequests":{"nodes":[ 213 { 214 "number": 13, 215 "state": "OPEN", 216 "baseRefName": "main", 217 "headRefName": "blueberries", 218 "isCrossRepository": false, 219 "headRepositoryOwner": {"login":"OWNER"} 220 } 221 ]} 222 }}}`)) 223 }, 224 wantPR: 13, 225 wantRepo: "https://github.com/OWNER/REPO", 226 }, 227 { 228 name: "current branch is error", 229 args: args{ 230 selector: "", 231 fields: []string{"id", "number"}, 232 baseRepoFn: func() (ghrepo.Interface, error) { 233 return ghrepo.FromFullName("OWNER/REPO") 234 }, 235 branchFn: func() (string, error) { 236 return "", errors.New("branchErr") 237 }, 238 }, 239 wantErr: true, 240 }, 241 { 242 name: "current branch with upstream configuration", 243 args: args{ 244 selector: "", 245 fields: []string{"id", "number"}, 246 baseRepoFn: func() (ghrepo.Interface, error) { 247 return ghrepo.FromFullName("OWNER/REPO") 248 }, 249 branchFn: func() (string, error) { 250 return "blueberries", nil 251 }, 252 branchConfig: func(branch string) (c git.BranchConfig) { 253 c.MergeRef = "refs/heads/blue-upstream-berries" 254 c.RemoteName = "origin" 255 return 256 }, 257 remotesFn: func() (context.Remotes, error) { 258 return context.Remotes{{ 259 Remote: &git.Remote{Name: "origin"}, 260 Repo: ghrepo.New("UPSTREAMOWNER", "REPO"), 261 }}, nil 262 }, 263 }, 264 httpStub: func(r *httpmock.Registry) { 265 r.Register( 266 httpmock.GraphQL(`query PullRequestForBranch\b`), 267 httpmock.StringResponse(`{"data":{"repository":{ 268 "pullRequests":{"nodes":[ 269 { 270 "number": 13, 271 "state": "OPEN", 272 "baseRefName": "main", 273 "headRefName": "blue-upstream-berries", 274 "isCrossRepository": true, 275 "headRepositoryOwner": {"login":"UPSTREAMOWNER"} 276 } 277 ]} 278 }}}`)) 279 }, 280 wantPR: 13, 281 wantRepo: "https://github.com/OWNER/REPO", 282 }, 283 { 284 name: "current branch with upstream configuration", 285 args: args{ 286 selector: "", 287 fields: []string{"id", "number"}, 288 baseRepoFn: func() (ghrepo.Interface, error) { 289 return ghrepo.FromFullName("OWNER/REPO") 290 }, 291 branchFn: func() (string, error) { 292 return "blueberries", nil 293 }, 294 branchConfig: func(branch string) (c git.BranchConfig) { 295 u, _ := url.Parse("https://github.com/UPSTREAMOWNER/REPO") 296 c.MergeRef = "refs/heads/blue-upstream-berries" 297 c.RemoteURL = u 298 return 299 }, 300 remotesFn: nil, 301 }, 302 httpStub: func(r *httpmock.Registry) { 303 r.Register( 304 httpmock.GraphQL(`query PullRequestForBranch\b`), 305 httpmock.StringResponse(`{"data":{"repository":{ 306 "pullRequests":{"nodes":[ 307 { 308 "number": 13, 309 "state": "OPEN", 310 "baseRefName": "main", 311 "headRefName": "blue-upstream-berries", 312 "isCrossRepository": true, 313 "headRepositoryOwner": {"login":"UPSTREAMOWNER"} 314 } 315 ]} 316 }}}`)) 317 }, 318 wantPR: 13, 319 wantRepo: "https://github.com/OWNER/REPO", 320 }, 321 { 322 name: "current branch made by pr checkout", 323 args: args{ 324 selector: "", 325 fields: []string{"id", "number"}, 326 baseRepoFn: func() (ghrepo.Interface, error) { 327 return ghrepo.FromFullName("OWNER/REPO") 328 }, 329 branchFn: func() (string, error) { 330 return "blueberries", nil 331 }, 332 branchConfig: func(branch string) (c git.BranchConfig) { 333 c.MergeRef = "refs/pull/13/head" 334 return 335 }, 336 }, 337 httpStub: func(r *httpmock.Registry) { 338 r.Register( 339 httpmock.GraphQL(`query PullRequestByNumber\b`), 340 httpmock.StringResponse(`{"data":{"repository":{ 341 "pullRequest":{"number":13} 342 }}}`)) 343 }, 344 wantPR: 13, 345 wantRepo: "https://github.com/OWNER/REPO", 346 }, 347 } 348 for _, tt := range tests { 349 t.Run(tt.name, func(t *testing.T) { 350 reg := &httpmock.Registry{} 351 defer reg.Verify(t) 352 if tt.httpStub != nil { 353 tt.httpStub(reg) 354 } 355 356 f := finder{ 357 httpClient: func() (*http.Client, error) { 358 return &http.Client{Transport: reg}, nil 359 }, 360 baseRepoFn: tt.args.baseRepoFn, 361 branchFn: tt.args.branchFn, 362 branchConfig: tt.args.branchConfig, 363 remotesFn: tt.args.remotesFn, 364 } 365 366 pr, repo, err := f.Find(FindOptions{ 367 Selector: tt.args.selector, 368 Fields: tt.args.fields, 369 BaseBranch: tt.args.baseBranch, 370 }) 371 if (err != nil) != tt.wantErr { 372 t.Errorf("Find() error = %v, wantErr %v", err, tt.wantErr) 373 return 374 } 375 if tt.wantErr { 376 if tt.wantPR > 0 { 377 t.Error("wantPR field is not checked in error case") 378 } 379 if tt.wantRepo != "" { 380 t.Error("wantRepo field is not checked in error case") 381 } 382 return 383 } 384 385 if pr.Number != tt.wantPR { 386 t.Errorf("want pr #%d, got #%d", tt.wantPR, pr.Number) 387 } 388 repoURL := ghrepo.GenerateRepoURL(repo, "") 389 if repoURL != tt.wantRepo { 390 t.Errorf("want repo %s, got %s", tt.wantRepo, repoURL) 391 } 392 }) 393 } 394 }