From 3f33d7324e4adfdbf811e978a69c965679bbcc2f Mon Sep 17 00:00:00 2001 From: Saqib Date: Tue, 29 Sep 2026 02:52:12 +0000 Subject: [PATCH] test: pending coverage for canonical/OG/Twitter meta tags (ParakhAI-frontend#444) Covers CivicDataLab/ParakhAI-frontend#444 (open, dev, >72h old), which adds canonical link, Open Graph and Twitter Card metadata to the homepage layout. Gated with pending_pr so it skips in CI until that PR merges. --- tests/api/test_seo_metadata.py | 56 ++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 tests/api/test_seo_metadata.py diff --git a/tests/api/test_seo_metadata.py b/tests/api/test_seo_metadata.py new file mode 100644 index 0000000..93f8664 --- /dev/null +++ b/tests/api/test_seo_metadata.py @@ -0,0 +1,56 @@ +""" +SEO metadata checks — canonical link and Open Graph/Twitter Card tags. + +Pending coverage for CivicDataLab/ParakhAI-frontend#444, which adds these tags +to `app/layout.tsx`. Gated with `pending_pr` so it only runs once that PR +merges (see conftest.py's `_pending_pr_state`). +""" + +import re + +import pytest +import requests + +from utils.config import Config + +pytestmark = [pytest.mark.api, pytest.mark.pending_pr("ParakhAI-frontend#444")] + +BASE = Config.BASE_URL.rstrip("/") + + +class TestSEOMetadata: + def test_homepage_has_canonical_link(self, api_client: requests.Session): + """The homepage must declare a canonical tag (PR #444).""" + resp = api_client.get(BASE + "/", allow_redirects=True, timeout=15) + assert resp.status_code == 200, ( + f"Homepage returned {resp.status_code}, expected 200" + ) + match = re.search(r']+rel=["\']canonical["\'][^>]*>', resp.text, re.I) + assert match, "No tag found on the homepage" + href_match = re.search(r'href=["\']([^"\']+)["\']', match.group(0), re.I) + assert href_match, f"canonical tag has no href: {match.group(0)}" + assert href_match.group(1).startswith("http"), ( + f"canonical href is not an absolute URL: {href_match.group(1)}" + ) + + def test_homepage_has_open_graph_tags(self, api_client: requests.Session): + """The homepage must declare og:title, og:description and og:url (PR #444).""" + resp = api_client.get(BASE + "/", allow_redirects=True, timeout=15) + html = resp.text + required_og_props = ["og:title", "og:description", "og:url"] + missing = [ + prop + for prop in required_og_props + if not re.search( + rf']+property=["\']{re.escape(prop)}["\']', html, re.I + ) + ] + assert not missing, f"Missing Open Graph meta tags: {missing}" + + def test_homepage_has_twitter_card_tag(self, api_client: requests.Session): + """The homepage must declare a twitter:card meta tag (PR #444).""" + resp = api_client.get(BASE + "/", allow_redirects=True, timeout=15) + match = re.search( + r']+name=["\']twitter:card["\'][^>]*>', resp.text, re.I + ) + assert match, "No tag found on the homepage"