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 }