mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-06 18:13:48 -06:00
chore: merge folded cards and one install command
This commit is contained in:
commit
793b16cf67
15 files changed
+974
-66
No files matched your search
@@ -5049,7 +5049,7 @@ class CollectionCardsCarryFullHashes(unittest.TestCase):
|
||||
"crc32": "504086c1", "sha256": "b" * 64}
|
||||
text = "\n".join(_system_file_card(entry, FileConsumers({}, {})))
|
||||
for value in (entry["sha1"], entry["md5"], entry["crc32"], entry["sha256"]):
|
||||
self.assertIn(f'<span class="rb-hash">{value}</span>', text)
|
||||
self.assertIn(f'<dd class="rb-hash">{value}</dd>', text)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
"""File cards and install boxes read at a glance (density round, 2026-10-27).
|
||||
|
||||
A system page wrote every setup's install command for each console, twice:
|
||||
12 long lines for the PSP. A file card showed four full hashes, the
|
||||
collection path and the catalogue records before the next file. Now a box
|
||||
shows one command for the setup picked, and a card shows the name, the
|
||||
size, the download, a short SHA1, the setups and the emulators. The rest
|
||||
sits in closed folds, every fact still on the page.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import sys
|
||||
import types
|
||||
import unittest
|
||||
from html.parser import HTMLParser
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(REPO_ROOT / "scripts"))
|
||||
|
||||
import generate_site as gs # noqa: E402
|
||||
import sitemarkup as markup # noqa: E402
|
||||
from cross_reference import FileConsumers # noqa: E402
|
||||
|
||||
DIST = REPO_ROOT / "website" / "dist"
|
||||
SITE_TS = REPO_ROOT / "website" / "src" / "scripts" / "site.ts"
|
||||
|
||||
SHA1 = "30a33f3651f8e1b0967a5dfe6ff714baebcce41a"
|
||||
MD5 = "866855cc330b9b95cc69135fb7b41d38"
|
||||
CRC32 = "7b57fa78"
|
||||
SHA256 = "3ab7fcf6956d0281ada94d501fc6d1cfa8fc034f139e25fed6c829f723d92a95"
|
||||
|
||||
|
||||
class _Visible(HTMLParser):
|
||||
"""Words shown before any fold is opened: text outside closed details
|
||||
(their summary counts), hidden elements, scripts and styles."""
|
||||
|
||||
VOID = {"br", "img", "input", "wbr", "hr", "meta", "link", "source"}
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__(convert_charrefs=True)
|
||||
self.stack: list[tuple[str, object]] = []
|
||||
self.hidden = 0
|
||||
self.words: list[str] = []
|
||||
|
||||
def handle_starttag(self, tag: str, attrs: list) -> None:
|
||||
if tag in self.VOID:
|
||||
return
|
||||
names = dict(attrs)
|
||||
if tag == "summary" and self.stack and self.stack[-1] == ("details", True):
|
||||
self.hidden -= 1
|
||||
self.stack.append((tag, "shown"))
|
||||
return
|
||||
hides = tag in ("script", "style") or "hidden" in names or (
|
||||
tag == "details" and "open" not in names)
|
||||
self.hidden += hides
|
||||
self.stack.append((tag, hides))
|
||||
|
||||
def handle_endtag(self, tag: str) -> None:
|
||||
while self.stack:
|
||||
name, hides = self.stack.pop()
|
||||
if hides == "shown":
|
||||
self.hidden += 1
|
||||
elif hides:
|
||||
self.hidden -= 1
|
||||
if name == tag:
|
||||
break
|
||||
|
||||
def handle_data(self, data: str) -> None:
|
||||
if not self.hidden:
|
||||
self.words += data.split()
|
||||
|
||||
|
||||
def visible_words(html_text: str) -> list[str]:
|
||||
parser = _Visible()
|
||||
parser.feed(html_text)
|
||||
return parser.words
|
||||
|
||||
|
||||
def _main(page: str) -> str:
|
||||
text = (DIST / page / "index.html").read_text(encoding="utf-8")
|
||||
return text[text.index("<main"):text.index("</main>")]
|
||||
|
||||
|
||||
def _card_consumers(sha1: str) -> types.SimpleNamespace:
|
||||
return types.SimpleNamespace(
|
||||
platforms={sha1: {"batocera", "retroarch"}}, emulators={sha1: {"ppsspp"}},
|
||||
platform_systems={sha1: {"batocera": {"sony-psp"}, "retroarch": {"sony-psp"}}},
|
||||
platform_destinations={sha1: {"batocera": {"psp/ppge_atlas.zim"},
|
||||
"retroarch": {"PPSSPP/ppge_atlas.zim"}}},
|
||||
installed={sha1: {"knulli": {"PPSSPP/ppge_atlas.zim"}}},
|
||||
emulator_entries={}, emulator_files={},
|
||||
)
|
||||
|
||||
|
||||
def _card() -> dict:
|
||||
return {"name": "ppge_atlas.zim", "sha1": SHA1, "md5": MD5, "crc32": CRC32,
|
||||
"sha256": SHA256, "size": 666539,
|
||||
"path": "bios/Sony/PlayStation Portable/ppge_atlas.zim",
|
||||
"provenance": {"tosec": {"name": "ppge_atlas (PPSSPP).zim"}}}
|
||||
|
||||
|
||||
class ASystemCardShowsTheAnswerFirst(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.lines = gs._system_file_card(_card(), _card_consumers(SHA1))
|
||||
self.text = "\n".join(self.lines)
|
||||
self.fold = self.text[self.text.index("<details"):self.text.index("</details>")]
|
||||
self.shown = self.text.replace(self.fold, "")
|
||||
|
||||
def test_the_open_part(self) -> None:
|
||||
for fact in ("<code>ppge_atlas.zim</code>", ">650.9 KB<", ">Download</a>",
|
||||
"<dt>On the setup's list</dt>", "<dt>Packed for its emulators by</dt>",
|
||||
"<dt>Emulators</dt>", f'<dt>SHA1</dt><dd class="rb-hash">{SHA1[:12]}</dd>'):
|
||||
self.assertIn(fact, self.shown)
|
||||
|
||||
def test_every_hash_whole_in_one_fold_with_the_rest(self) -> None:
|
||||
for label, value in (("SHA1", SHA1), ("MD5", MD5), ("CRC32", CRC32), ("SHA256", SHA256)):
|
||||
self.assertIn(f'<dt>{label}</dt><dd class="rb-hash">{value}</dd>', self.fold)
|
||||
shown = " ".join(visible_words(self.text))
|
||||
for value in (MD5, CRC32, SHA256, SHA1):
|
||||
self.assertNotIn(value, shown)
|
||||
self.assertIn("<dt>Collection path</dt>", self.fold)
|
||||
self.assertIn("<dt>Catalogued</dt>", self.fold)
|
||||
self.assertEqual(self.text.count("<details"), 1)
|
||||
self.assertIn("<summary>Hashes, collection path and catalogues</summary>", self.fold)
|
||||
|
||||
def test_the_fold_is_out_of_the_search(self) -> None:
|
||||
self.assertTrue(self.fold.startswith("<details data-pagefind-ignore>\n<summary>"))
|
||||
|
||||
def test_no_fact_is_lost(self) -> None:
|
||||
# The yardstick list a page is cut by holds every fact: the
|
||||
# Starlight card holds each of its values.
|
||||
with markup.using("mkdocs"):
|
||||
yardstick = "\n".join(gs._system_file_card(_card(), _card_consumers(SHA1)))
|
||||
for label, values in re.findall(r"(?m)^- ([^:]+): (.*)$", yardstick):
|
||||
self.assertIn(f"<dt>{label}</dt>", self.text)
|
||||
for value in re.findall(r"[0-9a-f]{8,64}|`[^`]+`", values):
|
||||
self.assertIn(value.strip("`"), self.text, label)
|
||||
|
||||
def test_a_card_reads_in_few_words(self) -> None:
|
||||
# Measured on this card: 31 words open, 40 before the round.
|
||||
self.assertLessEqual(len(visible_words(self.text)), min(40, int(31 * 1.05)))
|
||||
|
||||
|
||||
class AnEmulatorCardFoldsItsHashes(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
entry = {"name": "scph5501.bin", "md5": "490f666e1afb15b7362b406ed1cea246",
|
||||
"sha1": "b05def971d8ec59f346f2d9ac21fb742e3eb6917", "size": 524288,
|
||||
"required": True, "note": "Read at boot.", "priority": 5,
|
||||
"validation": ["md5"], "source_ref": "src/core/bios.cpp:47"}
|
||||
profile = {"emulator": "DuckStation", "files": [entry], "systems": ["sony-playstation"]}
|
||||
self.text = "\n".join(gs._render_emulator_file(
|
||||
entry, profile, None, profile["files"], lambda _f: True, anchor="file-scph5501-bin"))
|
||||
self.fold = self.text[self.text.index("<details"):self.text.index("</details>")]
|
||||
self.shown = self.text.replace(self.fold, "")
|
||||
|
||||
def test_a_short_hash_open_and_every_hash_folded(self) -> None:
|
||||
# On the size's line.
|
||||
self.assertIn('- Size: 512.0 KB, SHA1 <span class="rb-hash" '
|
||||
'data-copy="b05def971d8ec59f346f2d9ac21fb742e3eb6917">b05def971d8e</span>',
|
||||
self.shown)
|
||||
self.assertIn('<code class="rb-hash" data-copy="">490f666e1afb15b7362b406ed1cea246</code>',
|
||||
self.fold)
|
||||
self.assertNotIn("490f666e1afb15b7362b406ed1cea246", self.shown)
|
||||
|
||||
def test_notes_open_the_rest_folded(self) -> None:
|
||||
self.assertIn("Read at boot.", self.shown)
|
||||
for fact in ("Priority: 5", "Validation: md5", "Source:"):
|
||||
self.assertIn(fact, self.fold)
|
||||
self.assertNotIn(fact, self.shown)
|
||||
self.assertIn("<summary>Hashes, priority, validation and more</summary>", self.fold)
|
||||
|
||||
def test_the_markdown_yardstick_is_unchanged(self) -> None:
|
||||
with markup.using("mkdocs"):
|
||||
entry = {"name": "a.bin", "md5": "b" * 32, "size": 4}
|
||||
text = "\n".join(gs._render_emulator_file(
|
||||
entry, {"files": [entry]}, None, [entry], lambda _f: True))
|
||||
self.assertNotIn("<details", text)
|
||||
self.assertIn("- MD5: ", text)
|
||||
|
||||
|
||||
PAIRS = [("emudeck", "sony-psp"), ("retroarch", "sony-psp"), ("retrobat", "Neo Geo")]
|
||||
|
||||
|
||||
class AnInstallBoxShowsOneCommand(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.text = "\n".join(gs._console_install_block("PlayStation Portable", PAIRS))
|
||||
|
||||
def test_one_command_per_tab_for_the_setup_picked(self) -> None:
|
||||
tabs = self.text[self.text.index("<Tabs"):self.text.index("</Tabs>")]
|
||||
self.assertEqual(re.findall(r'<TabItem label="([^"]+)"', tabs),
|
||||
["Windows", "macOS", "Linux", "Steam Deck"])
|
||||
self.assertEqual(tabs.count("--platform"), 4)
|
||||
self.assertEqual(tabs.count("--platform emudeck --system sony-psp"), 4)
|
||||
|
||||
def test_the_setup_list_carries_every_command(self) -> None:
|
||||
select = re.search(r"<select>(.*?)</select>", self.text).group(1)
|
||||
options = re.findall(r'<option value="([^"]+)" data-sh="([^"]+)" data-ps="([^"]+)">', select)
|
||||
self.assertEqual([value for value, _sh, _ps in options], ["emudeck", "retroarch", "retrobat"])
|
||||
self.assertIn(("retrobat", "--platform retrobat --system 'Neo Geo'",
|
||||
"--platform retrobat --system 'Neo Geo'"), options)
|
||||
|
||||
def test_without_script_the_list_of_every_command_shows(self) -> None:
|
||||
self.assertIn('<div class="rb-install" data-rb-install="" hidden>', self.text)
|
||||
listed = self.text[self.text.index('<details class="rb-install-all" open>'):]
|
||||
for platform, _system in PAIRS:
|
||||
self.assertEqual(listed.count(f"--platform {platform} --system"), 2, platform)
|
||||
self.assertIn("install.sh | sh -s -- --platform retrobat --system 'Neo Geo'</code>", listed)
|
||||
self.assertIn("install.ps1))) --platform retrobat --system 'Neo Geo'</code>", listed)
|
||||
# The URL is no link inside the command, and the break adds nothing.
|
||||
self.assertIn("https://<wbr>raw.githubusercontent.com", listed)
|
||||
|
||||
def test_one_setup_keeps_its_two_blocks(self) -> None:
|
||||
text = "\n".join(gs._console_install_block("PlayStation Portable", PAIRS[:1]))
|
||||
self.assertNotIn("<select", text)
|
||||
self.assertIn('```sh title="Terminal"', text)
|
||||
self.assertIn('```powershell title="PowerShell"', text)
|
||||
|
||||
def test_the_yardstick_is_unchanged(self) -> None:
|
||||
# The budgets that cut a system page are measured on this Markdown:
|
||||
# a box that changed it would move cards to other pages.
|
||||
with markup.using("mkdocs"):
|
||||
text = "\n".join(gs._console_install_block("PlayStation Portable", PAIRS))
|
||||
self.assertNotIn("<select", text)
|
||||
self.assertEqual(text.count("# RetroBat"), 2)
|
||||
self.assertEqual(text.count("install.sh | sh"), 3)
|
||||
|
||||
|
||||
class TheSetupListLooksLikeAList(unittest.TestCase):
|
||||
"""The setup list had a rule of its own without the arrow, and read as
|
||||
a text field at 390 and 1440 px."""
|
||||
|
||||
def test_the_select_takes_the_site_arrow(self) -> None:
|
||||
css = (REPO_ROOT / "website" / "src" / "styles" / "retrobios.css").read_text(encoding="utf-8")
|
||||
shared = re.search(r"\.sl-markdown-content select \{([^}]*)\}", css)
|
||||
self.assertIsNotNone(shared)
|
||||
self.assertIn("appearance: none", shared.group(1))
|
||||
self.assertIn("var(--rb-select-arrow)", shared.group(1))
|
||||
# No rule for the install box's select overrides it.
|
||||
self.assertNotRegex(css, r"rb-install-setup select")
|
||||
# The arrow is defined for both themes.
|
||||
self.assertEqual(len(re.findall(r"--rb-select-arrow:", css)), 2)
|
||||
# The box's select sits in Markdown content, where the shared rule applies.
|
||||
box = "\n".join(gs._console_install_block("PlayStation Portable", PAIRS))
|
||||
self.assertIn('<label class="rb-install-setup">Your setup <select>', box)
|
||||
|
||||
def test_the_built_select_shows_the_arrow(self) -> None:
|
||||
if not (DIST / "systems").is_dir():
|
||||
self.skipTest("no built site")
|
||||
css = "".join(path.read_text(encoding="utf-8") for path in (DIST / "_astro").glob("*.css"))
|
||||
self.assertNotIn("rb-install-setup select", css)
|
||||
self.assertRegex(css, r"\.sl-markdown-content select\{[^}]*--rb-select-arrow")
|
||||
|
||||
|
||||
class TheScriptWiresBoth(unittest.TestCase):
|
||||
def test_pickers_and_copy_buttons_run(self) -> None:
|
||||
source = SITE_TS.read_text(encoding="utf-8")
|
||||
self.assertIn("\ninstallPickers();\n", source)
|
||||
self.assertIn("\ncopyButtons();\n", source)
|
||||
self.assertIn("const SETUP_KEY = 'rb-setup';", source)
|
||||
self.assertIn("const COPYABLE = '[data-copy], .rb-sys-file dd.rb-hash';", source)
|
||||
|
||||
|
||||
# Visible words of each built page: measured before the round and after it,
|
||||
# the ceiling being the after value with 5 % of room.
|
||||
WORD_CEILINGS = {
|
||||
"systems/sony": (2012, 1407),
|
||||
"systems/sony-playstation": (2709, 2130),
|
||||
"systems/nintendo": (3598, 2941),
|
||||
"systems/sega": (4151, 3370),
|
||||
"emulators/duckstation": (1188, 1117),
|
||||
"emulators/yaps2": (3159, 2655),
|
||||
}
|
||||
|
||||
|
||||
class BuiltPagesReadInFewerWords(unittest.TestCase):
|
||||
def test_visible_words_under_the_ceiling(self) -> None:
|
||||
if not (DIST / "systems").is_dir():
|
||||
self.skipTest("no built site")
|
||||
for page, (before, after) in WORD_CEILINGS.items():
|
||||
with self.subTest(page=page):
|
||||
ceiling = min(before, int(after * 1.05))
|
||||
self.assertLessEqual(len(visible_words(_main(page))), ceiling)
|
||||
|
||||
def test_a_built_card_holds_its_hashes(self) -> None:
|
||||
if not (DIST / "systems").is_dir():
|
||||
self.skipTest("no built site")
|
||||
main = _main("systems/sony")
|
||||
card = main[main.index('id="sha1-30a33f3651f8"'):]
|
||||
card = card[:card.index('class="rb-sys-file"')]
|
||||
self.assertRegex(card, r'<dd class="rb-hash">30a33f3651f8</dd>')
|
||||
self.assertIn('<details data-pagefind-ignore', card)
|
||||
self.assertIn(">30a33f3651f8e1b0967a5dfe6ff714baebcce41a</dd>", card)
|
||||
# No link inside a command of the list: the URL is text.
|
||||
listed = main[main.index("rb-install-all"):]
|
||||
self.assertNotRegex(listed[:listed.index("</details>")], r"<code[^>]*>[^<]*<a ")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -369,7 +369,7 @@ class AVariantShowsWhoPinsIt(unittest.TestCase):
|
||||
".variants/advision.zip.1c086064</code>", block)
|
||||
self.assertIn('<a href="../platforms/batocera.md">Batocera</a>', block)
|
||||
self.assertIn('<a href="../platforms/retrobat.md">RetroBat</a>', block)
|
||||
self.assertIn('<span class="rb-hash">' + "c" * 40 + "</span>", block)
|
||||
self.assertIn('<dd class="rb-hash">' + "c" * 40 + "</dd>", block)
|
||||
self.assertIn("Catalogued", block)
|
||||
|
||||
|
||||
@@ -992,7 +992,8 @@ class TheOneLinerIsWhereUsersLand(unittest.TestCase):
|
||||
page = generate_site.generate_system_page(
|
||||
"Microsoft", {"MSX": [entry]}, FileConsumers({"files": {}}),
|
||||
{"MSX": [("recalbox", "msx1,msx2,msxturbor"), ("batocera", "msx1")]})
|
||||
self.assertIn("--platform recalbox --system msx1,msx2,msxturbor\n", page)
|
||||
# The whole system id, up to the end of the command.
|
||||
self.assertRegex(page, r"--platform recalbox --system msx1,msx2,msxturbor(\n|</code>)")
|
||||
self.assertIn("--platform batocera --system msx1", page)
|
||||
|
||||
def test_a_system_is_offered_only_where_the_manifest_records_it(self):
|
||||
|
||||
@@ -285,7 +285,12 @@ class CommandBlocks(unittest.TestCase):
|
||||
self.assertIn("install.ps1", group)
|
||||
block = "\n".join(generate_site._console_install_block(
|
||||
"PlayStation", [("batocera", "psx"), ("recalbox", "psx")]))
|
||||
self.assertEqual(block.count("install.sh | sh"), block.count("install.ps1))) "))
|
||||
# Every setup's options in both forms: the list of every command,
|
||||
# and the one command under the OS tabs.
|
||||
sh_args = re.findall(r"install\.sh \| sh -s -- ([^<\n]+)", block)
|
||||
ps_args = re.findall(r"install\.ps1\)\)\) ([^<\n]+)", block)
|
||||
self.assertEqual(sorted(set(sh_args)), sorted(set(ps_args)))
|
||||
self.assertEqual(len(set(sh_args)), 2)
|
||||
self.assertIn('```powershell title="PowerShell"', block)
|
||||
for key, guide in siteguides.GUIDES.items():
|
||||
if "windows" in guide.run:
|
||||
|
||||
@@ -182,8 +182,14 @@ class TheCardLinesSayWhatTheyMean(unittest.TestCase):
|
||||
def test_the_facts_are_out_of_the_search(self):
|
||||
# The setup list made every card's excerpt a run of names and
|
||||
# paths (round 4, V6): the card's title is what the search reads.
|
||||
lists = [line for line in self.lines if line.startswith("<dl")]
|
||||
# The facts shown open are one list, the others one fold, both
|
||||
# out of the search.
|
||||
shown = self.lines[:next(i for i, line in enumerate(self.lines) if line.startswith("<details"))]
|
||||
lists = [line for line in shown if line.startswith("<dl")]
|
||||
self.assertEqual(lists, ['<dl class="rb-facts" data-pagefind-ignore>'])
|
||||
folds = [line for line in self.lines if line.startswith("<details")]
|
||||
self.assertEqual(len(folds), 1)
|
||||
self.assertEqual(folds, ["<details data-pagefind-ignore>"])
|
||||
|
||||
def test_the_page_defines_both_lines(self):
|
||||
page = gs.generate_system_page("Sony", {"PlayStation": [_file("scph5501.bin", "4")]},
|
||||
@@ -206,15 +212,17 @@ class FileFactsAreAGrid(unittest.TestCase):
|
||||
"provenance": {"redump": {"name": "ps-30a.bin"},
|
||||
"tosec": {"name": "SCPH-5501 (1996).bin"}}}
|
||||
lines = gs._system_file_card(entry, FileConsumers({"files": {}}))
|
||||
facts = [line for line in lines if line.startswith("<dt>")]
|
||||
self.assertTrue(facts)
|
||||
for line in facts:
|
||||
self.assertEqual(line.count("<dt>"), 1, line)
|
||||
self.assertEqual(line.count("<dd>"), 1, line)
|
||||
text = "\n".join(lines)
|
||||
self.assertIn('<dt>SHA1</dt><dd><span class="rb-hash">' + "4" * 40 + "</span></dd>", text)
|
||||
# One value cell after each label, in the open list and in the fold.
|
||||
facts = re.findall(r"<dt>[^<]*</dt><dd[^>]*>.*?</dd>", text)
|
||||
self.assertTrue(facts)
|
||||
self.assertEqual(len(facts), text.count("<dt>"))
|
||||
self.assertEqual(text.count("<dt>"), len(re.findall(r"<dd[ >]", text)))
|
||||
# The hash is the cell's text, styled by the cell: no element around it.
|
||||
self.assertIn('<dt>SHA1</dt><dd class="rb-hash">' + "4" * 40 + "</dd>", text)
|
||||
self.assertNotIn("<code class=\"rb-hash\">", text)
|
||||
catalogued = next(line for line in facts if line.startswith("<dt>Catalogued"))
|
||||
self.assertNotIn('<span class="rb-hash">', text)
|
||||
catalogued = next(fact for fact in facts if fact.startswith("<dt>Catalogued"))
|
||||
self.assertIn("<br>", catalogued)
|
||||
self.assertNotRegex(text, r"(?m)^- ")
|
||||
|
||||
|
||||
@@ -141,7 +141,10 @@ class TheVisitorsTab(unittest.TestCase):
|
||||
block = source[source.index("const osTabs = () =>"):source.index("// The sidebar lists")]
|
||||
self.assertIn("savedTab(OS_SYNC_KEY)", block)
|
||||
self.assertIn("set.switchTab(set.tabs[index], index, false)", block)
|
||||
self.assertNotIn("localStorage.setItem", source)
|
||||
self.assertNotIn("localStorage.setItem", block)
|
||||
# The one choice the script saves is the setup picked in an install
|
||||
# box, under its own key: never the OS guess.
|
||||
self.assertEqual(re.findall(r"localStorage\.setItem\((\w+)", source), ["SETUP_KEY"])
|
||||
self.assertNotIn("keepTabInView", source)
|
||||
|
||||
|
||||
|
||||
@@ -149,7 +149,8 @@ class TheNeoGeoOpensOnItsSet(unittest.TestCase):
|
||||
pairs = gs._install_pairs([("batocera", "snk-neogeo")], "a" * 40, consumers)
|
||||
self.assertIn(("retroarch", "arcade"), pairs)
|
||||
block = "\n".join(gs._console_install_block("Neo Geo", pairs))
|
||||
self.assertIn("# RetroArch\n", block)
|
||||
self.assertIn("<li>RetroArch: <code", block)
|
||||
self.assertIn("--platform retroarch --system arcade</code>", block)
|
||||
|
||||
def test_the_built_section(self) -> None:
|
||||
html = _page(DIST / "systems" / "snk" / "index.html")
|
||||
|
||||
@@ -260,8 +260,9 @@ class EnginesGoByEngine(unittest.TestCase):
|
||||
if not SYSTEMS.is_dir():
|
||||
self.skipTest("pages not generated")
|
||||
for old, new in gs.SYSTEM_PAGES_MOVED.items():
|
||||
self.assertFalse((CONTENT / old).exists(), old)
|
||||
self.assertTrue((CONTENT / new).exists(), new)
|
||||
self.assertFalse((CONTENT / old).exists() or (CONTENT / old).with_suffix(".mdx").exists(), old)
|
||||
# A page with tabs is written as MDX.
|
||||
self.assertTrue((CONTENT / new).exists() or (CONTENT / new).with_suffix(".mdx").exists(), new)
|
||||
redirects = CONTENT.parents[1] / "generated" / "redirects.json"
|
||||
if redirects.is_file():
|
||||
table = json.loads(redirects.read_text(encoding="utf-8"))
|
||||
|
||||
Reference in new issue
Block a user