Files
libretro/tests/test_site_render.py
T
Abdessamad Derraz fe652bf508 docs: keep neutral wording on every site page
The gaps page called each platform's file a corrected list, a word the
exports page test already kept off that page. The test now reads the
text of every site generator.
2026-10-21 05:06:37 +02:00

116 lines
4.5 KiB
Python

"""Renderings shared by the site pages, and the icon cache they read.
No network: icon checks are answered by a stub.
"""
from __future__ import annotations
import json
import sys
import tempfile
import unittest
import urllib.error
from pathlib import Path
from unittest import mock
REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
import siterender # noqa: E402
class _Served:
status = 200
def __enter__(self) -> "_Served":
return self
def __exit__(self, *exc: object) -> None:
return None
class IconCacheIsReplacedWhole(unittest.TestCase):
"""The cache was truncated then dumped in place: a concurrent reader saw
half a file, took it for empty, and an offline run then wrote ``{}``
over every recorded icon."""
def setUp(self) -> None:
tmp = tempfile.TemporaryDirectory()
self.addCleanup(tmp.cleanup)
self.path = Path(tmp.name) / "system_icons.json"
patcher = mock.patch.object(siterender, "ICON_CACHE_PATH", self.path)
patcher.start()
self.addCleanup(patcher.stop)
saved = dict(siterender._icon_available)
self.addCleanup(lambda: (siterender._icon_available.clear(),
siterender._icon_available.update(saved)))
def test_an_offline_run_leaves_an_unreadable_cache_untouched(self):
self.path.write_text('{"Sega - Mega Drive": tr')
offline = mock.patch.object(
siterender.urllib.request, "urlopen",
side_effect=urllib.error.URLError("offline"))
with offline, mock.patch("sys.stderr"), mock.patch("builtins.print"):
siterender.prime_system_icons({"Sega - Mega Drive"})
self.assertEqual(self.path.read_text(), '{"Sega - Mega Drive": tr')
def test_names_another_run_recorded_meanwhile_are_kept(self):
self.path.write_text(json.dumps({"A - One": True}))
def answer(*_args: object, **_kwargs: object) -> _Served:
# A second build records its own check while this one runs.
self.path.write_text(json.dumps({"A - One": True, "C - Three": False}))
return _Served()
with mock.patch.object(siterender.urllib.request, "urlopen", side_effect=answer), \
mock.patch("builtins.print"):
siterender.prime_system_icons({"A - One", "B - Two"})
self.assertEqual(json.loads(self.path.read_text()),
{"A - One": True, "B - Two": True, "C - Three": False})
self.assertEqual(sorted(p.name for p in self.path.parent.iterdir()),
["system_icons.json"])
def test_the_write_goes_through_a_scratch_file(self):
with mock.patch.object(siterender.urllib.request, "urlopen",
return_value=_Served()), \
mock.patch.object(siterender, "write_text_atomic",
wraps=siterender.write_text_atomic) as atomic, \
mock.patch("builtins.print"):
siterender.prime_system_icons({"B - Two"})
atomic.assert_called_once()
class EveryPageAddressesPlatformsAsPeers(unittest.TestCase):
"""The exports page was held to neutral wording, and the gaps page next
to it still called each platform's file a "corrected list". Reads the
text every site generator writes, docstrings and bare identifiers aside."""
WORDS = ("their file", "theirs", "of ours", "corrected", "left out", "drift")
SOURCES = ("generate_site.py", "siterender.py", "sitesources.py", "siteexports.py")
def test_no_page_text_judges_another_project(self):
import ast
import re
found = []
for name in self.SOURCES:
tree = ast.parse((REPO_ROOT / "scripts" / name).read_text(encoding="utf-8"))
docstrings = {
id(node.body[0].value) for node in ast.walk(tree)
if isinstance(node, (ast.Module, ast.ClassDef, ast.FunctionDef,
ast.AsyncFunctionDef))
and ast.get_docstring(node, clean=False) is not None
}
for node in ast.walk(tree):
if (not isinstance(node, ast.Constant) or not isinstance(node.value, str)
or id(node) in docstrings or re.fullmatch(r"\w+", node.value)):
continue
text = node.value.lower()
found += [f"{name}:{node.lineno} {word!r}"
for word in self.WORDS if word in text]
self.assertEqual(found, [])
if __name__ == "__main__":
unittest.main()