github.com/google/go-github/v68@v68.0.0/github/actions_artifacts_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 "errors" 11 "fmt" 12 "net/http" 13 "net/url" 14 "testing" 15 16 "github.com/google/go-cmp/cmp" 17 ) 18 19 func TestActionsService_ListArtifacts(t *testing.T) { 20 t.Parallel() 21 client, mux, _ := setup(t) 22 23 mux.HandleFunc("/repos/o/r/actions/artifacts", func(w http.ResponseWriter, r *http.Request) { 24 testMethod(t, r, "GET") 25 testFormValues(t, r, values{"page": "2", "name": "TheArtifact"}) 26 fmt.Fprint(w, 27 `{ 28 "total_count":1, 29 "artifacts":[{"id":1}] 30 }`, 31 ) 32 }) 33 34 opts := &ListArtifactsOptions{ 35 Name: Ptr("TheArtifact"), 36 ListOptions: ListOptions{Page: 2}, 37 } 38 ctx := context.Background() 39 artifacts, _, err := client.Actions.ListArtifacts(ctx, "o", "r", opts) 40 if err != nil { 41 t.Errorf("Actions.ListArtifacts returned error: %v", err) 42 } 43 44 want := &ArtifactList{TotalCount: Ptr(int64(1)), Artifacts: []*Artifact{{ID: Ptr(int64(1))}}} 45 if !cmp.Equal(artifacts, want) { 46 t.Errorf("Actions.ListArtifacts returned %+v, want %+v", artifacts, want) 47 } 48 49 const methodName = "ListArtifacts" 50 testBadOptions(t, methodName, func() (err error) { 51 _, _, err = client.Actions.ListArtifacts(ctx, "\n", "\n", opts) 52 return err 53 }) 54 55 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 56 got, resp, err := client.Actions.ListArtifacts(ctx, "o", "r", opts) 57 if got != nil { 58 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 59 } 60 return resp, err 61 }) 62 } 63 64 func TestActionsService_ListArtifacts_invalidOwner(t *testing.T) { 65 t.Parallel() 66 client, _, _ := setup(t) 67 68 ctx := context.Background() 69 _, _, err := client.Actions.ListArtifacts(ctx, "%", "r", nil) 70 testURLParseError(t, err) 71 } 72 73 func TestActionsService_ListArtifacts_invalidRepo(t *testing.T) { 74 t.Parallel() 75 client, _, _ := setup(t) 76 77 ctx := context.Background() 78 _, _, err := client.Actions.ListArtifacts(ctx, "o", "%", nil) 79 testURLParseError(t, err) 80 } 81 82 func TestActionsService_ListArtifacts_notFound(t *testing.T) { 83 t.Parallel() 84 client, mux, _ := setup(t) 85 86 mux.HandleFunc("/repos/o/r/actions/artifacts", func(w http.ResponseWriter, r *http.Request) { 87 testMethod(t, r, "GET") 88 w.WriteHeader(http.StatusNotFound) 89 }) 90 91 ctx := context.Background() 92 artifacts, resp, err := client.Actions.ListArtifacts(ctx, "o", "r", nil) 93 if err == nil { 94 t.Errorf("Expected HTTP 404 response") 95 } 96 if got, want := resp.Response.StatusCode, http.StatusNotFound; got != want { 97 t.Errorf("Actions.ListArtifacts return status %d, want %d", got, want) 98 } 99 if artifacts != nil { 100 t.Errorf("Actions.ListArtifacts return %+v, want nil", artifacts) 101 } 102 } 103 104 func TestActionsService_ListWorkflowRunArtifacts(t *testing.T) { 105 t.Parallel() 106 client, mux, _ := setup(t) 107 108 mux.HandleFunc("/repos/o/r/actions/runs/1/artifacts", func(w http.ResponseWriter, r *http.Request) { 109 testMethod(t, r, "GET") 110 testFormValues(t, r, values{"page": "2"}) 111 fmt.Fprint(w, 112 `{ 113 "total_count":1, 114 "artifacts":[{"id":1}] 115 }`, 116 ) 117 }) 118 119 opts := &ListOptions{Page: 2} 120 ctx := context.Background() 121 artifacts, _, err := client.Actions.ListWorkflowRunArtifacts(ctx, "o", "r", 1, opts) 122 if err != nil { 123 t.Errorf("Actions.ListWorkflowRunArtifacts returned error: %v", err) 124 } 125 126 want := &ArtifactList{TotalCount: Ptr(int64(1)), Artifacts: []*Artifact{{ID: Ptr(int64(1))}}} 127 if !cmp.Equal(artifacts, want) { 128 t.Errorf("Actions.ListWorkflowRunArtifacts returned %+v, want %+v", artifacts, want) 129 } 130 131 const methodName = "ListWorkflowRunArtifacts" 132 testBadOptions(t, methodName, func() (err error) { 133 _, _, err = client.Actions.ListWorkflowRunArtifacts(ctx, "\n", "\n", -1, opts) 134 return err 135 }) 136 137 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 138 got, resp, err := client.Actions.ListWorkflowRunArtifacts(ctx, "o", "r", 1, opts) 139 if got != nil { 140 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 141 } 142 return resp, err 143 }) 144 } 145 146 func TestActionsService_ListWorkflowRunArtifacts_invalidOwner(t *testing.T) { 147 t.Parallel() 148 client, _, _ := setup(t) 149 150 ctx := context.Background() 151 _, _, err := client.Actions.ListWorkflowRunArtifacts(ctx, "%", "r", 1, nil) 152 testURLParseError(t, err) 153 } 154 155 func TestActionsService_ListWorkflowRunArtifacts_invalidRepo(t *testing.T) { 156 t.Parallel() 157 client, _, _ := setup(t) 158 159 ctx := context.Background() 160 _, _, err := client.Actions.ListWorkflowRunArtifacts(ctx, "o", "%", 1, nil) 161 testURLParseError(t, err) 162 } 163 164 func TestActionsService_ListWorkflowRunArtifacts_notFound(t *testing.T) { 165 t.Parallel() 166 client, mux, _ := setup(t) 167 168 mux.HandleFunc("/repos/o/r/actions/runs/1/artifacts", func(w http.ResponseWriter, r *http.Request) { 169 testMethod(t, r, "GET") 170 w.WriteHeader(http.StatusNotFound) 171 }) 172 173 ctx := context.Background() 174 artifacts, resp, err := client.Actions.ListWorkflowRunArtifacts(ctx, "o", "r", 1, nil) 175 if err == nil { 176 t.Errorf("Expected HTTP 404 response") 177 } 178 if got, want := resp.Response.StatusCode, http.StatusNotFound; got != want { 179 t.Errorf("Actions.ListWorkflowRunArtifacts return status %d, want %d", got, want) 180 } 181 if artifacts != nil { 182 t.Errorf("Actions.ListWorkflowRunArtifacts return %+v, want nil", artifacts) 183 } 184 } 185 186 func TestActionsService_GetArtifact(t *testing.T) { 187 t.Parallel() 188 client, mux, _ := setup(t) 189 190 mux.HandleFunc("/repos/o/r/actions/artifacts/1", func(w http.ResponseWriter, r *http.Request) { 191 testMethod(t, r, "GET") 192 fmt.Fprint(w, `{ 193 "id":1, 194 "node_id":"xyz", 195 "name":"a", 196 "size_in_bytes":5, 197 "archive_download_url":"u" 198 }`) 199 }) 200 201 ctx := context.Background() 202 artifact, _, err := client.Actions.GetArtifact(ctx, "o", "r", 1) 203 if err != nil { 204 t.Errorf("Actions.GetArtifact returned error: %v", err) 205 } 206 207 want := &Artifact{ 208 ID: Ptr(int64(1)), 209 NodeID: Ptr("xyz"), 210 Name: Ptr("a"), 211 SizeInBytes: Ptr(int64(5)), 212 ArchiveDownloadURL: Ptr("u"), 213 } 214 if !cmp.Equal(artifact, want) { 215 t.Errorf("Actions.GetArtifact returned %+v, want %+v", artifact, want) 216 } 217 218 const methodName = "GetArtifact" 219 testBadOptions(t, methodName, func() (err error) { 220 _, _, err = client.Actions.GetArtifact(ctx, "\n", "\n", -1) 221 return err 222 }) 223 224 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 225 got, resp, err := client.Actions.GetArtifact(ctx, "o", "r", 1) 226 if got != nil { 227 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 228 } 229 return resp, err 230 }) 231 } 232 233 func TestActionsService_GetArtifact_invalidOwner(t *testing.T) { 234 t.Parallel() 235 client, _, _ := setup(t) 236 237 ctx := context.Background() 238 _, _, err := client.Actions.GetArtifact(ctx, "%", "r", 1) 239 testURLParseError(t, err) 240 } 241 242 func TestActionsService_GetArtifact_invalidRepo(t *testing.T) { 243 t.Parallel() 244 client, _, _ := setup(t) 245 246 ctx := context.Background() 247 _, _, err := client.Actions.GetArtifact(ctx, "o", "%", 1) 248 testURLParseError(t, err) 249 } 250 251 func TestActionsService_GetArtifact_notFound(t *testing.T) { 252 t.Parallel() 253 client, mux, _ := setup(t) 254 255 mux.HandleFunc("/repos/o/r/actions/artifacts/1", func(w http.ResponseWriter, r *http.Request) { 256 testMethod(t, r, "GET") 257 w.WriteHeader(http.StatusNotFound) 258 }) 259 260 ctx := context.Background() 261 artifact, resp, err := client.Actions.GetArtifact(ctx, "o", "r", 1) 262 if err == nil { 263 t.Errorf("Expected HTTP 404 response") 264 } 265 if got, want := resp.Response.StatusCode, http.StatusNotFound; got != want { 266 t.Errorf("Actions.GetArtifact return status %d, want %d", got, want) 267 } 268 if artifact != nil { 269 t.Errorf("Actions.GetArtifact return %+v, want nil", artifact) 270 } 271 } 272 273 func TestActionsService_DownloadArtifact(t *testing.T) { 274 t.Parallel() 275 client, mux, _ := setup(t) 276 277 mux.HandleFunc("/repos/o/r/actions/artifacts/1/zip", func(w http.ResponseWriter, r *http.Request) { 278 testMethod(t, r, "GET") 279 http.Redirect(w, r, "https://github.com/artifact", http.StatusFound) 280 }) 281 282 ctx := context.Background() 283 url, resp, err := client.Actions.DownloadArtifact(ctx, "o", "r", 1, 1) 284 if err != nil { 285 t.Errorf("Actions.DownloadArtifact returned error: %v", err) 286 } 287 if resp.StatusCode != http.StatusFound { 288 t.Errorf("Actions.DownloadArtifact returned status: %d, want %d", resp.StatusCode, http.StatusFound) 289 } 290 291 want := "https://github.com/artifact" 292 if url.String() != want { 293 t.Errorf("Actions.DownloadArtifact returned %+v, want %+v", url.String(), want) 294 } 295 296 const methodName = "DownloadArtifact" 297 testBadOptions(t, methodName, func() (err error) { 298 _, _, err = client.Actions.DownloadArtifact(ctx, "\n", "\n", -1, 1) 299 return err 300 }) 301 302 // Add custom round tripper 303 client.client.Transport = roundTripperFunc(func(r *http.Request) (*http.Response, error) { 304 return nil, errors.New("failed to download artifact") 305 }) 306 testBadOptions(t, methodName, func() (err error) { 307 _, _, err = client.Actions.DownloadArtifact(ctx, "o", "r", 1, 1) 308 return err 309 }) 310 } 311 312 func TestActionsService_DownloadArtifact_invalidOwner(t *testing.T) { 313 t.Parallel() 314 client, _, _ := setup(t) 315 316 ctx := context.Background() 317 _, _, err := client.Actions.DownloadArtifact(ctx, "%", "r", 1, 1) 318 testURLParseError(t, err) 319 } 320 321 func TestActionsService_DownloadArtifact_invalidRepo(t *testing.T) { 322 t.Parallel() 323 client, _, _ := setup(t) 324 325 ctx := context.Background() 326 _, _, err := client.Actions.DownloadArtifact(ctx, "o", "%", 1, 1) 327 testURLParseError(t, err) 328 } 329 330 func TestActionsService_DownloadArtifact_StatusMovedPermanently_dontFollowRedirects(t *testing.T) { 331 t.Parallel() 332 client, mux, _ := setup(t) 333 334 mux.HandleFunc("/repos/o/r/actions/artifacts/1/zip", func(w http.ResponseWriter, r *http.Request) { 335 testMethod(t, r, "GET") 336 http.Redirect(w, r, "https://github.com/artifact", http.StatusMovedPermanently) 337 }) 338 339 ctx := context.Background() 340 _, resp, _ := client.Actions.DownloadArtifact(ctx, "o", "r", 1, 0) 341 if resp.StatusCode != http.StatusMovedPermanently { 342 t.Errorf("Actions.DownloadArtifact return status %d, want %d", resp.StatusCode, http.StatusMovedPermanently) 343 } 344 } 345 346 func TestActionsService_DownloadArtifact_StatusMovedPermanently_followRedirects(t *testing.T) { 347 t.Parallel() 348 client, mux, serverURL := setup(t) 349 350 mux.HandleFunc("/repos/o/r/actions/artifacts/1/zip", func(w http.ResponseWriter, r *http.Request) { 351 testMethod(t, r, "GET") 352 redirectURL, _ := url.Parse(serverURL + baseURLPath + "/redirect") 353 http.Redirect(w, r, redirectURL.String(), http.StatusMovedPermanently) 354 }) 355 mux.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) { 356 testMethod(t, r, "GET") 357 http.Redirect(w, r, "http://github.com/artifact", http.StatusFound) 358 }) 359 360 ctx := context.Background() 361 url, resp, err := client.Actions.DownloadArtifact(ctx, "o", "r", 1, 1) 362 if err != nil { 363 t.Errorf("Actions.DownloadArtifact return error: %v", err) 364 } 365 if resp.StatusCode != http.StatusFound { 366 t.Errorf("Actions.DownloadArtifact return status %d, want %d", resp.StatusCode, http.StatusFound) 367 } 368 want := "http://github.com/artifact" 369 if url.String() != want { 370 t.Errorf("Actions.DownloadArtifact returned %+v, want %+v", url.String(), want) 371 } 372 } 373 374 func TestActionsService_DeleteArtifact(t *testing.T) { 375 t.Parallel() 376 client, mux, _ := setup(t) 377 378 mux.HandleFunc("/repos/o/r/actions/artifacts/1", func(w http.ResponseWriter, r *http.Request) { 379 testMethod(t, r, "DELETE") 380 }) 381 382 ctx := context.Background() 383 _, err := client.Actions.DeleteArtifact(ctx, "o", "r", 1) 384 if err != nil { 385 t.Errorf("Actions.DeleteArtifact return error: %v", err) 386 } 387 388 const methodName = "DeleteArtifact" 389 testBadOptions(t, methodName, func() (err error) { 390 _, err = client.Actions.DeleteArtifact(ctx, "\n", "\n", -1) 391 return err 392 }) 393 394 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 395 return client.Actions.DeleteArtifact(ctx, "o", "r", 1) 396 }) 397 } 398 399 func TestActionsService_DeleteArtifact_invalidOwner(t *testing.T) { 400 t.Parallel() 401 client, _, _ := setup(t) 402 403 ctx := context.Background() 404 _, err := client.Actions.DeleteArtifact(ctx, "%", "r", 1) 405 testURLParseError(t, err) 406 } 407 408 func TestActionsService_DeleteArtifact_invalidRepo(t *testing.T) { 409 t.Parallel() 410 client, _, _ := setup(t) 411 412 ctx := context.Background() 413 _, err := client.Actions.DeleteArtifact(ctx, "o", "%", 1) 414 testURLParseError(t, err) 415 } 416 417 func TestActionsService_DeleteArtifact_notFound(t *testing.T) { 418 t.Parallel() 419 client, mux, _ := setup(t) 420 421 mux.HandleFunc("/repos/o/r/actions/artifacts/1", func(w http.ResponseWriter, r *http.Request) { 422 testMethod(t, r, "DELETE") 423 w.WriteHeader(http.StatusNotFound) 424 }) 425 426 ctx := context.Background() 427 resp, err := client.Actions.DeleteArtifact(ctx, "o", "r", 1) 428 if err == nil { 429 t.Errorf("Expected HTTP 404 response") 430 } 431 if got, want := resp.Response.StatusCode, http.StatusNotFound; got != want { 432 t.Errorf("Actions.DeleteArtifact return status %d, want %d", got, want) 433 } 434 } 435 436 func TestArtifact_Marshal(t *testing.T) { 437 t.Parallel() 438 testJSONMarshal(t, &Artifact{}, "{}") 439 440 u := &Artifact{ 441 ID: Ptr(int64(1)), 442 NodeID: Ptr("nid"), 443 Name: Ptr("n"), 444 SizeInBytes: Ptr(int64(1)), 445 URL: Ptr("u"), 446 ArchiveDownloadURL: Ptr("a"), 447 Expired: Ptr(false), 448 CreatedAt: &Timestamp{referenceTime}, 449 UpdatedAt: &Timestamp{referenceTime}, 450 ExpiresAt: &Timestamp{referenceTime}, 451 WorkflowRun: &ArtifactWorkflowRun{ 452 ID: Ptr(int64(1)), 453 RepositoryID: Ptr(int64(1)), 454 HeadRepositoryID: Ptr(int64(1)), 455 HeadBranch: Ptr("b"), 456 HeadSHA: Ptr("s"), 457 }, 458 } 459 460 want := `{ 461 "id": 1, 462 "node_id": "nid", 463 "name": "n", 464 "size_in_bytes": 1, 465 "url": "u", 466 "archive_download_url": "a", 467 "expired": false, 468 "created_at": ` + referenceTimeStr + `, 469 "updated_at": ` + referenceTimeStr + `, 470 "expires_at": ` + referenceTimeStr + `, 471 "workflow_run": { 472 "id": 1, 473 "repository_id": 1, 474 "head_repository_id": 1, 475 "head_branch": "b", 476 "head_sha": "s" 477 } 478 }` 479 480 testJSONMarshal(t, u, want) 481 } 482 483 func TestArtifactList_Marshal(t *testing.T) { 484 t.Parallel() 485 testJSONMarshal(t, &ArtifactList{}, "{}") 486 487 u := &ArtifactList{ 488 TotalCount: Ptr(int64(1)), 489 Artifacts: []*Artifact{ 490 { 491 ID: Ptr(int64(1)), 492 NodeID: Ptr("nid"), 493 Name: Ptr("n"), 494 SizeInBytes: Ptr(int64(1)), 495 URL: Ptr("u"), 496 ArchiveDownloadURL: Ptr("a"), 497 Expired: Ptr(false), 498 CreatedAt: &Timestamp{referenceTime}, 499 UpdatedAt: &Timestamp{referenceTime}, 500 ExpiresAt: &Timestamp{referenceTime}, 501 WorkflowRun: &ArtifactWorkflowRun{ 502 ID: Ptr(int64(1)), 503 RepositoryID: Ptr(int64(1)), 504 HeadRepositoryID: Ptr(int64(1)), 505 HeadBranch: Ptr("b"), 506 HeadSHA: Ptr("s"), 507 }, 508 }, 509 }, 510 } 511 512 want := `{ 513 "total_count": 1, 514 "artifacts": [{ 515 "id": 1, 516 "node_id": "nid", 517 "name": "n", 518 "size_in_bytes": 1, 519 "url": "u", 520 "archive_download_url": "a", 521 "expired": false, 522 "created_at": ` + referenceTimeStr + `, 523 "updated_at": ` + referenceTimeStr + `, 524 "expires_at": ` + referenceTimeStr + `, 525 "workflow_run": { 526 "id": 1, 527 "repository_id": 1, 528 "head_repository_id": 1, 529 "head_branch": "b", 530 "head_sha": "s" 531 } 532 }] 533 }` 534 535 testJSONMarshal(t, u, want) 536 }