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