From 0682114ad65e0c94ff0038e7333513c38f930fdb Mon Sep 17 00:00:00 2001
From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com>
Date: Fri, 23 Oct 2026 19:23:05 +0200
Subject: [PATCH] chore: test system pages and file cards
---
tests/test_site_exports.py | 2 +-
tests/test_site_r2_systems.py | 38 ++--
tests/test_site_r3_systems.py | 20 +-
tests/test_site_r4_systems.py | 317 ++++++++++++++++++++++++++++++++
tests/test_site_render.py | 14 +-
tests/test_site_system_links.py | 6 +-
6 files changed, 362 insertions(+), 35 deletions(-)
create mode 100644 tests/test_site_r4_systems.py
diff --git a/tests/test_site_exports.py b/tests/test_site_exports.py
index a4a873c1..db84b5b6 100644
--- a/tests/test_site_exports.py
+++ b/tests/test_site_exports.py
@@ -1054,7 +1054,7 @@ class EveryPageLinksItsOwnData(unittest.TestCase):
"path": "bios/Sony/PlayStation/a.bin"}
page = generate_site.generate_system_page(
"Sony", {"PlayStation": [entry]}, FileConsumers({"files": {}}))
- self.assertIn("[JSON](../api/v1/systems/sony.json)", page)
+ self.assertIn(" as JSON](../api/v1/systems/sony.json)", page)
item = generate_site.system_export_item("sony", "Sony", {"PlayStation": [entry]})
self.assertEqual(item["consoles"]["PlayStation"][0]["sha1"], "a" * 40)
diff --git a/tests/test_site_r2_systems.py b/tests/test_site_r2_systems.py
index 70b44ba0..9fece26d 100644
--- a/tests/test_site_r2_systems.py
+++ b/tests/test_site_r2_systems.py
@@ -87,8 +87,18 @@ class TheConsoleBiosComesFirst(unittest.TestCase):
names = [re.search(r"(.*?)", card[2])[1] for _v, card, _s in cards]
self.assertEqual(names, sorted(names, key=str.casefold))
+ def required_only(self) -> types.SimpleNamespace:
+ """The BIOS readers alone: an emulator reading only an optional
+ file runs without the BIOS, and two of four would say so."""
+ return _consumers({
+ "4" * 40: [{"name": "scph5501.bin", "required": True, "priority": 2,
+ "region": ["north-america"]}],
+ "5" * 40: [{"name": "scph5500.bin", "required": True, "priority": 5,
+ "region": ["japan"]}],
+ })
+
def test_the_section_opens_on_the_bios_by_region(self):
- lines = gs._start_with(self.files, self.consumers)
+ lines = gs._start_with(self.files, self.required_only())
self.assertEqual(lines[0], "**Start with** the BIOS for the region of your games:")
self.assertIn("- **North America**: `scph5501.bin`", lines)
self.assertIn("- **Japan**: `scph5500.bin`", lines)
@@ -113,7 +123,7 @@ class TheConsoleBiosComesFirst(unittest.TestCase):
self.assertEqual(gs._start_with([_file("a.bin", "a")], _consumers({})), [])
def test_the_page_carries_the_line_under_the_console(self):
- page = gs.generate_system_page("Sony", {"PlayStation": self.files}, self.consumers)
+ page = gs.generate_system_page("Sony", {"PlayStation": self.files}, self.required_only())
heading = page.index("## PlayStation")
self.assertLess(heading, page.index("**Start with**"))
self.assertLess(page.index("**Start with**"), page.index('class="rb-sys-file"'))
@@ -156,23 +166,19 @@ class TheCardLinesSayWhatTheyMean(unittest.TestCase):
def test_labels_and_display_names(self):
text = "\n".join(self.lines)
- self.assertIn("
On the setup's listBatocera: scph5501.bin",
- text)
- self.assertIn("Packed for its emulators byRetroBat: bios/scph5501.bin", text)
+ # Grouped by where the setups put the file (round 4, 6.9).
+ self.assertIn("On the setup's listscph5501.bin: Batocera", text)
+ self.assertIn("Packed for its emulators bybios/scph5501.bin: "
+ "RetroBat", text)
self.assertNotIn("Platforms:", text)
self.assertNotIn("Also installed by", text)
- def test_the_setup_list_is_searched_and_the_rest_is_not(self):
+ 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("', ''])
- searched = "\n".join(self.lines).split('', 1)[1].split("
")[0]
- self.assertIn("On the setup's list", searched)
- self.assertNotIn("SHA1", searched)
- # The label stays out of the excerpt: the search ran the two
- # together, "On the setup's listAmberELEC".
- self.assertIn("- On the setup's list
- ", searched)
+ self.assertEqual(lists, ['
'])
def test_the_page_defines_both_lines(self):
page = gs.generate_system_page("Sony", {"PlayStation": [_file("scph5501.bin", "4")]},
@@ -246,7 +252,7 @@ class TheSystemsIndexListsConsoles(unittest.TestCase):
# A program's folder under Other is named alone, in its own table.
consoles = page.split("## Emulator folders")[0]
self.assertNotIn("ScummVM", consoles)
- self.assertIn("| [ScummVM](other.md#scummvm) | 1 | [Other](other.md) |",
+ self.assertIn("| [ScummVM](../emulators/scummvm.md) | [1 file](other.md#scummvm) |",
page.split("## Emulator folders")[1])
self.assertNotIn("TheXTech", consoles)
self.assertIn("| [TheXTech](game-engines.md#thextech)", page)
diff --git a/tests/test_site_r3_systems.py b/tests/test_site_r3_systems.py
index 3bd7c105..816a8e07 100644
--- a/tests/test_site_r3_systems.py
+++ b/tests/test_site_r3_systems.py
@@ -137,12 +137,12 @@ class ArcadeSetsAreNamedWhereverFiled(unittest.TestCase):
"system": "snk-neogeo-mvs"})],
}, db_files=[self.aes, neogeo, mega_cd, shader])
- def test_one_line_per_system_and_the_arcade_set_linked(self) -> None:
+ def test_the_file_most_emulators_read_leads_and_the_arcade_set_is_linked(self) -> None:
lines = gs._start_with([self.aes], self.consumers, section=("SNK", "Neo Geo"))
- self.assertEqual(lines[0], "**Start with** the files of your machine:")
link = f"[`neogeo.zip`](/retrobios/files/?sha1={'2' * 40})"
- self.assertIn(f"- **SNK Neo Geo MVS**: {link}", lines)
- self.assertIn("- **SNK Neo Geo AES**: `aes.zip`", lines)
+ self.assertEqual(lines[0], f"**Start with** {link}. Keep it zipped. "
+ "mame0, mame1 and mame2 read it.")
+ self.assertIn("Geolith reads `aes.zip` instead.", lines)
def test_another_consoles_file_or_an_emulators_folder_is_left_out(self) -> None:
text = "\n".join(gs._start_with([self.aes], self.consumers, section=("SNK", "Neo Geo")))
@@ -190,13 +190,12 @@ class CardsSayWhichReleaseTheSetMatches(unittest.TestCase):
return "\n".join(gs._system_file_card(f, _consumers({})))
def test_the_matching_releases_as_runs(self) -> None:
- self.assertIn("- Romset
- MAME 0.190 to 0.195, 0.220, FBNeo 1.0.0.03
",
- self.card())
+ self.assertIn("- Romset
- Same contents as MAME 0.190 to 0.195, 0.220 and "
+ "FBNeo 1.0.0.03
", self.card())
- def test_no_match_names_what_was_compared(self) -> None:
+ def test_no_match_counts_what_is_missing(self) -> None:
self.releases["set.zip"] = self.releases["set.zip"][2:]
- with mock.patch.object(gs, "_romset_coverage", return_value="MAME 0.190 to 0.289"):
- self.assertIn("- No match in MAME 0.190 to 0.289
", self.card())
+ self.assertIn("- No match: missing 1 ROM of MAME 0.289
", self.card())
def test_no_recipe_no_line(self) -> None:
self.releases = {}
@@ -256,7 +255,8 @@ class TheBuiltPages(unittest.TestCase):
page = (DIST / "systems" / "nintendo" / "index.html").read_text(encoding="utf-8")
start = page.index('id="nintendo-ds"')
section = page[start:page.index('id="nintendo-dsi"')]
- opening = section[:section.index('class="rb-sys-file"')]
+ # The section may have moved to a page of its own: no card follows.
+ opening = section.split('class="rb-sys-file"')[0]
self.assertRegex(opening, r"No file needed|Start with")
self.assertNotRegex(opening.casefold(), r"dsi_|bios7i|bios9i")
diff --git a/tests/test_site_r4_systems.py b/tests/test_site_r4_systems.py
new file mode 100644
index 00000000..40529d3f
--- /dev/null
+++ b/tests/test_site_r4_systems.py
@@ -0,0 +1,317 @@
+"""System pages and file cards (round 4, package 6).
+
+The Game Boy, NES and SNES sections said "Start with" a file one core of
+sixteen requires, under a home page saying they need none. The romset line
+said no MAME release matched sets MAME loads. The Neo Geo opened on files
+ares alone reads, and RetroArch had no install line. The Arcade page was
+sorted by storage folder: NAOMI, PGM and ZN-1 had no section, and their
+names were plain on every emulator page. Cards named emulators by id, part
+pages had no parent and no name, and four paragraphs came before the first
+console.
+"""
+
+from __future__ import annotations
+
+import json
+import re
+import sys
+import types
+import unittest
+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
+from sitestarlight import toc_slug # noqa: E402
+
+DIST = REPO_ROOT / "website" / "dist"
+CONTENT = REPO_ROOT / "website" / "src" / "content" / "docs"
+
+
+def _file(name: str, char: str, path: str = "") -> dict:
+ return {"name": name, "sha1": char * 40, "md5": char * 32, "size": 4096,
+ "path": path or f"bios/Nintendo/Game Boy/{name}"}
+
+
+def _consumers(readers: dict[str, list[tuple[str, dict]]],
+ systems: dict[str, dict[str, set[str]]] | None = None) -> types.SimpleNamespace:
+ """Consumers where each sha1 is read by the given (emulator, entry)."""
+ files_of: dict[str, list] = {}
+ entries: dict[str, dict[str, int]] = {}
+ emulators: dict[str, set[str]] = {}
+ for sha1, read_by in readers.items():
+ for emulator, entry in read_by:
+ files_of.setdefault(emulator, []).append(entry)
+ entries.setdefault(sha1, {})[emulator] = len(files_of[emulator]) - 1
+ emulators.setdefault(sha1, set()).add(emulator)
+ return types.SimpleNamespace(
+ platforms={}, emulators=emulators, emulator_entries=entries,
+ emulator_files=files_of, installed={}, platform_systems=systems or {},
+ platform_destinations={}, _db={"files": {}},
+ )
+
+
+def _page(path: Path) -> str:
+ if not path.is_file():
+ raise unittest.SkipTest(f"{path.relative_to(REPO_ROOT)} not built")
+ return path.read_text(encoding="utf-8")
+
+
+def _opening(html: str, anchor: str) -> str:
+ """The text of the first paragraph under a heading."""
+ start = html.index("", html.index(f'id="{anchor}"'))
+ return re.sub(r"<[^>]+>", "", html[start:html.index("
", start)]).strip()
+
+
+class AFileFewRequireIsNoStartFile(unittest.TestCase):
+ """6.1: one requiring emulator decided the line for the console."""
+
+ def test_one_of_four_says_no_file_needed_and_names_it(self) -> None:
+ boot = _file("dmg_boot.bin", "1")
+ optional = {"required": False, "system": "nintendo-gb"}
+ consumers = _consumers({"1" * 40: [
+ ("emux_gb", {"name": "dmg_boot.bin", "required": True}),
+ ("gambatte", optional), ("mgba", optional), ("sameboy", optional)]})
+ line = gs._start_with([boot], consumers)[0]
+ self.assertTrue(line.startswith("**No file needed** with "), line)
+ self.assertRegex(line, r"Only \S.* requires `dmg_boot.bin`\.$")
+
+ def test_most_requiring_keeps_the_start_line(self) -> None:
+ bios = _file("scph5501.bin", "2")
+ required = {"name": "scph5501.bin", "required": True}
+ consumers = _consumers({"2" * 40: [
+ ("a", required), ("b", required), ("c", {"required": False, "hle_fallback": True})]})
+ self.assertEqual(gs._start_with([bios], consumers)[0], "**Start with**: `scph5501.bin`.")
+
+ def test_an_entry_read_for_a_system_with_no_section_is_dropped(self) -> None:
+ sample = _file("ym2608_adpcm_rom.bin", "3", "bios/Nintendo/NES/ym2608_adpcm_rom.bin")
+ consumers = _consumers({"3" * 40: [
+ ("fbneo", {"name": "ym2608_adpcm_rom.bin", "required": True,
+ "system": "no-such-system-anywhere"})]})
+ self.assertEqual(gs._start_with([sample], consumers, section=("Nintendo", "NES")), [])
+
+ def test_the_home_usually_not_consoles_open_on_no_file_needed(self) -> None:
+ home = _page(DIST / "index.html")
+ match = re.search(r"Usually not for ([^<.]+)", home)
+ self.assertIsNotNone(match, "the home page no longer says Usually not")
+ names = re.split(r", | and ", match[1])
+ sections = {"NES": ("nintendo", "nes"), "Super Nintendo": ("nintendo", "snes"),
+ "Mega Drive": ("sega", "mega-drive"), "Game Boy": ("nintendo", "game-boy"),
+ "Game Boy Advance": ("nintendo", "game-boy-advance")}
+ for name in names:
+ self.assertIn(name, sections, f"map {name!r} to its section")
+ page, anchor = sections[name]
+ html = _page(DIST / "systems" / page / "index.html")
+ self.assertTrue(_opening(html, anchor).startswith("No file needed"), name)
+
+
+class TheRomsetLineMatchesByCrc(unittest.TestCase):
+ """6.2: a set with an extra BIOS revision read "No match"."""
+
+ def test_the_main_neogeo_set_names_every_mame_release(self) -> None:
+ db = json.loads((REPO_ROOT / "database.json").read_text(encoding="utf-8"))
+ main = next((f for sha1, f in db["files"].items() if sha1.startswith("447e2375")), None)
+ if main is None or not (REPO_ROOT / main["path"]).is_file():
+ self.skipTest("the main neogeo.zip is not in this checkout")
+ line = gs._romset_line(main)
+ self.assertIn("Holds every ROM of MAME 0.190 to 0.289", line)
+ self.assertNotIn("No match", line)
+
+
+class TheNeoGeoOpensOnItsSet(unittest.TestCase):
+ """6.3: the set 26 emulators read leads, RetroArch gets its command."""
+
+ def test_the_lead_names_the_exceptions(self) -> None:
+ neogeo = _file("neogeo.zip", "4", "bios/SNK/Neo Geo/neogeo.zip")
+ epo = _file("neo-epo.sp1", "5", "bios/SNK/Neo Geo/neo-epo.sp1")
+ mvs = {"name": "neogeo.zip", "required": True, "system": "snk-neogeo-mvs"}
+ consumers = _consumers({
+ "4" * 40: [(f"mame{n}", mvs) for n in range(4)],
+ "5" * 40: [("ares", {"name": "neo-epo.sp1", "required": True,
+ "system": "snk-neogeo"})],
+ })
+ lines = gs._start_with([neogeo, epo], consumers, section=("SNK", "Neo Geo"))
+ self.assertTrue(lines[0].startswith("**Start with** `neogeo.zip`. Keep it zipped. "))
+ self.assertIn("ares reads `neo-epo.sp1` instead.", lines)
+ cards = gs._console_cards("SNK", [epo, neogeo], consumers, set(),
+ start=gs._start_order([neogeo, epo], consumers,
+ ("SNK", "Neo Geo")))
+ self.assertIn("neogeo.zip", cards[0][1][2])
+
+ def test_a_setup_filing_the_set_elsewhere_gets_its_command(self) -> None:
+ consumers = _consumers({}, systems={"a" * 40: {"retroarch": {"arcade"}}})
+ 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)
+
+ def test_the_built_section(self) -> None:
+ html = _page(DIST / "systems" / "snk" / "index.html")
+ section = html[html.index('id="neo-geo"'):]
+ self.assertTrue(_opening(html, "neo-geo").startswith("Start with neogeo.zip"))
+ self.assertIn("--platform retroarch --system arcade", re.sub(r"<[^>]+>", "", section))
+
+
+BOARDS = ("Sega NAOMI", "Sammy Atomiswave", "Capcom ZN-1", "IGS PolyGame Master",
+ "Nintendo PlayChoice-10", "SNK Hyper Neo Geo 64")
+
+
+class EachArcadeBoardHasASection(unittest.TestCase):
+ """6.4: the Arcade page was cut by storage folder."""
+
+ def test_each_board_heads_its_page(self) -> None:
+ for name in BOARDS:
+ slug = toc_slug(name)
+ html = _page(DIST / "systems" / f"arcade-{slug}" / "index.html")
+ self.assertRegex(html, rf']*id="{re.escape(slug)}"', name)
+
+ def test_every_board_on_an_emulator_systems_row_is_a_link(self) -> None:
+ if not (DIST / "emulators").is_dir():
+ self.skipTest("site not built")
+ plain = []
+ for page in sorted((DIST / "emulators").glob("*/index.html")):
+ row = re.search(r"| Systems | \s*(.*?) | ", page.read_text(encoding="utf-8"),
+ re.S)
+ if not row:
+ continue
+ text = re.sub(r"]*>.*?", "", row[1])
+ plain += [(page.parent.name, name) for name in BOARDS if name in text]
+ self.assertEqual(plain, [])
+
+ def test_the_arcade_page_lists_the_boards_first(self) -> None:
+ md = _page(CONTENT / "systems" / "arcade.md")
+ headings = re.findall(r"^## (.+?) \{", md, re.M)
+ self.assertIn("Sega NAOMI", headings)
+ self.assertLess(headings.index("Sega NAOMI"), headings.index(gs.OTHER_ARCADE_LABEL))
+
+
+class CardsNameEmulatorsByName(unittest.TestCase):
+ """6.6: 19,499 card links read the profile id."""
+
+ def test_the_display_name_is_the_link_text(self) -> None:
+ sha1 = "6" * 40
+ consumers = _consumers({sha1: [("melonds_ds", {"name": "bios7.bin"})]})
+ link = gs._emulator_links(sha1, consumers)[0]
+ self.assertTrue(link.startswith("[melonDS DS]("), link)
+
+ def test_no_built_card_link_reads_an_id(self) -> None:
+ if not (DIST / "systems").is_dir():
+ self.skipTest("site not built")
+ profiles = gs._profiles_on_disk()
+ bad = set()
+ for page in (DIST / "systems").glob("*/index.html"):
+ for emulator, text in re.findall(
+ r'([^<]+)',
+ page.read_text(encoding="utf-8")):
+ display = str((profiles.get(emulator) or {}).get("emulator") or emulator)
+ if text == emulator and display != emulator:
+ bad.add(emulator)
+ self.assertEqual(sorted(bad), [])
+
+
+class PartPagesKnowWhereTheyAre(unittest.TestCase):
+ def tearDown(self) -> None:
+ # system_pages records where consoles went, for every later page.
+ gs.reset_console_pages()
+
+ """6.7: 128 system pages had no parent, parts were "part 3 of 5"."""
+
+ def test_every_part_has_a_parent_and_a_name(self) -> None:
+ if not (CONTENT / "systems").is_dir():
+ self.skipTest("pages not generated")
+ orphans, numbered = [], []
+ for page in sorted((CONTENT / "systems").glob("*.md*")):
+ text = page.read_text(encoding="utf-8")
+ if "Part of " in text and "\nparent:" not in text.split("\n---\n", 1)[0]:
+ orphans.append(page.name)
+ if re.search(r"^title: .*part \d+ of \d+", text, re.M | re.I):
+ numbered.append(page.name)
+ self.assertEqual(orphans, [])
+ self.assertEqual(numbered, [])
+
+ def test_parts_are_even_and_linked_to_their_neighbours(self) -> None:
+ files = [_file(f"rom{i:02}.bin", "0123456789"[i], f"bios/Sony/PlayStation 2/rom{i:02}.bin")
+ for i in range(10)]
+ consumers = _consumers({})
+ with gs.markup.using("mkdocs"):
+ one = sum(len(line) + 1 for line in gs._system_file_card(files[0], consumers))
+ pages = gs.system_pages("Sony", {"PlayStation 2": files}, consumers, budget=one * 7)
+ parts = [stem for stem in pages if stem != "sony"]
+ self.assertEqual(len(parts), 2)
+ counts = [pages[stem][0].count('class="rb-sys-file"') for stem in parts]
+ self.assertEqual(counts, [5, 5])
+ first = pages[parts[0]][0]
+ self.assertIn("parent:\n label: \"Sony\"\n link: \"/systems/sony/\"", first)
+ self.assertIn(f"next:\n label: \"PlayStation 2 files rom05.bin to rom09.bin\"\n"
+ f" link: \"/systems/{parts[1]}/\"", first)
+ self.assertIn("# PlayStation 2 files rom00.bin to rom04.bin", first)
+ self.assertIn(f"searchWeight: {gs._part_weight()}", first)
+
+
+def _consoles(page: str) -> list[str]:
+ """The consoles: front matter of a generated page."""
+ front = page.split("\n---\n", 1)[0] if page.startswith("---\n") else ""
+ block = re.search(r"^consoles:\n((?: - .*\n?)+)", front + "\n", re.M)
+ return [json.loads(line[4:]) for line in block[1].splitlines()] if block else []
+
+
+class ConsolesFieldNamesMachinesOnce(unittest.TestCase):
+ def tearDown(self) -> None:
+ # system_pages records where consoles went, for every later page.
+ gs.reset_console_pages()
+
+ """The consoles search field: only machine sections, and a console
+ with a page of its own is that page's, or "dolphin" found Other and
+ "playstation bios" found Sony before the PlayStation page."""
+
+ def test_no_emulator_folder_is_a_console(self) -> None:
+ for maker in ("Other", "Game Engines"):
+ page = gs.system_pages(maker, {"dolphin": [_file("a.bin", "a")]}, _consumers({}))
+ self.assertEqual(_consoles(page[gs._slug(maker)][0]), [], maker)
+
+ def test_a_console_with_its_own_page_is_left_to_it(self) -> None:
+ big = [_file(f"r{i:02}.bin", "0123456789"[i], f"bios/Sony/PlayStation/r{i:02}.bin")
+ for i in range(10)]
+ small = [_file("pocket.bin", "p", "bios/Sony/PocketStation/pocket.bin")]
+ consumers = _consumers({})
+ with gs.markup.using("mkdocs"):
+ one = sum(len(line) + 1 for line in gs._system_file_card(big[0], consumers))
+ pages = gs.system_pages("Sony", {"PlayStation": big, "PocketStation": small},
+ consumers, budget=one * 12)
+ self.assertIn("sony-playstation", pages)
+ self.assertEqual(_consoles(pages["sony"][0]), ["PocketStation"])
+ self.assertEqual(_consoles(pages["sony-playstation"][0]), ["PlayStation"])
+
+
+class OneLineBeforeTheFirstConsole(unittest.TestCase):
+ """6.8: four paragraphs, word for word on every maker's page."""
+
+ def test_the_intro_is_one_line_and_the_legend_closed(self) -> None:
+ page = gs.generate_system_page("SNK", {"Neo Geo": [_file("a.bin", "a")]}, _consumers({}))
+ body = page.split("# SNK\n", 1)[1]
+ before = body[:body.index("## Neo Geo")]
+ self.assertTrue(before.lstrip().startswith(
+ "Every BIOS file for SNK machines, one card per file.\n"))
+ legend = before[before.index(""):]
+ self.assertIn("How to read a card", legend)
+ self.assertNotIn(" open>", legend)
+ self.assertNotIn("JSON", before)
+ self.assertIn("as JSON](../api/v1/systems/snk.json)", page.split("## Next steps")[1])
+
+
+class SetupsGroupedByPlace(unittest.TestCase):
+ """6.9: each setup repeated the name it gives the file."""
+
+ def test_one_line_per_place(self) -> None:
+ places = [("Batocera", "b.md", ["scph5501.bin"]), ("KNULLI", "k.md", ["scph5501.bin"]),
+ ("RetroDECK", "r.md", ["bios/scph5501.bin"]), ("EmuDeck", "e.md", [])]
+ self.assertEqual(gs._places_lines(places), [
+ "scph5501.bin: [Batocera](b.md), [KNULLI](k.md)",
+ "bios/scph5501.bin: [RetroDECK](r.md)",
+ "[EmuDeck](e.md)",
+ ])
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_site_render.py b/tests/test_site_render.py
index dabf9d9a..28cf2efb 100644
--- a/tests/test_site_render.py
+++ b/tests/test_site_render.py
@@ -160,11 +160,11 @@ class FileCardsLinkTheReadingEntry(unittest.TestCase):
consumers.emulator_entries = {"s": {"duckstation": 1}, "t": {"blastem": 2}}
consumers.emulator_files = {"duckstation": files, "blastem": files}
self.assertEqual(generate_site._emulator_links("s", consumers), [
- "[duckstation](../emulators/duckstation.md#file-scph5501-bin)",
+ "[DuckStation](../emulators/duckstation.md#file-scph5501-bin)",
"[other](../emulators/other.md)",
])
self.assertEqual(generate_site._emulator_links("t", consumers),
- ["[blastem](../emulators/blastem.md#file-tmss-md-d0fd0c16)"])
+ ["[BlastEm](../emulators/blastem.md#file-tmss-md-d0fd0c16)"])
class DirectoryMembersNameTheirEmulator(unittest.TestCase):
@@ -193,7 +193,7 @@ class DirectoryMembersNameTheirEmulator(unittest.TestCase):
index = self.consumers.emulator_entries[self.SHA1]["alephone"]
self.assertEqual(files[index].get("type"), "directory")
self.assertEqual(generate_site._emulator_links(self.SHA1, self.consumers),
- ["[alephone](../emulators/alephone.md#file-marathon-plugins)"])
+ ["[Aleph One](../emulators/alephone.md#file-marathon-plugins)"])
def test_the_directory_card_points_at_its_copies(self):
import generate_site
@@ -360,12 +360,12 @@ class TheSearchSkipsLinkLists(unittest.TestCase):
self.assertIn("a.bin", lines[2])
text = "\n".join(lines)
searched, _sep, skipped = text.partition('')
- for label in ("MD5", "Emulators", "Packed for its emulators by"):
+ for label in ("MD5", "Emulators", "Packed for its emulators by", "On the setup's list"):
self.assertIn(f"- {label}
", skipped)
self.assertNotIn(f">{label}", searched)
- # The platforms line names the file as each setup does: the site
- # search reads it, so a file name finds its card.
- self.assertRegex(searched, r'\n- ]*>On the setup\'s list
')
+ # The card's title is what the search reads (round 4, V6): the setup
+ # list made every excerpt a run of names and paths.
+ self.assertNotIn('', searched)
def test_a_game_data_card_skips_its_name_too(self):
import generate_site
diff --git a/tests/test_site_system_links.py b/tests/test_site_system_links.py
index 33843c44..76521ff3 100644
--- a/tests/test_site_system_links.py
+++ b/tests/test_site_system_links.py
@@ -318,7 +318,11 @@ class EverySystemLinkLandsOnItsSection(unittest.TestCase):
self.assertIn(page, self.headings)
if match["anchor"]:
self.assertIn(match["anchor"], self.headings[page])
- _slug, console = self.siterender.system_section(sys_id)
+ slug, console = self.siterender.system_section(sys_id)
+ # The Arcade folder of sets no board claims is headed by
+ # what it holds, its id staying the folder's.
+ if slug == "arcade":
+ console = gs._section_label("Arcade", console)
self.assertEqual(self.headings[page][match["anchor"]], console)
self.assertGreater(linked, 200)