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