@@ -3538,6 +3538,273 @@ await FluentActions
35383538 . ThrowExactlyAsync < ArgumentNullException > ( ) ;
35393539 }
35403540
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+
35413808 private string Compact ( string source ) =>
35423809 source
35433810 . Replace ( "\r " , "" )
0 commit comments