Files
git-velocity/internal/domain/models/models_test.go
T

324 lines
6.6 KiB
Go

package models
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestAuthor_DisplayName(t *testing.T) {
t.Parallel()
tests := []struct {
name string
author Author
expected string
}{
{
name: "prefers name over login",
author: Author{Login: "johndoe", Name: "John Doe", Email: "john@example.com"},
expected: "John Doe",
},
{
name: "falls back to login",
author: Author{Login: "johndoe", Email: "john@example.com"},
expected: "johndoe",
},
{
name: "falls back to email",
author: Author{Email: "john@example.com"},
expected: "john@example.com",
},
{
name: "returns Unknown when empty",
author: Author{},
expected: "Unknown",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
assert.Equal(t, tt.expected, tt.author.DisplayName())
})
}
}
func TestPullRequest_IsMerged(t *testing.T) {
t.Parallel()
now := time.Now()
tests := []struct {
name string
pr PullRequest
expected bool
}{
{
name: "merged state",
pr: PullRequest{State: PRStateMerged},
expected: true,
},
{
name: "has merged_at",
pr: PullRequest{State: PRStateClosed, MergedAt: &now},
expected: true,
},
{
name: "open PR",
pr: PullRequest{State: PRStateOpen},
expected: false,
},
{
name: "closed without merge",
pr: PullRequest{State: PRStateClosed},
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
assert.Equal(t, tt.expected, tt.pr.IsMerged())
})
}
}
func TestPullRequest_Size(t *testing.T) {
t.Parallel()
tests := []struct {
name string
additions int
deletions int
expected PRSize
}{
{
name: "xs",
additions: 5,
deletions: 3,
expected: PRSizeXS,
},
{
name: "s",
additions: 30,
deletions: 15,
expected: PRSizeS,
},
{
name: "m",
additions: 100,
deletions: 50,
expected: PRSizeM,
},
{
name: "l",
additions: 300,
deletions: 100,
expected: PRSizeL,
},
{
name: "xl",
additions: 400,
deletions: 200,
expected: PRSizeXL,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
pr := PullRequest{Additions: tt.additions, Deletions: tt.deletions}
assert.Equal(t, tt.expected, pr.Size())
})
}
}
func TestPullRequest_CalculateTimeToMerge(t *testing.T) {
t.Parallel()
t.Run("returns duration when merged", func(t *testing.T) {
t.Parallel()
created := time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC)
merged := time.Date(2024, 1, 1, 14, 0, 0, 0, time.UTC)
pr := PullRequest{CreatedAt: created, MergedAt: &merged}
result := pr.CalculateTimeToMerge()
assert.NotNil(t, result)
assert.Equal(t, 4*time.Hour, *result)
})
t.Run("returns nil when not merged", func(t *testing.T) {
t.Parallel()
pr := PullRequest{CreatedAt: time.Now()}
assert.Nil(t, pr.CalculateTimeToMerge())
})
}
func TestPullRequest_CalculateTimeToFirstReview(t *testing.T) {
t.Parallel()
t.Run("returns duration to first review", func(t *testing.T) {
t.Parallel()
created := time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC)
review1 := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
review2 := time.Date(2024, 1, 1, 14, 0, 0, 0, time.UTC)
pr := PullRequest{
CreatedAt: created,
Reviews: []Review{
{SubmittedAt: review2},
{SubmittedAt: review1}, // Earlier review
},
}
result := pr.CalculateTimeToFirstReview()
assert.NotNil(t, result)
assert.Equal(t, 2*time.Hour, *result)
})
t.Run("returns nil when no reviews", func(t *testing.T) {
t.Parallel()
pr := PullRequest{CreatedAt: time.Now(), Reviews: []Review{}}
assert.Nil(t, pr.CalculateTimeToFirstReview())
})
}
func TestReview_IsApproval(t *testing.T) {
t.Parallel()
tests := []struct {
name string
state ReviewState
expected bool
}{
{name: "approved", state: ReviewApproved, expected: true},
{name: "changes requested", state: ReviewChangesRequested, expected: false},
{name: "commented", state: ReviewCommented, expected: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
r := Review{State: tt.state}
assert.Equal(t, tt.expected, r.IsApproval())
})
}
}
func TestReview_RequestsChanges(t *testing.T) {
t.Parallel()
tests := []struct {
name string
state ReviewState
expected bool
}{
{name: "approved", state: ReviewApproved, expected: false},
{name: "changes requested", state: ReviewChangesRequested, expected: true},
{name: "commented", state: ReviewCommented, expected: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
r := Review{State: tt.state}
assert.Equal(t, tt.expected, r.RequestsChanges())
})
}
}
func TestReview_IsSubstantive(t *testing.T) {
t.Parallel()
tests := []struct {
name string
review Review
expected bool
}{
{
name: "has body",
review: Review{Body: "Good work!"},
expected: true,
},
{
name: "has comments",
review: Review{CommentsCount: 3},
expected: true,
},
{
name: "requests changes",
review: Review{State: ReviewChangesRequested},
expected: true,
},
{
name: "empty approval",
review: Review{State: ReviewApproved},
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
assert.Equal(t, tt.expected, tt.review.IsSubstantive())
})
}
}
func TestIssue_IsClosed(t *testing.T) {
t.Parallel()
tests := []struct {
name string
state IssueState
expected bool
}{
{name: "open", state: IssueStateOpen, expected: false},
{name: "closed", state: IssueStateClosed, expected: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
issue := Issue{State: tt.state}
assert.Equal(t, tt.expected, issue.IsClosed())
})
}
}
func TestIssue_CalculateTimeToClose(t *testing.T) {
t.Parallel()
t.Run("returns duration when closed", func(t *testing.T) {
t.Parallel()
created := time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC)
closed := time.Date(2024, 1, 3, 10, 0, 0, 0, time.UTC)
issue := Issue{CreatedAt: created, ClosedAt: &closed}
result := issue.CalculateTimeToClose()
assert.NotNil(t, result)
assert.Equal(t, 48*time.Hour, *result)
})
t.Run("returns nil when not closed", func(t *testing.T) {
t.Parallel()
issue := Issue{CreatedAt: time.Now()}
assert.Nil(t, issue.CalculateTimeToClose())
})
}
func TestPullRequest_TotalChanges(t *testing.T) {
t.Parallel()
pr := PullRequest{Additions: 200, Deletions: 100}
assert.Equal(t, 300, pr.TotalChanges())
}