Files
RenewCMS/test/author_mutation_test.go
T

123 lines
4.2 KiB
Go

package test
import (
"RenewCMS/internal/domain/author"
"RenewCMS/internal/infrastructure/useCases"
"context"
"errors"
"testing"
)
type recordingAuthorRepo struct {
*mockAuthorRepo
created []author.Author
}
func (r *recordingAuthorRepo) Create(a author.Author) (author.Author, error) {
a.ID = uint32(len(r.created) + 100)
r.created = append(r.created, a)
return a, nil
}
func TestAuthorUseCaseGuards(t *testing.T) {
t.Run("A taken slug is rejected by the use case itself", func(t *testing.T) {
authors := &recordingAuthorRepo{mockAuthorRepo: plainAuthors()}
authors.seed(1, "A", "taken")
uc := useCases.NewCreateAuthorUseCase(authors, newMockUserRepo(), newMockImageRepo(), discardRecorder)
_, err := uc.Create(context.Background(), useCases.CreateAuthorCommand{Name: "B", Slug: "taken"})
if !errors.Is(err, author.ErrSlugTaken) || len(authors.created) != 0 {
t.Errorf("err %v created %d", err, len(authors.created))
}
})
t.Run("The linked flag follows the user id on creation", func(t *testing.T) {
users := newMockUserRepo()
users.users[7] = userNamed(7, "u7", "U Seven")
authors := &recordingAuthorRepo{mockAuthorRepo: plainAuthors()}
uc := useCases.NewCreateAuthorUseCase(authors, users, newMockImageRepo(), discardRecorder)
userID := uint32(7)
_, linkedErr := uc.Create(context.Background(), useCases.CreateAuthorCommand{Name: "Linked", UserID: &userID})
_, freeErr := uc.Create(context.Background(), useCases.CreateAuthorCommand{Name: "Free"})
if linkedErr != nil || freeErr != nil || len(authors.created) != 2 {
t.Fatalf("errs %v %v created %d", linkedErr, freeErr, len(authors.created))
}
if !authors.created[0].IsLinked || authors.created[1].IsLinked {
t.Errorf("flags %v %v", authors.created[0].IsLinked, authors.created[1].IsLinked)
}
})
t.Run("The own author can use the fiftieth slug candidate", func(t *testing.T) {
users := newMockUserRepo()
users.users[1] = userNamed(1, "marta", "Marta Alves")
authors := plainAuthors()
base := author.GenerateSlug("Marta Alves")
for attempt := 1; attempt < 50; attempt++ {
authors.seed(uint32(attempt), "X", author.SlugWithSuffix(base, attempt))
}
uc := useCases.NewCreateMyAuthorUseCase(authors, users, discardRecorder)
created, err := uc.Create(context.Background(), 1)
if err != nil || created.Slug != author.SlugWithSuffix(base, 50) {
t.Errorf("created %+v %v", created, err)
}
})
}
type staleCountAuthorRepo struct {
*mockAuthorRepo
}
func (s *staleCountAuthorRepo) Get(id uint32) (author.Author, error) {
found, err := s.mockAuthorRepo.Get(id)
found.ArticleCount = 0
return found, err
}
func TestAuthorDeleteRace(t *testing.T) {
t.Run("A credit added after the count was read blocks the delete", func(t *testing.T) {
base := plainAuthors()
base.seed(2, "B", "b")
base.articles.credits[10] = []uint32{2}
uc := useCases.NewDeleteAuthorUseCase(&staleCountAuthorRepo{base}, discardRecorder)
err := uc.Delete(context.Background(), 2, useCases.Reassignment{Mode: useCases.ReassignAbsent})
if !errors.Is(err, author.ErrAuthorHasArticles) {
t.Errorf("err = %v", err)
}
if _, exists := base.authors[2]; !exists {
t.Errorf("author deleted despite credits")
}
})
t.Run("Explicit removal uncredits the author", func(t *testing.T) {
base := plainAuthors()
base.seed(2, "B", "b")
base.articles.credits[10] = []uint32{2, 3}
uc := useCases.NewDeleteAuthorUseCase(base, discardRecorder)
err := uc.Delete(context.Background(), 2, useCases.Reassignment{Mode: useCases.ReassignNone})
if err != nil || len(base.articles.credits[10]) != 1 {
t.Errorf("err %v credits %v", err, base.articles.credits[10])
}
})
}
func TestAuthorSocialTypes(t *testing.T) {
for _, valid := range []string{author.SocialX, author.SocialLinkedIn, author.SocialGitHub, author.SocialMastodon, author.SocialCustom} {
if !author.IsValidSocialType(valid) || author.ValidateLinks([]author.SocialLink{{Type: valid, URL: "https://a.example/x"}}) != nil {
t.Errorf("%s refused", valid)
}
}
err := author.ValidateLinks([]author.SocialLink{{Type: "facebook", URL: "https://a.example/x"}})
if author.IsValidSocialType("") || !errors.Is(err, author.ErrInvalidSocialType) {
t.Errorf("err = %v", err)
}
}