177 lines
5.6 KiB
Go
177 lines
5.6 KiB
Go
package specialist_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/rs/zerolog"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/mock"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
appMock "base/internal/application/mock"
|
|
"base/internal/application/specialist"
|
|
domainAsset "base/internal/domain/asset"
|
|
domainProfile "base/internal/domain/profile"
|
|
)
|
|
|
|
func TestSpecialistService_Overview(t *testing.T) {
|
|
ctx := context.Background()
|
|
logger := zerolog.Nop()
|
|
userID := uuid.New()
|
|
profileID := uuid.New()
|
|
|
|
t.Run("success - returns overview with profile, assets, tasks", func(t *testing.T) {
|
|
assetRepo := new(appMock.MockAssetRepository)
|
|
profileRepo := new(appMock.MockProfileRepository)
|
|
|
|
profile := &domainProfile.Profile{
|
|
ID: profileID,
|
|
Handle: "specialist-user",
|
|
UserID: &userID,
|
|
Hero: domainProfile.Hero{
|
|
FirstName: "Jane",
|
|
LastName: "Doe",
|
|
ShortDescription: "ML Engineer",
|
|
},
|
|
About: domainProfile.About{
|
|
ProfilePicture: "avatar.jpg",
|
|
About: "About me",
|
|
},
|
|
Skills: []domainProfile.Skill{
|
|
{SkillName: "Go", Level: "expert"},
|
|
},
|
|
Contact: domainProfile.Contact{
|
|
Email: "jane@example.com",
|
|
SocialLinks: []domainProfile.SocialLink{{LinkType: "github", Link: "https://github.com/jane"}},
|
|
},
|
|
PageSetting: domainProfile.PageSetting{VisibilityLevel: "public"},
|
|
}
|
|
|
|
asset := &domainAsset.Asset{
|
|
ID: uuid.New(),
|
|
ProfileID: profileID,
|
|
Status: domainAsset.StatusPublished,
|
|
AssetCategoryID: uuid.New(),
|
|
Title: "My Project",
|
|
Description: "A cool project",
|
|
AssetArtifacts: []domainAsset.Artifact{{Type: "image", DownloadURL: "cover.png", Price: 0}},
|
|
}
|
|
|
|
otherProfile := &domainProfile.Profile{
|
|
ID: uuid.New(),
|
|
Handle: "other-user",
|
|
Hero: domainProfile.Hero{FirstName: "Other", LastName: "User"},
|
|
PageSetting: domainProfile.PageSetting{VisibilityLevel: "public"},
|
|
}
|
|
|
|
profileRepo.On("FindByUserID", ctx, userID).Return(profile, nil)
|
|
assetRepo.On("FindByProfileID", ctx, profileID).Return([]*domainAsset.Asset{asset}, nil)
|
|
profileRepo.On("FindAll", ctx, mock.MatchedBy(func(arg interface{}) bool {
|
|
f, ok := arg.(domainProfile.Filter)
|
|
if !ok {
|
|
return false
|
|
}
|
|
return f.Page == 1 && f.PageSize == 6 && f.SortedBy == "created_at" && !f.Ascending
|
|
})).Return([]*domainProfile.Profile{otherProfile}, 26, nil)
|
|
assetRepo.On("Count", ctx).Return(42, nil)
|
|
|
|
svc := specialist.New(specialist.Param{
|
|
Logger: logger,
|
|
ProfileRepo: profileRepo,
|
|
AssetRepo: assetRepo,
|
|
})
|
|
|
|
resp, err := svc.Overview(ctx, userID)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
|
|
assert.Equal(t, "", resp.Message)
|
|
assert.Len(t, resp.Data.Assets, 1)
|
|
assert.Equal(t, "My Project", resp.Data.Assets[0].Title)
|
|
|
|
assert.Len(t, resp.Data.RecentlyJoined, 1)
|
|
assert.Equal(t, "other-user", resp.Data.RecentlyJoined[0].ProfileHandle)
|
|
|
|
assert.Equal(t, 42, resp.Data.Analytics.TotalAssets)
|
|
assert.Equal(t, 26, resp.Data.Analytics.TotalProfiles)
|
|
|
|
require.NotNil(t, resp.Data.Profile)
|
|
assert.Equal(t, "specialist-user", resp.Data.Profile.Handle)
|
|
assert.Len(t, resp.Data.Skills, 1)
|
|
assert.Equal(t, "Go", resp.Data.Skills[0].SkillName)
|
|
|
|
// All sections complete -> 100% or high completion
|
|
assert.False(t, resp.Data.Tasks.ProfileAction)
|
|
assert.False(t, resp.Data.Tasks.AboutAction)
|
|
assert.False(t, resp.Data.Tasks.PublishAction)
|
|
assert.False(t, resp.Data.Tasks.WorksAction)
|
|
assert.False(t, resp.Data.Tasks.SkillsAction)
|
|
assert.False(t, resp.Data.Tasks.SocialAction)
|
|
assert.Equal(t, 100, resp.Data.CompletionPercent)
|
|
|
|
assetRepo.AssertExpectations(t)
|
|
profileRepo.AssertExpectations(t)
|
|
})
|
|
|
|
t.Run("profile not found returns ErrProfileNotFound", func(t *testing.T) {
|
|
assetRepo := new(appMock.MockAssetRepository)
|
|
profileRepo := new(appMock.MockProfileRepository)
|
|
|
|
profileRepo.On("FindByUserID", ctx, userID).Return(nil, domainProfile.ErrProfileNotFound)
|
|
|
|
svc := specialist.New(specialist.Param{
|
|
Logger: logger,
|
|
ProfileRepo: profileRepo,
|
|
AssetRepo: assetRepo,
|
|
})
|
|
|
|
resp, err := svc.Overview(ctx, userID)
|
|
assert.Error(t, err)
|
|
assert.True(t, errors.Is(err, domainProfile.ErrProfileNotFound))
|
|
assert.Nil(t, resp)
|
|
|
|
profileRepo.AssertExpectations(t)
|
|
})
|
|
|
|
t.Run("incomplete profile computes tasks and completion percent", func(t *testing.T) {
|
|
assetRepo := new(appMock.MockAssetRepository)
|
|
profileRepo := new(appMock.MockProfileRepository)
|
|
|
|
profile := &domainProfile.Profile{
|
|
ID: profileID,
|
|
Handle: "incomplete",
|
|
UserID: &userID,
|
|
Hero: domainProfile.Hero{FirstName: "A"}, // missing LastName, ShortDescription
|
|
About: domainProfile.About{}, // missing picture, about
|
|
Skills: []domainProfile.Skill{},
|
|
PageSetting: domainProfile.PageSetting{VisibilityLevel: "private"},
|
|
}
|
|
|
|
profileRepo.On("FindByUserID", ctx, userID).Return(profile, nil)
|
|
assetRepo.On("FindByProfileID", ctx, profileID).Return([]*domainAsset.Asset{}, nil)
|
|
profileRepo.On("FindAll", ctx, mock.Anything).Return([]*domainProfile.Profile{}, 0, nil)
|
|
assetRepo.On("Count", ctx).Return(0, nil)
|
|
|
|
svc := specialist.New(specialist.Param{
|
|
Logger: logger,
|
|
ProfileRepo: profileRepo,
|
|
AssetRepo: assetRepo,
|
|
})
|
|
|
|
resp, err := svc.Overview(ctx, userID)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
|
|
assert.True(t, resp.Data.Tasks.ProfileAction)
|
|
assert.True(t, resp.Data.Tasks.AboutAction)
|
|
assert.True(t, resp.Data.Tasks.PublishAction)
|
|
assert.True(t, resp.Data.Tasks.WorksAction)
|
|
assert.True(t, resp.Data.Tasks.SkillsAction)
|
|
assert.True(t, resp.Data.Tasks.SocialAction)
|
|
assert.Equal(t, 0, resp.Data.CompletionPercent)
|
|
})
|
|
}
|