github.com/google/go-github/v53@v53.2.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/ProtonMail/go-crypto/openpgp" 18 "github.com/google/go-cmp/cmp" 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_PathWithParent(t *testing.T) { 469 client, mux, _, teardown := setup() 470 defer teardown() 471 mux.HandleFunc("/repos/o/r/contents/some/../directory/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/file.go", &RepositoryContentGetOptions{}) 477 if err == nil { 478 t.Fatal("Repositories.GetContents expected error but got none") 479 } 480 } 481 482 func TestRepositoriesService_GetContents_DirectoryWithPlusChars(t *testing.T) { 483 client, mux, _, teardown := setup() 484 defer teardown() 485 mux.HandleFunc("/repos/o/r/contents/some directory+name/file.go", func(w http.ResponseWriter, r *http.Request) { 486 testMethod(t, r, "GET") 487 fmt.Fprint(w, `{}`) 488 }) 489 ctx := context.Background() 490 _, _, _, err := client.Repositories.GetContents(ctx, "o", "r", "some directory+name/file.go", &RepositoryContentGetOptions{}) 491 if err != nil { 492 t.Fatalf("Repositories.GetContents returned error: %v", err) 493 } 494 } 495 496 func TestRepositoriesService_GetContents_Directory(t *testing.T) { 497 client, mux, _, teardown := setup() 498 defer teardown() 499 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 500 testMethod(t, r, "GET") 501 fmt.Fprint(w, `[{ 502 "type": "dir", 503 "name": "lib", 504 "path": "lib" 505 }, 506 { 507 "type": "file", 508 "size": 20678, 509 "name": "LICENSE", 510 "path": "LICENSE" 511 }]`) 512 }) 513 ctx := context.Background() 514 _, directoryContents, _, err := client.Repositories.GetContents(ctx, "o", "r", "p", &RepositoryContentGetOptions{}) 515 if err != nil { 516 t.Errorf("Repositories.GetContents returned error: %v", err) 517 } 518 want := []*RepositoryContent{{Type: String("dir"), Name: String("lib"), Path: String("lib")}, 519 {Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Path: String("LICENSE")}} 520 if !cmp.Equal(directoryContents, want) { 521 t.Errorf("Repositories.GetContents_Directory returned %+v, want %+v", directoryContents, want) 522 } 523 } 524 525 func TestRepositoriesService_CreateFile(t *testing.T) { 526 client, mux, _, teardown := setup() 527 defer teardown() 528 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 529 testMethod(t, r, "PUT") 530 fmt.Fprint(w, `{ 531 "content":{ 532 "name":"p" 533 }, 534 "commit":{ 535 "message":"m", 536 "sha":"f5f369044773ff9c6383c087466d12adb6fa0828" 537 } 538 }`) 539 }) 540 message := "m" 541 content := []byte("c") 542 repositoryContentsOptions := &RepositoryContentFileOptions{ 543 Message: &message, 544 Content: content, 545 Committer: &CommitAuthor{Name: String("n"), Email: String("e")}, 546 } 547 ctx := context.Background() 548 createResponse, _, err := client.Repositories.CreateFile(ctx, "o", "r", "p", repositoryContentsOptions) 549 if err != nil { 550 t.Errorf("Repositories.CreateFile returned error: %v", err) 551 } 552 want := &RepositoryContentResponse{ 553 Content: &RepositoryContent{Name: String("p")}, 554 Commit: Commit{ 555 Message: String("m"), 556 SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"), 557 }, 558 } 559 if !cmp.Equal(createResponse, want) { 560 t.Errorf("Repositories.CreateFile returned %+v, want %+v", createResponse, want) 561 } 562 563 const methodName = "CreateFile" 564 testBadOptions(t, methodName, func() (err error) { 565 _, _, err = client.Repositories.CreateFile(ctx, "\n", "\n", "\n", repositoryContentsOptions) 566 return err 567 }) 568 569 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 570 got, resp, err := client.Repositories.CreateFile(ctx, "o", "r", "p", repositoryContentsOptions) 571 if got != nil { 572 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 573 } 574 return resp, err 575 }) 576 } 577 578 func TestRepositoriesService_UpdateFile(t *testing.T) { 579 client, mux, _, teardown := setup() 580 defer teardown() 581 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 582 testMethod(t, r, "PUT") 583 fmt.Fprint(w, `{ 584 "content":{ 585 "name":"p" 586 }, 587 "commit":{ 588 "message":"m", 589 "sha":"f5f369044773ff9c6383c087466d12adb6fa0828" 590 } 591 }`) 592 }) 593 message := "m" 594 content := []byte("c") 595 sha := "f5f369044773ff9c6383c087466d12adb6fa0828" 596 repositoryContentsOptions := &RepositoryContentFileOptions{ 597 Message: &message, 598 Content: content, 599 SHA: &sha, 600 Committer: &CommitAuthor{Name: String("n"), Email: String("e")}, 601 } 602 ctx := context.Background() 603 updateResponse, _, err := client.Repositories.UpdateFile(ctx, "o", "r", "p", repositoryContentsOptions) 604 if err != nil { 605 t.Errorf("Repositories.UpdateFile returned error: %v", err) 606 } 607 want := &RepositoryContentResponse{ 608 Content: &RepositoryContent{Name: String("p")}, 609 Commit: Commit{ 610 Message: String("m"), 611 SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"), 612 }, 613 } 614 if !cmp.Equal(updateResponse, want) { 615 t.Errorf("Repositories.UpdateFile returned %+v, want %+v", updateResponse, want) 616 } 617 618 const methodName = "UpdateFile" 619 testBadOptions(t, methodName, func() (err error) { 620 _, _, err = client.Repositories.UpdateFile(ctx, "\n", "\n", "\n", repositoryContentsOptions) 621 return err 622 }) 623 624 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 625 got, resp, err := client.Repositories.UpdateFile(ctx, "o", "r", "p", repositoryContentsOptions) 626 if got != nil { 627 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 628 } 629 return resp, err 630 }) 631 } 632 633 func TestRepositoriesService_DeleteFile(t *testing.T) { 634 client, mux, _, teardown := setup() 635 defer teardown() 636 mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) { 637 testMethod(t, r, "DELETE") 638 fmt.Fprint(w, `{ 639 "content": null, 640 "commit":{ 641 "message":"m", 642 "sha":"f5f369044773ff9c6383c087466d12adb6fa0828" 643 } 644 }`) 645 }) 646 message := "m" 647 sha := "f5f369044773ff9c6383c087466d12adb6fa0828" 648 repositoryContentsOptions := &RepositoryContentFileOptions{ 649 Message: &message, 650 SHA: &sha, 651 Committer: &CommitAuthor{Name: String("n"), Email: String("e")}, 652 } 653 ctx := context.Background() 654 deleteResponse, _, err := client.Repositories.DeleteFile(ctx, "o", "r", "p", repositoryContentsOptions) 655 if err != nil { 656 t.Errorf("Repositories.DeleteFile returned error: %v", err) 657 } 658 want := &RepositoryContentResponse{ 659 Content: nil, 660 Commit: Commit{ 661 Message: String("m"), 662 SHA: String("f5f369044773ff9c6383c087466d12adb6fa0828"), 663 }, 664 } 665 if !cmp.Equal(deleteResponse, want) { 666 t.Errorf("Repositories.DeleteFile returned %+v, want %+v", deleteResponse, want) 667 } 668 669 const methodName = "DeleteFile" 670 testBadOptions(t, methodName, func() (err error) { 671 _, _, err = client.Repositories.DeleteFile(ctx, "\n", "\n", "\n", repositoryContentsOptions) 672 return err 673 }) 674 675 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 676 got, resp, err := client.Repositories.DeleteFile(ctx, "o", "r", "p", repositoryContentsOptions) 677 if got != nil { 678 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 679 } 680 return resp, err 681 }) 682 } 683 684 func TestRepositoriesService_GetArchiveLink(t *testing.T) { 685 client, mux, _, teardown := setup() 686 defer teardown() 687 mux.HandleFunc("/repos/o/r/tarball/yo", func(w http.ResponseWriter, r *http.Request) { 688 testMethod(t, r, "GET") 689 http.Redirect(w, r, "http://github.com/a", http.StatusFound) 690 }) 691 ctx := context.Background() 692 url, resp, err := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{Ref: "yo"}, true) 693 if err != nil { 694 t.Errorf("Repositories.GetArchiveLink returned error: %v", err) 695 } 696 if resp.StatusCode != http.StatusFound { 697 t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusFound) 698 } 699 want := "http://github.com/a" 700 if url.String() != want { 701 t.Errorf("Repositories.GetArchiveLink returned %+v, want %+v", url.String(), want) 702 } 703 704 const methodName = "GetArchiveLink" 705 testBadOptions(t, methodName, func() (err error) { 706 _, _, err = client.Repositories.GetArchiveLink(ctx, "\n", "\n", Tarball, &RepositoryContentGetOptions{}, true) 707 return err 708 }) 709 710 // Add custom round tripper 711 client.client.Transport = roundTripperFunc(func(r *http.Request) (*http.Response, error) { 712 return nil, errors.New("failed to get archive link") 713 }) 714 testBadOptions(t, methodName, func() (err error) { 715 _, _, err = client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, true) 716 return err 717 }) 718 } 719 720 func TestRepositoriesService_GetArchiveLink_StatusMovedPermanently_dontFollowRedirects(t *testing.T) { 721 client, mux, _, teardown := setup() 722 defer teardown() 723 mux.HandleFunc("/repos/o/r/tarball", func(w http.ResponseWriter, r *http.Request) { 724 testMethod(t, r, "GET") 725 http.Redirect(w, r, "http://github.com/a", http.StatusMovedPermanently) 726 }) 727 ctx := context.Background() 728 _, resp, _ := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, false) 729 if resp.StatusCode != http.StatusMovedPermanently { 730 t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusMovedPermanently) 731 } 732 } 733 734 func TestRepositoriesService_GetArchiveLink_StatusMovedPermanently_followRedirects(t *testing.T) { 735 client, mux, serverURL, teardown := setup() 736 defer teardown() 737 // Mock a redirect link, which leads to an archive link 738 mux.HandleFunc("/repos/o/r/tarball", func(w http.ResponseWriter, r *http.Request) { 739 testMethod(t, r, "GET") 740 redirectURL, _ := url.Parse(serverURL + baseURLPath + "/redirect") 741 http.Redirect(w, r, redirectURL.String(), http.StatusMovedPermanently) 742 }) 743 mux.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) { 744 testMethod(t, r, "GET") 745 http.Redirect(w, r, "http://github.com/a", http.StatusFound) 746 }) 747 ctx := context.Background() 748 url, resp, err := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, true) 749 if err != nil { 750 t.Errorf("Repositories.GetArchiveLink returned error: %v", err) 751 } 752 if resp.StatusCode != http.StatusFound { 753 t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusFound) 754 } 755 want := "http://github.com/a" 756 if url.String() != want { 757 t.Errorf("Repositories.GetArchiveLink returned %+v, want %+v", url.String(), want) 758 } 759 } 760 761 func TestRepositoriesService_GetContents_NoTrailingSlashInDirectoryApiPath(t *testing.T) { 762 client, mux, _, teardown := setup() 763 defer teardown() 764 mux.HandleFunc("/repos/o/r/contents/.github", func(w http.ResponseWriter, r *http.Request) { 765 testMethod(t, r, "GET") 766 query := r.URL.Query() 767 if query.Get("ref") != "mybranch" { 768 t.Errorf("Repositories.GetContents returned %+v, want %+v", query.Get("ref"), "mybranch") 769 } 770 fmt.Fprint(w, `{}`) 771 }) 772 ctx := context.Background() 773 _, _, _, err := client.Repositories.GetContents(ctx, "o", "r", ".github/", &RepositoryContentGetOptions{ 774 Ref: "mybranch", 775 }) 776 if err != nil { 777 t.Fatalf("Repositories.GetContents returned error: %v", err) 778 } 779 } 780 781 func TestRepositoryContent_Marshal(t *testing.T) { 782 testJSONMarshal(t, &RepositoryContent{}, "{}") 783 784 r := &RepositoryContent{ 785 Type: String("type"), 786 Target: String("target"), 787 Encoding: String("encoding"), 788 Size: Int(1), 789 Name: String("name"), 790 Path: String("path"), 791 Content: String("content"), 792 SHA: String("sha"), 793 URL: String("url"), 794 GitURL: String("gurl"), 795 HTMLURL: String("hurl"), 796 DownloadURL: String("durl"), 797 } 798 799 want := `{ 800 "type": "type", 801 "target": "target", 802 "encoding": "encoding", 803 "size": 1, 804 "name": "name", 805 "path": "path", 806 "content": "content", 807 "sha": "sha", 808 "url": "url", 809 "git_url": "gurl", 810 "html_url": "hurl", 811 "download_url": "durl" 812 }` 813 814 testJSONMarshal(t, r, want) 815 } 816 817 func TestRepositoryContentResponse_Marshal(t *testing.T) { 818 testJSONMarshal(t, &RepositoryContentResponse{}, "{}") 819 820 r := &RepositoryContentResponse{ 821 Content: &RepositoryContent{ 822 Type: String("type"), 823 Target: String("target"), 824 Encoding: String("encoding"), 825 Size: Int(1), 826 Name: String("name"), 827 Path: String("path"), 828 Content: String("content"), 829 SHA: String("sha"), 830 URL: String("url"), 831 GitURL: String("gurl"), 832 HTMLURL: String("hurl"), 833 DownloadURL: String("durl"), 834 }, 835 Commit: Commit{ 836 SHA: String("s"), 837 Author: &CommitAuthor{ 838 Date: &Timestamp{referenceTime}, 839 Name: String("n"), 840 Email: String("e"), 841 Login: String("u"), 842 }, 843 Committer: &CommitAuthor{ 844 Date: &Timestamp{referenceTime}, 845 Name: String("n"), 846 Email: String("e"), 847 Login: String("u"), 848 }, 849 Message: String("m"), 850 Tree: &Tree{ 851 SHA: String("s"), 852 Entries: []*TreeEntry{{ 853 SHA: String("s"), 854 Path: String("p"), 855 Mode: String("m"), 856 Type: String("t"), 857 Size: Int(1), 858 Content: String("c"), 859 URL: String("u"), 860 }}, 861 Truncated: Bool(false), 862 }, 863 Parents: nil, 864 Stats: &CommitStats{ 865 Additions: Int(1), 866 Deletions: Int(1), 867 Total: Int(1), 868 }, 869 HTMLURL: String("h"), 870 URL: String("u"), 871 Verification: &SignatureVerification{ 872 Verified: Bool(false), 873 Reason: String("r"), 874 Signature: String("s"), 875 Payload: String("p"), 876 }, 877 NodeID: String("n"), 878 CommentCount: Int(1), 879 SigningKey: &openpgp.Entity{}, 880 }, 881 } 882 883 want := `{ 884 "content": { 885 "type": "type", 886 "target": "target", 887 "encoding": "encoding", 888 "size": 1, 889 "name": "name", 890 "path": "path", 891 "content": "content", 892 "sha": "sha", 893 "url": "url", 894 "git_url": "gurl", 895 "html_url": "hurl", 896 "download_url": "durl" 897 }, 898 "commit": { 899 "sha": "s", 900 "author": { 901 "date": ` + referenceTimeStr + `, 902 "name": "n", 903 "email": "e", 904 "username": "u" 905 }, 906 "committer": { 907 "date": ` + referenceTimeStr + `, 908 "name": "n", 909 "email": "e", 910 "username": "u" 911 }, 912 "message": "m", 913 "tree": { 914 "sha": "s", 915 "tree": [ 916 { 917 "sha": "s", 918 "path": "p", 919 "mode": "m", 920 "type": "t", 921 "size": 1, 922 "content": "c", 923 "url": "u" 924 } 925 ], 926 "truncated": false 927 }, 928 "stats": { 929 "additions": 1, 930 "deletions": 1, 931 "total": 1 932 }, 933 "html_url": "h", 934 "url": "u", 935 "verification": { 936 "verified": false, 937 "reason": "r", 938 "signature": "s", 939 "payload": "p" 940 }, 941 "node_id": "n", 942 "comment_count": 1 943 } 944 }` 945 946 testJSONMarshal(t, r, want) 947 } 948 949 func TestRepositoryContentFileOptions_Marshal(t *testing.T) { 950 testJSONMarshal(t, &RepositoryContentFileOptions{}, "{}") 951 952 r := &RepositoryContentFileOptions{ 953 Message: String("type"), 954 Content: []byte{1}, 955 SHA: String("type"), 956 Branch: String("type"), 957 Author: &CommitAuthor{ 958 Date: &Timestamp{referenceTime}, 959 Name: String("name"), 960 Email: String("email"), 961 Login: String("login"), 962 }, 963 Committer: &CommitAuthor{ 964 Date: &Timestamp{referenceTime}, 965 Name: String("name"), 966 Email: String("email"), 967 Login: String("login"), 968 }, 969 } 970 971 want := `{ 972 "message": "type", 973 "content": "AQ==", 974 "sha": "type", 975 "branch": "type", 976 "author": { 977 "date": ` + referenceTimeStr + `, 978 "name": "name", 979 "email": "email", 980 "username": "login" 981 }, 982 "committer": { 983 "date": ` + referenceTimeStr + `, 984 "name": "name", 985 "email": "email", 986 "username": "login" 987 } 988 }` 989 990 testJSONMarshal(t, r, want) 991 }