github.com/google/go-github/v60@v60.0.0/github/issue_import_test.go (about) 1 // Copyright 2020 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 "encoding/json" 11 "fmt" 12 "net/http" 13 "testing" 14 "time" 15 16 "github.com/google/go-cmp/cmp" 17 ) 18 19 func TestIssueImportService_Create(t *testing.T) { 20 client, mux, _, teardown := setup() 21 defer teardown() 22 23 createdAt := time.Date(2020, time.August, 11, 15, 30, 0, 0, time.UTC) 24 input := &IssueImportRequest{ 25 IssueImport: IssueImport{ 26 Assignee: String("developer"), 27 Body: "Dummy description", 28 CreatedAt: &Timestamp{createdAt}, 29 Labels: []string{"l1", "l2"}, 30 Milestone: Int(1), 31 Title: "Dummy Issue", 32 }, 33 Comments: []*Comment{{ 34 CreatedAt: &Timestamp{createdAt}, 35 Body: "Comment body", 36 }}, 37 } 38 39 mux.HandleFunc("/repos/o/r/import/issues", func(w http.ResponseWriter, r *http.Request) { 40 v := new(IssueImportRequest) 41 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 42 testMethod(t, r, "POST") 43 testHeader(t, r, "Accept", mediaTypeIssueImportAPI) 44 if !cmp.Equal(v, input) { 45 t.Errorf("Request body = %+v, want %+v", v, input) 46 } 47 48 assertWrite(t, w, issueImportResponseJSON) 49 }) 50 51 ctx := context.Background() 52 got, _, err := client.IssueImport.Create(ctx, "o", "r", input) 53 if err != nil { 54 t.Errorf("Create returned error: %v", err) 55 } 56 57 want := wantIssueImportResponse 58 if !cmp.Equal(got, want) { 59 t.Errorf("Create = %+v, want %+v", got, want) 60 } 61 62 const methodName = "Create" 63 testBadOptions(t, methodName, func() (err error) { 64 _, _, err = client.IssueImport.Create(ctx, "\n", "\n", input) 65 return err 66 }) 67 68 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 69 got, resp, err := client.IssueImport.Create(ctx, "o", "r", input) 70 if got != nil { 71 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 72 } 73 return resp, err 74 }) 75 } 76 77 func TestIssueImportService_Create_defered(t *testing.T) { 78 client, mux, _, teardown := setup() 79 defer teardown() 80 81 createdAt := time.Date(2020, time.August, 11, 15, 30, 0, 0, time.UTC) 82 input := &IssueImportRequest{ 83 IssueImport: IssueImport{ 84 Assignee: String("developer"), 85 Body: "Dummy description", 86 CreatedAt: &Timestamp{createdAt}, 87 Labels: []string{"l1", "l2"}, 88 Milestone: Int(1), 89 Title: "Dummy Issue", 90 }, 91 Comments: []*Comment{{ 92 CreatedAt: &Timestamp{createdAt}, 93 Body: "Comment body", 94 }}, 95 } 96 97 mux.HandleFunc("/repos/o/r/import/issues", func(w http.ResponseWriter, r *http.Request) { 98 v := new(IssueImportRequest) 99 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 100 testMethod(t, r, "POST") 101 testHeader(t, r, "Accept", mediaTypeIssueImportAPI) 102 if !cmp.Equal(v, input) { 103 t.Errorf("Request body = %+v, want %+v", v, input) 104 } 105 106 w.WriteHeader(http.StatusAccepted) 107 assertWrite(t, w, issueImportResponseJSON) 108 }) 109 110 ctx := context.Background() 111 got, _, err := client.IssueImport.Create(ctx, "o", "r", input) 112 113 if _, ok := err.(*AcceptedError); !ok { 114 t.Errorf("Create returned error: %v (want AcceptedError)", err) 115 } 116 117 want := wantIssueImportResponse 118 if !cmp.Equal(got, want) { 119 t.Errorf("Create = %+v, want %+v", got, want) 120 } 121 } 122 123 func TestIssueImportService_Create_badResponse(t *testing.T) { 124 client, mux, _, teardown := setup() 125 defer teardown() 126 127 createdAt := time.Date(2020, time.August, 11, 15, 30, 0, 0, time.UTC) 128 input := &IssueImportRequest{ 129 IssueImport: IssueImport{ 130 Assignee: String("developer"), 131 Body: "Dummy description", 132 CreatedAt: &Timestamp{createdAt}, 133 Labels: []string{"l1", "l2"}, 134 Milestone: Int(1), 135 Title: "Dummy Issue", 136 }, 137 Comments: []*Comment{{ 138 CreatedAt: &Timestamp{createdAt}, 139 Body: "Comment body", 140 }}, 141 } 142 143 mux.HandleFunc("/repos/o/r/import/issues", func(w http.ResponseWriter, r *http.Request) { 144 v := new(IssueImportRequest) 145 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 146 testMethod(t, r, "POST") 147 testHeader(t, r, "Accept", mediaTypeIssueImportAPI) 148 if !cmp.Equal(v, input) { 149 t.Errorf("Request body = %+v, want %+v", v, input) 150 } 151 152 w.WriteHeader(http.StatusAccepted) 153 assertWrite(t, w, []byte("{[}")) 154 }) 155 156 ctx := context.Background() 157 _, _, err := client.IssueImport.Create(ctx, "o", "r", input) 158 159 if err == nil || err.Error() != "invalid character '[' looking for beginning of object key string" { 160 t.Errorf("unexpected error: %v", err) 161 } 162 } 163 164 func TestIssueImportService_Create_invalidOwner(t *testing.T) { 165 client, _, _, teardown := setup() 166 defer teardown() 167 168 ctx := context.Background() 169 _, _, err := client.IssueImport.Create(ctx, "%", "r", nil) 170 testURLParseError(t, err) 171 } 172 173 func TestIssueImportService_CheckStatus(t *testing.T) { 174 client, mux, _, teardown := setup() 175 defer teardown() 176 177 mux.HandleFunc("/repos/o/r/import/issues/3", func(w http.ResponseWriter, r *http.Request) { 178 testMethod(t, r, "GET") 179 testHeader(t, r, "Accept", mediaTypeIssueImportAPI) 180 w.WriteHeader(http.StatusOK) 181 assertWrite(t, w, issueImportResponseJSON) 182 }) 183 184 ctx := context.Background() 185 got, _, err := client.IssueImport.CheckStatus(ctx, "o", "r", 3) 186 if err != nil { 187 t.Errorf("CheckStatus returned error: %v", err) 188 } 189 190 want := wantIssueImportResponse 191 if !cmp.Equal(got, want) { 192 t.Errorf("CheckStatus = %+v, want %+v", got, want) 193 } 194 195 const methodName = "CheckStatus" 196 testBadOptions(t, methodName, func() (err error) { 197 _, _, err = client.IssueImport.CheckStatus(ctx, "\n", "\n", -3) 198 return err 199 }) 200 201 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 202 got, resp, err := client.IssueImport.CheckStatus(ctx, "o", "r", 3) 203 if got != nil { 204 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 205 } 206 return resp, err 207 }) 208 } 209 210 func TestIssueImportService_CheckStatus_invalidOwner(t *testing.T) { 211 client, _, _, teardown := setup() 212 defer teardown() 213 214 ctx := context.Background() 215 _, _, err := client.IssueImport.CheckStatus(ctx, "%", "r", 1) 216 testURLParseError(t, err) 217 } 218 219 func TestIssueImportService_CheckStatusSince(t *testing.T) { 220 client, mux, _, teardown := setup() 221 defer teardown() 222 223 mux.HandleFunc("/repos/o/r/import/issues", func(w http.ResponseWriter, r *http.Request) { 224 testMethod(t, r, "GET") 225 testHeader(t, r, "Accept", mediaTypeIssueImportAPI) 226 w.WriteHeader(http.StatusOK) 227 assertWrite(t, w, []byte(fmt.Sprintf("[%s]", issueImportResponseJSON))) 228 }) 229 230 ctx := context.Background() 231 got, _, err := client.IssueImport.CheckStatusSince(ctx, "o", "r", Timestamp{time.Now()}) 232 if err != nil { 233 t.Errorf("CheckStatusSince returned error: %v", err) 234 } 235 236 want := []*IssueImportResponse{wantIssueImportResponse} 237 if !cmp.Equal(want, got) { 238 t.Errorf("CheckStatusSince = %v, want = %v", got, want) 239 } 240 241 const methodName = "CheckStatusSince" 242 testBadOptions(t, methodName, func() (err error) { 243 _, _, err = client.IssueImport.CheckStatusSince(ctx, "\n", "\n", Timestamp{time.Now()}) 244 return err 245 }) 246 247 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 248 got, resp, err := client.IssueImport.CheckStatusSince(ctx, "o", "r", Timestamp{time.Now()}) 249 if got != nil { 250 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 251 } 252 return resp, err 253 }) 254 } 255 256 func TestIssueImportService_CheckStatusSince_badResponse(t *testing.T) { 257 client, mux, _, teardown := setup() 258 defer teardown() 259 260 mux.HandleFunc("/repos/o/r/import/issues", func(w http.ResponseWriter, r *http.Request) { 261 testMethod(t, r, "GET") 262 testHeader(t, r, "Accept", mediaTypeIssueImportAPI) 263 w.WriteHeader(http.StatusOK) 264 assertWrite(t, w, []byte("{badly-formed JSON")) 265 }) 266 267 ctx := context.Background() 268 if _, _, err := client.IssueImport.CheckStatusSince(ctx, "o", "r", Timestamp{time.Now()}); err == nil { 269 t.Errorf("CheckStatusSince returned no error, want JSON err") 270 } 271 } 272 273 func TestIssueImportService_CheckStatusSince_invalidOwner(t *testing.T) { 274 client, _, _, teardown := setup() 275 defer teardown() 276 277 ctx := context.Background() 278 _, _, err := client.IssueImport.CheckStatusSince(ctx, "%", "r", Timestamp{time.Now()}) 279 testURLParseError(t, err) 280 } 281 282 var issueImportResponseJSON = []byte(`{ 283 "id": 3, 284 "status": "pending", 285 "url": "https://api.github.com/repos/o/r/import/issues/3", 286 "import_issues_url": "https://api.github.com/repos/o/r/import/issues", 287 "repository_url": "https://api.github.com/repos/o/r" 288 }`) 289 290 var wantIssueImportResponse = &IssueImportResponse{ 291 ID: Int(3), 292 Status: String("pending"), 293 URL: String("https://api.github.com/repos/o/r/import/issues/3"), 294 ImportIssuesURL: String("https://api.github.com/repos/o/r/import/issues"), 295 RepositoryURL: String("https://api.github.com/repos/o/r"), 296 } 297 298 func TestIssueImportError_Marshal(t *testing.T) { 299 testJSONMarshal(t, &IssueImportError{}, "{}") 300 301 u := &IssueImportError{ 302 Location: String("loc"), 303 Resource: String("res"), 304 Field: String("field"), 305 Value: String("value"), 306 Code: String("code"), 307 } 308 309 want := `{ 310 "location": "loc", 311 "resource": "res", 312 "field": "field", 313 "value": "value", 314 "code": "code" 315 }` 316 317 testJSONMarshal(t, u, want) 318 } 319 320 func TestIssueImportResponse_Marshal(t *testing.T) { 321 testJSONMarshal(t, &IssueImportResponse{}, "{}") 322 323 u := &IssueImportResponse{ 324 ID: Int(1), 325 Status: String("status"), 326 URL: String("url"), 327 ImportIssuesURL: String("iiu"), 328 RepositoryURL: String("ru"), 329 CreatedAt: &Timestamp{referenceTime}, 330 UpdatedAt: &Timestamp{referenceTime}, 331 Message: String("msg"), 332 DocumentationURL: String("durl"), 333 Errors: []*IssueImportError{ 334 { 335 Location: String("loc"), 336 Resource: String("res"), 337 Field: String("field"), 338 Value: String("value"), 339 Code: String("code"), 340 }, 341 }, 342 } 343 344 want := `{ 345 "id": 1, 346 "status": "status", 347 "url": "url", 348 "import_issues_url": "iiu", 349 "repository_url": "ru", 350 "created_at": ` + referenceTimeStr + `, 351 "updated_at": ` + referenceTimeStr + `, 352 "message": "msg", 353 "documentation_url": "durl", 354 "errors": [ 355 { 356 "location": "loc", 357 "resource": "res", 358 "field": "field", 359 "value": "value", 360 "code": "code" 361 } 362 ] 363 }` 364 365 testJSONMarshal(t, u, want) 366 } 367 368 func TestComment_Marshal(t *testing.T) { 369 testJSONMarshal(t, &Comment{}, "{}") 370 371 u := &Comment{ 372 CreatedAt: &Timestamp{referenceTime}, 373 Body: "body", 374 } 375 376 want := `{ 377 "created_at": ` + referenceTimeStr + `, 378 "body": "body" 379 }` 380 381 testJSONMarshal(t, u, want) 382 } 383 384 func TestIssueImport_Marshal(t *testing.T) { 385 testJSONMarshal(t, &IssueImport{}, "{}") 386 387 u := &IssueImport{ 388 Title: "title", 389 Body: "body", 390 CreatedAt: &Timestamp{referenceTime}, 391 ClosedAt: &Timestamp{referenceTime}, 392 UpdatedAt: &Timestamp{referenceTime}, 393 Assignee: String("a"), 394 Milestone: Int(1), 395 Closed: Bool(false), 396 Labels: []string{"l"}, 397 } 398 399 want := `{ 400 "title": "title", 401 "body": "body", 402 "created_at": ` + referenceTimeStr + `, 403 "closed_at": ` + referenceTimeStr + `, 404 "updated_at": ` + referenceTimeStr + `, 405 "assignee": "a", 406 "milestone": 1, 407 "closed": false, 408 "labels": [ 409 "l" 410 ] 411 }` 412 413 testJSONMarshal(t, u, want) 414 } 415 416 func TestIssueImportRequest_Marshal(t *testing.T) { 417 testJSONMarshal(t, &IssueImportRequest{}, "{}") 418 419 u := &IssueImportRequest{ 420 IssueImport: IssueImport{ 421 Title: "title", 422 Body: "body", 423 CreatedAt: &Timestamp{referenceTime}, 424 ClosedAt: &Timestamp{referenceTime}, 425 UpdatedAt: &Timestamp{referenceTime}, 426 Assignee: String("a"), 427 Milestone: Int(1), 428 Closed: Bool(false), 429 Labels: []string{"l"}, 430 }, 431 Comments: []*Comment{ 432 { 433 CreatedAt: &Timestamp{referenceTime}, 434 Body: "body", 435 }, 436 }, 437 } 438 439 want := `{ 440 "issue": { 441 "title": "title", 442 "body": "body", 443 "created_at": ` + referenceTimeStr + `, 444 "closed_at": ` + referenceTimeStr + `, 445 "updated_at": ` + referenceTimeStr + `, 446 "assignee": "a", 447 "milestone": 1, 448 "closed": false, 449 "labels": [ 450 "l" 451 ] 452 }, 453 "comments": [ 454 { 455 "created_at": ` + referenceTimeStr + `, 456 "body": "body" 457 } 458 ] 459 }` 460 461 testJSONMarshal(t, u, want) 462 }