github.com/google/go-github/v42@v42.0.0/github/repos_releases_test.go (about) 1 // Copyright 2013 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 "bytes" 10 "context" 11 "encoding/json" 12 "fmt" 13 "io/ioutil" 14 "net/http" 15 "os" 16 "strings" 17 "testing" 18 19 "github.com/google/go-cmp/cmp" 20 ) 21 22 func TestRepositoriesService_ListReleases(t *testing.T) { 23 client, mux, _, teardown := setup() 24 defer teardown() 25 26 mux.HandleFunc("/repos/o/r/releases", func(w http.ResponseWriter, r *http.Request) { 27 testMethod(t, r, "GET") 28 testFormValues(t, r, values{"page": "2"}) 29 fmt.Fprint(w, `[{"id":1}]`) 30 }) 31 32 opt := &ListOptions{Page: 2} 33 ctx := context.Background() 34 releases, _, err := client.Repositories.ListReleases(ctx, "o", "r", opt) 35 if err != nil { 36 t.Errorf("Repositories.ListReleases returned error: %v", err) 37 } 38 want := []*RepositoryRelease{{ID: Int64(1)}} 39 if !cmp.Equal(releases, want) { 40 t.Errorf("Repositories.ListReleases returned %+v, want %+v", releases, want) 41 } 42 43 const methodName = "ListReleases" 44 testBadOptions(t, methodName, func() (err error) { 45 _, _, err = client.Repositories.ListReleases(ctx, "\n", "\n", opt) 46 return err 47 }) 48 49 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 50 got, resp, err := client.Repositories.ListReleases(ctx, "o", "r", opt) 51 if got != nil { 52 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 53 } 54 return resp, err 55 }) 56 } 57 58 func TestRepositoriesService_GenerateReleaseNotes(t *testing.T) { 59 client, mux, _, teardown := setup() 60 defer teardown() 61 62 mux.HandleFunc("/repos/o/r/releases/generate-notes", func(w http.ResponseWriter, r *http.Request) { 63 testMethod(t, r, "POST") 64 testBody(t, r, `{"tag_name":"v1.0.0"}`+"\n") 65 fmt.Fprint(w, `{"name":"v1.0.0","body":"**Full Changelog**: https://github.com/o/r/compare/v0.9.0...v1.0.0"}`) 66 }) 67 68 opt := &GenerateNotesOptions{ 69 TagName: "v1.0.0", 70 } 71 ctx := context.Background() 72 releases, _, err := client.Repositories.GenerateReleaseNotes(ctx, "o", "r", opt) 73 if err != nil { 74 t.Errorf("Repositories.GenerateReleaseNotes returned error: %v", err) 75 } 76 want := &RepositoryReleaseNotes{ 77 Name: "v1.0.0", 78 Body: "**Full Changelog**: https://github.com/o/r/compare/v0.9.0...v1.0.0", 79 } 80 if !cmp.Equal(releases, want) { 81 t.Errorf("Repositories.GenerateReleaseNotes returned %+v, want %+v", releases, want) 82 } 83 84 const methodName = "GenerateReleaseNotes" 85 testBadOptions(t, methodName, func() (err error) { 86 _, _, err = client.Repositories.GenerateReleaseNotes(ctx, "\n", "\n", opt) 87 return err 88 }) 89 90 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 91 got, resp, err := client.Repositories.GenerateReleaseNotes(ctx, "o", "r", opt) 92 if got != nil { 93 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 94 } 95 return resp, err 96 }) 97 } 98 99 func TestRepositoriesService_GetRelease(t *testing.T) { 100 client, mux, _, teardown := setup() 101 defer teardown() 102 103 mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) { 104 testMethod(t, r, "GET") 105 fmt.Fprint(w, `{"id":1,"author":{"login":"l"}}`) 106 }) 107 108 ctx := context.Background() 109 release, resp, err := client.Repositories.GetRelease(ctx, "o", "r", 1) 110 if err != nil { 111 t.Errorf("Repositories.GetRelease returned error: %v\n%v", err, resp.Body) 112 } 113 114 want := &RepositoryRelease{ID: Int64(1), Author: &User{Login: String("l")}} 115 if !cmp.Equal(release, want) { 116 t.Errorf("Repositories.GetRelease returned %+v, want %+v", release, want) 117 } 118 119 const methodName = "GetRelease" 120 testBadOptions(t, methodName, func() (err error) { 121 _, _, err = client.Repositories.GetRelease(ctx, "\n", "\n", 1) 122 return err 123 }) 124 125 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 126 got, resp, err := client.Repositories.GetRelease(ctx, "o", "r", 1) 127 if got != nil { 128 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 129 } 130 return resp, err 131 }) 132 } 133 134 func TestRepositoriesService_GetLatestRelease(t *testing.T) { 135 client, mux, _, teardown := setup() 136 defer teardown() 137 138 mux.HandleFunc("/repos/o/r/releases/latest", func(w http.ResponseWriter, r *http.Request) { 139 testMethod(t, r, "GET") 140 fmt.Fprint(w, `{"id":3}`) 141 }) 142 143 ctx := context.Background() 144 release, resp, err := client.Repositories.GetLatestRelease(ctx, "o", "r") 145 if err != nil { 146 t.Errorf("Repositories.GetLatestRelease returned error: %v\n%v", err, resp.Body) 147 } 148 149 want := &RepositoryRelease{ID: Int64(3)} 150 if !cmp.Equal(release, want) { 151 t.Errorf("Repositories.GetLatestRelease returned %+v, want %+v", release, want) 152 } 153 154 const methodName = "GetLatestRelease" 155 testBadOptions(t, methodName, func() (err error) { 156 _, _, err = client.Repositories.GetLatestRelease(ctx, "\n", "\n") 157 return err 158 }) 159 160 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 161 got, resp, err := client.Repositories.GetLatestRelease(ctx, "o", "r") 162 if got != nil { 163 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 164 } 165 return resp, err 166 }) 167 } 168 169 func TestRepositoriesService_GetReleaseByTag(t *testing.T) { 170 client, mux, _, teardown := setup() 171 defer teardown() 172 173 mux.HandleFunc("/repos/o/r/releases/tags/foo", func(w http.ResponseWriter, r *http.Request) { 174 testMethod(t, r, "GET") 175 fmt.Fprint(w, `{"id":13}`) 176 }) 177 178 ctx := context.Background() 179 release, resp, err := client.Repositories.GetReleaseByTag(ctx, "o", "r", "foo") 180 if err != nil { 181 t.Errorf("Repositories.GetReleaseByTag returned error: %v\n%v", err, resp.Body) 182 } 183 184 want := &RepositoryRelease{ID: Int64(13)} 185 if !cmp.Equal(release, want) { 186 t.Errorf("Repositories.GetReleaseByTag returned %+v, want %+v", release, want) 187 } 188 189 const methodName = "GetReleaseByTag" 190 testBadOptions(t, methodName, func() (err error) { 191 _, _, err = client.Repositories.GetReleaseByTag(ctx, "\n", "\n", "foo") 192 return err 193 }) 194 195 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 196 got, resp, err := client.Repositories.GetReleaseByTag(ctx, "o", "r", "foo") 197 if got != nil { 198 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 199 } 200 return resp, err 201 }) 202 } 203 204 func TestRepositoriesService_CreateRelease(t *testing.T) { 205 client, mux, _, teardown := setup() 206 defer teardown() 207 208 input := &RepositoryRelease{ 209 Name: String("v1.0"), 210 DiscussionCategoryName: String("General"), 211 GenerateReleaseNotes: Bool(true), 212 // Fields to be removed: 213 ID: Int64(2), 214 CreatedAt: &Timestamp{referenceTime}, 215 PublishedAt: &Timestamp{referenceTime}, 216 URL: String("http://url/"), 217 HTMLURL: String("http://htmlurl/"), 218 AssetsURL: String("http://assetsurl/"), 219 Assets: []*ReleaseAsset{{ID: Int64(5)}}, 220 UploadURL: String("http://uploadurl/"), 221 ZipballURL: String("http://zipballurl/"), 222 TarballURL: String("http://tarballurl/"), 223 Author: &User{Name: String("octocat")}, 224 NodeID: String("nodeid"), 225 } 226 227 mux.HandleFunc("/repos/o/r/releases", func(w http.ResponseWriter, r *http.Request) { 228 v := new(repositoryReleaseRequest) 229 json.NewDecoder(r.Body).Decode(v) 230 231 testMethod(t, r, "POST") 232 want := &repositoryReleaseRequest{ 233 Name: String("v1.0"), 234 DiscussionCategoryName: String("General"), 235 GenerateReleaseNotes: Bool(true), 236 } 237 if !cmp.Equal(v, want) { 238 t.Errorf("Request body = %+v, want %+v", v, want) 239 } 240 fmt.Fprint(w, `{"id":1}`) 241 }) 242 243 ctx := context.Background() 244 release, _, err := client.Repositories.CreateRelease(ctx, "o", "r", input) 245 if err != nil { 246 t.Errorf("Repositories.CreateRelease returned error: %v", err) 247 } 248 249 want := &RepositoryRelease{ID: Int64(1)} 250 if !cmp.Equal(release, want) { 251 t.Errorf("Repositories.CreateRelease returned %+v, want %+v", release, want) 252 } 253 254 const methodName = "CreateRelease" 255 testBadOptions(t, methodName, func() (err error) { 256 _, _, err = client.Repositories.CreateRelease(ctx, "\n", "\n", input) 257 return err 258 }) 259 260 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 261 got, resp, err := client.Repositories.CreateRelease(ctx, "o", "r", input) 262 if got != nil { 263 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 264 } 265 return resp, err 266 }) 267 } 268 269 func TestRepositoriesService_EditRelease(t *testing.T) { 270 client, mux, _, teardown := setup() 271 defer teardown() 272 273 input := &RepositoryRelease{ 274 Name: String("n"), 275 DiscussionCategoryName: String("General"), 276 GenerateReleaseNotes: Bool(true), 277 // Fields to be removed: 278 ID: Int64(2), 279 CreatedAt: &Timestamp{referenceTime}, 280 PublishedAt: &Timestamp{referenceTime}, 281 URL: String("http://url/"), 282 HTMLURL: String("http://htmlurl/"), 283 AssetsURL: String("http://assetsurl/"), 284 Assets: []*ReleaseAsset{{ID: Int64(5)}}, 285 UploadURL: String("http://uploadurl/"), 286 ZipballURL: String("http://zipballurl/"), 287 TarballURL: String("http://tarballurl/"), 288 Author: &User{Name: String("octocat")}, 289 NodeID: String("nodeid"), 290 } 291 292 mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) { 293 v := new(repositoryReleaseRequest) 294 json.NewDecoder(r.Body).Decode(v) 295 296 testMethod(t, r, "PATCH") 297 want := &repositoryReleaseRequest{ 298 Name: String("n"), 299 DiscussionCategoryName: String("General"), 300 GenerateReleaseNotes: Bool(true), 301 } 302 if !cmp.Equal(v, want) { 303 t.Errorf("Request body = %+v, want %+v", v, want) 304 } 305 fmt.Fprint(w, `{"id":1}`) 306 }) 307 308 ctx := context.Background() 309 release, _, err := client.Repositories.EditRelease(ctx, "o", "r", 1, input) 310 if err != nil { 311 t.Errorf("Repositories.EditRelease returned error: %v", err) 312 } 313 want := &RepositoryRelease{ID: Int64(1)} 314 if !cmp.Equal(release, want) { 315 t.Errorf("Repositories.EditRelease returned = %+v, want %+v", release, want) 316 } 317 318 const methodName = "EditRelease" 319 testBadOptions(t, methodName, func() (err error) { 320 _, _, err = client.Repositories.EditRelease(ctx, "\n", "\n", 1, input) 321 return err 322 }) 323 324 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 325 got, resp, err := client.Repositories.EditRelease(ctx, "o", "r", 1, input) 326 if got != nil { 327 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 328 } 329 return resp, err 330 }) 331 } 332 333 func TestRepositoriesService_DeleteRelease(t *testing.T) { 334 client, mux, _, teardown := setup() 335 defer teardown() 336 337 mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) { 338 testMethod(t, r, "DELETE") 339 }) 340 341 ctx := context.Background() 342 _, err := client.Repositories.DeleteRelease(ctx, "o", "r", 1) 343 if err != nil { 344 t.Errorf("Repositories.DeleteRelease returned error: %v", err) 345 } 346 347 const methodName = "DeleteRelease" 348 testBadOptions(t, methodName, func() (err error) { 349 _, err = client.Repositories.DeleteRelease(ctx, "\n", "\n", 1) 350 return err 351 }) 352 353 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 354 return client.Repositories.DeleteRelease(ctx, "o", "r", 1) 355 }) 356 } 357 358 func TestRepositoriesService_ListReleaseAssets(t *testing.T) { 359 client, mux, _, teardown := setup() 360 defer teardown() 361 362 mux.HandleFunc("/repos/o/r/releases/1/assets", func(w http.ResponseWriter, r *http.Request) { 363 testMethod(t, r, "GET") 364 testFormValues(t, r, values{"page": "2"}) 365 fmt.Fprint(w, `[{"id":1}]`) 366 }) 367 368 opt := &ListOptions{Page: 2} 369 ctx := context.Background() 370 assets, _, err := client.Repositories.ListReleaseAssets(ctx, "o", "r", 1, opt) 371 if err != nil { 372 t.Errorf("Repositories.ListReleaseAssets returned error: %v", err) 373 } 374 want := []*ReleaseAsset{{ID: Int64(1)}} 375 if !cmp.Equal(assets, want) { 376 t.Errorf("Repositories.ListReleaseAssets returned %+v, want %+v", assets, want) 377 } 378 379 const methodName = "ListReleaseAssets" 380 testBadOptions(t, methodName, func() (err error) { 381 _, _, err = client.Repositories.ListReleaseAssets(ctx, "\n", "\n", 1, opt) 382 return err 383 }) 384 385 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 386 got, resp, err := client.Repositories.ListReleaseAssets(ctx, "o", "r", 1, opt) 387 if got != nil { 388 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 389 } 390 return resp, err 391 }) 392 } 393 394 func TestRepositoriesService_GetReleaseAsset(t *testing.T) { 395 client, mux, _, teardown := setup() 396 defer teardown() 397 398 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 399 testMethod(t, r, "GET") 400 fmt.Fprint(w, `{"id":1}`) 401 }) 402 403 ctx := context.Background() 404 asset, _, err := client.Repositories.GetReleaseAsset(ctx, "o", "r", 1) 405 if err != nil { 406 t.Errorf("Repositories.GetReleaseAsset returned error: %v", err) 407 } 408 want := &ReleaseAsset{ID: Int64(1)} 409 if !cmp.Equal(asset, want) { 410 t.Errorf("Repositories.GetReleaseAsset returned %+v, want %+v", asset, want) 411 } 412 413 const methodName = "GetReleaseAsset" 414 testBadOptions(t, methodName, func() (err error) { 415 _, _, err = client.Repositories.GetReleaseAsset(ctx, "\n", "\n", 1) 416 return err 417 }) 418 419 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 420 got, resp, err := client.Repositories.GetReleaseAsset(ctx, "o", "r", 1) 421 if got != nil { 422 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 423 } 424 return resp, err 425 }) 426 } 427 428 func TestRepositoriesService_DownloadReleaseAsset_Stream(t *testing.T) { 429 client, mux, _, teardown := setup() 430 defer teardown() 431 432 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 433 testMethod(t, r, "GET") 434 testHeader(t, r, "Accept", defaultMediaType) 435 w.Header().Set("Content-Type", "application/octet-stream") 436 w.Header().Set("Content-Disposition", "attachment; filename=hello-world.txt") 437 fmt.Fprint(w, "Hello World") 438 }) 439 440 ctx := context.Background() 441 reader, _, err := client.Repositories.DownloadReleaseAsset(ctx, "o", "r", 1, nil) 442 if err != nil { 443 t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err) 444 } 445 want := []byte("Hello World") 446 content, err := ioutil.ReadAll(reader) 447 if err != nil { 448 t.Errorf("Repositories.DownloadReleaseAsset returned bad reader: %v", err) 449 } 450 if !bytes.Equal(want, content) { 451 t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", content, want) 452 } 453 454 const methodName = "DownloadReleaseAsset" 455 testBadOptions(t, methodName, func() (err error) { 456 _, _, err = client.Repositories.DownloadReleaseAsset(ctx, "\n", "\n", -1, nil) 457 return err 458 }) 459 } 460 461 func TestRepositoriesService_DownloadReleaseAsset_Redirect(t *testing.T) { 462 client, mux, _, teardown := setup() 463 defer teardown() 464 465 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 466 testMethod(t, r, "GET") 467 testHeader(t, r, "Accept", defaultMediaType) 468 http.Redirect(w, r, "/yo", http.StatusFound) 469 }) 470 471 ctx := context.Background() 472 _, got, err := client.Repositories.DownloadReleaseAsset(ctx, "o", "r", 1, nil) 473 if err != nil { 474 t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err) 475 } 476 want := "/yo" 477 if !strings.HasSuffix(got, want) { 478 t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", got, want) 479 } 480 } 481 482 func TestRepositoriesService_DownloadReleaseAsset_FollowRedirect(t *testing.T) { 483 client, mux, _, teardown := setup() 484 defer teardown() 485 486 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 487 testMethod(t, r, "GET") 488 testHeader(t, r, "Accept", defaultMediaType) 489 // /yo, below will be served as baseURLPath/yo 490 http.Redirect(w, r, baseURLPath+"/yo", http.StatusFound) 491 }) 492 mux.HandleFunc("/yo", func(w http.ResponseWriter, r *http.Request) { 493 testMethod(t, r, "GET") 494 testHeader(t, r, "Accept", "*/*") 495 w.Header().Set("Content-Type", "application/octet-stream") 496 w.Header().Set("Content-Disposition", "attachment; filename=hello-world.txt") 497 fmt.Fprint(w, "Hello World") 498 }) 499 500 ctx := context.Background() 501 reader, _, err := client.Repositories.DownloadReleaseAsset(ctx, "o", "r", 1, http.DefaultClient) 502 content, err := ioutil.ReadAll(reader) 503 if err != nil { 504 t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err) 505 } 506 reader.Close() 507 want := []byte("Hello World") 508 if !bytes.Equal(want, content) { 509 t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", content, want) 510 } 511 } 512 513 func TestRepositoriesService_DownloadReleaseAsset_APIError(t *testing.T) { 514 client, mux, _, teardown := setup() 515 defer teardown() 516 517 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 518 testMethod(t, r, "GET") 519 testHeader(t, r, "Accept", defaultMediaType) 520 w.WriteHeader(http.StatusNotFound) 521 fmt.Fprint(w, `{"message":"Not Found","documentation_url":"https://developer.github.com/v3"}`) 522 }) 523 524 ctx := context.Background() 525 resp, loc, err := client.Repositories.DownloadReleaseAsset(ctx, "o", "r", 1, nil) 526 if err == nil { 527 t.Error("Repositories.DownloadReleaseAsset did not return an error") 528 } 529 530 if resp != nil { 531 resp.Close() 532 t.Error("Repositories.DownloadReleaseAsset returned stream, want nil") 533 } 534 535 if loc != "" { 536 t.Errorf(`Repositories.DownloadReleaseAsset returned "%s", want empty ""`, loc) 537 } 538 } 539 540 func TestRepositoriesService_EditReleaseAsset(t *testing.T) { 541 client, mux, _, teardown := setup() 542 defer teardown() 543 544 input := &ReleaseAsset{Name: String("n")} 545 546 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 547 v := new(ReleaseAsset) 548 json.NewDecoder(r.Body).Decode(v) 549 550 testMethod(t, r, "PATCH") 551 if !cmp.Equal(v, input) { 552 t.Errorf("Request body = %+v, want %+v", v, input) 553 } 554 fmt.Fprint(w, `{"id":1}`) 555 }) 556 557 ctx := context.Background() 558 asset, _, err := client.Repositories.EditReleaseAsset(ctx, "o", "r", 1, input) 559 if err != nil { 560 t.Errorf("Repositories.EditReleaseAsset returned error: %v", err) 561 } 562 want := &ReleaseAsset{ID: Int64(1)} 563 if !cmp.Equal(asset, want) { 564 t.Errorf("Repositories.EditReleaseAsset returned = %+v, want %+v", asset, want) 565 } 566 567 const methodName = "EditReleaseAsset" 568 testBadOptions(t, methodName, func() (err error) { 569 _, _, err = client.Repositories.EditReleaseAsset(ctx, "\n", "\n", 1, input) 570 return err 571 }) 572 573 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 574 got, resp, err := client.Repositories.EditReleaseAsset(ctx, "o", "r", 1, input) 575 if got != nil { 576 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 577 } 578 return resp, err 579 }) 580 } 581 582 func TestRepositoriesService_DeleteReleaseAsset(t *testing.T) { 583 client, mux, _, teardown := setup() 584 defer teardown() 585 586 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 587 testMethod(t, r, "DELETE") 588 }) 589 590 ctx := context.Background() 591 _, err := client.Repositories.DeleteReleaseAsset(ctx, "o", "r", 1) 592 if err != nil { 593 t.Errorf("Repositories.DeleteReleaseAsset returned error: %v", err) 594 } 595 596 const methodName = "DeleteReleaseAsset" 597 testBadOptions(t, methodName, func() (err error) { 598 _, err = client.Repositories.DeleteReleaseAsset(ctx, "\n", "\n", 1) 599 return err 600 }) 601 602 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 603 return client.Repositories.DeleteReleaseAsset(ctx, "o", "r", 1) 604 }) 605 } 606 607 func TestRepositoriesService_UploadReleaseAsset(t *testing.T) { 608 var ( 609 defaultUploadOptions = &UploadOptions{Name: "n"} 610 defaultExpectedFormValue = values{"name": "n"} 611 mediaTypeTextPlain = "text/plain; charset=utf-8" 612 ) 613 uploadTests := []struct { 614 uploadOpts *UploadOptions 615 fileName string 616 expectedFormValues values 617 expectedMediaType string 618 }{ 619 // No file extension and no explicit media type. 620 { 621 defaultUploadOptions, 622 "upload", 623 defaultExpectedFormValue, 624 defaultMediaType, 625 }, 626 // File extension and no explicit media type. 627 { 628 defaultUploadOptions, 629 "upload.txt", 630 defaultExpectedFormValue, 631 mediaTypeTextPlain, 632 }, 633 // No file extension and explicit media type. 634 { 635 &UploadOptions{Name: "n", MediaType: "image/png"}, 636 "upload", 637 defaultExpectedFormValue, 638 "image/png", 639 }, 640 // File extension and explicit media type. 641 { 642 &UploadOptions{Name: "n", MediaType: "image/png"}, 643 "upload.png", 644 defaultExpectedFormValue, 645 "image/png", 646 }, 647 // Label provided. 648 { 649 &UploadOptions{Name: "n", Label: "l"}, 650 "upload.txt", 651 values{"name": "n", "label": "l"}, 652 mediaTypeTextPlain, 653 }, 654 // No label provided. 655 { 656 defaultUploadOptions, 657 "upload.txt", 658 defaultExpectedFormValue, 659 mediaTypeTextPlain, 660 }, 661 } 662 663 client, mux, _, teardown := setup() 664 defer teardown() 665 666 for key, test := range uploadTests { 667 releaseEndpoint := fmt.Sprintf("/repos/o/r/releases/%d/assets", key) 668 mux.HandleFunc(releaseEndpoint, func(w http.ResponseWriter, r *http.Request) { 669 testMethod(t, r, "POST") 670 testHeader(t, r, "Content-Type", test.expectedMediaType) 671 testHeader(t, r, "Content-Length", "12") 672 testFormValues(t, r, test.expectedFormValues) 673 testBody(t, r, "Upload me !\n") 674 675 fmt.Fprintf(w, `{"id":1}`) 676 }) 677 678 file, dir, err := openTestFile(test.fileName, "Upload me !\n") 679 if err != nil { 680 t.Fatalf("Unable to create temp file: %v", err) 681 } 682 defer os.RemoveAll(dir) 683 684 ctx := context.Background() 685 asset, _, err := client.Repositories.UploadReleaseAsset(ctx, "o", "r", int64(key), test.uploadOpts, file) 686 if err != nil { 687 t.Errorf("Repositories.UploadReleaseAssert returned error: %v", err) 688 } 689 want := &ReleaseAsset{ID: Int64(1)} 690 if !cmp.Equal(asset, want) { 691 t.Errorf("Repositories.UploadReleaseAssert returned %+v, want %+v", asset, want) 692 } 693 694 const methodName = "UploadReleaseAsset" 695 testBadOptions(t, methodName, func() (err error) { 696 _, _, err = client.Repositories.UploadReleaseAsset(ctx, "\n", "\n", int64(key), test.uploadOpts, file) 697 return err 698 }) 699 } 700 } 701 702 func TestRepositoryReleaseRequest_Marshal(t *testing.T) { 703 testJSONMarshal(t, &repositoryReleaseRequest{}, "{}") 704 705 u := &repositoryReleaseRequest{ 706 TagName: String("tn"), 707 TargetCommitish: String("tc"), 708 Name: String("name"), 709 Body: String("body"), 710 Draft: Bool(false), 711 Prerelease: Bool(false), 712 DiscussionCategoryName: String("dcn"), 713 } 714 715 want := `{ 716 "tag_name": "tn", 717 "target_commitish": "tc", 718 "name": "name", 719 "body": "body", 720 "draft": false, 721 "prerelease": false, 722 "discussion_category_name": "dcn" 723 }` 724 725 testJSONMarshal(t, u, want) 726 } 727 728 func TestReleaseAsset_Marshal(t *testing.T) { 729 testJSONMarshal(t, &ReleaseAsset{}, "{}") 730 731 u := &ReleaseAsset{ 732 ID: Int64(1), 733 URL: String("url"), 734 Name: String("name"), 735 Label: String("label"), 736 State: String("state"), 737 ContentType: String("ct"), 738 Size: Int(1), 739 DownloadCount: Int(1), 740 CreatedAt: &Timestamp{referenceTime}, 741 UpdatedAt: &Timestamp{referenceTime}, 742 BrowserDownloadURL: String("bdu"), 743 Uploader: &User{ID: Int64(1)}, 744 NodeID: String("nid"), 745 } 746 747 want := `{ 748 "id": 1, 749 "url": "url", 750 "name": "name", 751 "label": "label", 752 "state": "state", 753 "content_type": "ct", 754 "size": 1, 755 "download_count": 1, 756 "created_at": ` + referenceTimeStr + `, 757 "updated_at": ` + referenceTimeStr + `, 758 "browser_download_url": "bdu", 759 "uploader": { 760 "id": 1 761 }, 762 "node_id": "nid" 763 }` 764 765 testJSONMarshal(t, u, want) 766 } 767 768 func TestRepositoryRelease_Marshal(t *testing.T) { 769 testJSONMarshal(t, &RepositoryRelease{}, "{}") 770 771 u := &RepositoryRelease{ 772 TagName: String("tn"), 773 TargetCommitish: String("tc"), 774 Name: String("name"), 775 Body: String("body"), 776 Draft: Bool(false), 777 Prerelease: Bool(false), 778 DiscussionCategoryName: String("dcn"), 779 ID: Int64(1), 780 CreatedAt: &Timestamp{referenceTime}, 781 PublishedAt: &Timestamp{referenceTime}, 782 URL: String("url"), 783 HTMLURL: String("hurl"), 784 AssetsURL: String("aurl"), 785 Assets: []*ReleaseAsset{{ID: Int64(1)}}, 786 UploadURL: String("uurl"), 787 ZipballURL: String("zurl"), 788 TarballURL: String("turl"), 789 Author: &User{ID: Int64(1)}, 790 NodeID: String("nid"), 791 } 792 793 want := `{ 794 "tag_name": "tn", 795 "target_commitish": "tc", 796 "name": "name", 797 "body": "body", 798 "draft": false, 799 "prerelease": false, 800 "discussion_category_name": "dcn", 801 "id": 1, 802 "created_at": ` + referenceTimeStr + `, 803 "published_at": ` + referenceTimeStr + `, 804 "url": "url", 805 "html_url": "hurl", 806 "assets_url": "aurl", 807 "assets": [ 808 { 809 "id": 1 810 } 811 ], 812 "upload_url": "uurl", 813 "zipball_url": "zurl", 814 "tarball_url": "turl", 815 "author": { 816 "id": 1 817 }, 818 "node_id": "nid" 819 }` 820 821 testJSONMarshal(t, u, want) 822 } 823 824 func TestGenerateNotesOptions_Marshal(t *testing.T) { 825 testJSONMarshal(t, &GenerateNotesOptions{}, "{}") 826 827 u := &GenerateNotesOptions{ 828 TagName: "tag_name", 829 PreviousTagName: String("previous_tag_name"), 830 TargetCommitish: String("target_commitish"), 831 } 832 833 want := `{ 834 "tag_name": "tag_name", 835 "previous_tag_name": "previous_tag_name", 836 "target_commitish": "target_commitish" 837 }` 838 839 testJSONMarshal(t, u, want) 840 }