@@ -13,11 +13,14 @@ import (
1313 issues_model "code.gitea.io/gitea/models/issues"
1414 repo_model "code.gitea.io/gitea/models/repo"
1515 "code.gitea.io/gitea/models/unittest"
16+ user_model "code.gitea.io/gitea/models/user"
1617 "code.gitea.io/gitea/modules/json"
1718 api "code.gitea.io/gitea/modules/structs"
19+ issue_service "code.gitea.io/gitea/services/issue"
1820 "code.gitea.io/gitea/tests"
1921
2022 "github.com/stretchr/testify/assert"
23+ "xorm.io/builder"
2124)
2225
2326func TestAPIPullReview (t * testing.T ) {
@@ -305,3 +308,126 @@ func TestAPIPullReviewRequest(t *testing.T) {
305308 req = NewRequestWithJSON (t , http .MethodDelete , fmt .Sprintf ("/api/v1/repos/%s/%s/pulls/%d/requested_reviewers?token=%s" , repo3 .OwnerName , repo3 .Name , pullIssue12 .Index , token ), & api.PullReviewRequestOptions {})
306309 MakeRequest (t , req , http .StatusNoContent )
307310}
311+
312+ func TestAPIPullReviewStayDismissed (t * testing.T ) {
313+ // This test against issue https://github.com/go-gitea/gitea/issues/28542
314+ // where old reviews surface after a review request got dismissed.
315+ defer tests .PrepareTestEnv (t )()
316+ pullIssue := unittest .AssertExistsAndLoadBean (t , & issues_model.Issue {ID : 3 })
317+ assert .NoError (t , pullIssue .LoadAttributes (db .DefaultContext ))
318+ repo := unittest .AssertExistsAndLoadBean (t , & repo_model.Repository {ID : pullIssue .RepoID })
319+ user2 := unittest .AssertExistsAndLoadBean (t , & user_model.User {ID : 2 })
320+ session2 := loginUser (t , user2 .LoginName )
321+ token2 := getTokenForLoggedInUser (t , session2 , auth_model .AccessTokenScopeWriteRepository )
322+ user8 := unittest .AssertExistsAndLoadBean (t , & user_model.User {ID : 8 })
323+ session8 := loginUser (t , user8 .LoginName )
324+ token8 := getTokenForLoggedInUser (t , session8 , auth_model .AccessTokenScopeWriteRepository )
325+
326+ // user2 request user8
327+ req := NewRequestWithJSON (t , http .MethodPost , fmt .Sprintf ("/api/v1/repos/%s/%s/pulls/%d/requested_reviewers?token=%s" , repo .OwnerName , repo .Name , pullIssue .Index , token2 ), & api.PullReviewRequestOptions {
328+ Reviewers : []string {user8 .LoginName },
329+ })
330+ MakeRequest (t , req , http .StatusCreated )
331+
332+ reviewsCountCheck (t ,
333+ "check we have only one review request" ,
334+ pullIssue .ID , user8 .ID , 0 , 1 , 1 , false )
335+
336+ // user2 request user8 again, it is expected to be ignored
337+ req = NewRequestWithJSON (t , http .MethodPost , fmt .Sprintf ("/api/v1/repos/%s/%s/pulls/%d/requested_reviewers?token=%s" , repo .OwnerName , repo .Name , pullIssue .Index , token2 ), & api.PullReviewRequestOptions {
338+ Reviewers : []string {user8 .LoginName },
339+ })
340+ MakeRequest (t , req , http .StatusCreated )
341+
342+ reviewsCountCheck (t ,
343+ "check we have only one review request, even after re-request it again" ,
344+ pullIssue .ID , user8 .ID , 0 , 1 , 1 , false )
345+
346+ // user8 reviews it as accept
347+ req = NewRequestWithJSON (t , http .MethodPost , fmt .Sprintf ("/api/v1/repos/%s/%s/pulls/%d/reviews?token=%s" , repo .OwnerName , repo .Name , pullIssue .Index , token8 ), & api.CreatePullReviewOptions {
348+ Event : "APPROVED" ,
349+ Body : "lgtm" ,
350+ })
351+ MakeRequest (t , req , http .StatusOK )
352+
353+ reviewsCountCheck (t ,
354+ "check we have one valid approval" ,
355+ pullIssue .ID , user8 .ID , 0 , 0 , 1 , true )
356+
357+ // emulate of auto-dismiss lgtm on a protected branch that where a pull just got an update
358+ _ , err := db .GetEngine (db .DefaultContext ).Where ("issue_id = ? AND reviewer_id = ?" , pullIssue .ID , user8 .ID ).
359+ Cols ("dismissed" ).Update (& issues_model.Review {Dismissed : true })
360+ assert .NoError (t , err )
361+
362+ // user2 request user8 again
363+ req = NewRequestWithJSON (t , http .MethodPost , fmt .Sprintf ("/api/v1/repos/%s/%s/pulls/%d/requested_reviewers?token=%s" , repo .OwnerName , repo .Name , pullIssue .Index , token2 ), & api.PullReviewRequestOptions {
364+ Reviewers : []string {user8 .LoginName },
365+ })
366+ MakeRequest (t , req , http .StatusCreated )
367+
368+ reviewsCountCheck (t ,
369+ "check we have no valid approval and one review request" ,
370+ pullIssue .ID , user8 .ID , 1 , 1 , 2 , false )
371+
372+ // user8 dismiss review
373+ _ , err = issue_service .ReviewRequest (db .DefaultContext , pullIssue , user8 , user8 , false )
374+ assert .NoError (t , err )
375+
376+ reviewsCountCheck (t ,
377+ "check new review request is now dismissed" ,
378+ pullIssue .ID , user8 .ID , 1 , 0 , 1 , false )
379+
380+ // add a new valid approval
381+ req = NewRequestWithJSON (t , http .MethodPost , fmt .Sprintf ("/api/v1/repos/%s/%s/pulls/%d/reviews?token=%s" , repo .OwnerName , repo .Name , pullIssue .Index , token8 ), & api.CreatePullReviewOptions {
382+ Event : "APPROVED" ,
383+ Body : "lgtm" ,
384+ })
385+ MakeRequest (t , req , http .StatusOK )
386+
387+ reviewsCountCheck (t ,
388+ "check that old reviews requests are deleted" ,
389+ pullIssue .ID , user8 .ID , 1 , 0 , 2 , true )
390+
391+ // now add a change request witch should dismiss the approval
392+ req = NewRequestWithJSON (t , http .MethodPost , fmt .Sprintf ("/api/v1/repos/%s/%s/pulls/%d/reviews?token=%s" , repo .OwnerName , repo .Name , pullIssue .Index , token8 ), & api.CreatePullReviewOptions {
393+ Event : "REQUEST_CHANGES" ,
394+ Body : "please change XYZ" ,
395+ })
396+ MakeRequest (t , req , http .StatusOK )
397+
398+ reviewsCountCheck (t ,
399+ "check that old reviews are dismissed" ,
400+ pullIssue .ID , user8 .ID , 2 , 0 , 3 , false )
401+ }
402+
403+ func reviewsCountCheck (t * testing.T , name string , issueID , reviewerID int64 , expectedDismissed , expectedRequested , expectedTotal int , expectApproval bool ) {
404+ t .Run (name , func (t * testing.T ) {
405+ unittest .AssertCountByCond (t , "review" , builder.Eq {
406+ "issue_id" : issueID ,
407+ "reviewer_id" : reviewerID ,
408+ "dismissed" : true ,
409+ }, expectedDismissed )
410+
411+ unittest .AssertCountByCond (t , "review" , builder.Eq {
412+ "issue_id" : issueID ,
413+ "reviewer_id" : reviewerID ,
414+ }, expectedTotal )
415+
416+ unittest .AssertCountByCond (t , "review" , builder.Eq {
417+ "issue_id" : issueID ,
418+ "reviewer_id" : reviewerID ,
419+ "type" : issues_model .ReviewTypeRequest ,
420+ }, expectedRequested )
421+
422+ approvalCount := 0
423+ if expectApproval {
424+ approvalCount = 1
425+ }
426+ unittest .AssertCountByCond (t , "review" , builder.Eq {
427+ "issue_id" : issueID ,
428+ "reviewer_id" : reviewerID ,
429+ "type" : issues_model .ReviewTypeApprove ,
430+ "dismissed" : false ,
431+ }, approvalCount )
432+ })
433+ }
0 commit comments