114 lines
3.5 KiB
Go
114 lines
3.5 KiB
Go
package processing
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
func TestFillMetaFromResult_buildsTitleAndDesc(t *testing.T) {
|
|
t.Parallel()
|
|
title, desc := fillMetaFromResult(StepResult{
|
|
ProcessedName: "Drill 18V",
|
|
Category: "Tools",
|
|
ProcessedDescription: "Cordless drill with battery pack for DIY projects.",
|
|
ProcessedAttributes: map[string]any{"brand": "Bosch"},
|
|
})
|
|
if title == "" || desc == "" {
|
|
t.Fatal("expected non-empty meta")
|
|
}
|
|
if !strings.Contains(title, "Drill 18V") {
|
|
t.Fatalf("title missing name: %q", title)
|
|
}
|
|
if !strings.Contains(title, "Bosch") {
|
|
t.Fatalf("title missing brand: %q", title)
|
|
}
|
|
if utf8.RuneCountInString(title) > metaTitleMaxChars {
|
|
t.Fatalf("title too long: %d", utf8.RuneCountInString(title))
|
|
}
|
|
if utf8.RuneCountInString(desc) > metaDescriptionMaxChars {
|
|
t.Fatalf("desc too long: %d", utf8.RuneCountInString(desc))
|
|
}
|
|
}
|
|
|
|
func TestFillMetaFromResult_usesCategoryNameNotUniqueID(t *testing.T) {
|
|
t.Parallel()
|
|
title, _ := fillMetaFromResult(StepResult{
|
|
ProcessedName: "Gorenje GEC5A21WG",
|
|
Category: "50",
|
|
CategoryName: "Štedilniki",
|
|
ProcessedAttributes: map[string]any{
|
|
"brand": "Gorenje",
|
|
},
|
|
})
|
|
if strings.Contains(title, "| 50") || strings.HasSuffix(title, "50") {
|
|
t.Fatalf("meta title must not use unique_id: %q", title)
|
|
}
|
|
if !strings.Contains(title, "Štedilniki") {
|
|
t.Fatalf("meta title missing display name: %q", title)
|
|
}
|
|
// Digits-only Category without CategoryName must omit category from title.
|
|
title2, _ := fillMetaFromResult(StepResult{
|
|
ProcessedName: "Cooker",
|
|
Category: "50",
|
|
})
|
|
if strings.Contains(title2, "50") {
|
|
t.Fatalf("digits-only unique_id must not appear in meta: %q", title2)
|
|
}
|
|
}
|
|
|
|
func TestTruncateMetaDescription_wordBoundary(t *testing.T) {
|
|
t.Parallel()
|
|
// 160+ runes with a clear word break near 155.
|
|
words := strings.Repeat("word ", 40) // 200 chars with spaces
|
|
out := truncateMetaDescription(words, v1MetaDescriptionMaxChars)
|
|
n := utf8.RuneCountInString(out)
|
|
if n > v1MetaDescriptionMaxChars {
|
|
t.Fatalf("len=%d want <= %d (%q)", n, v1MetaDescriptionMaxChars, out)
|
|
}
|
|
if strings.HasSuffix(out, "wor") || strings.HasSuffix(out, "wo") || strings.HasSuffix(out, "w") {
|
|
t.Fatalf("mid-word cut: %q", out)
|
|
}
|
|
if !strings.HasSuffix(out, "word") {
|
|
t.Fatalf("expected last full word, got %q", out)
|
|
}
|
|
}
|
|
|
|
func TestTruncateMetaDescription_collapsesSpace(t *testing.T) {
|
|
t.Parallel()
|
|
out := truncateMetaDescription(" hello \n\t world ", 155)
|
|
if out != "hello world" {
|
|
t.Fatalf("got %q", out)
|
|
}
|
|
}
|
|
|
|
func TestV1PollMetaFallback_usesTemplateWhenEmpty(t *testing.T) {
|
|
t.Parallel()
|
|
title := "Cordless Drill"
|
|
cat := "Tools"
|
|
plain := strings.Repeat("quality cordless drill for home and workshop use. ", 10)
|
|
synthTitle, synthDesc := fillMetaFromResult(StepResult{
|
|
Name: title,
|
|
ProcessedName: title,
|
|
Category: cat,
|
|
Description: plain,
|
|
ProcessedDescription: plain,
|
|
Attributes: map[string]any{"brand": "Makita"},
|
|
})
|
|
if synthTitle == "" || synthDesc == "" {
|
|
t.Fatal("expected synth meta")
|
|
}
|
|
if utf8.RuneCountInString(synthDesc) > v1MetaDescriptionMaxChars {
|
|
t.Fatalf("poll meta_description too long: %d", utf8.RuneCountInString(synthDesc))
|
|
}
|
|
// Word-safe: last rune should not be mid-word fragment from a hard cut.
|
|
r := []rune(synthDesc)
|
|
if len(r) == v1MetaDescriptionMaxChars {
|
|
// hard-cut path only when no good space; otherwise last char is letter from a word end
|
|
last := r[len(r)-1]
|
|
if last == ' ' {
|
|
t.Fatalf("trailing space in meta_description: %q", synthDesc)
|
|
}
|
|
}
|
|
}
|