Files
vue-seo-layer/testing/expect-seo.txt
Jakub Zych 3abc986f42 feat: route report and drift check at server start
- the module writes #seo-routes (static paths and route patterns) from the
  resolved pages; options seo.routeReport, seo.pagination and
  seo.htmlSitemap reach the public runtime config
- seo-route-report: POST /registry/routes once per process with the
  route-report token, one retry after 60 s on failure, nothing without a
  token, with the layer off or with routeReport false
- seo-drift: one "[vue-seo-layer] drift:" warning per mismatch between
  the CMS's site answer (URL patterns, pagination, HTML sitemap paths)
  and the build
- GET /api/__seo__/site and useSeoSite()
- smoke grammar routereport and log, fixture registry route, drift run
2026-11-04 11:49:21 +01:00

87 lines
5.1 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=/plain has=/about lacks=/konto lacks=/szkic lacks=/prywatne
log [vue-seo-layer] drift::0