github.com/google/go-github/v57@v57.0.0/github/secret_scanning_test.go (about) 1 // Copyright 2022 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 TestSecretScanningService_ListAlertsForEnterprise(t *testing.T) { 20 client, mux, _, teardown := setup() 21 defer teardown() 22 23 mux.HandleFunc("/enterprises/e/secret-scanning/alerts", func(w http.ResponseWriter, r *http.Request) { 24 testMethod(t, r, "GET") 25 testFormValues(t, r, values{"state": "open", "secret_type": "mailchimp_api_key"}) 26 27 fmt.Fprint(w, `[{ 28 "number": 1, 29 "created_at": "1996-06-20T00:00:00Z", 30 "url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1", 31 "html_url": "https://github.com/o/r/security/secret-scanning/1", 32 "locations_url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations", 33 "state": "open", 34 "resolution": null, 35 "resolved_at": null, 36 "resolved_by": null, 37 "secret_type": "mailchimp_api_key", 38 "secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2", 39 "repository": { 40 "id": 1, 41 "name": "n", 42 "url": "url" 43 } 44 }]`) 45 }) 46 47 ctx := context.Background() 48 opts := &SecretScanningAlertListOptions{State: "open", SecretType: "mailchimp_api_key"} 49 50 alerts, _, err := client.SecretScanning.ListAlertsForEnterprise(ctx, "e", opts) 51 if err != nil { 52 t.Errorf("SecretScanning.ListAlertsForEnterprise returned error: %v", err) 53 } 54 55 date := Timestamp{time.Date(1996, time.June, 20, 00, 00, 00, 0, time.UTC)} 56 want := []*SecretScanningAlert{ 57 { 58 Number: Int(1), 59 CreatedAt: &date, 60 URL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1"), 61 HTMLURL: String("https://github.com/o/r/security/secret-scanning/1"), 62 LocationsURL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations"), 63 State: String("open"), 64 Resolution: nil, 65 ResolvedAt: nil, 66 ResolvedBy: nil, 67 SecretType: String("mailchimp_api_key"), 68 Secret: String("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"), 69 Repository: &Repository{ 70 ID: Int64(1), 71 URL: String("url"), 72 Name: String("n"), 73 }, 74 }, 75 } 76 77 if !cmp.Equal(alerts, want) { 78 t.Errorf("SecretScanning.ListAlertsForEnterprise returned %+v, want %+v", alerts, want) 79 } 80 81 const methodName = "ListAlertsForEnterprise" 82 83 testBadOptions(t, methodName, func() (err error) { 84 _, _, err = client.SecretScanning.ListAlertsForEnterprise(ctx, "\n", opts) 85 return err 86 }) 87 88 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 89 _, resp, err := client.SecretScanning.ListAlertsForEnterprise(ctx, "e", opts) 90 return resp, err 91 }) 92 } 93 94 func TestSecretScanningService_ListAlertsForOrg(t *testing.T) { 95 client, mux, _, teardown := setup() 96 defer teardown() 97 98 mux.HandleFunc("/orgs/o/secret-scanning/alerts", func(w http.ResponseWriter, r *http.Request) { 99 testMethod(t, r, "GET") 100 testFormValues(t, r, values{"state": "open", "secret_type": "mailchimp_api_key"}) 101 102 fmt.Fprint(w, `[{ 103 "number": 1, 104 "created_at": "1996-06-20T00:00:00Z", 105 "url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1", 106 "html_url": "https://github.com/o/r/security/secret-scanning/1", 107 "locations_url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations", 108 "state": "open", 109 "resolution": null, 110 "resolved_at": null, 111 "resolved_by": null, 112 "secret_type": "mailchimp_api_key", 113 "secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2" 114 }]`) 115 }) 116 117 ctx := context.Background() 118 opts := &SecretScanningAlertListOptions{State: "open", SecretType: "mailchimp_api_key"} 119 120 alerts, _, err := client.SecretScanning.ListAlertsForOrg(ctx, "o", opts) 121 if err != nil { 122 t.Errorf("SecretScanning.ListAlertsForOrg returned error: %v", err) 123 } 124 125 date := Timestamp{time.Date(1996, time.June, 20, 00, 00, 00, 0, time.UTC)} 126 want := []*SecretScanningAlert{ 127 { 128 Number: Int(1), 129 CreatedAt: &date, 130 URL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1"), 131 HTMLURL: String("https://github.com/o/r/security/secret-scanning/1"), 132 LocationsURL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations"), 133 State: String("open"), 134 Resolution: nil, 135 ResolvedAt: nil, 136 ResolvedBy: nil, 137 SecretType: String("mailchimp_api_key"), 138 Secret: String("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"), 139 }, 140 } 141 142 if !cmp.Equal(alerts, want) { 143 t.Errorf("SecretScanning.ListAlertsForOrg returned %+v, want %+v", alerts, want) 144 } 145 146 const methodName = "ListAlertsForOrg" 147 148 testBadOptions(t, methodName, func() (err error) { 149 _, _, err = client.SecretScanning.ListAlertsForOrg(ctx, "\n", opts) 150 return err 151 }) 152 153 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 154 _, resp, err := client.SecretScanning.ListAlertsForOrg(ctx, "o", opts) 155 return resp, err 156 }) 157 } 158 159 func TestSecretScanningService_ListAlertsForOrgListOptions(t *testing.T) { 160 client, mux, _, teardown := setup() 161 defer teardown() 162 163 mux.HandleFunc("/orgs/o/secret-scanning/alerts", func(w http.ResponseWriter, r *http.Request) { 164 testMethod(t, r, "GET") 165 testFormValues(t, r, values{"state": "open", "secret_type": "mailchimp_api_key", "per_page": "1", "page": "1"}) 166 167 fmt.Fprint(w, `[{ 168 "number": 1, 169 "created_at": "1996-06-20T00:00:00Z", 170 "url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1", 171 "html_url": "https://github.com/o/r/security/secret-scanning/1", 172 "locations_url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations", 173 "state": "open", 174 "resolution": null, 175 "resolved_at": null, 176 "resolved_by": null, 177 "secret_type": "mailchimp_api_key", 178 "secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2" 179 }]`) 180 }) 181 182 ctx := context.Background() 183 184 // Testing pagination by index 185 opts := &SecretScanningAlertListOptions{State: "open", SecretType: "mailchimp_api_key", ListOptions: ListOptions{Page: 1, PerPage: 1}} 186 187 alerts, _, err := client.SecretScanning.ListAlertsForOrg(ctx, "o", opts) 188 if err != nil { 189 t.Errorf("SecretScanning.ListAlertsForOrg returned error: %v", err) 190 } 191 192 date := Timestamp{time.Date(1996, time.June, 20, 00, 00, 00, 0, time.UTC)} 193 want := []*SecretScanningAlert{ 194 { 195 Number: Int(1), 196 CreatedAt: &date, 197 URL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1"), 198 HTMLURL: String("https://github.com/o/r/security/secret-scanning/1"), 199 LocationsURL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations"), 200 State: String("open"), 201 Resolution: nil, 202 ResolvedAt: nil, 203 ResolvedBy: nil, 204 SecretType: String("mailchimp_api_key"), 205 Secret: String("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"), 206 }, 207 } 208 209 if !cmp.Equal(alerts, want) { 210 t.Errorf("SecretScanning.ListAlertsForOrg returned %+v, want %+v", alerts, want) 211 } 212 213 const methodName = "ListAlertsForOrg" 214 215 testBadOptions(t, methodName, func() (err error) { 216 _, _, err = client.SecretScanning.ListAlertsForOrg(ctx, "\n", opts) 217 return err 218 }) 219 220 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 221 _, resp, err := client.SecretScanning.ListAlertsForOrg(ctx, "o", opts) 222 return resp, err 223 }) 224 } 225 226 func TestSecretScanningService_ListAlertsForRepo(t *testing.T) { 227 client, mux, _, teardown := setup() 228 defer teardown() 229 230 mux.HandleFunc("/repos/o/r/secret-scanning/alerts", func(w http.ResponseWriter, r *http.Request) { 231 testMethod(t, r, "GET") 232 testFormValues(t, r, values{"state": "open", "secret_type": "mailchimp_api_key"}) 233 234 fmt.Fprint(w, `[{ 235 "number": 1, 236 "created_at": "1996-06-20T00:00:00Z", 237 "url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1", 238 "html_url": "https://github.com/o/r/security/secret-scanning/1", 239 "locations_url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations", 240 "state": "open", 241 "resolution": null, 242 "resolved_at": null, 243 "resolved_by": null, 244 "secret_type": "mailchimp_api_key", 245 "secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2" 246 }]`) 247 }) 248 249 ctx := context.Background() 250 opts := &SecretScanningAlertListOptions{State: "open", SecretType: "mailchimp_api_key"} 251 252 alerts, _, err := client.SecretScanning.ListAlertsForRepo(ctx, "o", "r", opts) 253 if err != nil { 254 t.Errorf("SecretScanning.ListAlertsForRepo returned error: %v", err) 255 } 256 257 date := Timestamp{time.Date(1996, time.June, 20, 00, 00, 00, 0, time.UTC)} 258 want := []*SecretScanningAlert{ 259 { 260 Number: Int(1), 261 CreatedAt: &date, 262 URL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1"), 263 HTMLURL: String("https://github.com/o/r/security/secret-scanning/1"), 264 LocationsURL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations"), 265 State: String("open"), 266 Resolution: nil, 267 ResolvedAt: nil, 268 ResolvedBy: nil, 269 SecretType: String("mailchimp_api_key"), 270 Secret: String("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"), 271 }, 272 } 273 274 if !cmp.Equal(alerts, want) { 275 t.Errorf("SecretScanning.ListAlertsForRepo returned %+v, want %+v", alerts, want) 276 } 277 278 const methodName = "ListAlertsForRepo" 279 280 testBadOptions(t, methodName, func() (err error) { 281 _, _, err = client.SecretScanning.ListAlertsForRepo(ctx, "\n", "\n", opts) 282 return err 283 }) 284 285 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 286 _, resp, err := client.SecretScanning.ListAlertsForRepo(ctx, "o", "r", opts) 287 return resp, err 288 }) 289 } 290 291 func TestSecretScanningService_GetAlert(t *testing.T) { 292 client, mux, _, teardown := setup() 293 defer teardown() 294 295 mux.HandleFunc("/repos/o/r/secret-scanning/alerts/1", func(w http.ResponseWriter, r *http.Request) { 296 testMethod(t, r, "GET") 297 298 fmt.Fprint(w, `{ 299 "number": 1, 300 "created_at": "1996-06-20T00:00:00Z", 301 "url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1", 302 "html_url": "https://github.com/o/r/security/secret-scanning/1", 303 "locations_url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations", 304 "state": "open", 305 "resolution": null, 306 "resolved_at": null, 307 "resolved_by": null, 308 "secret_type": "mailchimp_api_key", 309 "secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2" 310 }`) 311 }) 312 313 ctx := context.Background() 314 315 alert, _, err := client.SecretScanning.GetAlert(ctx, "o", "r", 1) 316 if err != nil { 317 t.Errorf("SecretScanning.GetAlert returned error: %v", err) 318 } 319 320 date := Timestamp{time.Date(1996, time.June, 20, 00, 00, 00, 0, time.UTC)} 321 want := &SecretScanningAlert{ 322 Number: Int(1), 323 CreatedAt: &date, 324 URL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1"), 325 HTMLURL: String("https://github.com/o/r/security/secret-scanning/1"), 326 LocationsURL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations"), 327 State: String("open"), 328 Resolution: nil, 329 ResolvedAt: nil, 330 ResolvedBy: nil, 331 SecretType: String("mailchimp_api_key"), 332 Secret: String("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"), 333 } 334 335 if !cmp.Equal(alert, want) { 336 t.Errorf("SecretScanning.GetAlert returned %+v, want %+v", alert, want) 337 } 338 339 const methodName = "GetAlert" 340 341 testBadOptions(t, methodName, func() (err error) { 342 _, _, err = client.SecretScanning.GetAlert(ctx, "\n", "\n", 0) 343 return err 344 }) 345 346 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 347 _, resp, err := client.SecretScanning.GetAlert(ctx, "o", "r", 1) 348 return resp, err 349 }) 350 } 351 352 func TestSecretScanningService_UpdateAlert(t *testing.T) { 353 client, mux, _, teardown := setup() 354 defer teardown() 355 356 mux.HandleFunc("/repos/o/r/secret-scanning/alerts/1", func(w http.ResponseWriter, r *http.Request) { 357 testMethod(t, r, "PATCH") 358 359 v := new(SecretScanningAlertUpdateOptions) 360 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 361 362 want := &SecretScanningAlertUpdateOptions{State: "resolved", Resolution: String("used_in_tests")} 363 364 if !cmp.Equal(v, want) { 365 t.Errorf("Request body = %+v, want %+v", v, want) 366 } 367 368 fmt.Fprint(w, `{ 369 "number": 1, 370 "created_at": "1996-06-20T00:00:00Z", 371 "url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1", 372 "html_url": "https://github.com/o/r/security/secret-scanning/1", 373 "locations_url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations", 374 "state": "resolved", 375 "resolution": "used_in_tests", 376 "resolved_at": "1996-06-20T00:00:00Z", 377 "resolved_by": null, 378 "secret_type": "mailchimp_api_key", 379 "secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2" 380 }`) 381 }) 382 383 ctx := context.Background() 384 opts := &SecretScanningAlertUpdateOptions{State: "resolved", Resolution: String("used_in_tests")} 385 386 alert, _, err := client.SecretScanning.UpdateAlert(ctx, "o", "r", 1, opts) 387 if err != nil { 388 t.Errorf("SecretScanning.UpdateAlert returned error: %v", err) 389 } 390 391 date := Timestamp{time.Date(1996, time.June, 20, 00, 00, 00, 0, time.UTC)} 392 want := &SecretScanningAlert{ 393 Number: Int(1), 394 CreatedAt: &date, 395 URL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1"), 396 HTMLURL: String("https://github.com/o/r/security/secret-scanning/1"), 397 LocationsURL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations"), 398 State: String("resolved"), 399 Resolution: String("used_in_tests"), 400 ResolvedAt: &date, 401 ResolvedBy: nil, 402 SecretType: String("mailchimp_api_key"), 403 Secret: String("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"), 404 } 405 406 if !cmp.Equal(alert, want) { 407 t.Errorf("SecretScanning.UpdateAlert returned %+v, want %+v", alert, want) 408 } 409 410 const methodName = "UpdateAlert" 411 412 testBadOptions(t, methodName, func() (err error) { 413 _, _, err = client.SecretScanning.UpdateAlert(ctx, "\n", "\n", 1, opts) 414 return err 415 }) 416 417 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 418 _, resp, err := client.SecretScanning.UpdateAlert(ctx, "o", "r", 1, opts) 419 return resp, err 420 }) 421 } 422 423 func TestSecretScanningService_ListLocationsForAlert(t *testing.T) { 424 client, mux, _, teardown := setup() 425 defer teardown() 426 427 mux.HandleFunc("/repos/o/r/secret-scanning/alerts/1/locations", func(w http.ResponseWriter, r *http.Request) { 428 testMethod(t, r, "GET") 429 testFormValues(t, r, values{"page": "1", "per_page": "100"}) 430 431 fmt.Fprint(w, `[{ 432 "type": "commit", 433 "details": { 434 "path": "/example/secrets.txt", 435 "start_line": 1, 436 "end_line": 1, 437 "start_column": 1, 438 "end_column": 64, 439 "blob_sha": "af5626b4a114abcb82d63db7c8082c3c4756e51b", 440 "blob_url": "https://api.github.com/repos/o/r/git/blobs/af5626b4a114abcb82d63db7c8082c3c4756e51b", 441 "commit_sha": "f14d7debf9775f957cf4f1e8176da0786431f72b", 442 "commit_url": "https://api.github.com/repos/o/r/git/commits/f14d7debf9775f957cf4f1e8176da0786431f72b" 443 } 444 }]`) 445 }) 446 447 ctx := context.Background() 448 opts := &ListOptions{Page: 1, PerPage: 100} 449 450 locations, _, err := client.SecretScanning.ListLocationsForAlert(ctx, "o", "r", 1, opts) 451 if err != nil { 452 t.Errorf("SecretScanning.ListLocationsForAlert returned error: %v", err) 453 } 454 455 want := []*SecretScanningAlertLocation{ 456 { 457 Type: String("commit"), 458 Details: &SecretScanningAlertLocationDetails{ 459 Path: String("/example/secrets.txt"), 460 Startline: Int(1), 461 EndLine: Int(1), 462 StartColumn: Int(1), 463 EndColumn: Int(64), 464 BlobSHA: String("af5626b4a114abcb82d63db7c8082c3c4756e51b"), 465 BlobURL: String("https://api.github.com/repos/o/r/git/blobs/af5626b4a114abcb82d63db7c8082c3c4756e51b"), 466 CommitSHA: String("f14d7debf9775f957cf4f1e8176da0786431f72b"), 467 CommitURL: String("https://api.github.com/repos/o/r/git/commits/f14d7debf9775f957cf4f1e8176da0786431f72b"), 468 }, 469 }, 470 } 471 472 if !cmp.Equal(locations, want) { 473 t.Errorf("SecretScanning.ListLocationsForAlert returned %+v, want %+v", locations, want) 474 } 475 476 const methodName = "ListLocationsForAlert" 477 478 testBadOptions(t, methodName, func() (err error) { 479 _, _, err = client.SecretScanning.ListLocationsForAlert(ctx, "\n", "\n", 1, opts) 480 return err 481 }) 482 483 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 484 _, resp, err := client.SecretScanning.ListLocationsForAlert(ctx, "o", "r", 1, opts) 485 return resp, err 486 }) 487 } 488 489 func TestSecretScanningAlert_Marshal(t *testing.T) { 490 testJSONMarshal(t, &SecretScanningAlert{}, `{}`) 491 492 u := &SecretScanningAlert{ 493 Number: Int(1), 494 CreatedAt: &Timestamp{referenceTime}, 495 URL: String("https://api.github.com/teams/2/discussions/3/comments"), 496 HTMLURL: String("https://api.github.com/teams/2/discussions/3/comments"), 497 LocationsURL: String("https://api.github.com/teams/2/discussions/3/comments"), 498 State: String("test_state"), 499 Resolution: String("test_resolution"), 500 ResolvedAt: &Timestamp{referenceTime}, 501 ResolvedBy: &User{ 502 Login: String("test"), 503 ID: Int64(10), 504 NodeID: String("A123"), 505 AvatarURL: String("https://api.github.com/teams/2/discussions/3/comments"), 506 }, 507 SecretType: String("test"), 508 Secret: String("test"), 509 } 510 511 want := `{ 512 "number": 1, 513 "created_at": ` + referenceTimeStr + `, 514 "url": "https://api.github.com/teams/2/discussions/3/comments", 515 "html_url": "https://api.github.com/teams/2/discussions/3/comments", 516 "locations_url": "https://api.github.com/teams/2/discussions/3/comments", 517 "state": "test_state", 518 "resolution": "test_resolution", 519 "resolved_at": ` + referenceTimeStr + `, 520 "resolved_by": { 521 "login": "test", 522 "id": 10, 523 "node_id": "A123", 524 "avatar_url": "https://api.github.com/teams/2/discussions/3/comments" 525 }, 526 "secret_type": "test", 527 "secret": "test" 528 }` 529 530 testJSONMarshal(t, u, want) 531 } 532 533 func TestSecretScanningAlertLocation_Marshal(t *testing.T) { 534 testJSONMarshal(t, &SecretScanningAlertLocation{}, `{}`) 535 536 u := &SecretScanningAlertLocation{ 537 Type: String("test"), 538 Details: &SecretScanningAlertLocationDetails{ 539 Path: String("test_path"), 540 Startline: Int(10), 541 EndLine: Int(20), 542 StartColumn: Int(30), 543 EndColumn: Int(40), 544 BlobSHA: String("test_sha"), 545 BlobURL: String("https://api.github.com/repos/o/r/git/commits/f14d7debf9775f957cf4f1e8176da0786431f72b"), 546 CommitSHA: String("test_sha"), 547 CommitURL: String("https://api.github.com/repos/o/r/git/commits/f14d7debf9775f957cf4f1e8176da0786431f72b"), 548 }, 549 } 550 551 want := `{ 552 "type": "test", 553 "details": { 554 "path": "test_path", 555 "start_line": 10, 556 "end_line": 20, 557 "start_column": 30, 558 "end_column": 40, 559 "blob_sha": "test_sha", 560 "blob_url": "https://api.github.com/repos/o/r/git/commits/f14d7debf9775f957cf4f1e8176da0786431f72b", 561 "commit_sha": "test_sha", 562 "commit_url": "https://api.github.com/repos/o/r/git/commits/f14d7debf9775f957cf4f1e8176da0786431f72b" 563 } 564 }` 565 566 testJSONMarshal(t, u, want) 567 } 568 569 func TestSecretScanningAlertLocationDetails_Marshal(t *testing.T) { 570 testJSONMarshal(t, &SecretScanningAlertLocationDetails{}, `{}`) 571 572 u := &SecretScanningAlertLocationDetails{ 573 Path: String("test_path"), 574 Startline: Int(10), 575 EndLine: Int(20), 576 StartColumn: Int(30), 577 EndColumn: Int(40), 578 BlobSHA: String("test_sha"), 579 BlobURL: String("https://api.github.com/repos/o/r/git/commits/f14d7debf9775f957cf4f1e8176da0786431f72b"), 580 CommitSHA: String("test_sha"), 581 CommitURL: String("https://api.github.com/repos/o/r/git/commits/f14d7debf9775f957cf4f1e8176da0786431f72b"), 582 } 583 584 want := `{ 585 "path": "test_path", 586 "start_line": 10, 587 "end_line": 20, 588 "start_column": 30, 589 "end_column": 40, 590 "blob_sha": "test_sha", 591 "blob_url": "https://api.github.com/repos/o/r/git/commits/f14d7debf9775f957cf4f1e8176da0786431f72b", 592 "commit_sha": "test_sha", 593 "commit_url": "https://api.github.com/repos/o/r/git/commits/f14d7debf9775f957cf4f1e8176da0786431f72b" 594 }` 595 596 testJSONMarshal(t, u, want) 597 }