github.com/google/go-github/v33@v33.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 "reflect" 17 "strings" 18 "testing" 19 ) 20 21 func TestRepositoriesService_ListReleases(t *testing.T) { 22 client, mux, _, teardown := setup() 23 defer teardown() 24 25 mux.HandleFunc("/repos/o/r/releases", func(w http.ResponseWriter, r *http.Request) { 26 testMethod(t, r, "GET") 27 testFormValues(t, r, values{"page": "2"}) 28 fmt.Fprint(w, `[{"id":1}]`) 29 }) 30 31 opt := &ListOptions{Page: 2} 32 releases, _, err := client.Repositories.ListReleases(context.Background(), "o", "r", opt) 33 if err != nil { 34 t.Errorf("Repositories.ListReleases returned error: %v", err) 35 } 36 want := []*RepositoryRelease{{ID: Int64(1)}} 37 if !reflect.DeepEqual(releases, want) { 38 t.Errorf("Repositories.ListReleases returned %+v, want %+v", releases, want) 39 } 40 } 41 42 func TestRepositoriesService_GetRelease(t *testing.T) { 43 client, mux, _, teardown := setup() 44 defer teardown() 45 46 mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) { 47 testMethod(t, r, "GET") 48 fmt.Fprint(w, `{"id":1,"author":{"login":"l"}}`) 49 }) 50 51 release, resp, err := client.Repositories.GetRelease(context.Background(), "o", "r", 1) 52 if err != nil { 53 t.Errorf("Repositories.GetRelease returned error: %v\n%v", err, resp.Body) 54 } 55 56 want := &RepositoryRelease{ID: Int64(1), Author: &User{Login: String("l")}} 57 if !reflect.DeepEqual(release, want) { 58 t.Errorf("Repositories.GetRelease returned %+v, want %+v", release, want) 59 } 60 } 61 62 func TestRepositoriesService_GetLatestRelease(t *testing.T) { 63 client, mux, _, teardown := setup() 64 defer teardown() 65 66 mux.HandleFunc("/repos/o/r/releases/latest", func(w http.ResponseWriter, r *http.Request) { 67 testMethod(t, r, "GET") 68 fmt.Fprint(w, `{"id":3}`) 69 }) 70 71 release, resp, err := client.Repositories.GetLatestRelease(context.Background(), "o", "r") 72 if err != nil { 73 t.Errorf("Repositories.GetLatestRelease returned error: %v\n%v", err, resp.Body) 74 } 75 76 want := &RepositoryRelease{ID: Int64(3)} 77 if !reflect.DeepEqual(release, want) { 78 t.Errorf("Repositories.GetLatestRelease returned %+v, want %+v", release, want) 79 } 80 } 81 82 func TestRepositoriesService_GetReleaseByTag(t *testing.T) { 83 client, mux, _, teardown := setup() 84 defer teardown() 85 86 mux.HandleFunc("/repos/o/r/releases/tags/foo", func(w http.ResponseWriter, r *http.Request) { 87 testMethod(t, r, "GET") 88 fmt.Fprint(w, `{"id":13}`) 89 }) 90 91 release, resp, err := client.Repositories.GetReleaseByTag(context.Background(), "o", "r", "foo") 92 if err != nil { 93 t.Errorf("Repositories.GetReleaseByTag returned error: %v\n%v", err, resp.Body) 94 } 95 96 want := &RepositoryRelease{ID: Int64(13)} 97 if !reflect.DeepEqual(release, want) { 98 t.Errorf("Repositories.GetReleaseByTag returned %+v, want %+v", release, want) 99 } 100 } 101 102 func TestRepositoriesService_CreateRelease(t *testing.T) { 103 client, mux, _, teardown := setup() 104 defer teardown() 105 106 input := &RepositoryRelease{ 107 Name: String("v1.0"), 108 // Fields to be removed: 109 ID: Int64(2), 110 CreatedAt: &Timestamp{referenceTime}, 111 PublishedAt: &Timestamp{referenceTime}, 112 URL: String("http://url/"), 113 HTMLURL: String("http://htmlurl/"), 114 AssetsURL: String("http://assetsurl/"), 115 Assets: []*ReleaseAsset{{ID: Int64(5)}}, 116 UploadURL: String("http://uploadurl/"), 117 ZipballURL: String("http://zipballurl/"), 118 TarballURL: String("http://tarballurl/"), 119 Author: &User{Name: String("octocat")}, 120 NodeID: String("nodeid"), 121 } 122 123 mux.HandleFunc("/repos/o/r/releases", func(w http.ResponseWriter, r *http.Request) { 124 v := new(repositoryReleaseRequest) 125 json.NewDecoder(r.Body).Decode(v) 126 127 testMethod(t, r, "POST") 128 want := &repositoryReleaseRequest{Name: String("v1.0")} 129 if !reflect.DeepEqual(v, want) { 130 t.Errorf("Request body = %+v, want %+v", v, want) 131 } 132 fmt.Fprint(w, `{"id":1}`) 133 }) 134 135 release, _, err := client.Repositories.CreateRelease(context.Background(), "o", "r", input) 136 if err != nil { 137 t.Errorf("Repositories.CreateRelease returned error: %v", err) 138 } 139 140 want := &RepositoryRelease{ID: Int64(1)} 141 if !reflect.DeepEqual(release, want) { 142 t.Errorf("Repositories.CreateRelease returned %+v, want %+v", release, want) 143 } 144 } 145 146 func TestRepositoriesService_EditRelease(t *testing.T) { 147 client, mux, _, teardown := setup() 148 defer teardown() 149 150 input := &RepositoryRelease{ 151 Name: String("n"), 152 // Fields to be removed: 153 ID: Int64(2), 154 CreatedAt: &Timestamp{referenceTime}, 155 PublishedAt: &Timestamp{referenceTime}, 156 URL: String("http://url/"), 157 HTMLURL: String("http://htmlurl/"), 158 AssetsURL: String("http://assetsurl/"), 159 Assets: []*ReleaseAsset{{ID: Int64(5)}}, 160 UploadURL: String("http://uploadurl/"), 161 ZipballURL: String("http://zipballurl/"), 162 TarballURL: String("http://tarballurl/"), 163 Author: &User{Name: String("octocat")}, 164 NodeID: String("nodeid"), 165 } 166 167 mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) { 168 v := new(repositoryReleaseRequest) 169 json.NewDecoder(r.Body).Decode(v) 170 171 testMethod(t, r, "PATCH") 172 want := &repositoryReleaseRequest{Name: String("n")} 173 if !reflect.DeepEqual(v, want) { 174 t.Errorf("Request body = %+v, want %+v", v, want) 175 } 176 fmt.Fprint(w, `{"id":1}`) 177 }) 178 179 release, _, err := client.Repositories.EditRelease(context.Background(), "o", "r", 1, input) 180 if err != nil { 181 t.Errorf("Repositories.EditRelease returned error: %v", err) 182 } 183 want := &RepositoryRelease{ID: Int64(1)} 184 if !reflect.DeepEqual(release, want) { 185 t.Errorf("Repositories.EditRelease returned = %+v, want %+v", release, want) 186 } 187 } 188 189 func TestRepositoriesService_DeleteRelease(t *testing.T) { 190 client, mux, _, teardown := setup() 191 defer teardown() 192 193 mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) { 194 testMethod(t, r, "DELETE") 195 }) 196 197 _, err := client.Repositories.DeleteRelease(context.Background(), "o", "r", 1) 198 if err != nil { 199 t.Errorf("Repositories.DeleteRelease returned error: %v", err) 200 } 201 } 202 203 func TestRepositoriesService_ListReleaseAssets(t *testing.T) { 204 client, mux, _, teardown := setup() 205 defer teardown() 206 207 mux.HandleFunc("/repos/o/r/releases/1/assets", func(w http.ResponseWriter, r *http.Request) { 208 testMethod(t, r, "GET") 209 testFormValues(t, r, values{"page": "2"}) 210 fmt.Fprint(w, `[{"id":1}]`) 211 }) 212 213 opt := &ListOptions{Page: 2} 214 assets, _, err := client.Repositories.ListReleaseAssets(context.Background(), "o", "r", 1, opt) 215 if err != nil { 216 t.Errorf("Repositories.ListReleaseAssets returned error: %v", err) 217 } 218 want := []*ReleaseAsset{{ID: Int64(1)}} 219 if !reflect.DeepEqual(assets, want) { 220 t.Errorf("Repositories.ListReleaseAssets returned %+v, want %+v", assets, want) 221 } 222 } 223 224 func TestRepositoriesService_GetReleaseAsset(t *testing.T) { 225 client, mux, _, teardown := setup() 226 defer teardown() 227 228 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 229 testMethod(t, r, "GET") 230 fmt.Fprint(w, `{"id":1}`) 231 }) 232 233 asset, _, err := client.Repositories.GetReleaseAsset(context.Background(), "o", "r", 1) 234 if err != nil { 235 t.Errorf("Repositories.GetReleaseAsset returned error: %v", err) 236 } 237 want := &ReleaseAsset{ID: Int64(1)} 238 if !reflect.DeepEqual(asset, want) { 239 t.Errorf("Repositories.GetReleaseAsset returned %+v, want %+v", asset, want) 240 } 241 } 242 243 func TestRepositoriesService_DownloadReleaseAsset_Stream(t *testing.T) { 244 client, mux, _, teardown := setup() 245 defer teardown() 246 247 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 248 testMethod(t, r, "GET") 249 testHeader(t, r, "Accept", defaultMediaType) 250 w.Header().Set("Content-Type", "application/octet-stream") 251 w.Header().Set("Content-Disposition", "attachment; filename=hello-world.txt") 252 fmt.Fprint(w, "Hello World") 253 }) 254 255 reader, _, err := client.Repositories.DownloadReleaseAsset(context.Background(), "o", "r", 1, nil) 256 if err != nil { 257 t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err) 258 } 259 want := []byte("Hello World") 260 content, err := ioutil.ReadAll(reader) 261 if err != nil { 262 t.Errorf("Repositories.DownloadReleaseAsset returned bad reader: %v", err) 263 } 264 if !bytes.Equal(want, content) { 265 t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", content, want) 266 } 267 } 268 269 func TestRepositoriesService_DownloadReleaseAsset_Redirect(t *testing.T) { 270 client, mux, _, teardown := setup() 271 defer teardown() 272 273 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 274 testMethod(t, r, "GET") 275 testHeader(t, r, "Accept", defaultMediaType) 276 http.Redirect(w, r, "/yo", http.StatusFound) 277 }) 278 279 _, got, err := client.Repositories.DownloadReleaseAsset(context.Background(), "o", "r", 1, nil) 280 if err != nil { 281 t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err) 282 } 283 want := "/yo" 284 if !strings.HasSuffix(got, want) { 285 t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", got, want) 286 } 287 } 288 289 func TestRepositoriesService_DownloadReleaseAsset_FollowRedirect(t *testing.T) { 290 client, mux, _, teardown := setup() 291 defer teardown() 292 293 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 294 testMethod(t, r, "GET") 295 testHeader(t, r, "Accept", defaultMediaType) 296 // /yo, below will be served as baseURLPath/yo 297 http.Redirect(w, r, baseURLPath+"/yo", http.StatusFound) 298 }) 299 mux.HandleFunc("/yo", func(w http.ResponseWriter, r *http.Request) { 300 testMethod(t, r, "GET") 301 testHeader(t, r, "Accept", "*/*") 302 w.Header().Set("Content-Type", "application/octet-stream") 303 w.Header().Set("Content-Disposition", "attachment; filename=hello-world.txt") 304 fmt.Fprint(w, "Hello World") 305 }) 306 307 reader, _, err := client.Repositories.DownloadReleaseAsset(context.Background(), "o", "r", 1, http.DefaultClient) 308 content, err := ioutil.ReadAll(reader) 309 if err != nil { 310 t.Errorf("Repositories.DownloadReleaseAsset returned error: %v", err) 311 } 312 reader.Close() 313 want := []byte("Hello World") 314 if !bytes.Equal(want, content) { 315 t.Errorf("Repositories.DownloadReleaseAsset returned %+v, want %+v", content, want) 316 } 317 } 318 319 func TestRepositoriesService_DownloadReleaseAsset_APIError(t *testing.T) { 320 client, mux, _, teardown := setup() 321 defer teardown() 322 323 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 324 testMethod(t, r, "GET") 325 testHeader(t, r, "Accept", defaultMediaType) 326 w.WriteHeader(http.StatusNotFound) 327 fmt.Fprint(w, `{"message":"Not Found","documentation_url":"https://developer.github.com/v3"}`) 328 }) 329 330 resp, loc, err := client.Repositories.DownloadReleaseAsset(context.Background(), "o", "r", 1, nil) 331 if err == nil { 332 t.Error("Repositories.DownloadReleaseAsset did not return an error") 333 } 334 335 if resp != nil { 336 resp.Close() 337 t.Error("Repositories.DownloadReleaseAsset returned stream, want nil") 338 } 339 340 if loc != "" { 341 t.Errorf(`Repositories.DownloadReleaseAsset returned "%s", want empty ""`, loc) 342 } 343 } 344 345 func TestRepositoriesService_EditReleaseAsset(t *testing.T) { 346 client, mux, _, teardown := setup() 347 defer teardown() 348 349 input := &ReleaseAsset{Name: String("n")} 350 351 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 352 v := new(ReleaseAsset) 353 json.NewDecoder(r.Body).Decode(v) 354 355 testMethod(t, r, "PATCH") 356 if !reflect.DeepEqual(v, input) { 357 t.Errorf("Request body = %+v, want %+v", v, input) 358 } 359 fmt.Fprint(w, `{"id":1}`) 360 }) 361 362 asset, _, err := client.Repositories.EditReleaseAsset(context.Background(), "o", "r", 1, input) 363 if err != nil { 364 t.Errorf("Repositories.EditReleaseAsset returned error: %v", err) 365 } 366 want := &ReleaseAsset{ID: Int64(1)} 367 if !reflect.DeepEqual(asset, want) { 368 t.Errorf("Repositories.EditReleaseAsset returned = %+v, want %+v", asset, want) 369 } 370 } 371 372 func TestRepositoriesService_DeleteReleaseAsset(t *testing.T) { 373 client, mux, _, teardown := setup() 374 defer teardown() 375 376 mux.HandleFunc("/repos/o/r/releases/assets/1", func(w http.ResponseWriter, r *http.Request) { 377 testMethod(t, r, "DELETE") 378 }) 379 380 _, err := client.Repositories.DeleteReleaseAsset(context.Background(), "o", "r", 1) 381 if err != nil { 382 t.Errorf("Repositories.DeleteReleaseAsset returned error: %v", err) 383 } 384 } 385 386 func TestRepositoriesService_UploadReleaseAsset(t *testing.T) { 387 var ( 388 defaultUploadOptions = &UploadOptions{Name: "n"} 389 defaultExpectedFormValue = values{"name": "n"} 390 mediaTypeTextPlain = "text/plain; charset=utf-8" 391 ) 392 uploadTests := []struct { 393 uploadOpts *UploadOptions 394 fileName string 395 expectedFormValues values 396 expectedMediaType string 397 }{ 398 // No file extension and no explicit media type. 399 { 400 defaultUploadOptions, 401 "upload", 402 defaultExpectedFormValue, 403 defaultMediaType, 404 }, 405 // File extension and no explicit media type. 406 { 407 defaultUploadOptions, 408 "upload.txt", 409 defaultExpectedFormValue, 410 mediaTypeTextPlain, 411 }, 412 // No file extension and explicit media type. 413 { 414 &UploadOptions{Name: "n", MediaType: "image/png"}, 415 "upload", 416 defaultExpectedFormValue, 417 "image/png", 418 }, 419 // File extension and explicit media type. 420 { 421 &UploadOptions{Name: "n", MediaType: "image/png"}, 422 "upload.png", 423 defaultExpectedFormValue, 424 "image/png", 425 }, 426 // Label provided. 427 { 428 &UploadOptions{Name: "n", Label: "l"}, 429 "upload.txt", 430 values{"name": "n", "label": "l"}, 431 mediaTypeTextPlain, 432 }, 433 // No label provided. 434 { 435 defaultUploadOptions, 436 "upload.txt", 437 defaultExpectedFormValue, 438 mediaTypeTextPlain, 439 }, 440 } 441 442 client, mux, _, teardown := setup() 443 defer teardown() 444 445 for key, test := range uploadTests { 446 releaseEndpoint := fmt.Sprintf("/repos/o/r/releases/%d/assets", key) 447 mux.HandleFunc(releaseEndpoint, func(w http.ResponseWriter, r *http.Request) { 448 testMethod(t, r, "POST") 449 testHeader(t, r, "Content-Type", test.expectedMediaType) 450 testHeader(t, r, "Content-Length", "12") 451 testFormValues(t, r, test.expectedFormValues) 452 testBody(t, r, "Upload me !\n") 453 454 fmt.Fprintf(w, `{"id":1}`) 455 }) 456 457 file, dir, err := openTestFile(test.fileName, "Upload me !\n") 458 if err != nil { 459 t.Fatalf("Unable to create temp file: %v", err) 460 } 461 defer os.RemoveAll(dir) 462 463 asset, _, err := client.Repositories.UploadReleaseAsset(context.Background(), "o", "r", int64(key), test.uploadOpts, file) 464 if err != nil { 465 t.Errorf("Repositories.UploadReleaseAssert returned error: %v", err) 466 } 467 want := &ReleaseAsset{ID: Int64(1)} 468 if !reflect.DeepEqual(asset, want) { 469 t.Errorf("Repositories.UploadReleaseAssert returned %+v, want %+v", asset, want) 470 } 471 } 472 }