mirror of
https://github.com/muety/wakapi.git
synced 2023-08-10 21:12:56 +03:00
refactor: introduce concept of durations (resolve #261)
This commit is contained in:
@ -13,33 +13,19 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
TestUserId = "muety"
|
||||
TestProject1 = "test-project-1"
|
||||
TestProject2 = "test-project-2"
|
||||
TestProjectLabel1 = "private"
|
||||
TestProjectLabel2 = "work"
|
||||
TestProjectLabel3 = "non-existing"
|
||||
TestLanguageGo = "Go"
|
||||
TestLanguageJava = "Java"
|
||||
TestLanguagePython = "Python"
|
||||
TestEditorGoland = "GoLand"
|
||||
TestEditorIntellij = "idea"
|
||||
TestEditorVscode = "vscode"
|
||||
TestOsLinux = "Linux"
|
||||
TestOsWin = "Windows"
|
||||
TestMachine1 = "muety-desktop"
|
||||
TestMachine2 = "muety-work"
|
||||
MinUnixTime1 = 1601510400000 * 1e6
|
||||
TestProjectLabel1 = "private"
|
||||
TestProjectLabel2 = "work"
|
||||
TestProjectLabel3 = "non-existing"
|
||||
)
|
||||
|
||||
type SummaryServiceTestSuite struct {
|
||||
suite.Suite
|
||||
TestUser *models.User
|
||||
TestStartTime time.Time
|
||||
TestHeartbeats []*models.Heartbeat
|
||||
TestDurations []*models.Duration
|
||||
TestLabels []*models.ProjectLabel
|
||||
SummaryRepository *mocks.SummaryRepositoryMock
|
||||
HeartbeatService *mocks.HeartbeatServiceMock
|
||||
DurationService *mocks.DurationServiceMock
|
||||
AliasService *mocks.AliasServiceMock
|
||||
ProjectLabelService *mocks.ProjectLabelServiceMock
|
||||
}
|
||||
@ -48,9 +34,8 @@ func (suite *SummaryServiceTestSuite) SetupSuite() {
|
||||
suite.TestUser = &models.User{ID: TestUserId}
|
||||
|
||||
suite.TestStartTime = time.Unix(0, MinUnixTime1)
|
||||
suite.TestHeartbeats = []*models.Heartbeat{
|
||||
suite.TestDurations = []*models.Duration{
|
||||
{
|
||||
ID: rand.Uint64(),
|
||||
UserID: TestUserId,
|
||||
Project: TestProject1,
|
||||
Language: TestLanguageGo,
|
||||
@ -58,19 +43,19 @@ func (suite *SummaryServiceTestSuite) SetupSuite() {
|
||||
OperatingSystem: TestOsLinux,
|
||||
Machine: TestMachine1,
|
||||
Time: models.CustomTime(suite.TestStartTime),
|
||||
Duration: 150 * time.Second,
|
||||
},
|
||||
{
|
||||
ID: rand.Uint64(),
|
||||
UserID: TestUserId,
|
||||
Project: TestProject1,
|
||||
Language: TestLanguageGo,
|
||||
Editor: TestEditorGoland,
|
||||
OperatingSystem: TestOsLinux,
|
||||
Machine: TestMachine1,
|
||||
Time: models.CustomTime(suite.TestStartTime.Add(30 * time.Second)),
|
||||
Time: models.CustomTime(suite.TestStartTime.Add((30 + 130) * time.Second)),
|
||||
Duration: 20 * time.Second,
|
||||
},
|
||||
{
|
||||
ID: rand.Uint64(),
|
||||
UserID: TestUserId,
|
||||
Project: TestProject1,
|
||||
Language: TestLanguageGo,
|
||||
@ -78,6 +63,7 @@ func (suite *SummaryServiceTestSuite) SetupSuite() {
|
||||
OperatingSystem: TestOsLinux,
|
||||
Machine: TestMachine1,
|
||||
Time: models.CustomTime(suite.TestStartTime.Add(3 * time.Minute)),
|
||||
Duration: 15 * time.Second,
|
||||
},
|
||||
}
|
||||
suite.TestLabels = []*models.ProjectLabel{
|
||||
@ -98,7 +84,7 @@ func (suite *SummaryServiceTestSuite) SetupSuite() {
|
||||
|
||||
func (suite *SummaryServiceTestSuite) BeforeTest(suiteName, testName string) {
|
||||
suite.SummaryRepository = new(mocks.SummaryRepositoryMock)
|
||||
suite.HeartbeatService = new(mocks.HeartbeatServiceMock)
|
||||
suite.DurationService = new(mocks.DurationServiceMock)
|
||||
suite.AliasService = new(mocks.AliasServiceMock)
|
||||
suite.ProjectLabelService = new(mocks.ProjectLabelServiceMock)
|
||||
}
|
||||
@ -108,7 +94,7 @@ func TestSummaryServiceTestSuite(t *testing.T) {
|
||||
}
|
||||
|
||||
func (suite *SummaryServiceTestSuite) TestSummaryService_Summarize() {
|
||||
sut := NewSummaryService(suite.SummaryRepository, suite.HeartbeatService, suite.AliasService, suite.ProjectLabelService)
|
||||
sut := NewSummaryService(suite.SummaryRepository, suite.DurationService, suite.AliasService, suite.ProjectLabelService)
|
||||
|
||||
var (
|
||||
from time.Time
|
||||
@ -119,7 +105,7 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Summarize() {
|
||||
|
||||
/* TEST 1 */
|
||||
from, to = suite.TestStartTime.Add(-1*time.Hour), suite.TestStartTime.Add(-1*time.Minute)
|
||||
suite.HeartbeatService.On("GetAllWithin", from, to, suite.TestUser).Return(filter(from, to, suite.TestHeartbeats), nil)
|
||||
suite.DurationService.On("Get", from, to, suite.TestUser).Return(filterDurations(from, to, suite.TestDurations), nil)
|
||||
|
||||
result, err = sut.Summarize(from, to, suite.TestUser)
|
||||
|
||||
@ -132,36 +118,36 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Summarize() {
|
||||
|
||||
/* TEST 2 */
|
||||
from, to = suite.TestStartTime.Add(-1*time.Hour), suite.TestStartTime.Add(1*time.Second)
|
||||
suite.HeartbeatService.On("GetAllWithin", from, to, suite.TestUser).Return(filter(from, to, suite.TestHeartbeats), nil)
|
||||
suite.DurationService.On("Get", from, to, suite.TestUser).Return(filterDurations(from, to, suite.TestDurations), nil)
|
||||
|
||||
result, err = sut.Summarize(from, to, suite.TestUser)
|
||||
|
||||
assert.Nil(suite.T(), err)
|
||||
assert.NotNil(suite.T(), result)
|
||||
assert.Equal(suite.T(), suite.TestHeartbeats[0].Time.T(), result.FromTime.T())
|
||||
assert.Equal(suite.T(), suite.TestHeartbeats[0].Time.T(), result.ToTime.T())
|
||||
assert.Zero(suite.T(), result.TotalTime())
|
||||
assert.Equal(suite.T(), suite.TestDurations[0].Time.T(), result.FromTime.T())
|
||||
assert.Equal(suite.T(), suite.TestDurations[0].Time.T(), result.ToTime.T())
|
||||
assert.Equal(suite.T(), 150*time.Second, result.TotalTime())
|
||||
assertNumAllItems(suite.T(), 1, result, "")
|
||||
|
||||
/* TEST 3 */
|
||||
from, to = suite.TestStartTime, suite.TestStartTime.Add(1*time.Hour)
|
||||
suite.HeartbeatService.On("GetAllWithin", from, to, suite.TestUser).Return(filter(from, to, suite.TestHeartbeats), nil)
|
||||
suite.DurationService.On("Get", from, to, suite.TestUser).Return(filterDurations(from, to, suite.TestDurations), nil)
|
||||
|
||||
result, err = sut.Summarize(from, to, suite.TestUser)
|
||||
|
||||
assert.Nil(suite.T(), err)
|
||||
assert.NotNil(suite.T(), result)
|
||||
assert.Equal(suite.T(), suite.TestHeartbeats[0].Time.T(), result.FromTime.T())
|
||||
assert.Equal(suite.T(), suite.TestHeartbeats[len(suite.TestHeartbeats)-1].Time.T(), result.ToTime.T())
|
||||
assert.Equal(suite.T(), 150*time.Second, result.TotalTime())
|
||||
assert.Equal(suite.T(), 30*time.Second, result.TotalTimeByKey(models.SummaryEditor, TestEditorGoland))
|
||||
assert.Equal(suite.T(), 120*time.Second, result.TotalTimeByKey(models.SummaryEditor, TestEditorVscode))
|
||||
assert.Equal(suite.T(), suite.TestDurations[0].Time.T(), result.FromTime.T())
|
||||
assert.Equal(suite.T(), suite.TestDurations[len(suite.TestDurations)-1].Time.T(), result.ToTime.T())
|
||||
assert.Equal(suite.T(), 185*time.Second, result.TotalTime())
|
||||
assert.Equal(suite.T(), 170*time.Second, result.TotalTimeByKey(models.SummaryEditor, TestEditorGoland))
|
||||
assert.Equal(suite.T(), 15*time.Second, result.TotalTimeByKey(models.SummaryEditor, TestEditorVscode))
|
||||
assert.Len(suite.T(), result.Editors, 2)
|
||||
assertNumAllItems(suite.T(), 1, result, "e")
|
||||
}
|
||||
|
||||
func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve() {
|
||||
sut := NewSummaryService(suite.SummaryRepository, suite.HeartbeatService, suite.AliasService, suite.ProjectLabelService)
|
||||
sut := NewSummaryService(suite.SummaryRepository, suite.DurationService, suite.AliasService, suite.ProjectLabelService)
|
||||
|
||||
var (
|
||||
summaries []*models.Summary
|
||||
@ -194,8 +180,8 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve() {
|
||||
}
|
||||
|
||||
suite.SummaryRepository.On("GetByUserWithin", suite.TestUser, from, to).Return(summaries, nil)
|
||||
suite.HeartbeatService.On("GetAllWithin", from, summaries[0].FromTime.T(), suite.TestUser).Return([]*models.Heartbeat{}, nil)
|
||||
suite.HeartbeatService.On("GetAllWithin", summaries[0].ToTime.T(), to, suite.TestUser).Return([]*models.Heartbeat{}, nil)
|
||||
suite.DurationService.On("Get", from, summaries[0].FromTime.T(), suite.TestUser).Return([]*models.Duration{}, nil)
|
||||
suite.DurationService.On("Get", summaries[0].ToTime.T(), to, suite.TestUser).Return([]*models.Duration{}, nil)
|
||||
|
||||
result, err = sut.Retrieve(from, to, suite.TestUser)
|
||||
|
||||
@ -203,7 +189,7 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve() {
|
||||
assert.NotNil(suite.T(), result)
|
||||
assert.Len(suite.T(), result.Projects, 1)
|
||||
assert.Equal(suite.T(), summaries[0].Projects[0].Total*time.Second, result.TotalTime())
|
||||
suite.HeartbeatService.AssertNumberOfCalls(suite.T(), "GetAllWithin", 2)
|
||||
suite.DurationService.AssertNumberOfCalls(suite.T(), "Get", 2)
|
||||
|
||||
/* TEST 2 */
|
||||
from, to = suite.TestStartTime.Add(-10*time.Minute), suite.TestStartTime.Add(12*time.Hour)
|
||||
@ -245,17 +231,17 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve() {
|
||||
}
|
||||
|
||||
suite.SummaryRepository.On("GetByUserWithin", suite.TestUser, from, to).Return(summaries, nil)
|
||||
suite.HeartbeatService.On("GetAllWithin", from, summaries[0].FromTime.T(), suite.TestUser).Return(filter(from, summaries[0].FromTime.T(), suite.TestHeartbeats), nil)
|
||||
suite.DurationService.On("Get", from, summaries[0].FromTime.T(), suite.TestUser).Return(filterDurations(from, summaries[0].FromTime.T(), suite.TestDurations), nil)
|
||||
|
||||
result, err = sut.Retrieve(from, to, suite.TestUser)
|
||||
|
||||
assert.Nil(suite.T(), err)
|
||||
assert.NotNil(suite.T(), result)
|
||||
assert.Len(suite.T(), result.Projects, 2)
|
||||
assert.Equal(suite.T(), 150*time.Second+90*time.Minute, result.TotalTime())
|
||||
assert.Equal(suite.T(), 150*time.Second+45*time.Minute, result.TotalTimeByKey(models.SummaryProject, TestProject1))
|
||||
assert.Equal(suite.T(), 185*time.Second+90*time.Minute, result.TotalTime())
|
||||
assert.Equal(suite.T(), 185*time.Second+45*time.Minute, result.TotalTimeByKey(models.SummaryProject, TestProject1))
|
||||
assert.Equal(suite.T(), 45*time.Minute, result.TotalTimeByKey(models.SummaryProject, TestProject2))
|
||||
suite.HeartbeatService.AssertNumberOfCalls(suite.T(), "GetAllWithin", 2+1)
|
||||
suite.DurationService.AssertNumberOfCalls(suite.T(), "Get", 2+1)
|
||||
|
||||
/* TEST 3 */
|
||||
from = time.Date(suite.TestStartTime.Year(), suite.TestStartTime.Month(), suite.TestStartTime.Day()+1, 0, 0, 0, 0, suite.TestStartTime.Location()) // start of next day
|
||||
@ -298,7 +284,7 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve() {
|
||||
}
|
||||
|
||||
suite.SummaryRepository.On("GetByUserWithin", suite.TestUser, from, to).Return(summaries, nil)
|
||||
suite.HeartbeatService.On("GetAllWithin", summaries[0].ToTime.T(), summaries[1].FromTime.T(), suite.TestUser).Return(filter(summaries[0].ToTime.T(), summaries[1].FromTime.T(), suite.TestHeartbeats), nil)
|
||||
suite.DurationService.On("Get", summaries[0].ToTime.T(), summaries[1].FromTime.T(), suite.TestUser).Return(filterDurations(summaries[0].ToTime.T(), summaries[1].FromTime.T(), suite.TestDurations), nil)
|
||||
|
||||
result, err = sut.Retrieve(from, to, suite.TestUser)
|
||||
|
||||
@ -308,11 +294,11 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve() {
|
||||
assert.Equal(suite.T(), 90*time.Minute, result.TotalTime())
|
||||
assert.Equal(suite.T(), 45*time.Minute, result.TotalTimeByKey(models.SummaryProject, TestProject1))
|
||||
assert.Equal(suite.T(), 45*time.Minute, result.TotalTimeByKey(models.SummaryProject, TestProject2))
|
||||
suite.HeartbeatService.AssertNumberOfCalls(suite.T(), "GetAllWithin", 2+1+1)
|
||||
suite.DurationService.AssertNumberOfCalls(suite.T(), "Get", 2+1+1)
|
||||
}
|
||||
|
||||
func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve_DuplicateSummaries() {
|
||||
sut := NewSummaryService(suite.SummaryRepository, suite.HeartbeatService, suite.AliasService, suite.ProjectLabelService)
|
||||
sut := NewSummaryService(suite.SummaryRepository, suite.DurationService, suite.AliasService, suite.ProjectLabelService)
|
||||
|
||||
suite.ProjectLabelService.On("GetByUser", suite.TestUser.ID).Return([]*models.ProjectLabel{}, nil)
|
||||
|
||||
@ -347,8 +333,8 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve_DuplicateSumma
|
||||
summaries = append(summaries, &(*summaries[0])) // add same summary again -> mustn't be counted twice!
|
||||
|
||||
suite.SummaryRepository.On("GetByUserWithin", suite.TestUser, from, to).Return(summaries, nil)
|
||||
suite.HeartbeatService.On("GetAllWithin", from, summaries[0].FromTime.T(), suite.TestUser).Return([]*models.Heartbeat{}, nil)
|
||||
suite.HeartbeatService.On("GetAllWithin", summaries[0].ToTime.T(), to, suite.TestUser).Return([]*models.Heartbeat{}, nil)
|
||||
suite.DurationService.On("Get", from, summaries[0].FromTime.T(), suite.TestUser).Return([]*models.Duration{}, nil)
|
||||
suite.DurationService.On("Get", summaries[0].ToTime.T(), to, suite.TestUser).Return([]*models.Duration{}, nil)
|
||||
|
||||
result, err = sut.Retrieve(from, to, suite.TestUser)
|
||||
|
||||
@ -356,11 +342,11 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve_DuplicateSumma
|
||||
assert.NotNil(suite.T(), result)
|
||||
assert.Len(suite.T(), result.Projects, 1)
|
||||
assert.Equal(suite.T(), summaries[0].Projects[0].Total*time.Second, result.TotalTime())
|
||||
suite.HeartbeatService.AssertNumberOfCalls(suite.T(), "GetAllWithin", 2)
|
||||
suite.DurationService.AssertNumberOfCalls(suite.T(), "Get", 2)
|
||||
}
|
||||
|
||||
func (suite *SummaryServiceTestSuite) TestSummaryService_Aliased() {
|
||||
sut := NewSummaryService(suite.SummaryRepository, suite.HeartbeatService, suite.AliasService, suite.ProjectLabelService)
|
||||
sut := NewSummaryService(suite.SummaryRepository, suite.DurationService, suite.AliasService, suite.ProjectLabelService)
|
||||
|
||||
suite.ProjectLabelService.On("GetByUser", suite.TestUser.ID).Return([]*models.ProjectLabel{}, nil)
|
||||
|
||||
@ -373,19 +359,19 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Aliased() {
|
||||
|
||||
from, to = suite.TestStartTime, suite.TestStartTime.Add(1*time.Hour)
|
||||
|
||||
heartbeats := filter(from, to, suite.TestHeartbeats)
|
||||
heartbeats = append(heartbeats, &models.Heartbeat{
|
||||
ID: rand.Uint64(),
|
||||
durations := filterDurations(from, to, suite.TestDurations)
|
||||
durations = append(durations, &models.Duration{
|
||||
UserID: TestUserId,
|
||||
Project: TestProject2,
|
||||
Language: TestLanguageGo,
|
||||
Editor: TestEditorGoland,
|
||||
OperatingSystem: TestOsLinux,
|
||||
Machine: TestMachine1,
|
||||
Time: models.CustomTime(heartbeats[len(heartbeats)-1].Time.T().Add(10 * time.Second)),
|
||||
Time: models.CustomTime(durations[len(durations)-1].Time.T().Add(10 * time.Second)),
|
||||
Duration: 0, // not relevant here
|
||||
})
|
||||
|
||||
suite.HeartbeatService.On("GetAllWithin", from, to, suite.TestUser).Return(heartbeats, nil)
|
||||
suite.DurationService.On("Get", from, to, suite.TestUser).Return(durations, nil)
|
||||
suite.AliasService.On("InitializeUser", TestUserId).Return(nil)
|
||||
suite.AliasService.On("GetAliasOrDefault", TestUserId, mock.Anything, TestProject1).Return(TestProject2, nil)
|
||||
suite.AliasService.On("GetAliasOrDefault", TestUserId, mock.Anything, TestProject2).Return(TestProject2, nil)
|
||||
@ -401,7 +387,7 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Aliased() {
|
||||
}
|
||||
|
||||
func (suite *SummaryServiceTestSuite) TestSummaryService_Aliased_ProjectLabels() {
|
||||
sut := NewSummaryService(suite.SummaryRepository, suite.HeartbeatService, suite.AliasService, suite.ProjectLabelService)
|
||||
sut := NewSummaryService(suite.SummaryRepository, suite.DurationService, suite.AliasService, suite.ProjectLabelService)
|
||||
|
||||
var (
|
||||
from time.Time
|
||||
@ -412,20 +398,20 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Aliased_ProjectLabels()
|
||||
|
||||
from, to = suite.TestStartTime, suite.TestStartTime.Add(1*time.Hour)
|
||||
|
||||
heartbeats := filter(from, to, suite.TestHeartbeats)
|
||||
heartbeats = append(heartbeats, &models.Heartbeat{
|
||||
ID: rand.Uint64(),
|
||||
durations := filterDurations(from, to, suite.TestDurations)
|
||||
durations = append(durations, &models.Duration{
|
||||
UserID: TestUserId,
|
||||
Project: TestProject2,
|
||||
Language: TestLanguageGo,
|
||||
Editor: TestEditorGoland,
|
||||
OperatingSystem: TestOsLinux,
|
||||
Machine: TestMachine1,
|
||||
Time: models.CustomTime(heartbeats[len(heartbeats)-1].Time.T().Add(10 * time.Second)),
|
||||
Time: models.CustomTime(durations[len(durations)-1].Time.T().Add(10 * time.Second)),
|
||||
Duration: 10 * time.Second,
|
||||
})
|
||||
|
||||
suite.ProjectLabelService.On("GetByUser", suite.TestUser.ID).Return(suite.TestLabels, nil).Once()
|
||||
suite.HeartbeatService.On("GetAllWithin", from, to, suite.TestUser).Return(heartbeats, nil)
|
||||
suite.DurationService.On("Get", from, to, suite.TestUser).Return(durations, nil)
|
||||
suite.AliasService.On("InitializeUser", TestUserId).Return(nil)
|
||||
suite.AliasService.On("GetAliasOrDefault", TestUserId, mock.Anything, TestProject1).Return(TestProject1, nil)
|
||||
suite.AliasService.On("GetAliasOrDefault", TestUserId, mock.Anything, TestProject2).Return(TestProject1, nil)
|
||||
@ -435,14 +421,14 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Aliased_ProjectLabels()
|
||||
|
||||
assert.Nil(suite.T(), err)
|
||||
assert.NotNil(suite.T(), result)
|
||||
assert.Equal(suite.T(), 160*time.Second, result.TotalTimeByKey(models.SummaryLabel, TestProjectLabel1))
|
||||
assert.Equal(suite.T(), 195*time.Second, result.TotalTimeByKey(models.SummaryLabel, TestProjectLabel1))
|
||||
}
|
||||
|
||||
func filter(from, to time.Time, heartbeats []*models.Heartbeat) []*models.Heartbeat {
|
||||
filtered := make([]*models.Heartbeat, 0, len(heartbeats))
|
||||
for _, h := range heartbeats {
|
||||
if (h.Time.T().Equal(from) || h.Time.T().After(from)) && h.Time.T().Before(to) {
|
||||
filtered = append(filtered, h)
|
||||
func filterDurations(from, to time.Time, durations []*models.Duration) []*models.Duration {
|
||||
filtered := make([]*models.Duration, 0, len(durations))
|
||||
for _, d := range durations {
|
||||
if (d.Time.T().Equal(from) || d.Time.T().After(from)) && d.Time.T().Before(to) {
|
||||
filtered = append(filtered, d)
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
|
Reference in New Issue
Block a user