Files
sm-sitemap-plugin/classes/indexnow_test.go
Jakub Zych 1048c01fd9 test: unit tests for the writer, News, IndexNow, HTML groups, slugs, lastmod and slots
- XML escaping and namespaces, no priority, the image cap and file names
- News window and cap, sources and languages, the publication name
- IndexNow batches of 10 000, answer outcomes, keys and the host filter
- HTML sitemap group order, tree order and paging
- default slugs, the effective type setting, lastmod config, slot edges
2026-11-04 19:36:10 +01:00

113 lines
4.1 KiB
Go

package classes
import (
"fmt"
"net/http"
"regexp"
"strings"
"testing"
"git.golem15.com/golem15/sm-sitemap-plugin/models"
)
// TestIndexNowBatches pins the requests of at most 10 000 addresses, in
// order, with nothing for no addresses.
func TestIndexNowBatches(t *testing.T) {
if MaxIndexNowURLs != 10000 {
t.Fatalf("MaxIndexNowURLs = %d", MaxIndexNowURLs)
}
urls := func(n int) []string {
out := make([]string, n)
for i := range out {
out[i] = fmt.Sprintf("https://example.test/%d", i)
}
return out
}
for _, tc := range []struct {
n int
want []int
}{{0, nil}, {1, []int{1}}, {10000, []int{10000}}, {10001, []int{10000, 1}}, {25000, []int{10000, 10000, 5000}}} {
got := indexNowBatches(urls(tc.n))
var sizes []int
next := 0
for _, b := range got {
sizes = append(sizes, len(b))
if len(b) > 0 && b[0] != fmt.Sprintf("https://example.test/%d", next) {
t.Fatalf("%d addresses: a batch starts at %s, want %d", tc.n, b[0], next)
}
next += len(b)
}
if fmt.Sprint(sizes) != fmt.Sprint(tc.want) {
t.Errorf("%d addresses: batches %v, want %v", tc.n, sizes, tc.want)
}
}
}
// TestIndexNowOutcome pins the answer mapping: 200 and 202 sent, 429 and
// 5xx retried, 400, 403 and 422 (and any other status) refused.
func TestIndexNowOutcome(t *testing.T) {
for status, want := range map[int]int{
http.StatusOK: indexNowSent, http.StatusAccepted: indexNowSent,
http.StatusTooManyRequests: indexNowRetry, 500: indexNowRetry, 502: indexNowRetry, 503: indexNowRetry,
http.StatusBadRequest: indexNowRefused, http.StatusForbidden: indexNowRefused, http.StatusUnprocessableEntity: indexNowRefused,
http.StatusNoContent: indexNowRefused, http.StatusNotFound: indexNowRefused,
} {
if got := indexNowOutcome(status); got != want {
t.Errorf("status %d: outcome %d, want %d", status, got, want)
}
}
}
// TestIndexNowKeys pins the key format (8 to 128 letters, digits and
// hyphens), the generated key (32 lowercase hex characters, a new one each
// time), the key file name and the active key only while IndexNow is on.
func TestIndexNowKeys(t *testing.T) {
for k, want := range map[string]bool{
"abcd1234": true, "ABCD-1234-efgh": true, strings.Repeat("a", 128): true,
"abc1234": false, strings.Repeat("a", 129): false, "abcd_1234": false, "abcd 1234": false, "../abcd1234": false, "": false,
} {
if ValidKey(k) != want {
t.Errorf("ValidKey(%q) = %v, want %v", k, !want, want)
}
}
a, err := GenerateKey()
if err != nil {
t.Fatal(err)
}
b, _ := GenerateKey()
if !regexp.MustCompile(`^[0-9a-f]{32}$`).MatchString(a) || a == b || !ValidKey(a) {
t.Fatalf("GenerateKey = %q, %q", a, b)
}
if KeyFileName(a) != a+".txt" || KeyFileName("short") != "" || KeyFileName("x/../y12345") != "" {
t.Fatal("KeyFileName is wrong")
}
key := " " + a + " "
bad := "bad key"
if ActiveKey(models.Settings{IndexNowEnabled: true, IndexNowKey: &key}) != a ||
ActiveKey(models.Settings{IndexNowEnabled: false, IndexNowKey: &key}) != "" ||
ActiveKey(models.Settings{IndexNowEnabled: true, IndexNowKey: &bad}) != "" ||
ActiveKey(models.Settings{IndexNowEnabled: true}) != "" {
t.Fatal("ActiveKey is wrong")
}
}
// TestSiteURLs pins the host filter: only http(s) addresses on the site's
// host (case-insensitive, any port or scheme), each once, in order;
// nothing without a site address.
func TestSiteURLs(t *testing.T) {
got := SiteURLs("https://Example.test", []string{
"https://example.test/a", "https://EXAMPLE.test/b", "http://example.test/c", "https://example.test:8443/d",
"https://example.test/a", "https://www.example.test/e", "https://other.test/f", "/g", "ftp://example.test/h", "",
})
want := "https://example.test/a https://EXAMPLE.test/b http://example.test/c https://example.test:8443/d"
if strings.Join(got, " ") != want {
t.Fatalf("SiteURLs = %v, want %s", got, want)
}
if SiteURLs("", []string{"https://example.test/a"}) != nil || SiteURLs("/relative", []string{"/a"}) != nil {
t.Fatal("without a site address nothing is kept")
}
if got := SiteURLs("https://example.test", nil); got == nil || len(got) != 0 {
t.Fatalf("no addresses: %v, want an empty list", got)
}
}