test: unit tests for the schema builder, crawler and page helpers

- schema: types per kind, @id links, every node kind, the publisher and
  local business, every validator rule, custom JSON-LD caps and merge
- crawl: HTML parse, each check's positive and negative case, fix routes
  with the fitting tool, the rendered comparison, allowRequest,
  resolverRules and NewRenderer
- pagination, alternates and x-default, primary parents, the filter's
  addresses, registry paths and fields, auto-link addresses
This commit is contained in:
Jakub Zych
2026-11-04 19:43:31 +01:00
parent dfc85bc805
commit 82b0dacff9
14 changed files with 1543 additions and 0 deletions

80
classes/crawl/fix_test.go Normal file
View File

@@ -0,0 +1,80 @@
package crawl
import (
"testing"
"git.golem15.com/golem15/sm-seo-plugin/models"
"git.golem15.com/golem15/summercms/modules/pact"
)
// TestRoute pins P33-38: a content finding names the record type's first
// fitting tool in the order given; without one a fixed CMS tool; else
// code with the finding's own what, the kind's default, or the page
// template.
func TestRoute(t *testing.T) {
both := &Record{Tools: map[string]string{pact.ContentToolHeadings: "acme_fix_headings", pact.ContentToolEdit: "acme_update"}}
editOnly := &Record{Tools: map[string]string{pact.ContentToolEdit: " acme_update "}}
for _, tc := range []struct {
name string
f Finding
fix, tool, what string
}{
{"headings first", Finding{Kind: KindH1Multiple, Content: []string{pact.ContentToolHeadings, pact.ContentToolEdit}, Record: both}, models.FixTool, "acme_fix_headings", ""},
{"edit fallback", Finding{Kind: KindH1Multiple, Content: []string{pact.ContentToolHeadings, pact.ContentToolEdit}, Record: editOnly}, models.FixTool, "acme_update", ""},
{"no record tool, fixed tool", Finding{Kind: KindJSONLDInvalid, Content: []string{pact.ContentToolEdit}, Record: &Record{}, Tool: ToolSetURLSEO}, models.FixTool, ToolSetURLSEO, ""},
{"nil record", Finding{Kind: KindImageAlt, Content: []string{pact.ContentToolImageAlt}}, models.FixCode, "", defaultWhat[KindImageAlt]},
{"fixed tool", Finding{Kind: KindMissingTitle, Tool: ToolSetURLSEO}, models.FixTool, ToolSetURLSEO, ""},
{"own what", Finding{Kind: KindContentJS, What: "links /a"}, models.FixCode, "", "links /a"},
{"default what", Finding{Kind: KindCanonicalMissing}, models.FixCode, "", defaultWhat[KindCanonicalMissing]},
{"page template", Finding{Kind: "unknown"}, models.FixCode, "", "the page template"},
} {
fix, tool, what := Route(tc.f)
if fix != tc.fix || tool != tc.tool || what != tc.what {
t.Errorf("%s: %s %q %q, want %s %q %q", tc.name, fix, tool, what, tc.fix, tc.tool, tc.what)
}
}
}
// TestRouteEveryKind pins that every kind gets a tool or a code fix.
func TestRouteEveryKind(t *testing.T) {
for _, k := range Kinds() {
fix, tool, what := Route(Finding{Kind: k})
if (fix == models.FixTool && tool == "") || (fix == models.FixCode && what == "") || (fix != models.FixTool && fix != models.FixCode) {
t.Errorf("%s: %s %q %q", k, fix, tool, what)
}
}
}
// TestFingerprint pins the identity of a finding across crawls: stable,
// 32 hex characters, and different for each of its four parts.
func TestFingerprint(t *testing.T) {
a := Fingerprint(KindContentJS, "/a", "pl", "cms")
if a != Fingerprint(KindContentJS, "/a", "pl", "cms") || len(a) != 32 {
t.Fatalf("fingerprint %q", a)
}
for _, other := range []string{
Fingerprint(KindH1Missing, "/a", "pl", "cms"), Fingerprint(KindContentJS, "/b", "pl", "cms"),
Fingerprint(KindContentJS, "/a", "en", "cms"), Fingerprint(KindContentJS, "/a", "pl", "rendered"),
Fingerprint(KindContentJS, "/a\x00pl", "", "cms"),
} {
if other == a {
t.Fatal("a different finding has the same fingerprint")
}
}
}
// TestRecordHeadingHelpers pins hasHeading (any level or text, compared
// without case and extra space) and hasEmptyHeading on a nil record too.
func TestRecordHeadingHelpers(t *testing.T) {
rec := &Record{Headings: []pact.ContentHeading{{Level: 2, Text: "Lwia Grzywa"}, {Level: 3, Text: " "}}}
if !rec.hasHeading(2, "lwia grzywa") || !rec.hasHeading(0, "") || rec.hasHeading(1, "") || rec.hasHeading(2, "Chaga") {
t.Fatal("hasHeading is wrong")
}
if !hasEmptyHeading(rec, 3) || hasEmptyHeading(rec, 2) || hasEmptyHeading(nil, 1) {
t.Fatal("hasEmptyHeading is wrong")
}
var none *Record
if none.hasHeading(0, "") || none.tool(pact.ContentToolEdit) != "" {
t.Fatal("a nil record has no headings and no tools")
}
}