...

Source file src/github.com/google/go-github/v47/github/repos_contents_test.go

Documentation: github.com/google/go-github/v47/github

     1  // Copyright 2014 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  	"context"
    10  	"errors"
    11  	"fmt"
    12  	"io/ioutil"
    13  	"net/http"
    14  	"net/url"
    15  	"testing"
    16  
    17  	"github.com/google/go-cmp/cmp"
    18  	"golang.org/x/crypto/openpgp"
    19  )
    20  
    21  func TestRepositoryContent_GetContent(t *testing.T) {
    22  	tests := []struct {
    23  		encoding, content *string // input encoding and content
    24  		want              string  // desired output
    25  		wantErr           bool    // whether an error is expected
    26  	}{
    27  		{
    28  			encoding: String(""),
    29  			content:  String("hello"),
    30  			want:     "hello",
    31  			wantErr:  false,
    32  		},
    33  		{
    34  			encoding: nil,
    35  			content:  String("hello"),
    36  			want:     "hello",
    37  			wantErr:  false,
    38  		},
    39  		{
    40  			encoding: nil,
    41  			content:  nil,
    42  			want:     "",
    43  			wantErr:  false,
    44  		},
    45  		{
    46  			encoding: String("base64"),
    47  			content:  String("aGVsbG8="),
    48  			want:     "hello",
    49  			wantErr:  false,
    50  		},
    51  		{
    52  			encoding: String("bad"),
    53  			content:  String("aGVsbG8="),
    54  			want:     "",
    55  			wantErr:  true,
    56  		},
    57  	}
    58  
    59  	for _, tt := range tests {
    60  		r := RepositoryContent{Encoding: tt.encoding, Content: tt.content}
    61  		got, err := r.GetContent()
    62  		if err != nil && !tt.wantErr {
    63  			t.Errorf("RepositoryContent(%s, %s) returned unexpected error: %v",
    64  				stringOrNil(tt.encoding), stringOrNil(tt.content), err)
    65  		}
    66  		if err == nil && tt.wantErr {
    67  			t.Errorf("RepositoryContent(%s, %s) did not return unexpected error",
    68  				stringOrNil(tt.encoding), stringOrNil(tt.content))
    69  		}
    70  		if want := tt.want; got != want {
    71  			t.Errorf("RepositoryContent.GetContent returned %+v, want %+v", got, want)
    72  		}
    73  	}
    74  }
    75  
    76  // stringOrNil converts a potentially null string pointer to string.
    77  // For non-nil input pointer, the returned string is enclosed in double-quotes.
    78  func stringOrNil(s *string) string {
    79  	if s == nil {
    80  		return "<nil>"
    81  	}
    82  	return fmt.Sprintf("%q", *s)
    83  }
    84  
    85  func TestRepositoriesService_GetReadme(t *testing.T) {
    86  	client, mux, _, teardown := setup()
    87  	defer teardown()
    88  	mux.HandleFunc("/repos/o/r/readme", func(w http.ResponseWriter, r *http.Request) {
    89  		testMethod(t, r, "GET")
    90  		fmt.Fprint(w, `{
    91  		  "type": "file",
    92  		  "encoding": "base64",
    93  		  "size": 5362,
    94  		  "name": "README.md",
    95  		  "path": "README.md"
    96  		}`)
    97  	})
    98  	ctx := context.Background()
    99  	readme, _, err := client.Repositories.GetReadme(ctx, "o", "r", &RepositoryContentGetOptions{})
   100  	if err != nil {
   101  		t.Errorf("Repositories.GetReadme returned error: %v", err)
   102  	}
   103  	want := &RepositoryContent{Type: String("file"), Name: String("README.md"), Size: Int(5362), Encoding: String("base64"), Path: String("README.md")}
   104  	if !cmp.Equal(readme, want) {
   105  		t.Errorf("Repositories.GetReadme returned %+v, want %+v", readme, want)
   106  	}
   107  
   108  	const methodName = "GetReadme"
   109  	testBadOptions(t, methodName, func() (err error) {
   110  		_, _, err = client.Repositories.GetReadme(ctx, "\n", "\n", &RepositoryContentGetOptions{})
   111  		return err
   112  	})
   113  
   114  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   115  		got, resp, err := client.Repositories.GetReadme(ctx, "o", "r", &RepositoryContentGetOptions{})
   116  		if got != nil {
   117  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   118  		}
   119  		return resp, err
   120  	})
   121  }
   122  
   123  func TestRepositoriesService_DownloadContents_Success(t *testing.T) {
   124  	client, mux, serverURL, teardown := setup()
   125  	defer teardown()
   126  	mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
   127  		testMethod(t, r, "GET")
   128  		fmt.Fprint(w, `[{
   129  		  "type": "file",
   130  		  "name": "f",
   131  		  "download_url": "`+serverURL+baseURLPath+`/download/f"
   132  		}]`)
   133  	})
   134  	mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) {
   135  		testMethod(t, r, "GET")
   136  		fmt.Fprint(w, "foo")
   137  	})
   138  
   139  	ctx := context.Background()
   140  	r, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil)
   141  	if err != nil {
   142  		t.Errorf("Repositories.DownloadContents returned error: %v", err)
   143  	}
   144  
   145  	if got, want := resp.Response.StatusCode, http.StatusOK; got != want {
   146  		t.Errorf("Repositories.DownloadContents returned status code %v, want %v", got, want)
   147  	}
   148  
   149  	bytes, err := ioutil.ReadAll(r)
   150  	if err != nil {
   151  		t.Errorf("Error reading response body: %v", err)
   152  	}
   153  	r.Close()
   154  
   155  	if got, want := string(bytes), "foo"; got != want {
   156  		t.Errorf("Repositories.DownloadContents returned %v, want %v", got, want)
   157  	}
   158  
   159  	const methodName = "DownloadContents"
   160  	testBadOptions(t, methodName, func() (err error) {
   161  		_, _, err = client.Repositories.DownloadContents(ctx, "\n", "\n", "\n", nil)
   162  		return err
   163  	})
   164  
   165  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   166  		got, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil)
   167  		if got != nil {
   168  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   169  		}
   170  		return resp, err
   171  	})
   172  }
   173  
   174  func TestRepositoriesService_DownloadContents_FailedResponse(t *testing.T) {
   175  	client, mux, serverURL, teardown := setup()
   176  	defer teardown()
   177  	mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
   178  		testMethod(t, r, "GET")
   179  		fmt.Fprint(w, `[{
   180  			"type": "file",
   181  			"name": "f",
   182  			"download_url": "`+serverURL+baseURLPath+`/download/f"
   183  		  }]`)
   184  	})
   185  	mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) {
   186  		testMethod(t, r, "GET")
   187  		w.WriteHeader(http.StatusInternalServerError)
   188  		fmt.Fprint(w, "foo error")
   189  	})
   190  
   191  	ctx := context.Background()
   192  	r, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil)
   193  	if err != nil {
   194  		t.Errorf("Repositories.DownloadContents returned error: %v", err)
   195  	}
   196  
   197  	if got, want := resp.Response.StatusCode, http.StatusInternalServerError; got != want {
   198  		t.Errorf("Repositories.DownloadContents returned status code %v, want %v", got, want)
   199  	}
   200  
   201  	bytes, err := ioutil.ReadAll(r)
   202  	if err != nil {
   203  		t.Errorf("Error reading response body: %v", err)
   204  	}
   205  	r.Close()
   206  
   207  	if got, want := string(bytes), "foo error"; got != want {
   208  		t.Errorf("Repositories.DownloadContents returned %v, want %v", got, want)
   209  	}
   210  }
   211  
   212  func TestRepositoriesService_DownloadContents_NoDownloadURL(t *testing.T) {
   213  	client, mux, _, teardown := setup()
   214  	defer teardown()
   215  	mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
   216  		testMethod(t, r, "GET")
   217  		fmt.Fprint(w, `[{
   218  		  "type": "file",
   219  		  "name": "f",
   220  		}]`)
   221  	})
   222  
   223  	ctx := context.Background()
   224  	_, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil)
   225  	if err == nil {
   226  		t.Errorf("Repositories.DownloadContents did not return expected error")
   227  	}
   228  
   229  	if resp == nil {
   230  		t.Errorf("Repositories.DownloadContents did not return expected response")
   231  	}
   232  }
   233  
   234  func TestRepositoriesService_DownloadContents_NoFile(t *testing.T) {
   235  	client, mux, _, teardown := setup()
   236  	defer teardown()
   237  	mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
   238  		testMethod(t, r, "GET")
   239  		fmt.Fprint(w, `[]`)
   240  	})
   241  
   242  	ctx := context.Background()
   243  	_, resp, err := client.Repositories.DownloadContents(ctx, "o", "r", "d/f", nil)
   244  	if err == nil {
   245  		t.Errorf("Repositories.DownloadContents did not return expected error")
   246  	}
   247  
   248  	if resp == nil {
   249  		t.Errorf("Repositories.DownloadContents did not return expected response")
   250  	}
   251  }
   252  
   253  func TestRepositoriesService_DownloadContentsWithMeta_Success(t *testing.T) {
   254  	client, mux, serverURL, teardown := setup()
   255  	defer teardown()
   256  	mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
   257  		testMethod(t, r, "GET")
   258  		fmt.Fprint(w, `[{
   259  		  "type": "file",
   260  		  "name": "f",
   261  		  "download_url": "`+serverURL+baseURLPath+`/download/f"
   262  		}]`)
   263  	})
   264  	mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) {
   265  		testMethod(t, r, "GET")
   266  		fmt.Fprint(w, "foo")
   267  	})
   268  
   269  	ctx := context.Background()
   270  	r, c, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil)
   271  	if err != nil {
   272  		t.Errorf("Repositories.DownloadContentsWithMeta returned error: %v", err)
   273  	}
   274  
   275  	if got, want := resp.Response.StatusCode, http.StatusOK; got != want {
   276  		t.Errorf("Repositories.DownloadContentsWithMeta returned status code %v, want %v", got, want)
   277  	}
   278  
   279  	bytes, err := ioutil.ReadAll(r)
   280  	if err != nil {
   281  		t.Errorf("Error reading response body: %v", err)
   282  	}
   283  	r.Close()
   284  
   285  	if got, want := string(bytes), "foo"; got != want {
   286  		t.Errorf("Repositories.DownloadContentsWithMeta returned %v, want %v", got, want)
   287  	}
   288  
   289  	if c != nil && c.Name != nil {
   290  		if got, want := *c.Name, "f"; got != want {
   291  			t.Errorf("Repositories.DownloadContentsWithMeta returned content name %v, want %v", got, want)
   292  		}
   293  	} else {
   294  		t.Errorf("Returned RepositoryContent is null")
   295  	}
   296  
   297  	const methodName = "DownloadContentsWithMeta"
   298  	testBadOptions(t, methodName, func() (err error) {
   299  		_, _, _, err = client.Repositories.DownloadContentsWithMeta(ctx, "\n", "\n", "\n", nil)
   300  		return err
   301  	})
   302  
   303  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   304  		got, cot, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil)
   305  		if got != nil {
   306  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   307  		}
   308  		if cot != nil {
   309  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, cot)
   310  		}
   311  		return resp, err
   312  	})
   313  }
   314  
   315  func TestRepositoriesService_DownloadContentsWithMeta_FailedResponse(t *testing.T) {
   316  	client, mux, serverURL, teardown := setup()
   317  	defer teardown()
   318  	mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
   319  		testMethod(t, r, "GET")
   320  		fmt.Fprint(w, `[{
   321  			"type": "file",
   322  			"name": "f",
   323  			"download_url": "`+serverURL+baseURLPath+`/download/f"
   324  		  }]`)
   325  	})
   326  	mux.HandleFunc("/download/f", func(w http.ResponseWriter, r *http.Request) {
   327  		testMethod(t, r, "GET")
   328  		w.WriteHeader(http.StatusInternalServerError)
   329  		fmt.Fprint(w, "foo error")
   330  	})
   331  
   332  	ctx := context.Background()
   333  	r, c, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil)
   334  	if err != nil {
   335  		t.Errorf("Repositories.DownloadContentsWithMeta returned error: %v", err)
   336  	}
   337  
   338  	if got, want := resp.Response.StatusCode, http.StatusInternalServerError; got != want {
   339  		t.Errorf("Repositories.DownloadContentsWithMeta returned status code %v, want %v", got, want)
   340  	}
   341  
   342  	bytes, err := ioutil.ReadAll(r)
   343  	if err != nil {
   344  		t.Errorf("Error reading response body: %v", err)
   345  	}
   346  	r.Close()
   347  
   348  	if got, want := string(bytes), "foo error"; got != want {
   349  		t.Errorf("Repositories.DownloadContentsWithMeta returned %v, want %v", got, want)
   350  	}
   351  
   352  	if c != nil && c.Name != nil {
   353  		if got, want := *c.Name, "f"; got != want {
   354  			t.Errorf("Repositories.DownloadContentsWithMeta returned content name %v, want %v", got, want)
   355  		}
   356  	} else {
   357  		t.Errorf("Returned RepositoryContent is null")
   358  	}
   359  }
   360  
   361  func TestRepositoriesService_DownloadContentsWithMeta_NoDownloadURL(t *testing.T) {
   362  	client, mux, _, teardown := setup()
   363  	defer teardown()
   364  	mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
   365  		testMethod(t, r, "GET")
   366  		fmt.Fprint(w, `[{
   367  		  "type": "file",
   368  		  "name": "f",
   369  		}]`)
   370  	})
   371  
   372  	ctx := context.Background()
   373  	_, _, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil)
   374  	if err == nil {
   375  		t.Errorf("Repositories.DownloadContentsWithMeta did not return expected error")
   376  	}
   377  
   378  	if resp == nil {
   379  		t.Errorf("Repositories.DownloadContentsWithMeta did not return expected response")
   380  	}
   381  }
   382  
   383  func TestRepositoriesService_DownloadContentsWithMeta_NoFile(t *testing.T) {
   384  	client, mux, _, teardown := setup()
   385  	defer teardown()
   386  	mux.HandleFunc("/repos/o/r/contents/d", func(w http.ResponseWriter, r *http.Request) {
   387  		testMethod(t, r, "GET")
   388  		fmt.Fprint(w, `[]`)
   389  	})
   390  
   391  	ctx := context.Background()
   392  	_, _, resp, err := client.Repositories.DownloadContentsWithMeta(ctx, "o", "r", "d/f", nil)
   393  	if err == nil {
   394  		t.Errorf("Repositories.DownloadContentsWithMeta did not return expected error")
   395  	}
   396  
   397  	if resp == nil {
   398  		t.Errorf("Repositories.DownloadContentsWithMeta did not return expected response")
   399  	}
   400  }
   401  
   402  func TestRepositoriesService_GetContents_File(t *testing.T) {
   403  	client, mux, _, teardown := setup()
   404  	defer teardown()
   405  	mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
   406  		testMethod(t, r, "GET")
   407  		fmt.Fprint(w, `{
   408  		  "type": "file",
   409  		  "encoding": "base64",
   410  		  "size": 20678,
   411  		  "name": "LICENSE",
   412  		  "path": "LICENSE"
   413  		}`)
   414  	})
   415  	ctx := context.Background()
   416  	fileContents, _, _, err := client.Repositories.GetContents(ctx, "o", "r", "p", &RepositoryContentGetOptions{})
   417  	if err != nil {
   418  		t.Errorf("Repositories.GetContents returned error: %v", err)
   419  	}
   420  	want := &RepositoryContent{Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Encoding: String("base64"), Path: String("LICENSE")}
   421  	if !cmp.Equal(fileContents, want) {
   422  		t.Errorf("Repositories.GetContents returned %+v, want %+v", fileContents, want)
   423  	}
   424  
   425  	const methodName = "GetContents"
   426  	testBadOptions(t, methodName, func() (err error) {
   427  		_, _, _, err = client.Repositories.GetContents(ctx, "\n", "\n", "\n", &RepositoryContentGetOptions{})
   428  		return err
   429  	})
   430  
   431  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   432  		got, _, resp, err := client.Repositories.GetContents(ctx, "o", "r", "p", &RepositoryContentGetOptions{})
   433  		if got != nil {
   434  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   435  		}
   436  		return resp, err
   437  	})
   438  }
   439  
   440  func TestRepositoriesService_GetContents_FilenameNeedsEscape(t *testing.T) {
   441  	client, mux, _, teardown := setup()
   442  	defer teardown()
   443  	mux.HandleFunc("/repos/o/r/contents/p#?%/中.go", func(w http.ResponseWriter, r *http.Request) {
   444  		testMethod(t, r, "GET")
   445  		fmt.Fprint(w, `{}`)
   446  	})
   447  	ctx := context.Background()
   448  	_, _, _, err := client.Repositories.GetContents(ctx, "o", "r", "p#?%/中.go", &RepositoryContentGetOptions{})
   449  	if err != nil {
   450  		t.Fatalf("Repositories.GetContents returned error: %v", err)
   451  	}
   452  }
   453  
   454  func TestRepositoriesService_GetContents_DirectoryWithSpaces(t *testing.T) {
   455  	client, mux, _, teardown := setup()
   456  	defer teardown()
   457  	mux.HandleFunc("/repos/o/r/contents/some directory/file.go", func(w http.ResponseWriter, r *http.Request) {
   458  		testMethod(t, r, "GET")
   459  		fmt.Fprint(w, `{}`)
   460  	})
   461  	ctx := context.Background()
   462  	_, _, _, err := client.Repositories.GetContents(ctx, "o", "r", "some directory/file.go", &RepositoryContentGetOptions{})
   463  	if err != nil {
   464  		t.Fatalf("Repositories.GetContents returned error: %v", err)
   465  	}
   466  }
   467  
   468  func TestRepositoriesService_GetContents_DirectoryWithPlusChars(t *testing.T) {
   469  	client, mux, _, teardown := setup()
   470  	defer teardown()
   471  	mux.HandleFunc("/repos/o/r/contents/some directory+name/file.go", func(w http.ResponseWriter, r *http.Request) {
   472  		testMethod(t, r, "GET")
   473  		fmt.Fprint(w, `{}`)
   474  	})
   475  	ctx := context.Background()
   476  	_, _, _, err := client.Repositories.GetContents(ctx, "o", "r", "some directory+name/file.go", &RepositoryContentGetOptions{})
   477  	if err != nil {
   478  		t.Fatalf("Repositories.GetContents returned error: %v", err)
   479  	}
   480  }
   481  
   482  func TestRepositoriesService_GetContents_Directory(t *testing.T) {
   483  	client, mux, _, teardown := setup()
   484  	defer teardown()
   485  	mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
   486  		testMethod(t, r, "GET")
   487  		fmt.Fprint(w, `[{
   488  		  "type": "dir",
   489  		  "name": "lib",
   490  		  "path": "lib"
   491  		},
   492  		{
   493  		  "type": "file",
   494  		  "size": 20678,
   495  		  "name": "LICENSE",
   496  		  "path": "LICENSE"
   497  		}]`)
   498  	})
   499  	ctx := context.Background()
   500  	_, directoryContents, _, err := client.Repositories.GetContents(ctx, "o", "r", "p", &RepositoryContentGetOptions{})
   501  	if err != nil {
   502  		t.Errorf("Repositories.GetContents returned error: %v", err)
   503  	}
   504  	want := []*RepositoryContent{{Type: String("dir"), Name: String("lib"), Path: String("lib")},
   505  		{Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Path: String("LICENSE")}}
   506  	if !cmp.Equal(directoryContents, want) {
   507  		t.Errorf("Repositories.GetContents_Directory returned %+v, want %+v", directoryContents, want)
   508  	}
   509  }
   510  
   511  func TestRepositoriesService_CreateFile(t *testing.T) {
   512  	client, mux, _, teardown := setup()
   513  	defer teardown()
   514  	mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
   515  		testMethod(t, r, "PUT")
   516  		fmt.Fprint(w, `{
   517  			"content":{
   518  				"name":"p"
   519  			},
   520  			"commit":{
   521  				"message":"m",
   522  				"sha":"f5f369044773ff9c6383c087466d12adb6fa0828"
   523  			}
   524  		}`)
   525  	})
   526  	message := "m"
   527  	content := []byte("c")
   528  	repositoryContentsOptions := &RepositoryContentFileOptions{
   529  		Message:   &message,
   530  		Content:   content,
   531  		Committer: &CommitAuthor{Name: String("n"), Email: String("e")},
   532  	}
   533  	ctx := context.Background()
   534  	createResponse, _, err := client.Repositories.CreateFile(ctx, "o", "r", "p", repositoryContentsOptions)
   535  	if err != nil {
   536  		t.Errorf("Repositories.CreateFile returned error: %v", err)
   537  	}
   538  	want := &RepositoryContentResponse{
   539  		Content: &RepositoryContent{Name: String("p")},
   540  		Commit: Commit{
   541  			Message: String("m"),
   542  			SHA:     String("f5f369044773ff9c6383c087466d12adb6fa0828"),
   543  		},
   544  	}
   545  	if !cmp.Equal(createResponse, want) {
   546  		t.Errorf("Repositories.CreateFile returned %+v, want %+v", createResponse, want)
   547  	}
   548  
   549  	const methodName = "CreateFile"
   550  	testBadOptions(t, methodName, func() (err error) {
   551  		_, _, err = client.Repositories.CreateFile(ctx, "\n", "\n", "\n", repositoryContentsOptions)
   552  		return err
   553  	})
   554  
   555  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   556  		got, resp, err := client.Repositories.CreateFile(ctx, "o", "r", "p", repositoryContentsOptions)
   557  		if got != nil {
   558  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   559  		}
   560  		return resp, err
   561  	})
   562  }
   563  
   564  func TestRepositoriesService_UpdateFile(t *testing.T) {
   565  	client, mux, _, teardown := setup()
   566  	defer teardown()
   567  	mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
   568  		testMethod(t, r, "PUT")
   569  		fmt.Fprint(w, `{
   570  			"content":{
   571  				"name":"p"
   572  			},
   573  			"commit":{
   574  				"message":"m",
   575  				"sha":"f5f369044773ff9c6383c087466d12adb6fa0828"
   576  			}
   577  		}`)
   578  	})
   579  	message := "m"
   580  	content := []byte("c")
   581  	sha := "f5f369044773ff9c6383c087466d12adb6fa0828"
   582  	repositoryContentsOptions := &RepositoryContentFileOptions{
   583  		Message:   &message,
   584  		Content:   content,
   585  		SHA:       &sha,
   586  		Committer: &CommitAuthor{Name: String("n"), Email: String("e")},
   587  	}
   588  	ctx := context.Background()
   589  	updateResponse, _, err := client.Repositories.UpdateFile(ctx, "o", "r", "p", repositoryContentsOptions)
   590  	if err != nil {
   591  		t.Errorf("Repositories.UpdateFile returned error: %v", err)
   592  	}
   593  	want := &RepositoryContentResponse{
   594  		Content: &RepositoryContent{Name: String("p")},
   595  		Commit: Commit{
   596  			Message: String("m"),
   597  			SHA:     String("f5f369044773ff9c6383c087466d12adb6fa0828"),
   598  		},
   599  	}
   600  	if !cmp.Equal(updateResponse, want) {
   601  		t.Errorf("Repositories.UpdateFile returned %+v, want %+v", updateResponse, want)
   602  	}
   603  
   604  	const methodName = "UpdateFile"
   605  	testBadOptions(t, methodName, func() (err error) {
   606  		_, _, err = client.Repositories.UpdateFile(ctx, "\n", "\n", "\n", repositoryContentsOptions)
   607  		return err
   608  	})
   609  
   610  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   611  		got, resp, err := client.Repositories.UpdateFile(ctx, "o", "r", "p", repositoryContentsOptions)
   612  		if got != nil {
   613  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   614  		}
   615  		return resp, err
   616  	})
   617  }
   618  
   619  func TestRepositoriesService_DeleteFile(t *testing.T) {
   620  	client, mux, _, teardown := setup()
   621  	defer teardown()
   622  	mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
   623  		testMethod(t, r, "DELETE")
   624  		fmt.Fprint(w, `{
   625  			"content": null,
   626  			"commit":{
   627  				"message":"m",
   628  				"sha":"f5f369044773ff9c6383c087466d12adb6fa0828"
   629  			}
   630  		}`)
   631  	})
   632  	message := "m"
   633  	sha := "f5f369044773ff9c6383c087466d12adb6fa0828"
   634  	repositoryContentsOptions := &RepositoryContentFileOptions{
   635  		Message:   &message,
   636  		SHA:       &sha,
   637  		Committer: &CommitAuthor{Name: String("n"), Email: String("e")},
   638  	}
   639  	ctx := context.Background()
   640  	deleteResponse, _, err := client.Repositories.DeleteFile(ctx, "o", "r", "p", repositoryContentsOptions)
   641  	if err != nil {
   642  		t.Errorf("Repositories.DeleteFile returned error: %v", err)
   643  	}
   644  	want := &RepositoryContentResponse{
   645  		Content: nil,
   646  		Commit: Commit{
   647  			Message: String("m"),
   648  			SHA:     String("f5f369044773ff9c6383c087466d12adb6fa0828"),
   649  		},
   650  	}
   651  	if !cmp.Equal(deleteResponse, want) {
   652  		t.Errorf("Repositories.DeleteFile returned %+v, want %+v", deleteResponse, want)
   653  	}
   654  
   655  	const methodName = "DeleteFile"
   656  	testBadOptions(t, methodName, func() (err error) {
   657  		_, _, err = client.Repositories.DeleteFile(ctx, "\n", "\n", "\n", repositoryContentsOptions)
   658  		return err
   659  	})
   660  
   661  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   662  		got, resp, err := client.Repositories.DeleteFile(ctx, "o", "r", "p", repositoryContentsOptions)
   663  		if got != nil {
   664  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   665  		}
   666  		return resp, err
   667  	})
   668  }
   669  
   670  func TestRepositoriesService_GetArchiveLink(t *testing.T) {
   671  	client, mux, _, teardown := setup()
   672  	defer teardown()
   673  	mux.HandleFunc("/repos/o/r/tarball/yo", func(w http.ResponseWriter, r *http.Request) {
   674  		testMethod(t, r, "GET")
   675  		http.Redirect(w, r, "http://github.com/a", http.StatusFound)
   676  	})
   677  	ctx := context.Background()
   678  	url, resp, err := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{Ref: "yo"}, true)
   679  	if err != nil {
   680  		t.Errorf("Repositories.GetArchiveLink returned error: %v", err)
   681  	}
   682  	if resp.StatusCode != http.StatusFound {
   683  		t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusFound)
   684  	}
   685  	want := "http://github.com/a"
   686  	if url.String() != want {
   687  		t.Errorf("Repositories.GetArchiveLink returned %+v, want %+v", url.String(), want)
   688  	}
   689  
   690  	const methodName = "GetArchiveLink"
   691  	testBadOptions(t, methodName, func() (err error) {
   692  		_, _, err = client.Repositories.GetArchiveLink(ctx, "\n", "\n", Tarball, &RepositoryContentGetOptions{}, true)
   693  		return err
   694  	})
   695  
   696  	// Add custom round tripper
   697  	client.client.Transport = roundTripperFunc(func(r *http.Request) (*http.Response, error) {
   698  		return nil, errors.New("failed to get archive link")
   699  	})
   700  	testBadOptions(t, methodName, func() (err error) {
   701  		_, _, err = client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, true)
   702  		return err
   703  	})
   704  }
   705  
   706  func TestRepositoriesService_GetArchiveLink_StatusMovedPermanently_dontFollowRedirects(t *testing.T) {
   707  	client, mux, _, teardown := setup()
   708  	defer teardown()
   709  	mux.HandleFunc("/repos/o/r/tarball", func(w http.ResponseWriter, r *http.Request) {
   710  		testMethod(t, r, "GET")
   711  		http.Redirect(w, r, "http://github.com/a", http.StatusMovedPermanently)
   712  	})
   713  	ctx := context.Background()
   714  	_, resp, _ := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, false)
   715  	if resp.StatusCode != http.StatusMovedPermanently {
   716  		t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusMovedPermanently)
   717  	}
   718  }
   719  
   720  func TestRepositoriesService_GetArchiveLink_StatusMovedPermanently_followRedirects(t *testing.T) {
   721  	client, mux, serverURL, teardown := setup()
   722  	defer teardown()
   723  	// Mock a redirect link, which leads to an archive link
   724  	mux.HandleFunc("/repos/o/r/tarball", func(w http.ResponseWriter, r *http.Request) {
   725  		testMethod(t, r, "GET")
   726  		redirectURL, _ := url.Parse(serverURL + baseURLPath + "/redirect")
   727  		http.Redirect(w, r, redirectURL.String(), http.StatusMovedPermanently)
   728  	})
   729  	mux.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
   730  		testMethod(t, r, "GET")
   731  		http.Redirect(w, r, "http://github.com/a", http.StatusFound)
   732  	})
   733  	ctx := context.Background()
   734  	url, resp, err := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, true)
   735  	if err != nil {
   736  		t.Errorf("Repositories.GetArchiveLink returned error: %v", err)
   737  	}
   738  	if resp.StatusCode != http.StatusFound {
   739  		t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusFound)
   740  	}
   741  	want := "http://github.com/a"
   742  	if url.String() != want {
   743  		t.Errorf("Repositories.GetArchiveLink returned %+v, want %+v", url.String(), want)
   744  	}
   745  }
   746  
   747  func TestRepositoriesService_GetArchiveLink_invalidLocationHeader(t *testing.T) {
   748  	client, mux, _, teardown := setup()
   749  	defer teardown()
   750  
   751  	mux.HandleFunc("/repos/o/r/tarball", func(w http.ResponseWriter, r *http.Request) {
   752  		testMethod(t, r, "GET")
   753  		ctlChar := 0x7f
   754  		badURL := "https://google.com" + string(byte(ctlChar))
   755  		w.Header().Add("Location", badURL)
   756  		w.WriteHeader(http.StatusFound)
   757  	})
   758  
   759  	ctx := context.Background()
   760  	_, _, err := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, false)
   761  	testURLParseError(t, err)
   762  }
   763  
   764  func TestRepositoriesService_GetContents_NoTrailingSlashInDirectoryApiPath(t *testing.T) {
   765  	client, mux, _, teardown := setup()
   766  	defer teardown()
   767  	mux.HandleFunc("/repos/o/r/contents/.github", func(w http.ResponseWriter, r *http.Request) {
   768  		testMethod(t, r, "GET")
   769  		query := r.URL.Query()
   770  		if query.Get("ref") != "mybranch" {
   771  			t.Errorf("Repositories.GetContents returned %+v, want %+v", query.Get("ref"), "mybranch")
   772  		}
   773  		fmt.Fprint(w, `{}`)
   774  	})
   775  	ctx := context.Background()
   776  	_, _, _, err := client.Repositories.GetContents(ctx, "o", "r", ".github/", &RepositoryContentGetOptions{
   777  		Ref: "mybranch",
   778  	})
   779  	if err != nil {
   780  		t.Fatalf("Repositories.GetContents returned error: %v", err)
   781  	}
   782  }
   783  
   784  func TestRepositoryContent_Marshal(t *testing.T) {
   785  	testJSONMarshal(t, &RepositoryContent{}, "{}")
   786  
   787  	r := &RepositoryContent{
   788  		Type:        String("type"),
   789  		Target:      String("target"),
   790  		Encoding:    String("encoding"),
   791  		Size:        Int(1),
   792  		Name:        String("name"),
   793  		Path:        String("path"),
   794  		Content:     String("content"),
   795  		SHA:         String("sha"),
   796  		URL:         String("url"),
   797  		GitURL:      String("gurl"),
   798  		HTMLURL:     String("hurl"),
   799  		DownloadURL: String("durl"),
   800  	}
   801  
   802  	want := `{
   803  		"type": "type",
   804  		"target": "target",
   805  		"encoding": "encoding",
   806  		"size": 1,
   807  		"name": "name",
   808  		"path": "path",
   809  		"content": "content",
   810  		"sha": "sha",
   811  		"url": "url",
   812  		"git_url": "gurl",
   813  		"html_url": "hurl",
   814  		"download_url": "durl"
   815  	}`
   816  
   817  	testJSONMarshal(t, r, want)
   818  }
   819  
   820  func TestRepositoryContentResponse_Marshal(t *testing.T) {
   821  	testJSONMarshal(t, &RepositoryContentResponse{}, "{}")
   822  
   823  	r := &RepositoryContentResponse{
   824  		Content: &RepositoryContent{
   825  			Type:        String("type"),
   826  			Target:      String("target"),
   827  			Encoding:    String("encoding"),
   828  			Size:        Int(1),
   829  			Name:        String("name"),
   830  			Path:        String("path"),
   831  			Content:     String("content"),
   832  			SHA:         String("sha"),
   833  			URL:         String("url"),
   834  			GitURL:      String("gurl"),
   835  			HTMLURL:     String("hurl"),
   836  			DownloadURL: String("durl"),
   837  		},
   838  		Commit: Commit{
   839  			SHA: String("s"),
   840  			Author: &CommitAuthor{
   841  				Date:  &referenceTime,
   842  				Name:  String("n"),
   843  				Email: String("e"),
   844  				Login: String("u"),
   845  			},
   846  			Committer: &CommitAuthor{
   847  				Date:  &referenceTime,
   848  				Name:  String("n"),
   849  				Email: String("e"),
   850  				Login: String("u"),
   851  			},
   852  			Message: String("m"),
   853  			Tree: &Tree{
   854  				SHA: String("s"),
   855  				Entries: []*TreeEntry{{
   856  					SHA:     String("s"),
   857  					Path:    String("p"),
   858  					Mode:    String("m"),
   859  					Type:    String("t"),
   860  					Size:    Int(1),
   861  					Content: String("c"),
   862  					URL:     String("u"),
   863  				}},
   864  				Truncated: Bool(false),
   865  			},
   866  			Parents: nil,
   867  			Stats: &CommitStats{
   868  				Additions: Int(1),
   869  				Deletions: Int(1),
   870  				Total:     Int(1),
   871  			},
   872  			HTMLURL: String("h"),
   873  			URL:     String("u"),
   874  			Verification: &SignatureVerification{
   875  				Verified:  Bool(false),
   876  				Reason:    String("r"),
   877  				Signature: String("s"),
   878  				Payload:   String("p"),
   879  			},
   880  			NodeID:       String("n"),
   881  			CommentCount: Int(1),
   882  			SigningKey:   &openpgp.Entity{},
   883  		},
   884  	}
   885  
   886  	want := `{
   887  		"content": {
   888  			"type": "type",
   889  			"target": "target",
   890  			"encoding": "encoding",
   891  			"size": 1,
   892  			"name": "name",
   893  			"path": "path",
   894  			"content": "content",
   895  			"sha": "sha",
   896  			"url": "url",
   897  			"git_url": "gurl",
   898  			"html_url": "hurl",
   899  			"download_url": "durl"
   900  		},
   901  		"commit": {
   902  			"sha": "s",
   903  			"author": {
   904  				"date": ` + referenceTimeStr + `,
   905  				"name": "n",
   906  				"email": "e",
   907  				"username": "u"
   908  			},
   909  			"committer": {
   910  				"date": ` + referenceTimeStr + `,
   911  				"name": "n",
   912  				"email": "e",
   913  				"username": "u"
   914  			},
   915  			"message": "m",
   916  			"tree": {
   917  				"sha": "s",
   918  				"tree": [
   919  					{
   920  						"sha": "s",
   921  						"path": "p",
   922  						"mode": "m",
   923  						"type": "t",
   924  						"size": 1,
   925  						"content": "c",
   926  						"url": "u"
   927  					}
   928  				],
   929  				"truncated": false
   930  			},
   931  			"stats": {
   932  				"additions": 1,
   933  				"deletions": 1,
   934  				"total": 1
   935  			},
   936  			"html_url": "h",
   937  			"url": "u",
   938  			"verification": {
   939  				"verified": false,
   940  				"reason": "r",
   941  				"signature": "s",
   942  				"payload": "p"
   943  			},
   944  			"node_id": "n",
   945  			"comment_count": 1
   946  		}
   947  	}`
   948  
   949  	testJSONMarshal(t, r, want)
   950  }
   951  
   952  func TestRepositoryContentFileOptions_Marshal(t *testing.T) {
   953  	testJSONMarshal(t, &RepositoryContentFileOptions{}, "{}")
   954  
   955  	r := &RepositoryContentFileOptions{
   956  		Message: String("type"),
   957  		Content: []byte{1},
   958  		SHA:     String("type"),
   959  		Branch:  String("type"),
   960  		Author: &CommitAuthor{
   961  			Date:  &referenceTime,
   962  			Name:  String("name"),
   963  			Email: String("email"),
   964  			Login: String("login"),
   965  		},
   966  		Committer: &CommitAuthor{
   967  			Date:  &referenceTime,
   968  			Name:  String("name"),
   969  			Email: String("email"),
   970  			Login: String("login"),
   971  		},
   972  	}
   973  
   974  	want := `{
   975  		"message": "type",
   976  		"content": "AQ==",
   977  		"sha": "type",
   978  		"branch": "type",
   979  		"author": {
   980  			"date": ` + referenceTimeStr + `,
   981  			"name": "name",
   982  			"email": "email",
   983  			"username": "login"
   984  		},
   985  		"committer": {
   986  			"date": ` + referenceTimeStr + `,
   987  			"name": "name",
   988  			"email": "email",
   989  			"username": "login"
   990  		}
   991  	}`
   992  
   993  	testJSONMarshal(t, r, want)
   994  }
   995  

View as plain text