github.com/secman-team/gh-api@v1.8.2/pkg/cmd/api/http_test.go (about)

     1  package api
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  func Test_groupGraphQLVariables(t *testing.T) {
    13  	tests := []struct {
    14  		name string
    15  		args map[string]interface{}
    16  		want map[string]interface{}
    17  	}{
    18  		{
    19  			name: "empty",
    20  			args: map[string]interface{}{},
    21  			want: map[string]interface{}{},
    22  		},
    23  		{
    24  			name: "query only",
    25  			args: map[string]interface{}{
    26  				"query": "QUERY",
    27  			},
    28  			want: map[string]interface{}{
    29  				"query": "QUERY",
    30  			},
    31  		},
    32  		{
    33  			name: "variables only",
    34  			args: map[string]interface{}{
    35  				"name": "hubot",
    36  			},
    37  			want: map[string]interface{}{
    38  				"variables": map[string]interface{}{
    39  					"name": "hubot",
    40  				},
    41  			},
    42  		},
    43  		{
    44  			name: "query + variables",
    45  			args: map[string]interface{}{
    46  				"query": "QUERY",
    47  				"name":  "hubot",
    48  				"power": 9001,
    49  			},
    50  			want: map[string]interface{}{
    51  				"query": "QUERY",
    52  				"variables": map[string]interface{}{
    53  					"name":  "hubot",
    54  					"power": 9001,
    55  				},
    56  			},
    57  		},
    58  		{
    59  			name: "query + operationName + variables",
    60  			args: map[string]interface{}{
    61  				"query":         "query Q1{} query Q2{}",
    62  				"operationName": "Q1",
    63  				"power":         9001,
    64  			},
    65  			want: map[string]interface{}{
    66  				"query":         "query Q1{} query Q2{}",
    67  				"operationName": "Q1",
    68  				"variables": map[string]interface{}{
    69  					"power": 9001,
    70  				},
    71  			},
    72  		},
    73  	}
    74  	for _, tt := range tests {
    75  		t.Run(tt.name, func(t *testing.T) {
    76  			got := groupGraphQLVariables(tt.args)
    77  			assert.Equal(t, tt.want, got)
    78  		})
    79  	}
    80  }
    81  
    82  type roundTripper func(*http.Request) (*http.Response, error)
    83  
    84  func (f roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
    85  	return f(req)
    86  }
    87  
    88  func Test_httpRequest(t *testing.T) {
    89  	var tr roundTripper = func(req *http.Request) (*http.Response, error) {
    90  		return &http.Response{Request: req}, nil
    91  	}
    92  	httpClient := http.Client{Transport: tr}
    93  
    94  	type args struct {
    95  		client  *http.Client
    96  		host    string
    97  		method  string
    98  		p       string
    99  		params  interface{}
   100  		headers []string
   101  	}
   102  	type expects struct {
   103  		method  string
   104  		u       string
   105  		body    string
   106  		headers string
   107  	}
   108  	tests := []struct {
   109  		name    string
   110  		args    args
   111  		want    expects
   112  		wantErr bool
   113  	}{
   114  		{
   115  			name: "simple GET",
   116  			args: args{
   117  				client:  &httpClient,
   118  				host:    "github.com",
   119  				method:  "GET",
   120  				p:       "repos/octocat/spoon-knife",
   121  				params:  nil,
   122  				headers: []string{},
   123  			},
   124  			wantErr: false,
   125  			want: expects{
   126  				method:  "GET",
   127  				u:       "https://api.github.com/repos/octocat/spoon-knife",
   128  				body:    "",
   129  				headers: "",
   130  			},
   131  		},
   132  		{
   133  			name: "GET with leading slash",
   134  			args: args{
   135  				client:  &httpClient,
   136  				host:    "github.com",
   137  				method:  "GET",
   138  				p:       "/repos/octocat/spoon-knife",
   139  				params:  nil,
   140  				headers: []string{},
   141  			},
   142  			wantErr: false,
   143  			want: expects{
   144  				method:  "GET",
   145  				u:       "https://api.github.com/repos/octocat/spoon-knife",
   146  				body:    "",
   147  				headers: "",
   148  			},
   149  		},
   150  		{
   151  			name: "Enterprise REST",
   152  			args: args{
   153  				client:  &httpClient,
   154  				host:    "example.org",
   155  				method:  "GET",
   156  				p:       "repos/octocat/spoon-knife",
   157  				params:  nil,
   158  				headers: []string{},
   159  			},
   160  			wantErr: false,
   161  			want: expects{
   162  				method:  "GET",
   163  				u:       "https://example.org/api/v3/repos/octocat/spoon-knife",
   164  				body:    "",
   165  				headers: "",
   166  			},
   167  		},
   168  		{
   169  			name: "GET with params",
   170  			args: args{
   171  				client: &httpClient,
   172  				host:   "github.com",
   173  				method: "GET",
   174  				p:      "repos/octocat/spoon-knife",
   175  				params: map[string]interface{}{
   176  					"a": "b",
   177  				},
   178  				headers: []string{},
   179  			},
   180  			wantErr: false,
   181  			want: expects{
   182  				method:  "GET",
   183  				u:       "https://api.github.com/repos/octocat/spoon-knife?a=b",
   184  				body:    "",
   185  				headers: "",
   186  			},
   187  		},
   188  		{
   189  			name: "POST with params",
   190  			args: args{
   191  				client: &httpClient,
   192  				host:   "github.com",
   193  				method: "POST",
   194  				p:      "repos",
   195  				params: map[string]interface{}{
   196  					"a": "b",
   197  				},
   198  				headers: []string{},
   199  			},
   200  			wantErr: false,
   201  			want: expects{
   202  				method:  "POST",
   203  				u:       "https://api.github.com/repos",
   204  				body:    `{"a":"b"}`,
   205  				headers: "Content-Type: application/json; charset=utf-8\r\n",
   206  			},
   207  		},
   208  		{
   209  			name: "POST GraphQL",
   210  			args: args{
   211  				client: &httpClient,
   212  				host:   "github.com",
   213  				method: "POST",
   214  				p:      "graphql",
   215  				params: map[string]interface{}{
   216  					"a": []byte("b"),
   217  				},
   218  				headers: []string{},
   219  			},
   220  			wantErr: false,
   221  			want: expects{
   222  				method:  "POST",
   223  				u:       "https://api.github.com/graphql",
   224  				body:    `{"variables":{"a":"b"}}`,
   225  				headers: "Content-Type: application/json; charset=utf-8\r\n",
   226  			},
   227  		},
   228  		{
   229  			name: "Enterprise GraphQL",
   230  			args: args{
   231  				client:  &httpClient,
   232  				host:    "example.org",
   233  				method:  "POST",
   234  				p:       "graphql",
   235  				params:  map[string]interface{}{},
   236  				headers: []string{},
   237  			},
   238  			wantErr: false,
   239  			want: expects{
   240  				method:  "POST",
   241  				u:       "https://example.org/api/graphql",
   242  				body:    `{}`,
   243  				headers: "Content-Type: application/json; charset=utf-8\r\n",
   244  			},
   245  		},
   246  		{
   247  			name: "POST with body and type",
   248  			args: args{
   249  				client: &httpClient,
   250  				host:   "github.com",
   251  				method: "POST",
   252  				p:      "repos",
   253  				params: bytes.NewBufferString("CUSTOM"),
   254  				headers: []string{
   255  					"content-type: text/plain",
   256  					"accept: application/json",
   257  				},
   258  			},
   259  			wantErr: false,
   260  			want: expects{
   261  				method:  "POST",
   262  				u:       "https://api.github.com/repos",
   263  				body:    `CUSTOM`,
   264  				headers: "Accept: application/json\r\nContent-Type: text/plain\r\n",
   265  			},
   266  		},
   267  	}
   268  	for _, tt := range tests {
   269  		t.Run(tt.name, func(t *testing.T) {
   270  			got, err := httpRequest(tt.args.client, tt.args.host, tt.args.method, tt.args.p, tt.args.params, tt.args.headers)
   271  			if (err != nil) != tt.wantErr {
   272  				t.Errorf("httpRequest() error = %v, wantErr %v", err, tt.wantErr)
   273  				return
   274  			}
   275  			req := got.Request
   276  			if req.Method != tt.want.method {
   277  				t.Errorf("Request.Method = %q, want %q", req.Method, tt.want.method)
   278  			}
   279  			if req.URL.String() != tt.want.u {
   280  				t.Errorf("Request.URL = %q, want %q", req.URL.String(), tt.want.u)
   281  			}
   282  
   283  			if tt.want.body != "" {
   284  				bb, err := ioutil.ReadAll(req.Body)
   285  				if err != nil {
   286  					t.Errorf("Request.Body ReadAll error = %v", err)
   287  					return
   288  				}
   289  				if string(bb) != tt.want.body {
   290  					t.Errorf("Request.Body = %q, want %q", string(bb), tt.want.body)
   291  				}
   292  			}
   293  
   294  			h := bytes.Buffer{}
   295  			err = req.Header.WriteSubset(&h, map[string]bool{})
   296  			if err != nil {
   297  				t.Errorf("Request.Header WriteSubset error = %v", err)
   298  				return
   299  			}
   300  			if h.String() != tt.want.headers {
   301  				t.Errorf("Request.Header = %q, want %q", h.String(), tt.want.headers)
   302  			}
   303  		})
   304  	}
   305  }
   306  
   307  func Test_addQuery(t *testing.T) {
   308  	type args struct {
   309  		path   string
   310  		params map[string]interface{}
   311  	}
   312  	tests := []struct {
   313  		name string
   314  		args args
   315  		want string
   316  	}{
   317  		{
   318  			name: "string",
   319  			args: args{
   320  				path:   "",
   321  				params: map[string]interface{}{"a": "hello"},
   322  			},
   323  			want: "?a=hello",
   324  		},
   325  		{
   326  			name: "append",
   327  			args: args{
   328  				path:   "path",
   329  				params: map[string]interface{}{"a": "b"},
   330  			},
   331  			want: "path?a=b",
   332  		},
   333  		{
   334  			name: "append query",
   335  			args: args{
   336  				path:   "path?foo=bar",
   337  				params: map[string]interface{}{"a": "b"},
   338  			},
   339  			want: "path?foo=bar&a=b",
   340  		},
   341  		{
   342  			name: "[]byte",
   343  			args: args{
   344  				path:   "",
   345  				params: map[string]interface{}{"a": []byte("hello")},
   346  			},
   347  			want: "?a=hello",
   348  		},
   349  		{
   350  			name: "int",
   351  			args: args{
   352  				path:   "",
   353  				params: map[string]interface{}{"a": 123},
   354  			},
   355  			want: "?a=123",
   356  		},
   357  		{
   358  			name: "nil",
   359  			args: args{
   360  				path:   "",
   361  				params: map[string]interface{}{"a": nil},
   362  			},
   363  			want: "?a=",
   364  		},
   365  		{
   366  			name: "bool",
   367  			args: args{
   368  				path:   "",
   369  				params: map[string]interface{}{"a": true, "b": false},
   370  			},
   371  			want: "?a=true&b=false",
   372  		},
   373  	}
   374  	for _, tt := range tests {
   375  		t.Run(tt.name, func(t *testing.T) {
   376  			if got := addQuery(tt.args.path, tt.args.params); got != tt.want {
   377  				t.Errorf("addQuery() = %v, want %v", got, tt.want)
   378  			}
   379  		})
   380  	}
   381  }