github.com/cli/cli@v1.14.1-0.20210902173923-1af6a669e342/api/client_test.go (about)

     1  package api
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"testing"
     9  
    10  	"github.com/cli/cli/pkg/httpmock"
    11  	"github.com/stretchr/testify/assert"
    12  )
    13  
    14  func TestGraphQL(t *testing.T) {
    15  	http := &httpmock.Registry{}
    16  	client := NewClient(
    17  		ReplaceTripper(http),
    18  		AddHeader("Authorization", "token OTOKEN"),
    19  	)
    20  
    21  	vars := map[string]interface{}{"name": "Mona"}
    22  	response := struct {
    23  		Viewer struct {
    24  			Login string
    25  		}
    26  	}{}
    27  
    28  	http.Register(
    29  		httpmock.GraphQL("QUERY"),
    30  		httpmock.StringResponse(`{"data":{"viewer":{"login":"hubot"}}}`),
    31  	)
    32  
    33  	err := client.GraphQL("github.com", "QUERY", vars, &response)
    34  	assert.NoError(t, err)
    35  	assert.Equal(t, "hubot", response.Viewer.Login)
    36  
    37  	req := http.Requests[0]
    38  	reqBody, _ := ioutil.ReadAll(req.Body)
    39  	assert.Equal(t, `{"query":"QUERY","variables":{"name":"Mona"}}`, string(reqBody))
    40  	assert.Equal(t, "token OTOKEN", req.Header.Get("Authorization"))
    41  }
    42  
    43  func TestGraphQLError(t *testing.T) {
    44  	http := &httpmock.Registry{}
    45  	client := NewClient(ReplaceTripper(http))
    46  
    47  	response := struct{}{}
    48  
    49  	http.Register(
    50  		httpmock.GraphQL(""),
    51  		httpmock.StringResponse(`
    52  			{ "errors": [
    53  				{"message":"OH NO"},
    54  				{"message":"this is fine"}
    55  			  ]
    56  			}
    57  		`),
    58  	)
    59  
    60  	err := client.GraphQL("github.com", "", nil, &response)
    61  	if err == nil || err.Error() != "GraphQL error: OH NO\nthis is fine" {
    62  		t.Fatalf("got %q", err.Error())
    63  	}
    64  }
    65  
    66  func TestRESTGetDelete(t *testing.T) {
    67  	http := &httpmock.Registry{}
    68  
    69  	client := NewClient(
    70  		ReplaceTripper(http),
    71  	)
    72  
    73  	http.Register(
    74  		httpmock.REST("DELETE", "applications/CLIENTID/grant"),
    75  		httpmock.StatusStringResponse(204, "{}"),
    76  	)
    77  
    78  	r := bytes.NewReader([]byte(`{}`))
    79  	err := client.REST("github.com", "DELETE", "applications/CLIENTID/grant", r, nil)
    80  	assert.NoError(t, err)
    81  }
    82  
    83  func TestRESTWithFullURL(t *testing.T) {
    84  	http := &httpmock.Registry{}
    85  	client := NewClient(ReplaceTripper(http))
    86  
    87  	http.Register(
    88  		httpmock.REST("GET", "api/v3/user/repos"),
    89  		httpmock.StatusStringResponse(200, "{}"))
    90  	http.Register(
    91  		httpmock.REST("GET", "user/repos"),
    92  		httpmock.StatusStringResponse(200, "{}"))
    93  
    94  	err := client.REST("example.com", "GET", "user/repos", nil, nil)
    95  	assert.NoError(t, err)
    96  	err = client.REST("example.com", "GET", "https://another.net/user/repos", nil, nil)
    97  	assert.NoError(t, err)
    98  
    99  	assert.Equal(t, "example.com", http.Requests[0].URL.Hostname())
   100  	assert.Equal(t, "another.net", http.Requests[1].URL.Hostname())
   101  }
   102  
   103  func TestRESTError(t *testing.T) {
   104  	fakehttp := &httpmock.Registry{}
   105  	client := NewClient(ReplaceTripper(fakehttp))
   106  
   107  	fakehttp.Register(httpmock.MatchAny, func(req *http.Request) (*http.Response, error) {
   108  		return &http.Response{
   109  			Request:    req,
   110  			StatusCode: 422,
   111  			Body:       ioutil.NopCloser(bytes.NewBufferString(`{"message": "OH NO"}`)),
   112  			Header: map[string][]string{
   113  				"Content-Type": {"application/json; charset=utf-8"},
   114  			},
   115  		}, nil
   116  	})
   117  
   118  	var httpErr HTTPError
   119  	err := client.REST("github.com", "DELETE", "repos/branch", nil, nil)
   120  	if err == nil || !errors.As(err, &httpErr) {
   121  		t.Fatalf("got %v", err)
   122  	}
   123  
   124  	if httpErr.StatusCode != 422 {
   125  		t.Errorf("expected status code 422, got %d", httpErr.StatusCode)
   126  	}
   127  	if httpErr.Error() != "HTTP 422: OH NO (https://api.github.com/repos/branch)" {
   128  		t.Errorf("got %q", httpErr.Error())
   129  
   130  	}
   131  }
   132  
   133  func TestHandleHTTPError_GraphQL502(t *testing.T) {
   134  	req, err := http.NewRequest("GET", "https://api.github.com/user", nil)
   135  	if err != nil {
   136  		t.Fatal(err)
   137  	}
   138  	resp := &http.Response{
   139  		Request:    req,
   140  		StatusCode: 502,
   141  		Body:       ioutil.NopCloser(bytes.NewBufferString(`{ "data": null, "errors": [{ "message": "Something went wrong" }] }`)),
   142  		Header:     map[string][]string{"Content-Type": {"application/json"}},
   143  	}
   144  	err = HandleHTTPError(resp)
   145  	if err == nil || err.Error() != "HTTP 502: Something went wrong (https://api.github.com/user)" {
   146  		t.Errorf("got error: %v", err)
   147  	}
   148  }