Files
RenewCMS/test/article_domain_rules_test.go
T

103 lines
3.0 KiB
Go

package test
import (
"RenewCMS/internal/domain/article"
"RenewCMS/internal/domain/author"
"errors"
"strings"
"testing"
)
func TestArticleTitleLengthBounds(t *testing.T) {
cases := []struct {
runes int
valid bool
}{
{article.MinTitleRunes - 1, false},
{article.MinTitleRunes, true},
{article.MaxTitleRunes, true},
{article.MaxTitleRunes + 1, false},
}
for _, c := range cases {
err := article.ValidateTitle(strings.Repeat("é", c.runes))
if (err == nil) != c.valid || (err != nil && !errors.Is(err, article.ErrInvalidTitle)) {
t.Errorf("%d runes: err = %v", c.runes, err)
}
}
}
func TestArticleDetailedErrorsMatchTheirSentinel(t *testing.T) {
cases := []struct {
err error
sentinel error
}{
{&article.RevisionConflictError{Current: 4}, article.ErrRevisionConflict},
{&article.LanguageExistsError{ArticleID: 9}, article.ErrLanguageExists},
{&article.LanguageNotEnabledError{Missing: []string{"de"}}, article.ErrLanguageNotEnabled},
{&article.SlugConflictError{ArticleIDs: []uint32{3}}, article.ErrSlugConflict},
}
for _, c := range cases {
if !errors.Is(c.err, c.sentinel) || c.err.Error() != c.sentinel.Error() {
t.Errorf("%T does not match %v", c.err, c.sentinel)
}
if errors.Is(c.err, article.ErrArticleNotFound) {
t.Errorf("%T matches an unrelated sentinel", c.err)
}
}
}
func TestArticleRevisionsMoveByOne(t *testing.T) {
opened := article.Article{}.Opened()
cases := []struct {
impact article.Impact
edit, content uint32
}{
{article.Impact{}, 1, 1},
{article.Impact{Edited: true}, 2, 1},
{article.Impact{Edited: true, Content: true}, 2, 2},
}
for _, c := range cases {
revised := opened.Revised(c.impact)
if revised.EditRevision != c.edit || revised.ContentRevision != c.content {
t.Errorf("%+v: edit %d content %d", c.impact, revised.EditRevision, revised.ContentRevision)
}
}
}
func TestArticleCopiedIntoKeepsAnAuthorList(t *testing.T) {
source := article.Article{ID: 7, Body: "<p>Body</p>", ContentRevision: 3}
copied := source.CopiedInto(article.Article{Lang: "fr"})
if copied.Authors == nil || len(copied.Authors) != 0 {
t.Fatalf("authors = %#v", copied.Authors)
}
if *copied.SourceArticleID != 7 || copied.SourceRevision != 3 || copied.Body != "<p>Body</p>" {
t.Fatalf("copied = %+v", copied)
}
credited := article.Article{Authors: []author.Byline{{}}}.CopiedInto(article.Article{})
if len(credited.Authors) != 1 {
t.Fatalf("credited authors = %#v", credited.Authors)
}
}
func TestArticleStoryFiltersPerLanguage(t *testing.T) {
cases := []struct {
filters article.StoryFilters
want bool
}{
{article.StoryFilters{Lang: "fr"}, true},
{article.StoryFilters{Lang: "fr", Missing: true}, false},
{article.StoryFilters{}, false},
}
for _, c := range cases {
if got := c.filters.PerLanguage(); got != c.want {
t.Errorf("%+v: PerLanguage = %v", c.filters, got)
}
}
}
func TestArticleSEOSummaryStale(t *testing.T) {
if !(article.SEOSummary{}).Stale() || (article.SEOSummary{Status: article.SEOStatusReady}).Stale() {
t.Fatal("only a summary without status is stale")
}
}