github.com/google/go-github/v49@v49.1.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" 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 // Fields to be removed: 277 GenerateReleaseNotes: Bool(true), 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 } 301 if !cmp.Equal(v, want) { 302 t.Errorf("Request body = %+v, want %+v", v, want) 303 } 304 fmt.Fprint(w, `{"id":1}`) 305 }) 306 307 ctx := context.Background() 308 release, _, err := client.Repositories.EditRelease(ctx, "o", "r", 1, input) 309 if err != nil { 310 t.Errorf("Repositories.EditRelease returned error: %v", err) 311 } 312 want := &RepositoryRelease{ID: Int64(1)} 313 if !cmp.Equal(release, want) { 314 t.Errorf("Repositories.EditRelease returned = %+v, want %+v", release, want) 315 } 316 317 const methodName = "EditRelease" 318 testBadOptions(t, methodName, func() (err error) { 319 _, _, err = client.Repositories.EditRelease(ctx, "\n", "\n", 1, input) 320 return err 321 }) 322 323 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 324 got, resp, err := client.Repositories.EditRelease(ctx, "o", "r", 1, input) 325 if got != nil { 326 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 327 } 328 return resp, err 329 }) 330 } 331 332 func TestRepositoriesService_DeleteRelease(t *testing.T) { 333 client, mux, _, teardown := setup() 334 defer teardown() 335 336 mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) { 337 testMethod(t, r, "DELETE") 338 }) 339 340 ctx := context.Background() 341 _, err := client.Repositories.DeleteRelease(ctx, "o", "r", 1) 342 if err != nil { 343 t.Errorf("Repositories.DeleteRelease returned error: %v", err) 344 } 345 346 const methodName = "DeleteRelease" 347 testBadOptions(t, methodName, func() (err error) { 348 _, err = client.Repositories.DeleteRelease(ctx, "\n", "\n", 1) 349 return err 350 }) 351 352 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 353 return client.Repositories.DeleteRelease(ctx, "o", "r", 1) 354 }) 355 } 356 357 func TestRepositoriesService_ListReleaseAssets(t *testing.T) { 358 client, mux, _, teardown := setup() 359 defer teardown() 360 361 mux.HandleFunc("/repos/o/r/releases/1/assets", func(w http.ResponseWriter, r *http.Request) { 362 testMethod(t, r, "GET") 363 testFormValues(t, r, values{"page": "2"}) 364 fmt.Fprint(w, `[{"id":1}]`) 365 }) 366 367 opt := &ListOptions{Page: 2} 368 ctx := context.Background() 369 assets, _, err := client.Repositories.ListReleaseAssets(ctx, "o", "r", 1, opt) 370 if err != nil { 371 t.Errorf("Repositories.ListReleaseAssets returned error: %v", err) 372 } 373 want := []*ReleaseAsset{{ID: Int64(1)}} 374 if !cmp.Equal(assets, want) { 375 t.Errorf("Repositories.ListReleaseAssets returned %+v, want %+v", assets, want) 376 } 377 378 const methodName = "ListReleaseAssets" 379 testBadOptions(t, methodName, func() (err error) { 380 _, _, err = client.Repositories.ListReleaseAssets(ctx, "\n", "\n", 1, opt) 381 return err 382 }) 383 384 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 385 got, resp, err := client.Repositories.ListReleaseAssets(ctx, "o", "r", 1, opt) 386 if got != nil { 387 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 388 } 389 return resp, err 390 }) 391 } 392 393 func TestRepositoriesService_GetReleaseAsset(t *testing.T) { 394 client, mux, _, teardown := setup() 395 defer teardown() 396 397 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 398 testMethod(t, r, "GET") 399 fmt.Fprint(w, `{"id":1}`) 400 }) 401 402 ctx := context.Background() 403 asset, _, err := client.Repositories.GetReleaseAsset(ctx, "o", "r", 1) 404 if err != nil { 405 t.Errorf("Repositories.GetReleaseAsset returned error: %v", err) 406 } 407 want := &ReleaseAsset{ID: Int64(1)} 408 if !cmp.Equal(asset, want) { 409 t.Errorf("Repositories.GetReleaseAsset returned %+v, want %+v", asset, want) 410 } 411 412 const methodName = "GetReleaseAsset" 413 testBadOptions(t, methodName, func() (err error) { 414 _, _, err = client.Repositories.GetReleaseAsset(ctx, "\n", "\n", 1) 415 return err 416 }) 417 418 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 419 got, resp, err := client.Repositories.GetReleaseAsset(ctx, "o", "r", 1) 420 if got != nil { 421 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 422 } 423 return resp, err 424 }) 425 } 426 427 func TestRepositoriesService_DownloadReleaseAsset_Stream(t *testing.T) { 428 client, mux, _, teardown := setup() 429 defer teardown() 430 431 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 432 testMethod(t, r, "GET") 433 testHeader(t, r, "Accept", defaultMediaType) 434 w.Header().Set("Content-Type", "application/octet-stream") 435 w.Header().Set("Content-Disposition", "attachment; filename=hello-world.txt") 436 fmt.Fprint(w, "Hello World") 437 }) 438 439 ctx := context.Background() 440 reader, _, err := client.Repositories.DownloadReleaseAsset(ctx, "o", "r", 1, nil) 441 if err != nil { 442 t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err) 443 } 444 want := []byte("Hello World") 445 content, err := io.ReadAll(reader) 446 if err != nil { 447 t.Errorf("Repositories.DownloadReleaseAsset returned bad reader: %v", err) 448 } 449 if !bytes.Equal(want, content) { 450 t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", content, want) 451 } 452 453 const methodName = "DownloadReleaseAsset" 454 testBadOptions(t, methodName, func() (err error) { 455 _, _, err = client.Repositories.DownloadReleaseAsset(ctx, "\n", "\n", -1, nil) 456 return err 457 }) 458 } 459 460 func TestRepositoriesService_DownloadReleaseAsset_Redirect(t *testing.T) { 461 client, mux, _, teardown := setup() 462 defer teardown() 463 464 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 465 testMethod(t, r, "GET") 466 testHeader(t, r, "Accept", defaultMediaType) 467 http.Redirect(w, r, "/yo", http.StatusFound) 468 }) 469 470 ctx := context.Background() 471 _, got, err := client.Repositories.DownloadReleaseAsset(ctx, "o", "r", 1, nil) 472 if err != nil { 473 t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err) 474 } 475 want := "/yo" 476 if !strings.HasSuffix(got, want) { 477 t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", got, want) 478 } 479 } 480 481 func TestRepositoriesService_DownloadReleaseAsset_FollowRedirect(t *testing.T) { 482 client, mux, _, teardown := setup() 483 defer teardown() 484 485 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 486 testMethod(t, r, "GET") 487 testHeader(t, r, "Accept", defaultMediaType) 488 // /yo, below will be served as baseURLPath/yo 489 http.Redirect(w, r, baseURLPath+"/yo", http.StatusFound) 490 }) 491 mux.HandleFunc("/yo", func(w http.ResponseWriter, r *http.Request) { 492 testMethod(t, r, "GET") 493 testHeader(t, r, "Accept", "*/*") 494 w.Header().Set("Content-Type", "application/octet-stream") 495 w.Header().Set("Content-Disposition", "attachment; filename=hello-world.txt") 496 fmt.Fprint(w, "Hello World") 497 }) 498 499 ctx := context.Background() 500 reader, _, err := client.Repositories.DownloadReleaseAsset(ctx, "o", "r", 1, http.DefaultClient) 501 content, err := io.ReadAll(reader) 502 if err != nil { 503 t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err) 504 } 505 reader.Close() 506 want := []byte("Hello World") 507 if !bytes.Equal(want, content) { 508 t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", content, want) 509 } 510 } 511 512 func TestRepositoriesService_DownloadReleaseAsset_APIError(t *testing.T) { 513 client, mux, _, teardown := setup() 514 defer teardown() 515 516 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 517 testMethod(t, r, "GET") 518 testHeader(t, r, "Accept", defaultMediaType) 519 w.WriteHeader(http.StatusNotFound) 520 fmt.Fprint(w, `{"message":"Not Found","documentation_url":"https://developer.github.com/v3"}`) 521 }) 522 523 ctx := context.Background() 524 resp, loc, err := client.Repositories.DownloadReleaseAsset(ctx, "o", "r", 1, nil) 525 if err == nil { 526 t.Error("Repositories.DownloadReleaseAsset did not return an error") 527 } 528 529 if resp != nil { 530 resp.Close() 531 t.Error("Repositories.DownloadReleaseAsset returned stream, want nil") 532 } 533 534 if loc != "" { 535 t.Errorf(`Repositories.DownloadReleaseAsset returned "%s", want empty ""`, loc) 536 } 537 } 538 539 func TestRepositoriesService_EditReleaseAsset(t *testing.T) { 540 client, mux, _, teardown := setup() 541 defer teardown() 542 543 input := &ReleaseAsset{Name: String("n")} 544 545 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 546 v := new(ReleaseAsset) 547 json.NewDecoder(r.Body).Decode(v) 548 549 testMethod(t, r, "PATCH") 550 if !cmp.Equal(v, input) { 551 t.Errorf("Request body = %+v, want %+v", v, input) 552 } 553 fmt.Fprint(w, `{"id":1}`) 554 }) 555 556 ctx := context.Background() 557 asset, _, err := client.Repositories.EditReleaseAsset(ctx, "o", "r", 1, input) 558 if err != nil { 559 t.Errorf("Repositories.EditReleaseAsset returned error: %v", err) 560 } 561 want := &ReleaseAsset{ID: Int64(1)} 562 if !cmp.Equal(asset, want) { 563 t.Errorf("Repositories.EditReleaseAsset returned = %+v, want %+v", asset, want) 564 } 565 566 const methodName = "EditReleaseAsset" 567 testBadOptions(t, methodName, func() (err error) { 568 _, _, err = client.Repositories.EditReleaseAsset(ctx, "\n", "\n", 1, input) 569 return err 570 }) 571 572 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 573 got, resp, err := client.Repositories.EditReleaseAsset(ctx, "o", "r", 1, input) 574 if got != nil { 575 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 576 } 577 return resp, err 578 }) 579 } 580 581 func TestRepositoriesService_DeleteReleaseAsset(t *testing.T) { 582 client, mux, _, teardown := setup() 583 defer teardown() 584 585 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 586 testMethod(t, r, "DELETE") 587 }) 588 589 ctx := context.Background() 590 _, err := client.Repositories.DeleteReleaseAsset(ctx, "o", "r", 1) 591 if err != nil { 592 t.Errorf("Repositories.DeleteReleaseAsset returned error: %v", err) 593 } 594 595 const methodName = "DeleteReleaseAsset" 596 testBadOptions(t, methodName, func() (err error) { 597 _, err = client.Repositories.DeleteReleaseAsset(ctx, "\n", "\n", 1) 598 return err 599 }) 600 601 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 602 return client.Repositories.DeleteReleaseAsset(ctx, "o", "r", 1) 603 }) 604 } 605 606 func TestRepositoriesService_UploadReleaseAsset(t *testing.T) { 607 var ( 608 defaultUploadOptions = &UploadOptions{Name: "n"} 609 defaultExpectedFormValue = values{"name": "n"} 610 mediaTypeTextPlain = "text/plain; charset=utf-8" 611 ) 612 uploadTests := []struct { 613 uploadOpts *UploadOptions 614 fileName string 615 expectedFormValues values 616 expectedMediaType string 617 }{ 618 // No file extension and no explicit media type. 619 { 620 defaultUploadOptions, 621 "upload", 622 defaultExpectedFormValue, 623 defaultMediaType, 624 }, 625 // File extension and no explicit media type. 626 { 627 defaultUploadOptions, 628 "upload.txt", 629 defaultExpectedFormValue, 630 mediaTypeTextPlain, 631 }, 632 // No file extension and explicit media type. 633 { 634 &UploadOptions{Name: "n", MediaType: "image/png"}, 635 "upload", 636 defaultExpectedFormValue, 637 "image/png", 638 }, 639 // File extension and explicit media type. 640 { 641 &UploadOptions{Name: "n", MediaType: "image/png"}, 642 "upload.png", 643 defaultExpectedFormValue, 644 "image/png", 645 }, 646 // Label provided. 647 { 648 &UploadOptions{Name: "n", Label: "l"}, 649 "upload.txt", 650 values{"name": "n", "label": "l"}, 651 mediaTypeTextPlain, 652 }, 653 // No label provided. 654 { 655 defaultUploadOptions, 656 "upload.txt", 657 defaultExpectedFormValue, 658 mediaTypeTextPlain, 659 }, 660 } 661 662 client, mux, _, teardown := setup() 663 defer teardown() 664 665 for key, test := range uploadTests { 666 releaseEndpoint := fmt.Sprintf("/repos/o/r/releases/%d/assets", key) 667 mux.HandleFunc(releaseEndpoint, func(w http.ResponseWriter, r *http.Request) { 668 testMethod(t, r, "POST") 669 testHeader(t, r, "Content-Type", test.expectedMediaType) 670 testHeader(t, r, "Content-Length", "12") 671 testFormValues(t, r, test.expectedFormValues) 672 testBody(t, r, "Upload me !\n") 673 674 fmt.Fprintf(w, `{"id":1}`) 675 }) 676 677 file, dir, err := openTestFile(test.fileName, "Upload me !\n") 678 if err != nil { 679 t.Fatalf("Unable to create temp file: %v", err) 680 } 681 defer os.RemoveAll(dir) 682 683 ctx := context.Background() 684 asset, _, err := client.Repositories.UploadReleaseAsset(ctx, "o", "r", int64(key), test.uploadOpts, file) 685 if err != nil { 686 t.Errorf("Repositories.UploadReleaseAssert returned error: %v", err) 687 } 688 want := &ReleaseAsset{ID: Int64(1)} 689 if !cmp.Equal(asset, want) { 690 t.Errorf("Repositories.UploadReleaseAssert returned %+v, want %+v", asset, want) 691 } 692 693 const methodName = "UploadReleaseAsset" 694 testBadOptions(t, methodName, func() (err error) { 695 _, _, err = client.Repositories.UploadReleaseAsset(ctx, "\n", "\n", int64(key), test.uploadOpts, file) 696 return err 697 }) 698 } 699 } 700 701 func TestRepositoryReleaseRequest_Marshal(t *testing.T) { 702 testJSONMarshal(t, &repositoryReleaseRequest{}, "{}") 703 704 u := &repositoryReleaseRequest{ 705 TagName: String("tn"), 706 TargetCommitish: String("tc"), 707 Name: String("name"), 708 Body: String("body"), 709 Draft: Bool(false), 710 Prerelease: Bool(false), 711 MakeLatest: String("legacy"), 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 "make_latest": "legacy", 723 "discussion_category_name": "dcn" 724 }` 725 726 testJSONMarshal(t, u, want) 727 } 728 729 func TestReleaseAsset_Marshal(t *testing.T) { 730 testJSONMarshal(t, &ReleaseAsset{}, "{}") 731 732 u := &ReleaseAsset{ 733 ID: Int64(1), 734 URL: String("url"), 735 Name: String("name"), 736 Label: String("label"), 737 State: String("state"), 738 ContentType: String("ct"), 739 Size: Int(1), 740 DownloadCount: Int(1), 741 CreatedAt: &Timestamp{referenceTime}, 742 UpdatedAt: &Timestamp{referenceTime}, 743 BrowserDownloadURL: String("bdu"), 744 Uploader: &User{ID: Int64(1)}, 745 NodeID: String("nid"), 746 } 747 748 want := `{ 749 "id": 1, 750 "url": "url", 751 "name": "name", 752 "label": "label", 753 "state": "state", 754 "content_type": "ct", 755 "size": 1, 756 "download_count": 1, 757 "created_at": ` + referenceTimeStr + `, 758 "updated_at": ` + referenceTimeStr + `, 759 "browser_download_url": "bdu", 760 "uploader": { 761 "id": 1 762 }, 763 "node_id": "nid" 764 }` 765 766 testJSONMarshal(t, u, want) 767 } 768 769 func TestRepositoryRelease_Marshal(t *testing.T) { 770 testJSONMarshal(t, &RepositoryRelease{}, "{}") 771 772 u := &RepositoryRelease{ 773 TagName: String("tn"), 774 TargetCommitish: String("tc"), 775 Name: String("name"), 776 Body: String("body"), 777 Draft: Bool(false), 778 Prerelease: Bool(false), 779 MakeLatest: String("legacy"), 780 DiscussionCategoryName: String("dcn"), 781 ID: Int64(1), 782 CreatedAt: &Timestamp{referenceTime}, 783 PublishedAt: &Timestamp{referenceTime}, 784 URL: String("url"), 785 HTMLURL: String("hurl"), 786 AssetsURL: String("aurl"), 787 Assets: []*ReleaseAsset{{ID: Int64(1)}}, 788 UploadURL: String("uurl"), 789 ZipballURL: String("zurl"), 790 TarballURL: String("turl"), 791 Author: &User{ID: Int64(1)}, 792 NodeID: String("nid"), 793 } 794 795 want := `{ 796 "tag_name": "tn", 797 "target_commitish": "tc", 798 "name": "name", 799 "body": "body", 800 "draft": false, 801 "prerelease": false, 802 "make_latest": "legacy", 803 "discussion_category_name": "dcn", 804 "id": 1, 805 "created_at": ` + referenceTimeStr + `, 806 "published_at": ` + referenceTimeStr + `, 807 "url": "url", 808 "html_url": "hurl", 809 "assets_url": "aurl", 810 "assets": [ 811 { 812 "id": 1 813 } 814 ], 815 "upload_url": "uurl", 816 "zipball_url": "zurl", 817 "tarball_url": "turl", 818 "author": { 819 "id": 1 820 }, 821 "node_id": "nid" 822 }` 823 824 testJSONMarshal(t, u, want) 825 } 826 827 func TestGenerateNotesOptions_Marshal(t *testing.T) { 828 testJSONMarshal(t, &GenerateNotesOptions{}, "{}") 829 830 u := &GenerateNotesOptions{ 831 TagName: "tag_name", 832 PreviousTagName: String("previous_tag_name"), 833 TargetCommitish: String("target_commitish"), 834 } 835 836 want := `{ 837 "tag_name": "tag_name", 838 "previous_tag_name": "previous_tag_name", 839 "target_commitish": "target_commitish" 840 }` 841 842 testJSONMarshal(t, u, want) 843 }