@@ -3538,6 +3538,273 @@ await FluentActions
3538
3538
. ThrowExactlyAsync < ArgumentNullException > ( ) ;
3539
3539
}
3540
3540
3541
+ [ Fact ]
3542
+ public async Task GetSecretScanningAlertsLocations_Handles_Missing_Fields_Gracefully ( )
3543
+ {
3544
+ // Arrange
3545
+ const int alertNumber = 1 ;
3546
+ var url = $ "https://api.github.com/repos/{ GITHUB_ORG } /{ GITHUB_REPO } /secret-scanning/alerts/{ alertNumber } /locations?per_page=100";
3547
+
3548
+ var locationWithMissingFields = $@ "
3549
+ {{
3550
+ ""type"": ""commit"",
3551
+ ""details"": {{
3552
+ ""path"": ""src/index.js"",
3553
+ ""start_line"": 5,
3554
+ ""end_line"": 5,
3555
+ ""blob_sha"": ""2044bb6ccd535142b974776db108c32a19f89e80""
3556
+ // Missing start_column and end_column
3557
+ }}
3558
+ }}
3559
+ " ;
3560
+
3561
+ _githubClientMock
3562
+ . Setup ( m => m . GetAllAsync ( url , null ) )
3563
+ . Returns ( new [ ] { JToken . Parse ( locationWithMissingFields ) } . ToAsyncEnumerable ( ) ) ;
3564
+
3565
+ // Act
3566
+ var locations = await _githubApi . GetSecretScanningAlertsLocations ( GITHUB_ORG , GITHUB_REPO , alertNumber ) ;
3567
+
3568
+ // Assert
3569
+ locations . Should ( ) . HaveCount ( 1 ) ;
3570
+ var location = locations . First ( ) ;
3571
+ location . Path . Should ( ) . Be ( "src/index.js" ) ;
3572
+ location . StartLine . Should ( ) . Be ( 5 ) ;
3573
+ location . EndLine . Should ( ) . Be ( 5 ) ;
3574
+ location . StartColumn . Should ( ) . Be ( 0 ) ;
3575
+ location . EndColumn . Should ( ) . Be ( 0 ) ;
3576
+ }
3577
+
3578
+ [ Fact ]
3579
+ public async Task GetSecretScanningAlertsLocations_Handles_Extra_Fields_Gracefully ( )
3580
+ {
3581
+ // Arrange
3582
+ const int alertNumber = 1 ;
3583
+ var url = $ "https://api.github.com/repos/{ GITHUB_ORG } /{ GITHUB_REPO } /secret-scanning/alerts/{ alertNumber } /locations?per_page=100";
3584
+
3585
+ var locationWithExtraFields = $@ "
3586
+ {{
3587
+ ""type"": ""commit"",
3588
+ ""details"": {{
3589
+ ""path"": ""src/index.js"",
3590
+ ""start_line"": 5,
3591
+ ""end_line"": 5,
3592
+ ""start_column"": 12,
3593
+ ""end_column"": 52,
3594
+ ""blob_sha"": ""2044bb6ccd535142b974776db108c32a19f89e80"",
3595
+ ""extra_field"": ""extra_value""
3596
+ }}
3597
+ }}
3598
+ " ;
3599
+
3600
+ _githubClientMock
3601
+ . Setup ( m => m . GetAllAsync ( url , null ) )
3602
+ . Returns ( new [ ] { JToken . Parse ( locationWithExtraFields ) } . ToAsyncEnumerable ( ) ) ;
3603
+
3604
+ // Act
3605
+ var locations = await _githubApi . GetSecretScanningAlertsLocations ( GITHUB_ORG , GITHUB_REPO , alertNumber ) ;
3606
+
3607
+ // Assert
3608
+ locations . Should ( ) . HaveCount ( 1 ) ;
3609
+ var location = locations . First ( ) ;
3610
+ location . Path . Should ( ) . Be ( "src/index.js" ) ;
3611
+ location . StartLine . Should ( ) . Be ( 5 ) ;
3612
+ location . EndLine . Should ( ) . Be ( 5 ) ;
3613
+ location . StartColumn . Should ( ) . Be ( 12 ) ;
3614
+ location . EndColumn . Should ( ) . Be ( 52 ) ;
3615
+ }
3616
+
3617
+ [ Fact ]
3618
+ public async Task GetSecretScanningAlertsLocations_Handles_Commit_Location ( )
3619
+ {
3620
+ // Arrange
3621
+ const int alertNumber = 1 ;
3622
+ var url = $ "https://api.github.com/repos/{ GITHUB_ORG } /{ GITHUB_REPO } /secret-scanning/alerts/{ alertNumber } /locations?per_page=100";
3623
+
3624
+ var commitLocation = $@ "
3625
+ {{
3626
+ ""type"": ""commit"",
3627
+ ""details"": {{
3628
+ ""path"": ""storage/src/main/resources/.env"",
3629
+ ""start_line"": 6,
3630
+ ""end_line"": 6,
3631
+ ""start_column"": 17,
3632
+ ""end_column"": 49,
3633
+ ""blob_sha"": ""40ecdbab769bc2cb0e4e2114fd6986ae1acc3df2"",
3634
+ ""blob_url"": ""https://api.github.com/repos/ORG/REPO/git/blobs/40ecdbab769bc2cb0e4e2114fd6986ae1acc3df2"",
3635
+ ""commit_sha"": ""b350b85436a872ccdc1a0cfa73f59264b8dbf4eb"",
3636
+ ""commit_url"": ""https://api.github.com/repos/ORG/REPO/git/commits/b350b85436a872ccdc1a0cfa73f59264b8dbf4eb""
3637
+ }}
3638
+ }}
3639
+ " ;
3640
+
3641
+ _githubClientMock
3642
+ . Setup ( m => m . GetAllAsync ( url , null ) )
3643
+ . Returns ( new [ ] { JToken . Parse ( commitLocation ) } . ToAsyncEnumerable ( ) ) ;
3644
+
3645
+ // Act
3646
+ var locations = await _githubApi . GetSecretScanningAlertsLocations ( GITHUB_ORG , GITHUB_REPO , alertNumber ) ;
3647
+
3648
+ // Assert
3649
+ locations . Should ( ) . HaveCount ( 1 ) ;
3650
+ var location = locations . First ( ) ;
3651
+ location . Path . Should ( ) . Be ( "storage/src/main/resources/.env" ) ;
3652
+ location . StartLine . Should ( ) . Be ( 6 ) ;
3653
+ location . EndLine . Should ( ) . Be ( 6 ) ;
3654
+ location . StartColumn . Should ( ) . Be ( 17 ) ;
3655
+ location . EndColumn . Should ( ) . Be ( 49 ) ;
3656
+ }
3657
+
3658
+ [ Fact ]
3659
+ public async Task GetSecretScanningAlertsLocations_Handles_Pull_Request_Comment_Location ( )
3660
+ {
3661
+ // Arrange
3662
+ const int alertNumber = 1 ;
3663
+ var url = $ "https://api.github.com/repos/{ GITHUB_ORG } /{ GITHUB_REPO } /secret-scanning/alerts/{ alertNumber } /locations?per_page=100";
3664
+
3665
+ var prCommentLocation = $@ "
3666
+ {{
3667
+ ""type"": ""pull_request_comment"",
3668
+ ""details"": {{
3669
+ ""pull_request_comment_url"": ""https://api.github.com/repos/ORG/REPO/issues/comments/2758069588""
3670
+ }}
3671
+ }}
3672
+ " ;
3673
+
3674
+ _githubClientMock
3675
+ . Setup ( m => m . GetAllAsync ( url , null ) )
3676
+ . Returns ( new [ ] { JToken . Parse ( prCommentLocation ) } . ToAsyncEnumerable ( ) ) ;
3677
+
3678
+ // Act
3679
+ var locations = await _githubApi . GetSecretScanningAlertsLocations ( GITHUB_ORG , GITHUB_REPO , alertNumber ) ;
3680
+
3681
+ // Assert
3682
+ locations . Should ( ) . HaveCount ( 1 ) ;
3683
+ var location = locations . First ( ) ;
3684
+ location . LocationType . Should ( ) . Be ( "pull_request_comment" ) ;
3685
+ location . PullRequestCommentUrl . Should ( ) . Be ( "https://api.github.com/repos/ORG/REPO/issues/comments/2758069588" ) ;
3686
+ }
3687
+
3688
+ [ Fact ]
3689
+ public async Task GetSecretScanningAlertsLocations_Handles_Pull_Request_Body_Location ( )
3690
+ {
3691
+ // Arrange
3692
+ const int alertNumber = 1 ;
3693
+ var url = $ "https://api.github.com/repos/{ GITHUB_ORG } /{ GITHUB_REPO } /secret-scanning/alerts/{ alertNumber } /locations?per_page=100";
3694
+
3695
+ var prBodyLocation = $@ "
3696
+ {{
3697
+ ""type"": ""pull_request_body"",
3698
+ ""details"": {{
3699
+ ""pull_request_body_url"": ""https://api.github.com/repos/ORG/REPO/pulls/6""
3700
+ }}
3701
+ }}
3702
+ " ;
3703
+
3704
+ _githubClientMock
3705
+ . Setup ( m => m . GetAllAsync ( url , null ) )
3706
+ . Returns ( new [ ] { JToken . Parse ( prBodyLocation ) } . ToAsyncEnumerable ( ) ) ;
3707
+
3708
+ // Act
3709
+ var locations = await _githubApi . GetSecretScanningAlertsLocations ( GITHUB_ORG , GITHUB_REPO , alertNumber ) ;
3710
+
3711
+ // Assert
3712
+ locations . Should ( ) . HaveCount ( 1 ) ;
3713
+ var location = locations . First ( ) ;
3714
+ location . LocationType . Should ( ) . Be ( "pull_request_body" ) ;
3715
+ location . PullRequestBodyUrl . Should ( ) . Be ( "https://api.github.com/repos/ORG/REPO/pulls/6" ) ;
3716
+ }
3717
+
3718
+ [ Fact ]
3719
+ public async Task GetSecretScanningAlertsLocations_Handles_Issue_Title_Location ( )
3720
+ {
3721
+ // Arrange
3722
+ const int alertNumber = 1 ;
3723
+ var url = $ "https://api.github.com/repos/{ GITHUB_ORG } /{ GITHUB_REPO } /secret-scanning/alerts/{ alertNumber } /locations?per_page=100";
3724
+
3725
+ var issueTitleLocation = $@ "
3726
+ {{
3727
+ ""type"": ""issue_title"",
3728
+ ""details"": {{
3729
+ ""issue_title_url"": ""https://api.github.com/repos/ORG/REPO/issues/7""
3730
+ }}
3731
+ }}
3732
+ " ;
3733
+
3734
+ _githubClientMock
3735
+ . Setup ( m => m . GetAllAsync ( url , null ) )
3736
+ . Returns ( new [ ] { JToken . Parse ( issueTitleLocation ) } . ToAsyncEnumerable ( ) ) ;
3737
+
3738
+ // Act
3739
+ var locations = await _githubApi . GetSecretScanningAlertsLocations ( GITHUB_ORG , GITHUB_REPO , alertNumber ) ;
3740
+
3741
+ // Assert
3742
+ locations . Should ( ) . HaveCount ( 1 ) ;
3743
+ var location = locations . First ( ) ;
3744
+ location . LocationType . Should ( ) . Be ( "issue_title" ) ;
3745
+ location . IssueTitleUrl . Should ( ) . Be ( "https://api.github.com/repos/ORG/REPO/issues/7" ) ;
3746
+ }
3747
+
3748
+ [ Fact ]
3749
+ public async Task GetSecretScanningAlertsLocations_Handles_Issue_Body_Location ( )
3750
+ {
3751
+ // Arrange
3752
+ const int alertNumber = 1 ;
3753
+ var url = $ "https://api.github.com/repos/{ GITHUB_ORG } /{ GITHUB_REPO } /secret-scanning/alerts/{ alertNumber } /locations?per_page=100";
3754
+
3755
+ var issueBodyLocation = $@ "
3756
+ {{
3757
+ ""type"": ""issue_body"",
3758
+ ""details"": {{
3759
+ ""issue_body_url"": ""https://api.github.com/repos/ORG/REPO/issues/7""
3760
+ }}
3761
+ }}
3762
+ " ;
3763
+
3764
+ _githubClientMock
3765
+ . Setup ( m => m . GetAllAsync ( url , null ) )
3766
+ . Returns ( new [ ] { JToken . Parse ( issueBodyLocation ) } . ToAsyncEnumerable ( ) ) ;
3767
+
3768
+ // Act
3769
+ var locations = await _githubApi . GetSecretScanningAlertsLocations ( GITHUB_ORG , GITHUB_REPO , alertNumber ) ;
3770
+
3771
+ // Assert
3772
+ locations . Should ( ) . HaveCount ( 1 ) ;
3773
+ var location = locations . First ( ) ;
3774
+ location . LocationType . Should ( ) . Be ( "issue_body" ) ;
3775
+ location . IssueBodyUrl . Should ( ) . Be ( "https://api.github.com/repos/ORG/REPO/issues/7" ) ;
3776
+ }
3777
+
3778
+ [ Fact ]
3779
+ public async Task GetSecretScanningAlertsLocations_Handles_Issue_Comment_Location ( )
3780
+ {
3781
+ // Arrange
3782
+ const int alertNumber = 1 ;
3783
+ var url = $ "https://api.github.com/repos/{ GITHUB_ORG } /{ GITHUB_REPO } /secret-scanning/alerts/{ alertNumber } /locations?per_page=100";
3784
+
3785
+ var issueCommentLocation = $@ "
3786
+ {{
3787
+ ""type"": ""issue_comment"",
3788
+ ""details"": {{
3789
+ ""issue_comment_url"": ""https://api.github.com/repos/ORG/REPO/issues/comments/2758578142""
3790
+ }}
3791
+ }}
3792
+ " ;
3793
+
3794
+ _githubClientMock
3795
+ . Setup ( m => m . GetAllAsync ( url , null ) )
3796
+ . Returns ( new [ ] { JToken . Parse ( issueCommentLocation ) } . ToAsyncEnumerable ( ) ) ;
3797
+
3798
+ // Act
3799
+ var locations = await _githubApi . GetSecretScanningAlertsLocations ( GITHUB_ORG , GITHUB_REPO , alertNumber ) ;
3800
+
3801
+ // Assert
3802
+ locations . Should ( ) . HaveCount ( 1 ) ;
3803
+ var location = locations . First ( ) ;
3804
+ location . LocationType . Should ( ) . Be ( "issue_comment" ) ;
3805
+ location . IssueCommentUrl . Should ( ) . Be ( "https://api.github.com/repos/ORG/REPO/issues/comments/2758578142" ) ;
3806
+ }
3807
+
3541
3808
private string Compact ( string source ) =>
3542
3809
source
3543
3810
. Replace ( "\r " , "" )
0 commit comments