github.com/google/go-github/v49@v49.1.0/github/repos_contents_test.go (about) 1 // Copyright 2014 The go-github AUTHORS. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package github 7 8 import ( 9 "context" 10 "errors" 11 "fmt" 12 "io" 13 "net/http" 14 "net/url" 15 "testing" 16 17 "github.com/google/go-cmp/cmp" 18 "golang.org/x/crypto/openpgp" 19 ) 20 21 func TestRepositoryContent_GetContent(t *testing.T) { 22 tests := []struct { 23 encoding, content *string // input encoding and content 24 want string // desired output 25 wantErr bool // whether an error is expected 26 }{ 27 { 28 encoding: String(""), 29 content: String("hello"), 30 want: "hello", 31 wantErr: false, 32 }, 33 { 34 encoding: nil, 35 content: String("hello"), 36 want: "hello", 37 wantErr: false, 38 }, 39 { 40 encoding: nil, 41 content: nil, 42 want: "", 43 wantErr: false, 44 }, 45 { 46 encoding: String("base64"), 47 content: String("aGVsbG8="), 48 want: "hello", 49 wantErr: false, 50 }, 51 { 52 encoding: String("bad"), 53 content: String("aGVsbG8="), 54 want: "", 55 wantErr: true, 56 }, 57 } 58 59 for _, tt := range tests { 60 r := RepositoryContent{Encoding: tt.encoding, Content: tt.content} 61 got, err := r.GetContent() 62 if err != nil && !tt.wantErr { 63 t.Errorf("RepositoryContent(%s, %s) returned unexpected error: %v", 64 stringOrNil(tt.encoding), stringOrNil(tt.content), err) 65 } 66 if err == nil && tt.wantErr { 67 t.Errorf("RepositoryContent(%s, %s) did not return unexpected error", 68 stringOrNil(tt.encoding), stringOrNil(tt.content)) 69 } 70 if want := tt.want; got != want { 71 t.Errorf("RepositoryContent.GetContent returned %+v, want %+v", got, want) 72 } 73 } 74 } 75 76 // stringOrNil converts a potentially null string pointer to string. 77 // For non-nil input pointer, the returned string is enclosed in double-quotes. 78 func stringOrNil(s *string) string { 79 if s == nil { 80 return "<nil>" 81 } 82 return fmt.Sprintf("%q", *s) 83 } 84 85 func TestRepositoriesService_GetReadme(t *testing.T) { 86 client, mux, _, teardown := setup() 87 defer teardown() 88 mux.HandleFunc("/repos/o/r/readme", func(w http.ResponseWriter, r *http.Request) { 89 testMethod(t, r, "GET") 90 fmt.Fprint(w, `{ 91 "type": "file", 92 "encoding": "base64", 93 "size": 5362, 94 "name": "README.md", 95 "path": "README.md" 96 }`) 97 }) 98 ctx := context.Background() 99 readme, _, err := client.Repositories.GetReadme(ctx, "o", "r", &RepositoryContentGetOptions{}) 100 if err != nil { 101 t.Errorf("Repositories.GetReadme returned error: %v", err) 102 } 103 want := &RepositoryContent{Type: String("file"), Name: String("README.md"), Size: Int(5362), Encoding: String("base64"), Path: String("README.md")} 104 if !cmp.Equal(readme, want) { 105 t.Errorf("Repositories.GetReadme returned %+v, want %+v", readme, want) 106 } 107 108 const methodName = "GetReadme" 109 testBadOptions(t, methodName, func() (err error) { 110 _, _, err = client.Repositories.GetReadme(ctx, "\n", "\n", &RepositoryContentGetOptions{}) 111 return err 112 }) 113 114 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 115 got, resp, err := client.Repositories.GetReadme(ctx, "o", "r", &RepositoryContentGetOptions{}) 116 if got != nil { 117 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 118 } 119 return resp, err 120 }) 121 } 122 123 func TestRepositoriesService_DownloadContents_Success(t *testing.T) { 124 client, mux, serverURL, teardown := setup() 125 defer teardown() 126 mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { 127 testMethod(t, r, "GET") 128 fmt.Fprint(w, `[{ 129 "type": "file", 130 "name": "f", 131 "download_url": "`+serverURL+baseURLPath+`/download/f" 132 }]`) 133 }) 134 mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) { 135 testMethod(t, r, "GET") 136 fmt.Fprint(w, "foo") 137 }) 138 139 ctx := context.Background() 140 r, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil) 141 if err != nil { 142 t.Errorf("Repositories.DownloadContents returned error: %v", err) 143 } 144 145 if got, want := resp.Response.StatusCode, http.StatusOK; got != want { 146 t.Errorf("Repositories.DownloadContents returned status code %v, want %v", got, want) 147 } 148 149 bytes, err := io.ReadAll(r) 150 if err != nil { 151 t.Errorf("Error reading response body: %v", err) 152 } 153 r.Close() 154 155 if got, want := string(bytes), "foo"; got != want { 156 t.Errorf("Repositories.DownloadContents returned %v, want %v", got, want) 157 } 158 159 const methodName = "DownloadContents" 160 testBadOptions(t, methodName, func() (err error) { 161 _, _, err = client.Repositories.DownloadContents(ctx, "\n", "\n", "\n", nil) 162 return err 163 }) 164 165 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 166 got, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil) 167 if got != nil { 168 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 169 } 170 return resp, err 171 }) 172 } 173 174 func TestRepositoriesService_DownloadContents_FailedResponse(t *testing.T) { 175 client, mux, serverURL, teardown := setup() 176 defer teardown() 177 mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { 178 testMethod(t, r, "GET") 179 fmt.Fprint(w, `[{ 180 "type": "file", 181 "name": "f", 182 "download_url": "`+serverURL+baseURLPath+`/download/f" 183 }]`) 184 }) 185 mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) { 186 testMethod(t, r, "GET") 187 w.WriteHeader(http.StatusInternalServerError) 188 fmt.Fprint(w, "foo error") 189 }) 190 191 ctx := context.Background() 192 r, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil) 193 if err != nil { 194 t.Errorf("Repositories.DownloadContents returned error: %v", err) 195 } 196 197 if got, want := resp.Response.StatusCode, http.StatusInternalServerError; got != want { 198 t.Errorf("Repositories.DownloadContents returned status code %v, want %v", got, want) 199 } 200 201 bytes, err := io.ReadAll(r) 202 if err != nil { 203 t.Errorf("Error reading response body: %v", err) 204 } 205 r.Close() 206 207 if got, want := string(bytes), "foo error"; got != want { 208 t.Errorf("Repositories.DownloadContents returned %v, want %v", got, want) 209 } 210 } 211 212 func TestRepositoriesService_DownloadContents_NoDownloadURL(t *testing.T) { 213 client, mux, _, teardown := setup() 214 defer teardown() 215 mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { 216 testMethod(t, r, "GET") 217 fmt.Fprint(w, `[{ 218 "type": "file", 219 "name": "f", 220 }]`) 221 }) 222 223 ctx := context.Background() 224 _, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil) 225 if err == nil { 226 t.Errorf("Repositories.DownloadContents did not return expected error") 227 } 228 229 if resp == nil { 230 t.Errorf("Repositories.DownloadContents did not return expected response") 231 } 232 } 233 234 func TestRepositoriesService_DownloadContents_NoFile(t *testing.T) { 235 client, mux, _, teardown := setup() 236 defer teardown() 237 mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { 238 testMethod(t, r, "GET") 239 fmt.Fprint(w, `[]`) 240 }) 241 242 ctx := context.Background() 243 _, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil) 244 if err == nil { 245 t.Errorf("Repositories.DownloadContents did not return expected error") 246 } 247 248 if resp == nil { 249 t.Errorf("Repositories.DownloadContents did not return expected response") 250 } 251 } 252 253 func TestRepositoriesService_DownloadContentsWithMeta_Success(t *testing.T) { 254 client, mux, serverURL, teardown := setup() 255 defer teardown() 256 mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { 257 testMethod(t, r, "GET") 258 fmt.Fprint(w, `[{ 259 "type": "file", 260 "name": "f", 261 "download_url": "`+serverURL+baseURLPath+`/download/f" 262 }]`) 263 }) 264 mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) { 265 testMethod(t, r, "GET") 266 fmt.Fprint(w, "foo") 267 }) 268 269 ctx := context.Background() 270 r, c, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil) 271 if err != nil { 272 t.Errorf("Repositories.DownloadContentsWithMeta returned error: %v", err) 273 } 274 275 if got, want := resp.Response.StatusCode, http.StatusOK; got != want { 276 t.Errorf("Repositories.DownloadContentsWithMeta returned status code %v, want %v", got, want) 277 } 278 279 bytes, err := io.ReadAll(r) 280 if err != nil { 281 t.Errorf("Error reading response body: %v", err) 282 } 283 r.Close() 284 285 if got, want := string(bytes), "foo"; got != want { 286 t.Errorf("Repositories.DownloadContentsWithMeta returned %v, want %v", got, want) 287 } 288 289 if c != nil && c.Name != nil { 290 if got, want := *c.Name, "f"; got != want { 291 t.Errorf("Repositories.DownloadContentsWithMeta returned content name %v, want %v", got, want) 292 } 293 } else { 294 t.Errorf("Returned RepositoryContent is null") 295 } 296 297 const methodName = "DownloadContentsWithMeta" 298 testBadOptions(t, methodName, func() (err error) { 299 _, _, _, err = client.Repositories.DownloadContentsWithMeta(ctx, "\n", "\n", "\n", nil) 300 return err 301 }) 302 303 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 304 got, cot, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil) 305 if got != nil { 306 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 307 } 308 if cot != nil { 309 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, cot) 310 } 311 return resp, err 312 }) 313 } 314 315 func TestRepositoriesService_DownloadContentsWithMeta_FailedResponse(t *testing.T) { 316 client, mux, serverURL, teardown := setup() 317 defer teardown() 318 mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { 319 testMethod(t, r, "GET") 320 fmt.Fprint(w, `[{ 321 "type": "file", 322 "name": "f", 323 "download_url": "`+serverURL+baseURLPath+`/download/f" 324 }]`) 325 }) 326 mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) { 327 testMethod(t, r, "GET") 328 w.WriteHeader(http.StatusInternalServerError) 329 fmt.Fprint(w, "foo error") 330 }) 331 332 ctx := context.Background() 333 r, c, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil) 334 if err != nil { 335 t.Errorf("Repositories.DownloadContentsWithMeta returned error: %v", err) 336 } 337 338 if got, want := resp.Response.StatusCode, http.StatusInternalServerError; got != want { 339 t.Errorf("Repositories.DownloadContentsWithMeta returned status code %v, want %v", got, want) 340 } 341 342 bytes, err := io.ReadAll(r) 343 if err != nil { 344 t.Errorf("Error reading response body: %v", err) 345 } 346 r.Close() 347 348 if got, want := string(bytes), "foo error"; got != want { 349 t.Errorf("Repositories.DownloadContentsWithMeta returned %v, want %v", got, want) 350 } 351 352 if c != nil && c.Name != nil { 353 if got, want := *c.Name, "f"; got != want { 354 t.Errorf("Repositories.DownloadContentsWithMeta returned content name %v, want %v", got, want) 355 } 356 } else { 357 t.Errorf("Returned RepositoryContent is null") 358 } 359 } 360 361 func TestRepositoriesService_DownloadContentsWithMeta_NoDownloadURL(t *testing.T) { 362 client, mux, _, teardown := setup() 363 defer teardown() 364 mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { 365 testMethod(t, r, "GET") 366 fmt.Fprint(w, `[{ 367 "type": "file", 368 "name": "f", 369 }]`) 370 }) 371 372 ctx := context.Background() 373 _, _, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil) 374 if err == nil { 375 t.Errorf("Repositories.DownloadContentsWithMeta did not return expected error") 376 } 377 378 if resp == nil { 379 t.Errorf("Repositories.DownloadContentsWithMeta did not return expected response") 380 } 381 } 382 383 func TestRepositoriesService_DownloadContentsWithMeta_NoFile(t *testing.T) { 384 client, mux, _, teardown := setup() 385 defer teardown() 386 mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) { 387 testMethod(t, r, "GET") 388 fmt.Fprint(w, `[]`) 389 }) 390 391 ctx := context.Background() 392 _, _, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil) 393 if err == nil { 394 t.Errorf("Repositories.DownloadContentsWithMeta did not return expected error") 395 } 396 397 if resp == nil { 398 t.Errorf("Repositories.DownloadContentsWithMeta did not return expected response") 399 } 400 } 401 402 func TestRepositoriesService_GetContents_File(t *testing.T) { 403 client, mux, _, teardown := setup() 404 defer teardown() 405 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 406 testMethod(t, r, "GET") 407 fmt.Fprint(w, `{ 408 "type": "file", 409 "encoding": "base64", 410 "size": 20678, 411 "name": "LICENSE", 412 "path": "LICENSE" 413 }`) 414 }) 415 ctx := context.Background() 416 fileContents, _, _, err := client.Repositories.GetContents(ctx, "o", "r", "p", &RepositoryContentGetOptions{}) 417 if err != nil { 418 t.Errorf("Repositories.GetContents returned error: %v", err) 419 } 420 want := &RepositoryContent{Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Encoding: String("base64"), Path: String("LICENSE")} 421 if !cmp.Equal(fileContents, want) { 422 t.Errorf("Repositories.GetContents returned %+v, want %+v", fileContents, want) 423 } 424 425 const methodName = "GetContents" 426 testBadOptions(t, methodName, func() (err error) { 427 _, _, _, err = client.Repositories.GetContents(ctx, "\n", "\n", "\n", &RepositoryContentGetOptions{}) 428 return err 429 }) 430 431 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 432 got, _, resp, err := client.Repositories.GetContents(ctx, "o", "r", "p", &RepositoryContentGetOptions{}) 433 if got != nil { 434 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 435 } 436 return resp, err 437 }) 438 } 439 440 func TestRepositoriesService_GetContents_FilenameNeedsEscape(t *testing.T) { 441 client, mux, _, teardown := setup() 442 defer teardown() 443 mux.HandleFunc("/repos/o/r/contents/p#?%/中.go", func(w http.ResponseWriter, r *http.Request) { 444 testMethod(t, r, "GET") 445 fmt.Fprint(w, `{}`) 446 }) 447 ctx := context.Background() 448 _, _, _, err := client.Repositories.GetContents(ctx, "o", "r", "p#?%/中.go", &RepositoryContentGetOptions{}) 449 if err != nil { 450 t.Fatalf("Repositories.GetContents returned error: %v", err) 451 } 452 } 453 454 func TestRepositoriesService_GetContents_DirectoryWithSpaces(t *testing.T) { 455 client, mux, _, teardown := setup() 456 defer teardown() 457 mux.HandleFunc("/repos/o/r/contents/some directory/file.go", func(w http.ResponseWriter, r *http.Request) { 458 testMethod(t, r, "GET") 459 fmt.Fprint(w, `{}`) 460 }) 461 ctx := context.Background() 462 _, _, _, err := client.Repositories.GetContents(ctx, "o", "r", "some directory/file.go", &RepositoryContentGetOptions{}) 463 if err != nil { 464 t.Fatalf("Repositories.GetContents returned error: %v", err) 465 } 466 } 467 468 func TestRepositoriesService_GetContents_DirectoryWithPlusChars(t *testing.T) { 469 client, mux, _, teardown := setup() 470 defer teardown() 471 mux.HandleFunc("/repos/o/r/contents/some directory+name/file.go", func(w http.ResponseWriter, r *http.Request) { 472 testMethod(t, r, "GET") 473 fmt.Fprint(w, `{}`) 474 }) 475 ctx := context.Background() 476 _, _, _, err := client.Repositories.GetContents(ctx, "o", "r", "some directory+name/file.go", &RepositoryContentGetOptions{}) 477 if err != nil { 478 t.Fatalf("Repositories.GetContents returned error: %v", err) 479 } 480 } 481 482 func TestRepositoriesService_GetContents_Directory(t *testing.T) { 483 client, mux, _, teardown := setup() 484 defer teardown() 485 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 486 testMethod(t, r, "GET") 487 fmt.Fprint(w, `[{ 488 "type": "dir", 489 "name": "lib", 490 "path": "lib" 491 }, 492 { 493 "type": "file", 494 "size": 20678, 495 "name": "LICENSE", 496 "path": "LICENSE" 497 }]`) 498 }) 499 ctx := context.Background() 500 _, directoryContents, _, err := client.Repositories.GetContents(ctx, "o", "r", "p", &RepositoryContentGetOptions{}) 501 if err != nil { 502 t.Errorf("Repositories.GetContents returned error: %v", err) 503 } 504 want := []*RepositoryContent{{Type: String("dir"), Name: String("lib"), Path: String("lib")}, 505 {Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Path: String("LICENSE")}} 506 if !cmp.Equal(directoryContents, want) { 507 t.Errorf("Repositories.GetContents_Directory returned %+v, want %+v", directoryContents, want) 508 } 509 } 510 511 func TestRepositoriesService_CreateFile(t *testing.T) { 512 client, mux, _, teardown := setup() 513 defer teardown() 514 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 515 testMethod(t, r, "PUT") 516 fmt.Fprint(w, `{ 517 "content":{ 518 "name":"p" 519 }, 520 "commit":{ 521 "message":"m", 522 "sha":"f5f369044773ff9c6383c087466d12adb6fa0828" 523 } 524 }`) 525 }) 526 message := "m" 527 content := []byte("c") 528 repositoryContentsOptions := &RepositoryContentFileOptions{ 529 Message: &message, 530 Content: content, 531 Committer: &CommitAuthor{Name: String("n"), Email: String("e")}, 532 } 533 ctx := context.Background() 534 createResponse, _, err := client.Repositories.CreateFile(ctx, "o", "r", "p", repositoryContentsOptions) 535 if err != nil { 536 t.Errorf("Repositories.CreateFile returned error: %v", err) 537 } 538 want := &RepositoryContentResponse{ 539 Content: &RepositoryContent{Name: String("p")}, 540 Commit: Commit{ 541 Message: String("m"), 542 SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"), 543 }, 544 } 545 if !cmp.Equal(createResponse, want) { 546 t.Errorf("Repositories.CreateFile returned %+v, want %+v", createResponse, want) 547 } 548 549 const methodName = "CreateFile" 550 testBadOptions(t, methodName, func() (err error) { 551 _, _, err = client.Repositories.CreateFile(ctx, "\n", "\n", "\n", repositoryContentsOptions) 552 return err 553 }) 554 555 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 556 got, resp, err := client.Repositories.CreateFile(ctx, "o", "r", "p", repositoryContentsOptions) 557 if got != nil { 558 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 559 } 560 return resp, err 561 }) 562 } 563 564 func TestRepositoriesService_UpdateFile(t *testing.T) { 565 client, mux, _, teardown := setup() 566 defer teardown() 567 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 568 testMethod(t, r, "PUT") 569 fmt.Fprint(w, `{ 570 "content":{ 571 "name":"p" 572 }, 573 "commit":{ 574 "message":"m", 575 "sha":"f5f369044773ff9c6383c087466d12adb6fa0828" 576 } 577 }`) 578 }) 579 message := "m" 580 content := []byte("c") 581 sha := "f5f369044773ff9c6383c087466d12adb6fa0828" 582 repositoryContentsOptions := &RepositoryContentFileOptions{ 583 Message: &message, 584 Content: content, 585 SHA: &sha, 586 Committer: &CommitAuthor{Name: String("n"), Email: String("e")}, 587 } 588 ctx := context.Background() 589 updateResponse, _, err := client.Repositories.UpdateFile(ctx, "o", "r", "p", repositoryContentsOptions) 590 if err != nil { 591 t.Errorf("Repositories.UpdateFile returned error: %v", err) 592 } 593 want := &RepositoryContentResponse{ 594 Content: &RepositoryContent{Name: String("p")}, 595 Commit: Commit{ 596 Message: String("m"), 597 SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"), 598 }, 599 } 600 if !cmp.Equal(updateResponse, want) { 601 t.Errorf("Repositories.UpdateFile returned %+v, want %+v", updateResponse, want) 602 } 603 604 const methodName = "UpdateFile" 605 testBadOptions(t, methodName, func() (err error) { 606 _, _, err = client.Repositories.UpdateFile(ctx, "\n", "\n", "\n", repositoryContentsOptions) 607 return err 608 }) 609 610 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 611 got, resp, err := client.Repositories.UpdateFile(ctx, "o", "r", "p", repositoryContentsOptions) 612 if got != nil { 613 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 614 } 615 return resp, err 616 }) 617 } 618 619 func TestRepositoriesService_DeleteFile(t *testing.T) { 620 client, mux, _, teardown := setup() 621 defer teardown() 622 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 623 testMethod(t, r, "DELETE") 624 fmt.Fprint(w, `{ 625 "content": null, 626 "commit":{ 627 "message":"m", 628 "sha":"f5f369044773ff9c6383c087466d12adb6fa0828" 629 } 630 }`) 631 }) 632 message := "m" 633 sha := "f5f369044773ff9c6383c087466d12adb6fa0828" 634 repositoryContentsOptions := &RepositoryContentFileOptions{ 635 Message: &message, 636 SHA: &sha, 637 Committer: &CommitAuthor{Name: String("n"), Email: String("e")}, 638 } 639 ctx := context.Background() 640 deleteResponse, _, err := client.Repositories.DeleteFile(ctx, "o", "r", "p", repositoryContentsOptions) 641 if err != nil { 642 t.Errorf("Repositories.DeleteFile returned error: %v", err) 643 } 644 want := &RepositoryContentResponse{ 645 Content: nil, 646 Commit: Commit{ 647 Message: String("m"), 648 SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"), 649 }, 650 } 651 if !cmp.Equal(deleteResponse, want) { 652 t.Errorf("Repositories.DeleteFile returned %+v, want %+v", deleteResponse, want) 653 } 654 655 const methodName = "DeleteFile" 656 testBadOptions(t, methodName, func() (err error) { 657 _, _, err = client.Repositories.DeleteFile(ctx, "\n", "\n", "\n", repositoryContentsOptions) 658 return err 659 }) 660 661 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 662 got, resp, err := client.Repositories.DeleteFile(ctx, "o", "r", "p", repositoryContentsOptions) 663 if got != nil { 664 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 665 } 666 return resp, err 667 }) 668 } 669 670 func TestRepositoriesService_GetArchiveLink(t *testing.T) { 671 client, mux, _, teardown := setup() 672 defer teardown() 673 mux.HandleFunc("/repos/o/r/tarball/yo", func(w http.ResponseWriter, r *http.Request) { 674 testMethod(t, r, "GET") 675 http.Redirect(w, r, "http://github.com/a", http.StatusFound) 676 }) 677 ctx := context.Background() 678 url, resp, err := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{Ref: "yo"}, true) 679 if err != nil { 680 t.Errorf("Repositories.GetArchiveLink returned error: %v", err) 681 } 682 if resp.StatusCode != http.StatusFound { 683 t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusFound) 684 } 685 want := "http://github.com/a" 686 if url.String() != want { 687 t.Errorf("Repositories.GetArchiveLink returned %+v, want %+v", url.String(), want) 688 } 689 690 const methodName = "GetArchiveLink" 691 testBadOptions(t, methodName, func() (err error) { 692 _, _, err = client.Repositories.GetArchiveLink(ctx, "\n", "\n", Tarball, &RepositoryContentGetOptions{}, true) 693 return err 694 }) 695 696 // Add custom round tripper 697 client.client.Transport = roundTripperFunc(func(r *http.Request) (*http.Response, error) { 698 return nil, errors.New("failed to get archive link") 699 }) 700 testBadOptions(t, methodName, func() (err error) { 701 _, _, err = client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, true) 702 return err 703 }) 704 } 705 706 func TestRepositoriesService_GetArchiveLink_StatusMovedPermanently_dontFollowRedirects(t *testing.T) { 707 client, mux, _, teardown := setup() 708 defer teardown() 709 mux.HandleFunc("/repos/o/r/tarball", func(w http.ResponseWriter, r *http.Request) { 710 testMethod(t, r, "GET") 711 http.Redirect(w, r, "http://github.com/a", http.StatusMovedPermanently) 712 }) 713 ctx := context.Background() 714 _, resp, _ := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, false) 715 if resp.StatusCode != http.StatusMovedPermanently { 716 t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusMovedPermanently) 717 } 718 } 719 720 func TestRepositoriesService_GetArchiveLink_StatusMovedPermanently_followRedirects(t *testing.T) { 721 client, mux, serverURL, teardown := setup() 722 defer teardown() 723 // Mock a redirect link, which leads to an archive link 724 mux.HandleFunc("/repos/o/r/tarball", func(w http.ResponseWriter, r *http.Request) { 725 testMethod(t, r, "GET") 726 redirectURL, _ := url.Parse(serverURL + baseURLPath + "/redirect") 727 http.Redirect(w, r, redirectURL.String(), http.StatusMovedPermanently) 728 }) 729 mux.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) { 730 testMethod(t, r, "GET") 731 http.Redirect(w, r, "http://github.com/a", http.StatusFound) 732 }) 733 ctx := context.Background() 734 url, resp, err := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, true) 735 if err != nil { 736 t.Errorf("Repositories.GetArchiveLink returned error: %v", err) 737 } 738 if resp.StatusCode != http.StatusFound { 739 t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusFound) 740 } 741 want := "http://github.com/a" 742 if url.String() != want { 743 t.Errorf("Repositories.GetArchiveLink returned %+v, want %+v", url.String(), want) 744 } 745 } 746 747 func TestRepositoriesService_GetArchiveLink_invalidLocationHeader(t *testing.T) { 748 client, mux, _, teardown := setup() 749 defer teardown() 750 751 mux.HandleFunc("/repos/o/r/tarball", func(w http.ResponseWriter, r *http.Request) { 752 testMethod(t, r, "GET") 753 ctlChar := 0x7f 754 badURL := "https://google.com" + string(byte(ctlChar)) 755 w.Header().Add("Location", badURL) 756 w.WriteHeader(http.StatusFound) 757 }) 758 759 ctx := context.Background() 760 _, _, err := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, false) 761 testURLParseError(t, err) 762 } 763 764 func TestRepositoriesService_GetContents_NoTrailingSlashInDirectoryApiPath(t *testing.T) { 765 client, mux, _, teardown := setup() 766 defer teardown() 767 mux.HandleFunc("/repos/o/r/contents/.github", func(w http.ResponseWriter, r *http.Request) { 768 testMethod(t, r, "GET") 769 query := r.URL.Query() 770 if query.Get("ref") != "mybranch" { 771 t.Errorf("Repositories.GetContents returned %+v, want %+v", query.Get("ref"), "mybranch") 772 } 773 fmt.Fprint(w, `{}`) 774 }) 775 ctx := context.Background() 776 _, _, _, err := client.Repositories.GetContents(ctx, "o", "r", ".github/", &RepositoryContentGetOptions{ 777 Ref: "mybranch", 778 }) 779 if err != nil { 780 t.Fatalf("Repositories.GetContents returned error: %v", err) 781 } 782 } 783 784 func TestRepositoryContent_Marshal(t *testing.T) { 785 testJSONMarshal(t, &RepositoryContent{}, "{}") 786 787 r := &RepositoryContent{ 788 Type: String("type"), 789 Target: String("target"), 790 Encoding: String("encoding"), 791 Size: Int(1), 792 Name: String("name"), 793 Path: String("path"), 794 Content: String("content"), 795 SHA: String("sha"), 796 URL: String("url"), 797 GitURL: String("gurl"), 798 HTMLURL: String("hurl"), 799 DownloadURL: String("durl"), 800 } 801 802 want := `{ 803 "type": "type", 804 "target": "target", 805 "encoding": "encoding", 806 "size": 1, 807 "name": "name", 808 "path": "path", 809 "content": "content", 810 "sha": "sha", 811 "url": "url", 812 "git_url": "gurl", 813 "html_url": "hurl", 814 "download_url": "durl" 815 }` 816 817 testJSONMarshal(t, r, want) 818 } 819 820 func TestRepositoryContentResponse_Marshal(t *testing.T) { 821 testJSONMarshal(t, &RepositoryContentResponse{}, "{}") 822 823 r := &RepositoryContentResponse{ 824 Content: &RepositoryContent{ 825 Type: String("type"), 826 Target: String("target"), 827 Encoding: String("encoding"), 828 Size: Int(1), 829 Name: String("name"), 830 Path: String("path"), 831 Content: String("content"), 832 SHA: String("sha"), 833 URL: String("url"), 834 GitURL: String("gurl"), 835 HTMLURL: String("hurl"), 836 DownloadURL: String("durl"), 837 }, 838 Commit: Commit{ 839 SHA: String("s"), 840 Author: &CommitAuthor{ 841 Date: &referenceTime, 842 Name: String("n"), 843 Email: String("e"), 844 Login: String("u"), 845 }, 846 Committer: &CommitAuthor{ 847 Date: &referenceTime, 848 Name: String("n"), 849 Email: String("e"), 850 Login: String("u"), 851 }, 852 Message: String("m"), 853 Tree: &Tree{ 854 SHA: String("s"), 855 Entries: []*TreeEntry{{ 856 SHA: String("s"), 857 Path: String("p"), 858 Mode: String("m"), 859 Type: String("t"), 860 Size: Int(1), 861 Content: String("c"), 862 URL: String("u"), 863 }}, 864 Truncated: Bool(false), 865 }, 866 Parents: nil, 867 Stats: &CommitStats{ 868 Additions: Int(1), 869 Deletions: Int(1), 870 Total: Int(1), 871 }, 872 HTMLURL: String("h"), 873 URL: String("u"), 874 Verification: &SignatureVerification{ 875 Verified: Bool(false), 876 Reason: String("r"), 877 Signature: String("s"), 878 Payload: String("p"), 879 }, 880 NodeID: String("n"), 881 CommentCount: Int(1), 882 SigningKey: &openpgp.Entity{}, 883 }, 884 } 885 886 want := `{ 887 "content": { 888 "type": "type", 889 "target": "target", 890 "encoding": "encoding", 891 "size": 1, 892 "name": "name", 893 "path": "path", 894 "content": "content", 895 "sha": "sha", 896 "url": "url", 897 "git_url": "gurl", 898 "html_url": "hurl", 899 "download_url": "durl" 900 }, 901 "commit": { 902 "sha": "s", 903 "author": { 904 "date": ` + referenceTimeStr + `, 905 "name": "n", 906 "email": "e", 907 "username": "u" 908 }, 909 "committer": { 910 "date": ` + referenceTimeStr + `, 911 "name": "n", 912 "email": "e", 913 "username": "u" 914 }, 915 "message": "m", 916 "tree": { 917 "sha": "s", 918 "tree": [ 919 { 920 "sha": "s", 921 "path": "p", 922 "mode": "m", 923 "type": "t", 924 "size": 1, 925 "content": "c", 926 "url": "u" 927 } 928 ], 929 "truncated": false 930 }, 931 "stats": { 932 "additions": 1, 933 "deletions": 1, 934 "total": 1 935 }, 936 "html_url": "h", 937 "url": "u", 938 "verification": { 939 "verified": false, 940 "reason": "r", 941 "signature": "s", 942 "payload": "p" 943 }, 944 "node_id": "n", 945 "comment_count": 1 946 } 947 }` 948 949 testJSONMarshal(t, r, want) 950 } 951 952 func TestRepositoryContentFileOptions_Marshal(t *testing.T) { 953 testJSONMarshal(t, &RepositoryContentFileOptions{}, "{}") 954 955 r := &RepositoryContentFileOptions{ 956 Message: String("type"), 957 Content: []byte{1}, 958 SHA: String("type"), 959 Branch: String("type"), 960 Author: &CommitAuthor{ 961 Date: &referenceTime, 962 Name: String("name"), 963 Email: String("email"), 964 Login: String("login"), 965 }, 966 Committer: &CommitAuthor{ 967 Date: &referenceTime, 968 Name: String("name"), 969 Email: String("email"), 970 Login: String("login"), 971 }, 972 } 973 974 want := `{ 975 "message": "type", 976 "content": "AQ==", 977 "sha": "type", 978 "branch": "type", 979 "author": { 980 "date": ` + referenceTimeStr + `, 981 "name": "name", 982 "email": "email", 983 "username": "login" 984 }, 985 "committer": { 986 "date": ` + referenceTimeStr + `, 987 "name": "name", 988 "email": "email", 989 "username": "login" 990 } 991 }` 992 993 testJSONMarshal(t, r, want) 994 }