Files
autogits/common/reviews_test.go
Adam Majer 69dcebcf74 common: use Timeline for reviews
Gitea doesn't keep track of Stale reviews well. We should parse
Timeline of a PR *always* and apply our own logic to this instead
2025-05-30 16:51:30 +02:00

171 lines
6.0 KiB
Go

package common_test
import (
"errors"
"testing"
"go.uber.org/mock/gomock"
"src.opensuse.org/autogits/common"
"src.opensuse.org/autogits/common/gitea-generated/models"
mock_common "src.opensuse.org/autogits/common/mock"
)
func TestReviews(t *testing.T) {
tests := []struct {
name string
reviews []*models.PullReview
timeline []*models.TimelineComment
reviewers []string
fetchErr error
isApproved bool
isReviewedByTest1 bool
isPendingByTest1 bool
}{
{
name: "Reviews of PR with no review requirements",
isApproved: true,
},
{
name: "Single reviewer done",
reviews: []*models.PullReview{&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}}},
reviewers: []string{"user1"},
isApproved: true,
isReviewedByTest1: true,
},
{
name: "Two reviewer, one not approved",
reviews: []*models.PullReview{&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}}},
reviewers: []string{"user1", "user2"},
isApproved: false,
isReviewedByTest1: true,
},
{
name: "Two reviewer, one stale approved",
reviews: []*models.PullReview{
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}},
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user2"}, Stale: true},
},
reviewers: []string{"user1", "user2"},
isApproved: false,
isReviewedByTest1: true,
},
{
name: "Two reviewer, one is pending",
reviews: []*models.PullReview{
&models.PullReview{State: common.ReviewStateRequestReview, User: &models.User{UserName: "user1"}},
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user2"}},
},
reviewers: []string{"user1", "user2"},
isApproved: false,
isPendingByTest1: true,
},
{
name: "Two reviewer, one stale and pending",
reviews: []*models.PullReview{
&models.PullReview{State: common.ReviewStateRequestReview, User: &models.User{UserName: "user1"}, Stale: true},
},
reviewers: []string{"user1", "user2"},
isApproved: false,
isPendingByTest1: false,
isReviewedByTest1: false,
},
{
name: "Two reviewer approved",
reviews: []*models.PullReview{
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}},
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user2"}},
},
reviewers: []string{"user1", "user2"},
isApproved: true,
isReviewedByTest1: true,
},
{
name: "Two reviewer approved, one is dismissed",
reviews: []*models.PullReview{
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}},
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user2"}, Dismissed: true},
},
reviewers: []string{"user1", "user2"},
isApproved: false,
isReviewedByTest1: true,
},
{
name: "Two reviewer approved, but fetch error",
reviews: []*models.PullReview{
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}},
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user2"}},
},
reviewers: []string{"user1", "user2"},
fetchErr: errors.New("System error fetching reviews."),
isApproved: true,
isReviewedByTest1: true,
},
{
name: "Extra reviewers are ignored",
reviews: []*models.PullReview{
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}},
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user4"}},
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user2"}},
},
reviewers: []string{"user1", "user2"},
isApproved: true,
isReviewedByTest1: true,
},
{
name: "Review ignored before push",
reviews: []*models.PullReview{
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user1"}, ID: 1001},
&models.PullReview{State: common.ReviewStateApproved, User: &models.User{UserName: "user2"}, ID: 1000},
},
timeline: []*models.TimelineComment{
&models.TimelineComment{Type: common.TimelineCommentType_Review, ReviewID: 1001},
&models.TimelineComment{Type: common.TimelineCommentType_PushPull},
&models.TimelineComment{Type: common.TimelineCommentType_Review, ReviewID: 1000},
},
reviewers: []string{"user1", "user2"},
isApproved: false,
isReviewedByTest1: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ctl := gomock.NewController(t)
rf := mock_common.NewMockGiteaReviewTimelineFetcher(ctl)
if test.timeline == nil {
test.timeline = reviewsToTimeline(test.reviews)
}
rf.EXPECT().GetTimeline("test", "pr", int64(1)).Return(test.timeline, nil)
rf.EXPECT().GetPullRequestReviews("test", "pr", int64(1)).Return(test.reviews, test.fetchErr)
reviews, err := common.FetchGiteaReviews(rf, test.reviewers, "test", "pr", 1)
if test.fetchErr != nil {
if err != test.fetchErr {
t.Fatal("FetchReviews() failed with unexpected error:", err)
}
return
}
if r := reviews.IsApproved(); r != test.isApproved {
t.Fatal("Unexpected IsReviewed():", r, "vs. expected", test.isApproved)
}
if r := reviews.HasPendingReviewBy("user1"); r != test.isPendingByTest1 {
t.Fatal("Unexpected IsReviewPendingBy(user1):", r)
}
if r := reviews.IsReviewedBy("user1"); r != test.isReviewedByTest1 {
t.Fatal("Unexpected IsReviewedBy(user1):", r)
}
if r := reviews.HasPendingReviewBy("random"); r {
t.Fatal("Unexpected IsReviewPendingBy(random):", r)
}
if r := reviews.IsReviewedBy("random"); r {
t.Fatal("Unexpected IsReviewedBy(random):", r)
}
})
}
}