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  }