Pure tests of the classes package (no database): the resolver's value chains with every layer present and absent, robots per directive, the staging lock and drafts; the redirect graph (chains, flattened and back-and-forth graphs, loops by exact, pattern and regex probes, the 10-hop cap); URL normalisation across every address rule; the robots grammar over every directive combination; Google's robots.txt matcher examples; templates and unknown placeholders; CSV export and import; owner resolution; and every kind of the issue report. go.mod: gorm.io/driver/postgres becomes a direct requirement (the tests' dry-run database).
75 lines
3.4 KiB
Go
75 lines
3.4 KiB
Go
package classes
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
// TestOwnerResolution: a URL's SEO belongs to the record behind it in the
|
|
// matched locale when the URL is the record's exact address without a
|
|
// query; otherwise, and with force_rule, to an exact URL rule on the
|
|
// normalised address (D-11, P-25).
|
|
func TestOwnerResolution(t *testing.T) {
|
|
svc := testServiceWithPages(t, "https://example.test",
|
|
testPage{id: "1", slugs: map[string]string{"en": "about", "pl": "o-nas"}, published: true},
|
|
testPage{id: "2", slugs: map[string]string{"en": "draft"}, published: false},
|
|
)
|
|
db := dryDB(t)
|
|
for _, tc := range []struct {
|
|
name, url string
|
|
force bool
|
|
writtenTo string
|
|
id string
|
|
locale string
|
|
address string
|
|
published bool
|
|
}{
|
|
{"the record's own address", "/pages/about", false, WrittenToRecord, "1", "en", "/pages/about", true},
|
|
{"an absolute URL of the site", "https://example.test/pages/about", false, WrittenToRecord, "1", "en", "/pages/about", true},
|
|
{"the locale prefix names the locale", "/pl/pages/o-nas", false, WrittenToRecord, "1", "pl", "/pl/pages/o-nas", true},
|
|
{"a trailing slash still finds the record", "/pages/about/", false, WrittenToRecord, "1", "en", "/pages/about/", true},
|
|
{"double slashes are normalised first", "//pages//about", false, "", "", "", "", false},
|
|
{"force_rule writes a rule on the record's address", "/pages/about", true, WrittenToRule, "", "", "/pages/about", false},
|
|
{"a query makes it a rule", "/pages/about?page=2", false, WrittenToRule, "", "", "/pages/about?page=2", false},
|
|
{"another locale's slug is not the record's address", "/pages/o-nas", false, WrittenToRule, "", "", "/pages/o-nas", false},
|
|
{"a draft is not matched", "/pages/draft", false, WrittenToRule, "", "", "/pages/draft", false},
|
|
{"an address without a record", "/landing", false, WrittenToRule, "", "", "/landing", false},
|
|
{"the home page", "/", false, WrittenToRule, "", "", "/", false},
|
|
{"an index file is normalised away", "/pages/about/index.html", false, WrittenToRecord, "1", "en", "/pages/about", true},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
owner, typ, err := svc.FindOwner(t.Context(), db, tc.url, tc.force)
|
|
if tc.writtenTo == "" {
|
|
if !errors.Is(err, ErrBadURL) {
|
|
t.Fatalf("FindOwner(%q) = %+v, %v; want ErrBadURL", tc.url, owner, err)
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if owner.WrittenTo != tc.writtenTo || owner.ID != tc.id || owner.Locale != tc.locale || owner.URL != tc.address || owner.Published != tc.published {
|
|
t.Fatalf("FindOwner(%q) = %+v", tc.url, owner)
|
|
}
|
|
if tc.writtenTo == WrittenToRecord && (owner.Type != "acme-page" || typ.Key != "acme-page") {
|
|
t.Fatalf("type = %q %q", owner.Type, typ.Key)
|
|
}
|
|
if tc.writtenTo == WrittenToRule && (owner.Type != "" || typ.Key != "" || owner.RuleID != 0) {
|
|
t.Fatalf("rule owner = %+v (%s)", owner, typ.Key)
|
|
}
|
|
})
|
|
}
|
|
for _, bad := range []string{"", "pages/about", "ftp://example.test/a", "javascript:alert(1)"} {
|
|
if _, _, err := svc.FindOwner(t.Context(), db, bad, false); !errors.Is(err, ErrBadURL) {
|
|
t.Errorf("FindOwner(%q) = %v, want ErrBadURL", bad, err)
|
|
}
|
|
}
|
|
|
|
t.Run("without a signpost registry every URL is a rule", func(t *testing.T) {
|
|
owner, _, err := testService(t, "production", "https://example.test").FindOwner(t.Context(), db, "/pages/about", false)
|
|
if err != nil || owner.WrittenTo != WrittenToRule || owner.URL != "/pages/about" {
|
|
t.Fatalf("owner = %+v, %v", owner, err)
|
|
}
|
|
})
|
|
}
|