github.com/google/go-github/v60@v60.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" 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 assertNilError(t, 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 assertNilError(t, 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 if err != nil { 502 t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err) 503 } 504 content, err := io.ReadAll(reader) 505 if err != nil { 506 t.Errorf("Reading Repositories.DownloadReleaseAsset returned error: %v", err) 507 } 508 reader.Close() 509 want := []byte("Hello World") 510 if !bytes.Equal(want, content) { 511 t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", content, want) 512 } 513 } 514 515 func TestRepositoriesService_DownloadReleaseAsset_FollowRedirectToError(t *testing.T) { 516 client, mux, _, teardown := setup() 517 defer teardown() 518 519 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 520 testMethod(t, r, "GET") 521 testHeader(t, r, "Accept", defaultMediaType) 522 // /yo, below will be served as baseURLPath/yo 523 http.Redirect(w, r, baseURLPath+"/yo", http.StatusFound) 524 }) 525 mux.HandleFunc("/yo", func(w http.ResponseWriter, r *http.Request) { 526 testMethod(t, r, "GET") 527 testHeader(t, r, "Accept", "*/*") 528 w.WriteHeader(http.StatusNotFound) 529 }) 530 531 ctx := context.Background() 532 resp, loc, err := client.Repositories.DownloadReleaseAsset(ctx, "o", "r", 1, http.DefaultClient) 533 if err == nil { 534 t.Error("Repositories.DownloadReleaseAsset did not return an error") 535 } 536 if resp != nil { 537 resp.Close() 538 t.Error("Repositories.DownloadReleaseAsset returned stream, want nil") 539 } 540 if loc != "" { 541 t.Errorf(`Repositories.DownloadReleaseAsset returned "%s", want empty ""`, loc) 542 } 543 } 544 545 func TestRepositoriesService_DownloadReleaseAsset_APIError(t *testing.T) { 546 client, mux, _, teardown := setup() 547 defer teardown() 548 549 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 550 testMethod(t, r, "GET") 551 testHeader(t, r, "Accept", defaultMediaType) 552 w.WriteHeader(http.StatusNotFound) 553 fmt.Fprint(w, `{"message":"Not Found","documentation_url":"https://developer.github.com/v3"}`) 554 }) 555 556 ctx := context.Background() 557 resp, loc, err := client.Repositories.DownloadReleaseAsset(ctx, "o", "r", 1, nil) 558 if err == nil { 559 t.Error("Repositories.DownloadReleaseAsset did not return an error") 560 } 561 562 if resp != nil { 563 resp.Close() 564 t.Error("Repositories.DownloadReleaseAsset returned stream, want nil") 565 } 566 567 if loc != "" { 568 t.Errorf(`Repositories.DownloadReleaseAsset returned "%s", want empty ""`, loc) 569 } 570 } 571 572 func TestRepositoriesService_EditReleaseAsset(t *testing.T) { 573 client, mux, _, teardown := setup() 574 defer teardown() 575 576 input := &ReleaseAsset{Name: String("n")} 577 578 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 579 v := new(ReleaseAsset) 580 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 581 582 testMethod(t, r, "PATCH") 583 if !cmp.Equal(v, input) { 584 t.Errorf("Request body = %+v, want %+v", v, input) 585 } 586 fmt.Fprint(w, `{"id":1}`) 587 }) 588 589 ctx := context.Background() 590 asset, _, err := client.Repositories.EditReleaseAsset(ctx, "o", "r", 1, input) 591 if err != nil { 592 t.Errorf("Repositories.EditReleaseAsset returned error: %v", err) 593 } 594 want := &ReleaseAsset{ID: Int64(1)} 595 if !cmp.Equal(asset, want) { 596 t.Errorf("Repositories.EditReleaseAsset returned = %+v, want %+v", asset, want) 597 } 598 599 const methodName = "EditReleaseAsset" 600 testBadOptions(t, methodName, func() (err error) { 601 _, _, err = client.Repositories.EditReleaseAsset(ctx, "\n", "\n", 1, input) 602 return err 603 }) 604 605 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 606 got, resp, err := client.Repositories.EditReleaseAsset(ctx, "o", "r", 1, input) 607 if got != nil { 608 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 609 } 610 return resp, err 611 }) 612 } 613 614 func TestRepositoriesService_DeleteReleaseAsset(t *testing.T) { 615 client, mux, _, teardown := setup() 616 defer teardown() 617 618 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 619 testMethod(t, r, "DELETE") 620 }) 621 622 ctx := context.Background() 623 _, err := client.Repositories.DeleteReleaseAsset(ctx, "o", "r", 1) 624 if err != nil { 625 t.Errorf("Repositories.DeleteReleaseAsset returned error: %v", err) 626 } 627 628 const methodName = "DeleteReleaseAsset" 629 testBadOptions(t, methodName, func() (err error) { 630 _, err = client.Repositories.DeleteReleaseAsset(ctx, "\n", "\n", 1) 631 return err 632 }) 633 634 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 635 return client.Repositories.DeleteReleaseAsset(ctx, "o", "r", 1) 636 }) 637 } 638 639 func TestRepositoriesService_UploadReleaseAsset(t *testing.T) { 640 var ( 641 defaultUploadOptions = &UploadOptions{Name: "n"} 642 defaultExpectedFormValue = values{"name": "n"} 643 mediaTypeTextPlain = "text/plain; charset=utf-8" 644 ) 645 uploadTests := []struct { 646 uploadOpts *UploadOptions 647 fileName string 648 expectedFormValues values 649 expectedMediaType string 650 }{ 651 // No file extension and no explicit media type. 652 { 653 defaultUploadOptions, 654 "upload", 655 defaultExpectedFormValue, 656 defaultMediaType, 657 }, 658 // File extension and no explicit media type. 659 { 660 defaultUploadOptions, 661 "upload.txt", 662 defaultExpectedFormValue, 663 mediaTypeTextPlain, 664 }, 665 // No file extension and explicit media type. 666 { 667 &UploadOptions{Name: "n", MediaType: "image/png"}, 668 "upload", 669 defaultExpectedFormValue, 670 "image/png", 671 }, 672 // File extension and explicit media type. 673 { 674 &UploadOptions{Name: "n", MediaType: "image/png"}, 675 "upload.png", 676 defaultExpectedFormValue, 677 "image/png", 678 }, 679 // Label provided. 680 { 681 &UploadOptions{Name: "n", Label: "l"}, 682 "upload.txt", 683 values{"name": "n", "label": "l"}, 684 mediaTypeTextPlain, 685 }, 686 // No label provided. 687 { 688 defaultUploadOptions, 689 "upload.txt", 690 defaultExpectedFormValue, 691 mediaTypeTextPlain, 692 }, 693 } 694 695 client, mux, _, teardown := setup() 696 defer teardown() 697 698 for key, test := range uploadTests { 699 releaseEndpoint := fmt.Sprintf("/repos/o/r/releases/%d/assets", key) 700 mux.HandleFunc(releaseEndpoint, func(w http.ResponseWriter, r *http.Request) { 701 testMethod(t, r, "POST") 702 testHeader(t, r, "Content-Type", test.expectedMediaType) 703 testHeader(t, r, "Content-Length", "12") 704 testFormValues(t, r, test.expectedFormValues) 705 testBody(t, r, "Upload me !\n") 706 707 fmt.Fprintf(w, `{"id":1}`) 708 }) 709 710 file, dir, err := openTestFile(test.fileName, "Upload me !\n") 711 if err != nil { 712 t.Fatalf("Unable to create temp file: %v", err) 713 } 714 defer os.RemoveAll(dir) 715 716 ctx := context.Background() 717 asset, _, err := client.Repositories.UploadReleaseAsset(ctx, "o", "r", int64(key), test.uploadOpts, file) 718 if err != nil { 719 t.Errorf("Repositories.UploadReleaseAssert returned error: %v", err) 720 } 721 want := &ReleaseAsset{ID: Int64(1)} 722 if !cmp.Equal(asset, want) { 723 t.Errorf("Repositories.UploadReleaseAssert returned %+v, want %+v", asset, want) 724 } 725 726 const methodName = "UploadReleaseAsset" 727 testBadOptions(t, methodName, func() (err error) { 728 _, _, err = client.Repositories.UploadReleaseAsset(ctx, "\n", "\n", int64(key), test.uploadOpts, file) 729 return err 730 }) 731 } 732 } 733 734 func TestRepositoryReleaseRequest_Marshal(t *testing.T) { 735 testJSONMarshal(t, &repositoryReleaseRequest{}, "{}") 736 737 u := &repositoryReleaseRequest{ 738 TagName: String("tn"), 739 TargetCommitish: String("tc"), 740 Name: String("name"), 741 Body: String("body"), 742 Draft: Bool(false), 743 Prerelease: Bool(false), 744 MakeLatest: String("legacy"), 745 DiscussionCategoryName: String("dcn"), 746 } 747 748 want := `{ 749 "tag_name": "tn", 750 "target_commitish": "tc", 751 "name": "name", 752 "body": "body", 753 "draft": false, 754 "prerelease": false, 755 "make_latest": "legacy", 756 "discussion_category_name": "dcn" 757 }` 758 759 testJSONMarshal(t, u, want) 760 } 761 762 func TestReleaseAsset_Marshal(t *testing.T) { 763 testJSONMarshal(t, &ReleaseAsset{}, "{}") 764 765 u := &ReleaseAsset{ 766 ID: Int64(1), 767 URL: String("url"), 768 Name: String("name"), 769 Label: String("label"), 770 State: String("state"), 771 ContentType: String("ct"), 772 Size: Int(1), 773 DownloadCount: Int(1), 774 CreatedAt: &Timestamp{referenceTime}, 775 UpdatedAt: &Timestamp{referenceTime}, 776 BrowserDownloadURL: String("bdu"), 777 Uploader: &User{ID: Int64(1)}, 778 NodeID: String("nid"), 779 } 780 781 want := `{ 782 "id": 1, 783 "url": "url", 784 "name": "name", 785 "label": "label", 786 "state": "state", 787 "content_type": "ct", 788 "size": 1, 789 "download_count": 1, 790 "created_at": ` + referenceTimeStr + `, 791 "updated_at": ` + referenceTimeStr + `, 792 "browser_download_url": "bdu", 793 "uploader": { 794 "id": 1 795 }, 796 "node_id": "nid" 797 }` 798 799 testJSONMarshal(t, u, want) 800 } 801 802 func TestRepositoryRelease_Marshal(t *testing.T) { 803 testJSONMarshal(t, &RepositoryRelease{}, "{}") 804 805 u := &RepositoryRelease{ 806 TagName: String("tn"), 807 TargetCommitish: String("tc"), 808 Name: String("name"), 809 Body: String("body"), 810 Draft: Bool(false), 811 Prerelease: Bool(false), 812 MakeLatest: String("legacy"), 813 DiscussionCategoryName: String("dcn"), 814 ID: Int64(1), 815 CreatedAt: &Timestamp{referenceTime}, 816 PublishedAt: &Timestamp{referenceTime}, 817 URL: String("url"), 818 HTMLURL: String("hurl"), 819 AssetsURL: String("aurl"), 820 Assets: []*ReleaseAsset{{ID: Int64(1)}}, 821 UploadURL: String("uurl"), 822 ZipballURL: String("zurl"), 823 TarballURL: String("turl"), 824 Author: &User{ID: Int64(1)}, 825 NodeID: String("nid"), 826 } 827 828 want := `{ 829 "tag_name": "tn", 830 "target_commitish": "tc", 831 "name": "name", 832 "body": "body", 833 "draft": false, 834 "prerelease": false, 835 "make_latest": "legacy", 836 "discussion_category_name": "dcn", 837 "id": 1, 838 "created_at": ` + referenceTimeStr + `, 839 "published_at": ` + referenceTimeStr + `, 840 "url": "url", 841 "html_url": "hurl", 842 "assets_url": "aurl", 843 "assets": [ 844 { 845 "id": 1 846 } 847 ], 848 "upload_url": "uurl", 849 "zipball_url": "zurl", 850 "tarball_url": "turl", 851 "author": { 852 "id": 1 853 }, 854 "node_id": "nid" 855 }` 856 857 testJSONMarshal(t, u, want) 858 } 859 860 func TestGenerateNotesOptions_Marshal(t *testing.T) { 861 testJSONMarshal(t, &GenerateNotesOptions{}, "{}") 862 863 u := &GenerateNotesOptions{ 864 TagName: "tag_name", 865 PreviousTagName: String("previous_tag_name"), 866 TargetCommitish: String("target_commitish"), 867 } 868 869 want := `{ 870 "tag_name": "tag_name", 871 "previous_tag_name": "previous_tag_name", 872 "target_commitish": "target_commitish" 873 }` 874 875 testJSONMarshal(t, u, want) 876 }