Files
RenewCMS/test/seo_output_hardening_test.go

85 lines
2.6 KiB
Go

package test
import (
articlehandler "RenewCMS/api/handlers/article"
"RenewCMS/internal/domain/article"
"RenewCMS/internal/infrastructure/useCases"
"math"
"net/http"
"reflect"
"strconv"
"strings"
"testing"
)
func TestSeoOutputListPagingNeverPanics(t *testing.T) {
e := newSeoOutEnv(t)
e.cleanArticles()
for id := uint32(200); id < 207; id++ {
e.seedListed(id, "Listed "+strconv.Itoa(int(id)), true, nil)
}
run := func(page int, size int) useCases.ArticlePage {
t.Helper()
result, err := e.container.ListArticlesUseCase.ListArticlesPage(useCases.ListArticlesCommand{
Verified: true, Page: page, Size: size, SEO: article.SEOStatusReady, Sort: article.Sort{Field: "title", Direction: "asc"},
})
if err != nil {
t.Fatalf("page %d size %d: %v", page, size, err)
}
return result
}
total := run(1, 100).Total
if total != 7 {
t.Fatalf("ready total = %d, want 7", total)
}
cases := []struct {
page, size, items int
}{
{math.MaxInt, 25, 0},
{math.MaxInt, math.MaxInt, 0},
{1, -5, 0},
{0, -5, 0},
{1, 0, 0},
{2, math.MaxInt, 0},
{1, math.MaxInt, 7},
{0, 5, 5},
{-3, 5, 5},
{2, 5, 2},
{3, 5, 0},
{2, 4, 3},
{3, 4, 0},
{math.MinInt, 5, 5},
}
for _, c := range cases {
result := run(c.page, c.size)
if len(result.Items) != c.items || result.Total != total {
t.Errorf("page %d size %d: items %d total %d, want items %d total %d", c.page, c.size, len(result.Items), result.Total, c.items, total)
}
}
}
func TestSeoOutputContractParity(t *testing.T) {
oneof := "oneof=" + strings.Join(article.DismissCodes(), " ")
max := "max=" + strconv.Itoa(article.MaxCanonicalURLRunes)
for _, subject := range []reflect.Type{reflect.TypeOf(articlehandler.CheckArticleSEOBody{}), reflect.TypeOf(articlehandler.UpdateArticleBody{})} {
dismissed, _ := subject.FieldByName("SEODismissed")
if !strings.HasSuffix(dismissed.Tag.Get("validate"), oneof) {
t.Errorf("%s seo_dismissed tag %q lacks %q", subject.Name(), dismissed.Tag.Get("validate"), oneof)
}
canonical, _ := subject.FieldByName("CanonicalURL")
if !strings.Contains(canonical.Tag.Get("validate"), max) {
t.Errorf("%s canonical_url tag %q lacks %q", subject.Name(), canonical.Tag.Get("validate"), max)
}
}
e := newSeoOutEnv(t)
for _, status := range []string{article.SEOStatusReady, article.SEOStatusSuggestions, article.SEOStatusHidden} {
rec := e.call(t, "owner", http.MethodGet, "/v1/article/?seo="+status, "")
if rec.Code != http.StatusOK {
t.Errorf("seo=%s: %d", status, rec.Code)
}
}
if rec := e.call(t, "owner", http.MethodGet, "/v1/article/?seo=bogus", ""); rec.Code != http.StatusBadRequest {
t.Errorf("seo=bogus: %d", rec.Code)
}
}