package seo_test import ( "net/http" "strings" "testing" sitemapclasses "git.golem15.com/golem15/sm-sitemap-plugin/classes" ) // rebuildSitemap runs the sitemap plugin's rebuild on the test app, as its // job and command do. func (e *testEnv) rebuildSitemap(t *testing.T) { t.Helper() if _, err := sitemapclasses.Rebuild(t.Context(), e.app); err != nil { t.Fatalf("sitemap rebuild: %v", err) } } // sitemapFile fetches one sitemap file by name; a missing file is "". func (e *testEnv) sitemapFile(t *testing.T, name string) string { t.Helper() rec := e.call(t, http.MethodGet, "/_sitemap/files/"+name, "", nil) if rec.Code == http.StatusNotFound { return "" } if rec.Code != http.StatusOK { t.Fatalf("GET %s = %d: %s", name, rec.Code, rec.Body.String()) } return rec.Body.String() } // sitemapReason is the excluded reason the sitemap stored for a record's // address in a locale ("" while it is listed). func (e *testEnv) sitemapReason(t *testing.T, typeKey, id, locale string) string { t.Helper() var rows []string if err := e.db.Raw(`SELECT excluded_reason FROM golem15_sitemap_urls WHERE type_key = ? AND record_id = ? AND locale = ?`, typeKey, id, locale).Scan(&rows).Error; err != nil { t.Fatal(err) } if len(rows) == 0 { t.Fatalf("no sitemap row for %s %s %s", typeKey, id, locale) } return rows[0] } // TestSitemapFilterTracer is the plan's tracer: an editor sets a page to // noindex in the SEO tab, the sitemap rebuild asks the SEO plugin's // published filter, and the page leaves the sitemap file with the reason // noindex. Staging lists the same set as production (the non-production // lock never excludes an address). func TestSitemapFilterTracer(t *testing.T) { for _, envName := range []string{"production", "staging"} { t.Run(envName, func(t *testing.T) { env := bootEnv(t, "SUMMER_ENV="+envName) token := env.admin(t, true) first := env.createPage(t, token, map[string]any{"title": "First", "slug": "first", "published": true}) second := env.createPage(t, token, map[string]any{"title": "Second", "slug": "second", "published": true}) env.rebuildSitemap(t) file := env.sitemapFile(t, "sitemap-pages-1.xml") if !strings.Contains(file, ".test/pages/first") || !strings.Contains(file, ".test/pages/second") { t.Fatalf("before noindex the file lists both pages:\n%s", file) } env.expect(t, http.StatusOK, http.MethodPut, adminAPI("/acme/pages/pages/"+first), token, map[string]any{ "title": "First", "slug": "first", "published": true, "seo_robots": map[string]any{"en": "noindex"}, }) env.rebuildSitemap(t) file = env.sitemapFile(t, "sitemap-pages-1.xml") if strings.Contains(file, ".test/pages/first") { t.Fatalf("the noindex page is still listed:\n%s", file) } if !strings.Contains(file, ".test/pages/second") { t.Fatalf("the indexable page left the file:\n%s", file) } if got := env.sitemapReason(t, "acme-page", first, "en"); got != "noindex" { t.Fatalf("excluded reason = %q, want noindex", got) } if got := env.sitemapReason(t, "acme-page", second, "en"); got != "" { t.Fatalf("second page reason = %q, want listed", got) } // The pl address has no noindex of its own and stays listed. if got := env.sitemapReason(t, "acme-page", first, "pl"); got != "" { t.Fatalf("pl address reason = %q, want listed", got) } }) } }