- the module registers seo-sitemap-<locale> at seo.htmlSitemap.paths (defaults pl /mapa-strony, en /sitemap) and seo-sitemap-group-<locale> at <path>/:group (plus <path>/:group/<segment>/:page in the path form); a path an app page already has stays the app's - SeoHtmlSitemapPage (global, overridable): H1, an H2 per non-empty group, categories nested, a large group's link to its group page, sitemap.empty; group pages with a built trail, page suffix and <SeoPagination>; 404 for an unknown group or a page past the last, 301 for ?page=1, 503 when the sitemap API fails - GET /api/__seo__/sitemap proxies the sitemap plugin's HTML API (only while the CMS has the HTML sitemap on for the locale) - <SeoSitemapLink>: the footer link while the HTML sitemap is on - L3 default styles
128 lines
8.9 KiB
Plaintext
128 lines
8.9 KiB
Plaintext
# SSR expectations of the SEO layer's v0.2.0 features against the fixture
|
||
# SEO API (testing/fixtures, answers in testing/fixtures/seo). Grammar in
|
||
# testing/smoke-ssr.mjs. testing/expect.txt keeps the v0.1.1 behaviour and
|
||
# runs against a backend without /site (--no-site).
|
||
|
||
# Tracer: a page rendered by Nuxt carries the CMS title, canonical, hreflang
|
||
# and one JSON-LD graph from the resolve answer.
|
||
200 /blog/lwia-grzywa contains=<title>Lwia grzywa | Example</title> count=application/ld+json:1 count=rel="canonical":1 contains=hreflang="x-default" contains=lang="pl"><head>
|
||
200 /blog/lwia-grzywa contains=<link rel="alternate" hreflang="en" href="https://example.test/en/blog/lions-mane" contains=hreflang="pl"
|
||
200 /blog/lwia-grzywa contains=<meta property="og:locale" content="pl_PL"> contains=<meta property="og:locale:alternate" content="en_US">
|
||
200 /blog/lwia-grzywa notcontains=Own catch-all title
|
||
# One graph: the CMS nodes, the layer's node merged by @id (CMS values win),
|
||
# a new layer node appended; "<" inside the JSON cannot end the script.
|
||
200 /blog/lwia-grzywa count=data-hid="seo-jsonld":1 count="@type":"WebPage":1 contains="name":"Lwia grzywa" notcontains=Layer name loses contains="inLanguage":"pl" contains=#itemlist
|
||
200 /blog/lwia-grzywa notcontains=</script><script>alert
|
||
|
||
# Redirect decision before the page (and its route cache): the Location
|
||
# comes from the answer only; a target on the site's origin becomes a path,
|
||
# another host stays absolute; a crafted Host or X-Forwarded-Host changes
|
||
# nothing. No X-Robots-Tag on a redirect.
|
||
301 /stary header=Location: /nowy noheader=X-Robots-Tag
|
||
301 /stary reqheader=Host: evil.test reqheader=X-Forwarded-Host: evil.test reqheader=X-Forwarded-Proto: http header=Location: /nowy
|
||
302 /stary-zewnetrzny header=Location: https://partner.test/oferta?a=1
|
||
# 410 with the app's error page, also on staging with the noindex header.
|
||
410 /usuniety
|
||
410 /usuniety-staging header=X-Robots-Tag: noindex, nofollow
|
||
# A page's x_robots_tag becomes the header.
|
||
200 /blog/ukryty header=X-Robots-Tag: noindex, nofollow contains=<meta name="robots" content="noindex, nofollow">
|
||
# not_found: a pagination.invalid answer is a 404 (also on a page that would
|
||
# render); any other not_found is left to Nuxt's routing.
|
||
404 /plain?page=abc
|
||
200 /plain?page=2 contains=<title>Plain page | Playground</title>
|
||
404 /nieznana-strona
|
||
|
||
# The resolve cache: every request above to the tracer page made one call.
|
||
resolves /blog/lwia-grzywa 1
|
||
resolves /stary 1
|
||
# The Nuxt-server resolve route answers through the same cache.
|
||
200 /api/__seo__/resolve?url=/blog/lwia-grzywa contains="title":"Lwia grzywa | Example" header=X-Robots-Tag: noindex
|
||
resolves /blog/lwia-grzywa 1
|
||
422 /api/__seo__/resolve?url=https://evil.test/
|
||
|
||
# Root files from the backend, with its status, content type and
|
||
# X-Robots-Tag; a backend failure is 503 with Retry-After.
|
||
200 /robots.txt contains=Disallow: /konto type=text/plain header=X-Content-Type-Options: nosniff
|
||
200 /sitemap.xml contains=<sitemapindex type=application/xml
|
||
200 /sitemap-posts-1.xml contains=<urlset type=application/xml header=X-Robots-Tag: noindex
|
||
200 /llms.txt contains=Fixture llms.txt header=X-Robots-Tag: noindex
|
||
404 /sitemap-missing-1.xml
|
||
503 /sitemap-fail-1.xml header=Retry-After: 60
|
||
# Listed root files: a verification file and the IndexNow key file.
|
||
200 /google1234.html contains=google-site-verification: google1234.html header=X-Robots-Tag: noindex header=X-Content-Type-Options: nosniff
|
||
200 /a1b2c3d4e5f60718293a4b5c6d7e8f90.txt contains=a1b2c3d4e5f60718293a4b5c6d7e8f90 type=text/plain
|
||
# Not listed: passes through to Nuxt, which renders its 404 (the route
|
||
# middleware resolves it; no verification lookup is made).
|
||
404 /random.txt
|
||
404 /google0123.html
|
||
404 /kontakt
|
||
|
||
# 404 pages report themselves once with the bearer token; a 410 or a
|
||
# redirect does not.
|
||
report /kontakt
|
||
report /nieznana-strona
|
||
noreport /usuniety
|
||
noreport /stary
|
||
|
||
# Labels in the page's content locale (pl answer: the pl dictionary).
|
||
200 /blog/lwia-grzywa contains=<p class="seo-visually-hidden">Ścieżka nawigacji</p>
|
||
|
||
# Declared noindex without page code: a page whose meta requires sign-in,
|
||
# a page with its own seo.robots and a path under seo.noindexRoutes get the
|
||
# meta tag and the header; an ordinary page keeps the CMS robots.
|
||
200 /konto contains=<meta name="robots" content="noindex, nofollow"> count=name="robots":1 header=X-Robots-Tag: noindex, nofollow
|
||
200 /szkic contains=<meta name="robots" content="noindex, follow"> header=X-Robots-Tag: noindex, follow
|
||
200 /prywatne contains=<meta name="robots" content="noindex, nofollow"> header=X-Robots-Tag: noindex, nofollow
|
||
200 /plain noheader=X-Robots-Tag count=name="robots":0
|
||
200 /blog/lwia-grzywa contains=<meta name="robots" content="index, follow">
|
||
|
||
# The site answer through the layer's server, for useSeoSite().
|
||
200 /api/__seo__/site contains="site_url":"https://example.test" header=X-Robots-Tag: noindex
|
||
|
||
# The route report at server start: the static paths with the token, not
|
||
# the signed-in page, the page with a noindex seo.robots or the declared
|
||
# noindex route. The build matches the site answer: no drift warning.
|
||
routereport 1 has=/ has=/blog has=/plain has=/about lacks=/konto lacks=/szkic lacks=/prywatne lacks=/mapa-strony
|
||
log [vue-seo-layer] drift::0
|
||
|
||
# L1 breadcrumbs: a layout instance (app.vue) and a page instance render
|
||
# exactly one trail, server-rendered links, the last item as text with
|
||
# aria-current; none on the home page (one item) or a page without a trail.
|
||
200 /blog/lwia-grzywa count=<nav class="seo-breadcrumbs":1 contains=<a class="seo-breadcrumbs__link" href="/">Start</a> contains=<span class="seo-breadcrumbs__current" aria-current="page">Lwia grzywa</span> count=aria-current="page":1
|
||
200 / count=seo-breadcrumbs:0
|
||
200 /plain count=seo-breadcrumbs:0
|
||
|
||
# L2 pagination: numbered links in the CMS form, page 1 unnumbered, five
|
||
# pages around the current one plus the first and the last with two gaps,
|
||
# rel prev/next anchors and head links, and %pages% filled in the CMS title
|
||
# and description (the payload keeps the raw answer); one page renders
|
||
# none. aria-current: the current page and the breadcrumbs' last item.
|
||
200 /blog?page=5 count=<nav class="seo-pagination":1 contains=<a class="seo-pagination__prev" href="/blog?page=4" rel="prev"> contains=<a class="seo-pagination__next" href="/blog?page=6" rel="next"> contains=<span class="seo-pagination__current" aria-current="page">5</span> count=aria-current="page":2
|
||
200 /blog?page=5 contains=<a href="/blog" aria-label="Strona 1">1</a> contains=<a href="/blog?page=14" aria-label="Strona 14">14</a> count=seo-pagination__gap:2
|
||
200 /blog?page=5 contains=<link rel="prev" href="/blog?page=4" contains=<link rel="next" href="/blog?page=6" contains=<title>Blog – strona 5 z 14 | Example</title> contains=content="Wpisy o grzybach, strona 5 z 14" notcontains=z %pages% |</title> notcontains=content="Wpisy o grzybach, strona 5 z %pages%"
|
||
200 /blog?page=14&sort=new contains=<a class="seo-pagination__prev" href="/blog?sort=new&page=13" rel="prev"> count=seo-pagination__next:0 count=rel="next":0
|
||
200 /blog?pages=1 count=seo-pagination:0 count=rel="prev":0
|
||
|
||
# L3 HTML sitemap: H1, one H2 per non-empty group (the empty one left out),
|
||
# the category tree nested, a large group's link to its group page; a URL
|
||
# that is not http(s) renders as text; long titles stay whole.
|
||
200 /mapa-strony contains=<h1 class="seo-sitemap__title">Mapa strony</h1> count=<h2:3 notcontains=Tagi contains=<a href="/mapa-strony/posts" class="">Wpisy: wszystkie (1234)</a> notcontains=href="javascript: notcontains=<script>alert
|
||
200 /mapa-strony contains=Grzyby</a><ul class="seo-sitemap__list"> contains=<a href="/grzyby/lecznicze" contains=musi się zawinąć</a> count=<h1:1
|
||
# A group page: built trail, H1 with the page suffix, pagination; ?page=1
|
||
# is a 301 to the unnumbered URL; an unknown group or a page past the last
|
||
# is a 404; a failing sitemap API is a 503 (never an empty cached page).
|
||
200 /mapa-strony/posts?page=2 contains=<h1 class="seo-sitemap__title">Mapa strony: Wpisy · Strona 2</h1> contains=<a class="seo-breadcrumbs__link" href="/mapa-strony">Mapa strony</a> contains=<span class="seo-breadcrumbs__current" aria-current="page">Wpisy</span> count=<nav class="seo-breadcrumbs":1 count=<nav class="seo-pagination":1 contains=href="/mapa-strony/posts?page=3"
|
||
200 /mapa-strony/posts contains=<h1 class="seo-sitemap__title">Mapa strony: Wpisy</h1> contains=Lwia grzywa
|
||
301 /mapa-strony/posts?page=1 header=Location: /mapa-strony/posts
|
||
404 /mapa-strony/nope
|
||
404 /mapa-strony/posts?page=9
|
||
404 /mapa-strony/posts?page=abc
|
||
503 /mapa-strony/fail
|
||
# Every group empty: the empty message (en labels on the en path).
|
||
200 /en/sitemap contains=<h1 class="seo-sitemap__title">Sitemap</h1> contains=<p class="seo-sitemap__empty">There are no pages to list yet.</p> count=<h2:0
|
||
# A locale the CMS has no HTML sitemap path for.
|
||
404 /sitemap
|
||
|
||
# L4: the footer link to the locale's HTML sitemap.
|
||
200 /blog/lwia-grzywa contains=<footer><a href="/mapa-strony" class="seo-sitemap-link">Mapa strony</a></footer>
|