Files
libretro/tests/test_site_privacy.py
T
Abdessamad Derraz 057fd2d0f6 fix: isolate every test module however it runs
tests/__init__.py keeps a run offline, its scratch under tmp/ and its
installer cache its own, but only discover -s tests -t . imported it.
discover tests ran with RETROBIOS_OFFLINE unset, scratch on the /tmp
tmpfs and the user's real installer cache, the setting in which e2e
fixtures had written into the shared .cache/large. Every test module now
imports the package first, and a test fails on a module that does not.
test_verify_listing.py took its line with the previous commit.
2026-11-06 15:14:05 +01:00

82 lines
3.5 KiB
Python

"""What the site counts stays what wiki/privacy.md says it counts.
The counter is website/src/scripts/count.ts. These checks read its source:
the guarantees are in a few lines that a later edit could drop without any
page looking different.
"""
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import re
import unittest
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
COUNTER = REPO_ROOT / "website" / "src" / "scripts" / "count.ts"
FOOTER = REPO_ROOT / "website" / "src" / "components" / "Footer.astro"
PRIVACY = REPO_ROOT / "wiki" / "privacy.md"
class TheCounterAsksNothingOfTheDevice(unittest.TestCase):
def setUp(self) -> None:
self.source = COUNTER.read_text(encoding="utf-8")
# Comments state the rules: only the code must keep them.
self.code = re.sub(r"^\s*//.*$", "", self.source, flags=re.M)
def test_no_storage_on_the_device(self) -> None:
for api in ("document.cookie", "localStorage", "sessionStorage", "indexedDB"):
with self.subTest(api=api):
self.assertNotIn(api, self.code)
def test_a_declined_browser_sends_nothing(self) -> None:
self.assertIn("doNotTrack === '1'", self.code)
self.assertIn("globalPrivacyControl === true", self.code)
self.assertRegex(self.code, r"const send = .*\n\tif \(!enabled\) return;")
def test_only_the_published_site_counts(self) -> None:
self.assertIn("location.hostname === HOST", self.code)
def test_no_query_anchor_or_device_detail_is_read(self) -> None:
for read in ("location.search", "location.hash", "location.href,", "screen.", "navigator.language"):
with self.subTest(read=read):
self.assertNotIn(read, self.code)
def test_the_referrer_is_reduced_to_its_domain(self) -> None:
self.assertIn("from.origin", self.code)
self.assertNotIn("from.pathname", self.code)
def test_a_search_is_sent_only_as_a_file_name_or_a_hash(self) -> None:
self.assertIn("isHash(query) || isFileName(query) || isFileStem(query) ? query : 'other'", self.code)
self.assertIn("countEvent(`search-none/${searchWords(query)}`)", self.code)
self.assertIn("message.startsWith('No results for')", self.code)
def test_one_endpoint(self) -> None:
self.assertEqual(set(re.findall(r"https://[\w.-]+", self.code)),
{"https://retrobios.goatcounter.com"})
class ThePageSaysWhatIsCounted(unittest.TestCase):
def test_every_page_loads_the_counter_and_links_the_page(self) -> None:
footer = FOOTER.read_text(encoding="utf-8")
self.assertIn("import '../scripts/count.ts';", footer)
self.assertIn("wiki/privacy/", footer)
# Hidden until the script shows it: a declined browser is not asked.
self.assertRegex(footer, r"data-rb-helpful-box hidden")
def test_the_page_names_each_thing_sent(self) -> None:
page = PRIVACY.read_text(encoding="utf-8")
for said in ("No cookies", "Do Not Track", "Global Privacy Control",
"copy button", "found nothing", "Did this page help?",
"The installer sends nothing back", "retrobios.goatcounter.com"):
with self.subTest(said=said):
self.assertIn(said, page)
def test_the_installer_has_no_counter(self) -> None:
installer = (REPO_ROOT / "install.py").read_text(encoding="utf-8")
self.assertNotIn("goatcounter", installer.lower())
if __name__ == "__main__":
unittest.main()