...

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

Documentation: github.com/google/go-github/v55/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"
    13  	"net/http"
    14  	"net/url"
    15  	"testing"
    16  
    17  	"github.com/ProtonMail/go-crypto/openpgp"
    18  	"github.com/google/go-cmp/cmp"
    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 := io.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 := io.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 := io.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 := io.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_PathWithParent(t *testing.T) {
   469  	client, mux, _, teardown := setup()
   470  	defer teardown()
   471  	mux.HandleFunc("/repos/o/r/contents/some/../directory/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/file.go", &RepositoryContentGetOptions{})
   477  	if err == nil {
   478  		t.Fatal("Repositories.GetContents expected error but got none")
   479  	}
   480  }
   481  
   482  func TestRepositoriesService_GetContents_DirectoryWithPlusChars(t *testing.T) {
   483  	client, mux, _, teardown := setup()
   484  	defer teardown()
   485  	mux.HandleFunc("/repos/o/r/contents/some directory+name/file.go", func(w http.ResponseWriter, r *http.Request) {
   486  		testMethod(t, r, "GET")
   487  		fmt.Fprint(w, `{}`)
   488  	})
   489  	ctx := context.Background()
   490  	_, _, _, err := client.Repositories.GetContents(ctx, "o", "r", "some directory+name/file.go", &RepositoryContentGetOptions{})
   491  	if err != nil {
   492  		t.Fatalf("Repositories.GetContents returned error: %v", err)
   493  	}
   494  }
   495  
   496  func TestRepositoriesService_GetContents_Directory(t *testing.T) {
   497  	client, mux, _, teardown := setup()
   498  	defer teardown()
   499  	mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
   500  		testMethod(t, r, "GET")
   501  		fmt.Fprint(w, `[{
   502  		  "type": "dir",
   503  		  "name": "lib",
   504  		  "path": "lib"
   505  		},
   506  		{
   507  		  "type": "file",
   508  		  "size": 20678,
   509  		  "name": "LICENSE",
   510  		  "path": "LICENSE"
   511  		}]`)
   512  	})
   513  	ctx := context.Background()
   514  	_, directoryContents, _, err := client.Repositories.GetContents(ctx, "o", "r", "p", &RepositoryContentGetOptions{})
   515  	if err != nil {
   516  		t.Errorf("Repositories.GetContents returned error: %v", err)
   517  	}
   518  	want := []*RepositoryContent{{Type: String("dir"), Name: String("lib"), Path: String("lib")},
   519  		{Type: String("file"), Name: String("LICENSE"), Size: Int(20678), Path: String("LICENSE")}}
   520  	if !cmp.Equal(directoryContents, want) {
   521  		t.Errorf("Repositories.GetContents_Directory returned %+v, want %+v", directoryContents, want)
   522  	}
   523  }
   524  
   525  func TestRepositoriesService_CreateFile(t *testing.T) {
   526  	client, mux, _, teardown := setup()
   527  	defer teardown()
   528  	mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
   529  		testMethod(t, r, "PUT")
   530  		fmt.Fprint(w, `{
   531  			"content":{
   532  				"name":"p"
   533  			},
   534  			"commit":{
   535  				"message":"m",
   536  				"sha":"f5f369044773ff9c6383c087466d12adb6fa0828"
   537  			}
   538  		}`)
   539  	})
   540  	message := "m"
   541  	content := []byte("c")
   542  	repositoryContentsOptions := &RepositoryContentFileOptions{
   543  		Message:   &message,
   544  		Content:   content,
   545  		Committer: &CommitAuthor{Name: String("n"), Email: String("e")},
   546  	}
   547  	ctx := context.Background()
   548  	createResponse, _, err := client.Repositories.CreateFile(ctx, "o", "r", "p", repositoryContentsOptions)
   549  	if err != nil {
   550  		t.Errorf("Repositories.CreateFile returned error: %v", err)
   551  	}
   552  	want := &RepositoryContentResponse{
   553  		Content: &RepositoryContent{Name: String("p")},
   554  		Commit: Commit{
   555  			Message: String("m"),
   556  			SHA:     String("f5f369044773ff9c6383c087466d12adb6fa0828"),
   557  		},
   558  	}
   559  	if !cmp.Equal(createResponse, want) {
   560  		t.Errorf("Repositories.CreateFile returned %+v, want %+v", createResponse, want)
   561  	}
   562  
   563  	const methodName = "CreateFile"
   564  	testBadOptions(t, methodName, func() (err error) {
   565  		_, _, err = client.Repositories.CreateFile(ctx, "\n", "\n", "\n", repositoryContentsOptions)
   566  		return err
   567  	})
   568  
   569  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   570  		got, resp, err := client.Repositories.CreateFile(ctx, "o", "r", "p", repositoryContentsOptions)
   571  		if got != nil {
   572  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   573  		}
   574  		return resp, err
   575  	})
   576  }
   577  
   578  func TestRepositoriesService_UpdateFile(t *testing.T) {
   579  	client, mux, _, teardown := setup()
   580  	defer teardown()
   581  	mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
   582  		testMethod(t, r, "PUT")
   583  		fmt.Fprint(w, `{
   584  			"content":{
   585  				"name":"p"
   586  			},
   587  			"commit":{
   588  				"message":"m",
   589  				"sha":"f5f369044773ff9c6383c087466d12adb6fa0828"
   590  			}
   591  		}`)
   592  	})
   593  	message := "m"
   594  	content := []byte("c")
   595  	sha := "f5f369044773ff9c6383c087466d12adb6fa0828"
   596  	repositoryContentsOptions := &RepositoryContentFileOptions{
   597  		Message:   &message,
   598  		Content:   content,
   599  		SHA:       &sha,
   600  		Committer: &CommitAuthor{Name: String("n"), Email: String("e")},
   601  	}
   602  	ctx := context.Background()
   603  	updateResponse, _, err := client.Repositories.UpdateFile(ctx, "o", "r", "p", repositoryContentsOptions)
   604  	if err != nil {
   605  		t.Errorf("Repositories.UpdateFile returned error: %v", err)
   606  	}
   607  	want := &RepositoryContentResponse{
   608  		Content: &RepositoryContent{Name: String("p")},
   609  		Commit: Commit{
   610  			Message: String("m"),
   611  			SHA:     String("f5f369044773ff9c6383c087466d12adb6fa0828"),
   612  		},
   613  	}
   614  	if !cmp.Equal(updateResponse, want) {
   615  		t.Errorf("Repositories.UpdateFile returned %+v, want %+v", updateResponse, want)
   616  	}
   617  
   618  	const methodName = "UpdateFile"
   619  	testBadOptions(t, methodName, func() (err error) {
   620  		_, _, err = client.Repositories.UpdateFile(ctx, "\n", "\n", "\n", repositoryContentsOptions)
   621  		return err
   622  	})
   623  
   624  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   625  		got, resp, err := client.Repositories.UpdateFile(ctx, "o", "r", "p", repositoryContentsOptions)
   626  		if got != nil {
   627  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   628  		}
   629  		return resp, err
   630  	})
   631  }
   632  
   633  func TestRepositoriesService_DeleteFile(t *testing.T) {
   634  	client, mux, _, teardown := setup()
   635  	defer teardown()
   636  	mux.HandleFunc("/repos/o/r/contents/p", func(w http.ResponseWriter, r *http.Request) {
   637  		testMethod(t, r, "DELETE")
   638  		fmt.Fprint(w, `{
   639  			"content": null,
   640  			"commit":{
   641  				"message":"m",
   642  				"sha":"f5f369044773ff9c6383c087466d12adb6fa0828"
   643  			}
   644  		}`)
   645  	})
   646  	message := "m"
   647  	sha := "f5f369044773ff9c6383c087466d12adb6fa0828"
   648  	repositoryContentsOptions := &RepositoryContentFileOptions{
   649  		Message:   &message,
   650  		SHA:       &sha,
   651  		Committer: &CommitAuthor{Name: String("n"), Email: String("e")},
   652  	}
   653  	ctx := context.Background()
   654  	deleteResponse, _, err := client.Repositories.DeleteFile(ctx, "o", "r", "p", repositoryContentsOptions)
   655  	if err != nil {
   656  		t.Errorf("Repositories.DeleteFile returned error: %v", err)
   657  	}
   658  	want := &RepositoryContentResponse{
   659  		Content: nil,
   660  		Commit: Commit{
   661  			Message: String("m"),
   662  			SHA:     String("f5f369044773ff9c6383c087466d12adb6fa0828"),
   663  		},
   664  	}
   665  	if !cmp.Equal(deleteResponse, want) {
   666  		t.Errorf("Repositories.DeleteFile returned %+v, want %+v", deleteResponse, want)
   667  	}
   668  
   669  	const methodName = "DeleteFile"
   670  	testBadOptions(t, methodName, func() (err error) {
   671  		_, _, err = client.Repositories.DeleteFile(ctx, "\n", "\n", "\n", repositoryContentsOptions)
   672  		return err
   673  	})
   674  
   675  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   676  		got, resp, err := client.Repositories.DeleteFile(ctx, "o", "r", "p", repositoryContentsOptions)
   677  		if got != nil {
   678  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   679  		}
   680  		return resp, err
   681  	})
   682  }
   683  
   684  func TestRepositoriesService_GetArchiveLink(t *testing.T) {
   685  	client, mux, _, teardown := setup()
   686  	defer teardown()
   687  	mux.HandleFunc("/repos/o/r/tarball/yo", func(w http.ResponseWriter, r *http.Request) {
   688  		testMethod(t, r, "GET")
   689  		http.Redirect(w, r, "http://github.com/a", http.StatusFound)
   690  	})
   691  	ctx := context.Background()
   692  	url, resp, err := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{Ref: "yo"}, true)
   693  	if err != nil {
   694  		t.Errorf("Repositories.GetArchiveLink returned error: %v", err)
   695  	}
   696  	if resp.StatusCode != http.StatusFound {
   697  		t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusFound)
   698  	}
   699  	want := "http://github.com/a"
   700  	if url.String() != want {
   701  		t.Errorf("Repositories.GetArchiveLink returned %+v, want %+v", url.String(), want)
   702  	}
   703  
   704  	const methodName = "GetArchiveLink"
   705  	testBadOptions(t, methodName, func() (err error) {
   706  		_, _, err = client.Repositories.GetArchiveLink(ctx, "\n", "\n", Tarball, &RepositoryContentGetOptions{}, true)
   707  		return err
   708  	})
   709  
   710  	// Add custom round tripper
   711  	client.client.Transport = roundTripperFunc(func(r *http.Request) (*http.Response, error) {
   712  		return nil, errors.New("failed to get archive link")
   713  	})
   714  	testBadOptions(t, methodName, func() (err error) {
   715  		_, _, err = client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, true)
   716  		return err
   717  	})
   718  }
   719  
   720  func TestRepositoriesService_GetArchiveLink_StatusMovedPermanently_dontFollowRedirects(t *testing.T) {
   721  	client, mux, _, teardown := setup()
   722  	defer teardown()
   723  	mux.HandleFunc("/repos/o/r/tarball", func(w http.ResponseWriter, r *http.Request) {
   724  		testMethod(t, r, "GET")
   725  		http.Redirect(w, r, "http://github.com/a", http.StatusMovedPermanently)
   726  	})
   727  	ctx := context.Background()
   728  	_, resp, _ := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, false)
   729  	if resp.StatusCode != http.StatusMovedPermanently {
   730  		t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusMovedPermanently)
   731  	}
   732  }
   733  
   734  func TestRepositoriesService_GetArchiveLink_StatusMovedPermanently_followRedirects(t *testing.T) {
   735  	client, mux, serverURL, teardown := setup()
   736  	defer teardown()
   737  	// Mock a redirect link, which leads to an archive link
   738  	mux.HandleFunc("/repos/o/r/tarball", func(w http.ResponseWriter, r *http.Request) {
   739  		testMethod(t, r, "GET")
   740  		redirectURL, _ := url.Parse(serverURL + baseURLPath + "/redirect")
   741  		http.Redirect(w, r, redirectURL.String(), http.StatusMovedPermanently)
   742  	})
   743  	mux.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
   744  		testMethod(t, r, "GET")
   745  		http.Redirect(w, r, "http://github.com/a", http.StatusFound)
   746  	})
   747  	ctx := context.Background()
   748  	url, resp, err := client.Repositories.GetArchiveLink(ctx, "o", "r", Tarball, &RepositoryContentGetOptions{}, true)
   749  	if err != nil {
   750  		t.Errorf("Repositories.GetArchiveLink returned error: %v", err)
   751  	}
   752  	if resp.StatusCode != http.StatusFound {
   753  		t.Errorf("Repositories.GetArchiveLink returned status: %d, want %d", resp.StatusCode, http.StatusFound)
   754  	}
   755  	want := "http://github.com/a"
   756  	if url.String() != want {
   757  		t.Errorf("Repositories.GetArchiveLink returned %+v, want %+v", url.String(), want)
   758  	}
   759  }
   760  
   761  func TestRepositoriesService_GetContents_NoTrailingSlashInDirectoryApiPath(t *testing.T) {
   762  	client, mux, _, teardown := setup()
   763  	defer teardown()
   764  	mux.HandleFunc("/repos/o/r/contents/.github", func(w http.ResponseWriter, r *http.Request) {
   765  		testMethod(t, r, "GET")
   766  		query := r.URL.Query()
   767  		if query.Get("ref") != "mybranch" {
   768  			t.Errorf("Repositories.GetContents returned %+v, want %+v", query.Get("ref"), "mybranch")
   769  		}
   770  		fmt.Fprint(w, `{}`)
   771  	})
   772  	ctx := context.Background()
   773  	_, _, _, err := client.Repositories.GetContents(ctx, "o", "r", ".github/", &RepositoryContentGetOptions{
   774  		Ref: "mybranch",
   775  	})
   776  	if err != nil {
   777  		t.Fatalf("Repositories.GetContents returned error: %v", err)
   778  	}
   779  }
   780  
   781  func TestRepositoryContent_Marshal(t *testing.T) {
   782  	testJSONMarshal(t, &RepositoryContent{}, "{}")
   783  
   784  	r := &RepositoryContent{
   785  		Type:            String("type"),
   786  		Target:          String("target"),
   787  		Encoding:        String("encoding"),
   788  		Size:            Int(1),
   789  		Name:            String("name"),
   790  		Path:            String("path"),
   791  		Content:         String("content"),
   792  		SHA:             String("sha"),
   793  		URL:             String("url"),
   794  		GitURL:          String("gurl"),
   795  		HTMLURL:         String("hurl"),
   796  		DownloadURL:     String("durl"),
   797  		SubmoduleGitURL: String("smgurl"),
   798  	}
   799  
   800  	want := `{
   801  		"type": "type",
   802  		"target": "target",
   803  		"encoding": "encoding",
   804  		"size": 1,
   805  		"name": "name",
   806  		"path": "path",
   807  		"content": "content",
   808  		"sha": "sha",
   809  		"url": "url",
   810  		"git_url": "gurl",
   811  		"html_url": "hurl",
   812  		"download_url": "durl",
   813  		"submodule_git_url": "smgurl"
   814  	}`
   815  
   816  	testJSONMarshal(t, r, want)
   817  }
   818  
   819  func TestRepositoryContentResponse_Marshal(t *testing.T) {
   820  	testJSONMarshal(t, &RepositoryContentResponse{}, "{}")
   821  
   822  	r := &RepositoryContentResponse{
   823  		Content: &RepositoryContent{
   824  			Type:            String("type"),
   825  			Target:          String("target"),
   826  			Encoding:        String("encoding"),
   827  			Size:            Int(1),
   828  			Name:            String("name"),
   829  			Path:            String("path"),
   830  			Content:         String("content"),
   831  			SHA:             String("sha"),
   832  			URL:             String("url"),
   833  			GitURL:          String("gurl"),
   834  			HTMLURL:         String("hurl"),
   835  			DownloadURL:     String("durl"),
   836  			SubmoduleGitURL: String("smgurl"),
   837  		},
   838  		Commit: Commit{
   839  			SHA: String("s"),
   840  			Author: &CommitAuthor{
   841  				Date:  &Timestamp{referenceTime},
   842  				Name:  String("n"),
   843  				Email: String("e"),
   844  				Login: String("u"),
   845  			},
   846  			Committer: &CommitAuthor{
   847  				Date:  &Timestamp{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  			"submodule_git_url": "smgurl"
   901  		},
   902  		"commit": {
   903  			"sha": "s",
   904  			"author": {
   905  				"date": ` + referenceTimeStr + `,
   906  				"name": "n",
   907  				"email": "e",
   908  				"username": "u"
   909  			},
   910  			"committer": {
   911  				"date": ` + referenceTimeStr + `,
   912  				"name": "n",
   913  				"email": "e",
   914  				"username": "u"
   915  			},
   916  			"message": "m",
   917  			"tree": {
   918  				"sha": "s",
   919  				"tree": [
   920  					{
   921  						"sha": "s",
   922  						"path": "p",
   923  						"mode": "m",
   924  						"type": "t",
   925  						"size": 1,
   926  						"content": "c",
   927  						"url": "u"
   928  					}
   929  				],
   930  				"truncated": false
   931  			},
   932  			"stats": {
   933  				"additions": 1,
   934  				"deletions": 1,
   935  				"total": 1
   936  			},
   937  			"html_url": "h",
   938  			"url": "u",
   939  			"verification": {
   940  				"verified": false,
   941  				"reason": "r",
   942  				"signature": "s",
   943  				"payload": "p"
   944  			},
   945  			"node_id": "n",
   946  			"comment_count": 1
   947  		}
   948  	}`
   949  
   950  	testJSONMarshal(t, r, want)
   951  }
   952  
   953  func TestRepositoryContentFileOptions_Marshal(t *testing.T) {
   954  	testJSONMarshal(t, &RepositoryContentFileOptions{}, "{}")
   955  
   956  	r := &RepositoryContentFileOptions{
   957  		Message: String("type"),
   958  		Content: []byte{1},
   959  		SHA:     String("type"),
   960  		Branch:  String("type"),
   961  		Author: &CommitAuthor{
   962  			Date:  &Timestamp{referenceTime},
   963  			Name:  String("name"),
   964  			Email: String("email"),
   965  			Login: String("login"),
   966  		},
   967  		Committer: &CommitAuthor{
   968  			Date:  &Timestamp{referenceTime},
   969  			Name:  String("name"),
   970  			Email: String("email"),
   971  			Login: String("login"),
   972  		},
   973  	}
   974  
   975  	want := `{
   976  		"message": "type",
   977  		"content": "AQ==",
   978  		"sha": "type",
   979  		"branch": "type",
   980  		"author": {
   981  			"date": ` + referenceTimeStr + `,
   982  			"name": "name",
   983  			"email": "email",
   984  			"username": "login"
   985  		},
   986  		"committer": {
   987  			"date": ` + referenceTimeStr + `,
   988  			"name": "name",
   989  			"email": "email",
   990  			"username": "login"
   991  		}
   992  	}`
   993  
   994  	testJSONMarshal(t, r, want)
   995  }
   996  

View as plain text