From b12c0af4b8ab9003fcc9a2837526877dc135e003 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sat, 24 Oct 2026 00:52:33 +0200 Subject: [PATCH 1/4] feat: card computers and retrooz folder in guides --- platforms/_guides.yml | 10 ++++++++++ scripts/siteguides.py | 14 ++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/platforms/_guides.yml b/platforms/_guides.yml index 0cf62299..2730cc33 100644 --- a/platforms/_guides.yml +++ b/platforms/_guides.yml @@ -10,6 +10,7 @@ # `{folders}` in it is the folder list of the page. # `runs_on` names the hardware in the project's own words, cited beside it. # `terminal` is how this system opens a terminal, from its own documentation. +# `card_run` names the computers that open the device's card, when not all do. # `lead` comes before the folder table, `finish` closes the guide. # `logo_owner` and `logo_licence` credit the logo the registry links: it is # shown only to name the platform, with the licence of the repository the @@ -214,7 +215,13 @@ handheld_guide: folder_source: https://github.com/game-de-it/plumOS-XU20V32/blob/main/docs/developer/storage-and-updates.md devices: [MagicX XU20 V32] devices_source: https://github.com/game-de-it/plumOS-XU20V32 + # RetroOZ publishes no build source. Its wiki keeps games under /roms and + # sends BIOS questions to the ArkOS wiki, whose folder is bios in roms. The + # 0.60 image sets system_directory "/roms/bios" (retroarch32/retroarch.cfg:3046). + # Written as the device path: no RetroOZ page names the card's parts. - name: RetroOZ + folder: '`/roms/bios`, as the device names it' + folder_source: https://github.com/southoz/RetroOZ/wiki/Home/4ce4fafb78d647d422e9e468d5bd9cbc63dbe3ea devices: [OGS, OGA, RGB10Max, RGB10Max2] devices_source: https://github.com/southoz/RetroOZ/wiki - name: UnofficialOS @@ -618,6 +625,9 @@ guides: # is the network folder above. terminal: >- Press **F4** in the game menu for a terminal. Paste the line. Press Enter. + # The BIOS folder is on the card's Linux partition (pack_manual below): + # from a computer, only Linux opens it. + card_run: [linux] notes: - >- Install with `--platform retropie`, not RetroArch's files. The command does not run on diff --git a/scripts/siteguides.py b/scripts/siteguides.py index 59c98491..46b59d43 100644 --- a/scripts/siteguides.py +++ b/scripts/siteguides.py @@ -41,7 +41,9 @@ class Guide: README inside the pack. `logo_owner` and `logo_licence` credit the logo the registry links. `runs_on` names the hardware, in the project's own words, for its tile and its row. `terminal` replaces the shared - "On the device" text with how this system opens a terminal. `lead` comes + "On the device" text with how this system opens a terminal. `card_run` + names the computers that can open the BIOS folder on the device's card, + when not every one can. `lead` comes before the folder table, `finish` closes the guide. `{folders}` in `pack_manual` is the folder list of the page, so the README and the page cannot name two folders for one device. @@ -66,6 +68,7 @@ class Guide: terminal: str = "" lead: str = "" finish: str = "" + card_run: tuple[str, ...] = () @dataclass(frozen=True) @@ -180,10 +183,13 @@ def _guide(name: str, data: object, extract_to: str, terminals: dict) -> Guide: if missing: raise GuideError(f"{where}: missing {', '.join(missing)}") run = _texts(data["run"], f"{where}.run") - unknown_tabs = [key for key in run if key not in terminals] - if unknown_tabs: - raise GuideError(f"{where}.run: no terminal named {', '.join(unknown_tabs)}") + card_run = _texts(data["card_run"], f"{where}.card_run") if "card_run" in data else () + for key, tabs in (("run", run), ("card_run", card_run)): + unknown_tabs = [tab for tab in tabs if tab not in terminals] + if unknown_tabs: + raise GuideError(f"{where}.{key}: no terminal named {', '.join(unknown_tabs)}") values: dict = { + "card_run": card_run, "summary": _text(data["summary"], f"{where}.summary"), "folders": _folder_rows(data["folders"], extract_to, f"{where}.folders"), "run": run, From 0695b5404bd3c5209c482a84743060d7e2172bb3 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sat, 24 Oct 2026 00:52:36 +0200 Subject: [PATCH 2/4] feat: setup routes on get pages, card route --- scripts/generate_site.py | 180 +++++++++++++++++++++++++++++++----- tests/test_release_packs.py | 2 +- 2 files changed, 159 insertions(+), 23 deletions(-) diff --git a/scripts/generate_site.py b/scripts/generate_site.py index 2d5a7b57..e9269996 100644 --- a/scripts/generate_site.py +++ b/scripts/generate_site.py @@ -546,7 +546,7 @@ def generate_home( "", *markup.steps([ "**Pick your device.** Its page shows your BIOS folder.", - "**Run one command**, or download a ZIP file.", + "**Run one command.** Some setups have a ZIP.", "**Start a game.**", ]), "## Pick your device", @@ -719,6 +719,45 @@ def get_page_link(platform_name: str, prefix: str = "") -> str: return f"{prefix}{release_record.GET_DIR}/{platform_name}.md" +def get_page_title(platform_name: str, display: str) -> str: + """What a get/ page holds, by its name: the ZIP of a setup a release + publishes one for, the files of any other. "Download KNULLI" read as + the system's own download.""" + return f"{display} BIOS pack" if has_release_pack(platform_name) else f"{display} BIOS files" + + +def _unzip_into(platform_name: str, display: str, extract_to: str | None, parts: int) -> list[str]: + """Where the ZIP is unzipped, on the get/ page. A folder the registry + writes relative to the setup's own (`system/`, `bios/`) is named as the + setup's, with the way to find it.""" + what = "them all" if parts > 1 else "it" + if not _setup_relative(extract_to): + return [f"- Unzip {what} into {_folder_words(display, extract_to)}.", ""] + lead = GUIDES[platform_name].lead if platform_name in GUIDES else "" + return [ + f"- Unzip {what} into {_folder_words(display, extract_to)}. " + f"[Where is it?](../platforms/{platform_name}.md#where-the-files-go)", + "", + *([lead, ""] if lead else []), + ] + + +def _setup_relative(extract_to: str | None) -> bool: + """Whether the registry writes the folder relative to the setup's own + (`system/`, `Firmware/`), not as a path the device reads.""" + return bool(extract_to) and not extract_to.startswith(("/", "~", "<")) + + +def _folder_words(display: str, extract_to: str | None) -> str: + """The folder a pack or a copy goes into, in words: the device's path, + or a folder of the setup named as the setup's.""" + if not extract_to: + return "your BIOS folder" + if _setup_relative(extract_to): + return f"{display}'s `{extract_to.rstrip('/')}` folder" + return f"`{extract_to}`" + + def _pack_buttons(platform_name: str, label: str = "Pack", prefix: str = "../", display: str | None = None) -> str: """The way to the platform's ZIP from its setup page: a button to its @@ -756,7 +795,17 @@ def generate_get_page(platform_name: str) -> str: record = release_record.load_advertised() pack = release_record.pack_for(platform_name, record) released = has_release_pack(platform_name) - lines = ["---", "search: exclude", "---", "", f"# Download {display}", ""] + title = get_page_title(platform_name, display) + if released and pack and pack.get("assets"): + description = (f"The BIOS pack for {display}: {_fmt_size(pack['download_size'])} to " + "download. The address stays the same and always gives the latest ZIP.") + else: + description = f"The BIOS files for {display}: one command installs and checks them." + lines = [ + "---", "search: exclude", f"description: {json.dumps(description)}", + *_parent_front_matter((display, f"/platforms/{platform_name}/")), "---", "", + f"# {title}", "", + ] if released and pack and pack.get("assets"): parts = len(pack["assets"]) release = release_line(platform_name, record) @@ -771,9 +820,7 @@ def generate_get_page(platform_name: str) -> str: f"{_fmt_size(pack['extracted_size'])} once unzipped.", *(["- You need both parts." if parts == 2 else f"- You need all {parts} parts."] if parts > 1 else []), - f"- Unzip {'them all' if parts > 1 else 'it'} into " - + (f"`{extract_to}`." if extract_to else "your BIOS folder."), - "", + *_unzip_into(platform_name, display, extract_to, parts), *(line for text in release for line in (text, "")), version_line(platform_name, record, named=len(release) > 1), "", @@ -783,7 +830,7 @@ def generate_get_page(platform_name: str) -> str: f"No {display} ZIP yet. The next release has one. " "The command installs every file and checks it.", "", - *install_commands(f"--platform {platform_name}"), + *_setup_routes(platform_name, display), ] elif released: lines += [ @@ -796,7 +843,7 @@ def generate_get_page(platform_name: str) -> str: lines += [ no_zip_line(display), "", - *install_commands(f"--platform {platform_name}"), + *_setup_routes(platform_name, display), f"[Why no ZIP?](../{NO_ZIP_FAQ})", "", ] @@ -808,6 +855,29 @@ def generate_get_page(platform_name: str) -> str: return "\n".join(lines) +def generate_get_index() -> str: + """get/: the permanent page of every setup, grouped as the home tiles + are. A link trimmed to /get/ answered 404.""" + registry = load_platform_registry("platforms") + lines = [ + "---", "search: exclude", + 'description: "The BIOS files of every setup, one page each. Each address stays the same."', + "---", "", + "# BIOS files by setup", "", + "One page per setup. Its address stays the same, so it is the one to share.", "", + ] + for group, (label, _description) in DEVICE_GROUPS.items(): + names = [name for name, entry in registry.items() if entry.get("device_group") == group] + if not names: + continue + lines += [f"## {label}", ""] + for name in names: + display = load_platform_config(name, "platforms").get("platform", name) + lines.append(f"- [{get_page_title(name, display)}]({name}.md)") + lines.append("") + return "\n".join(lines) + + # The home tile counts the whole collection. Labelled "Files" above a table # of pack buttons, it read as what one pack contains. COLLECTION_FILES_LABEL = "Files collected" @@ -3520,6 +3590,12 @@ MISSING_IN_PLACE = "Reported missing anyway? `--check` names a wrong file." # page shows in full, so the setup page links it. SAFE_LINK = "[Is it safe?](../index.md#is-it-safe)" +# The pass line of "How to check". `--check` prints "All files up to date." +# only when no file is missing or wrong (install.py, the args.check branch +# after check_local). "0 wrong hash" alone is also what an empty folder +# prints: 0/14508 present (0 verified, 0 wrong hash). +CHECK_PASS_LINE = "All good when it says `All files up to date.`" + # Under "From your computer": a device with no network installs from the ZIP # (`--from-pack`). The id is the one wiki/installer.md gives its section. OFFLINE_LINE = ("No internet on the device? " @@ -3545,6 +3621,71 @@ def _offline_line(name: str) -> list[str]: return [OFFLINE_LINE, ""] if pack and pack.get("assets") else [] +# The route of a setup with no ZIP when the device has no network: the +# command writes to any folder named after --dest (wiki/installer.md), so a +# computer fills the device's card. The FAQ answers it with an example. +CARD_ROUTE_FAQ = "wiki/faq.md#fill-an-sd-card-from-a-computer" + + +def _card_route(name: str, display: str, guide: Guide) -> list[str]: + """The route with no network on the device, for a setup whose ZIP no + release publishes: the command run on a computer, into the card. A + setup with a ZIP has the offline line, a card setup's command already + runs on the computer. The folder named after --dest is the one the + command fills on the device (the registry's extract_to): AmberELEC's is + `/storage/roms/`, which holds `bios/` and `neogeo/`. How a computer + sees it is the reader's to name: no guide cites it.""" + if guide.on_card or _offline_line(name): + return [] + extract_to = (load_platform_registry("platforms").get(name) or {}).get("extract_to") + leaf = (extract_to or "bios").rstrip("/").rsplit("/", 1)[-1].lstrip("~") or "bios" + tabs = guide.card_run or ("windows", "macos", "linux") + args = {key: f"--platform {name} --dest " + + (f"E:\\path\\to\\{leaf}" if key == "windows" else f"/path/to/{leaf}") + for key in tabs} + if guide.run != ("device",): + lead = ("No network here? Run the command on a computer that has one, with a USB " + f"drive's folder after `--dest`. Then copy it into {_folder_words(display, extract_to)}.") + return [lead, "", *terminal_tabs(tabs, args, steps=False)] + lead = ("No network? Put the device's card in your computer. After `--dest`, " + f"name the folder the device calls `{extract_to}`.") + return [lead, "", *terminal_tabs(tabs, args, steps=False), + f"[More on SD cards](../{CARD_ROUTE_FAQ})", ""] + + +def _get_page_line(name: str, display: str) -> list[str]: + """The setup's get/ page, under the command of a setup with no ZIP: the + address a guide writer keeps. A setup with a ZIP links it by its button.""" + if has_release_pack(name): + return [] + return [f"Link to share: [{get_page_title(name, display)}](../{get_page_link(name)})", ""] + + +def _setup_routes(name: str, display: str, page_link: bool = False) -> list[str]: + """The ways to run the command for a setup no ZIP serves first, written + once for its setup page and its get/ page: the network folder from a + computer, the card from a computer when the device has no network, and + the device's own terminal. *page_link* adds the get/ page, on the setup + page only.""" + guide = GUIDES[name] + share = _network_share(name, guide) + card = _card_route(name, display, guide) + shared = _get_page_line(name, display) if page_link else [] + if share or (card and guide.run == ("device",)): + computer = ["## From your computer { #from-your-computer }", ""] + if share: + computer += [ + "Needs the device on your network. Run the command on the computer.", + "", + *terminal_tabs(("windows",), {"windows": f"--platform {name} --dest {share}"}), + SAFE_LINK, + "", + ] + return [*computer, *card, + *_guide_install(name, guide, "## On the device { #install }"), *shared] + return [*_guide_install(name, guide, "## Install"), *shared, *card] + + # Shown in the "On the device" tab of a guide that has no `terminal:` of its own. DEVICE_TERMINAL_FALLBACK = "Or fill the folder from your computer, with the ZIP." @@ -3755,7 +3896,6 @@ def _platform_guide(name: str, display: str, cov: dict, registry: dict, no_list: ]) if guide.on_card: lines += ["", ""] - share = _network_share(name, guide) if _computer_first(name, guide): lines += [ *_guide_download(name, display, guide, extract_to, @@ -3763,21 +3903,9 @@ def _platform_guide(name: str, display: str, cov: dict, registry: dict, no_list: *_offline_line(name), *_guide_install(name, guide, "## On the device { #install }"), ] - elif share: - lines += [ - "## From your computer { #from-your-computer }", - "", - "Needs the device on your network. Run the command on the computer.", - "", - *terminal_tabs(("windows",), {"windows": f"--platform {name} --dest {share}"}), - SAFE_LINK, - "", - *_guide_install(name, guide, "## On the device { #install }"), - *_guide_download(name, display, guide, extract_to, "## Download"), - ] else: lines += [ - *_guide_install(name, guide, "## Install"), + *_setup_routes(name, display, page_link=True), *_guide_download(name, display, guide, extract_to, "## Download"), *_offline_line(name), ] @@ -3788,7 +3916,7 @@ def _platform_guide(name: str, display: str, cov: dict, registry: dict, no_list: "Add `--check` to the command. It changes nothing.", "", *terminal_tabs(guide.run, check_args, steps=False), - "All good when you see `0 wrong hash`.", + CHECK_PASS_LINE, "", _check_sentence(display, cov["mode"], cov["config"], no_list), "", @@ -9573,6 +9701,9 @@ IOS_SOURCES = { "provenance": "https://wiki.provenance-emu.com/using-provenance/importing-roms", } IOS_DEVICES = ("iPhone", "iPad", "iOS", "Delta", "Provenance") +# The same names as which-pack's search terms, the section's meta field +# alone leaving "ios" unanswered. +IOS_TERMS = tuple(name.lower() for name in IOS_DEVICES) def ios_section() -> list[str]: @@ -9609,6 +9740,10 @@ def generate_which_pack() -> str: display = {key: load_platform_config(key, "platforms").get("platform", key) for key in registry} all_tabs = ("windows", "macos", "linux", "steamdeck", "android") lines = [ + "---", + f"terms: {', '.join(IOS_TERMS)}", + "---", + "", "# Get your files", "", "Pick your setup. Its page gives the folder and the command.", @@ -10294,6 +10429,7 @@ def _generate(args: argparse.Namespace) -> None: get_dir.mkdir(parents=True, exist_ok=True) for name in platform_names: write_if_changed(str(get_dir / f"{name}.md"), generate_get_page(name)) + write_if_changed(str(get_dir / "index.md"), generate_get_index()) print("Generating contributing page...") write_if_changed(str(docs / "contributing.md"), generate_contributing()) diff --git a/tests/test_release_packs.py b/tests/test_release_packs.py index 95618067..4b73d9eb 100644 --- a/tests/test_release_packs.py +++ b/tests/test_release_packs.py @@ -314,7 +314,7 @@ class EveryPlatformHasAPermanentPage(unittest.TestCase): page = generate_site.generate_get_page(name) pack = release_record.pack_for(name, record) with self.subTest(platform=name): - self.assertIn("# Download ", page) + self.assertRegex(page, r"\n# .+ BIOS (pack|files)\n") if name in RELEASED and pack: for asset in pack["assets"]: self.assertIn( From 00649d0377e597fb6f292a95a94a0a0915f0a2c5 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sat, 24 Oct 2026 00:52:36 +0200 Subject: [PATCH 3/4] chore: tests for the round 5 entry pages --- tests/test_site_r5_entry.py | 235 ++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 tests/test_site_r5_entry.py diff --git a/tests/test_site_r5_entry.py b/tests/test_site_r5_entry.py new file mode 100644 index 00000000..c59f4783 --- /dev/null +++ b/tests/test_site_r5_entry.py @@ -0,0 +1,235 @@ +"""Entry pages, get/ and guides (round 5, package 4). + +The get/ page of a setup with no ZIP printed one command for three +systems, with no --dest, so it failed on the computer most readers open +it on. "All good when you see 0 wrong hash" was also what an empty folder +prints. Setups with no ZIP lost every route that works without a network. +The get/ pages were titled "Download KNULLI", /get/ answered 404, and two +Linux handheld rows sent the reader to a menu. +""" + +from __future__ import annotations + +import re +import sys +import unittest +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(REPO_ROOT / "scripts")) +sys.path.insert(0, str(REPO_ROOT)) + +import generate_site # noqa: E402 +import release_record # noqa: E402 +import siteguides # noqa: E402 +from common import load_platform_config, load_platform_registry # noqa: E402 +from tests import sitepages # noqa: E402 + +REGISTRY = load_platform_registry(str(REPO_ROOT / "platforms")) +SETUPS = [name for name in siteguides.GUIDES if name in REGISTRY] +COMMAND = re.compile(r"^(?:curl -fsSL |&\(\[scriptblock\]|irm ).*$", re.M) +OFFLINE_ANCHOR = "#without-a-network-offline-install" +CARD_FAQ = "/retrobios/wiki/faq/#fill-an-sd-card-from-a-computer" + + +def _page(name: str) -> str: + sitepages.require() + return re.sub(r"]*>", "", sitepages.page(name).read_text(encoding="utf-8")) + + +def _guide_part(text: str) -> str: + match = re.search(r"^## Reference\b", text, re.M) + return text[: match.start()] if match else text + + +def _with_zip(name: str) -> bool: + pack = release_record.pack_for(name, release_record.load_advertised()) + return bool(pack and pack.get("assets")) + + +def _display(name: str) -> str: + return load_platform_config(name, str(REPO_ROOT / "platforms")).get("platform", name) + + +def _tab_labels(text: str) -> set[str]: + return set(re.findall(r' Directory > System/BIOS**", text) + self.assertIn("into RetroBat's `bios` folder", _page("get/retrobat.md")) + self.assertNotIn("into `system/`", text) + + +class HandheldRowsSayWhere(unittest.TestCase): + def test_retrooz_names_its_folder_with_a_pinned_source(self): + system = next(s for s in siteguides.HANDHELD_GUIDE.systems if s.name == "RetroOZ") + self.assertIn("`/roms/bios`", system.folder) + self.assertRegex(system.folder_source, r"/wiki/Home/[0-9a-f]{40}$") + row = next(line for line in _page("platforms/linux-handhelds.md").splitlines() + if line.startswith("| RetroOZ |")) + self.assertNotIn(generate_site.RETROARCH_FOLDER_SETTING, row) + + +class GetIndex(unittest.TestCase): + def test_every_setup_is_linked_under_its_group(self): + text = _page("get/index.md") + for name in SETUPS: + with self.subTest(setup=name): + self.assertIn(f"(/retrobios/get/{name}/)", text) + for label, _description in siteguides.DEVICE_GROUPS.values(): + self.assertIn(f"## {label}", text) + + +class HomeAndWhichPack(unittest.TestCase): + def test_the_home_step_does_not_promise_a_zip(self): + text = _page("index.md") + self.assertIn("**Run one command.** Some setups have a ZIP.", text) + self.assertNotIn("or download a ZIP file", text) + + def test_which_pack_answers_ios(self): + text = _page("which-pack.md") + meta = re.search(r'data-pagefind-meta="terms:([^"]+)"', text) + self.assertIsNotNone(meta) + for word in ("ios", "iphone", "ipad", "delta", "provenance"): + self.assertIn(word, meta[1].split()) + + +if __name__ == "__main__": + unittest.main() From 33c2c64c0caef298e14a4d90713beb44c98e185b Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sat, 24 Oct 2026 00:54:00 +0200 Subject: [PATCH 4/4] fix: keep the bizhawk get title unique --- scripts/generate_site.py | 8 ++++++-- tests/test_release_packs.py | 2 +- tests/test_site_r5_entry.py | 9 +++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/scripts/generate_site.py b/scripts/generate_site.py index e9269996..5e110168 100644 --- a/scripts/generate_site.py +++ b/scripts/generate_site.py @@ -722,8 +722,12 @@ def get_page_link(platform_name: str, prefix: str = "") -> str: def get_page_title(platform_name: str, display: str) -> str: """What a get/ page holds, by its name: the ZIP of a setup a release publishes one for, the files of any other. "Download KNULLI" read as - the system's own download.""" - return f"{display} BIOS pack" if has_release_pack(platform_name) else f"{display} BIOS files" + the system's own download. A setup that is also an emulator (BizHawk) + names it last: "BizHawk BIOS files" is the title of its emulator page.""" + kind = "BIOS pack" if has_release_pack(platform_name) else "BIOS files" + if (_REPO_ROOT / "emulators" / f"{platform_name}.yml").is_file(): + return f"{kind} for {display}" + return f"{display} {kind}" def _unzip_into(platform_name: str, display: str, extract_to: str | None, parts: int) -> list[str]: diff --git a/tests/test_release_packs.py b/tests/test_release_packs.py index 4b73d9eb..a403d2f7 100644 --- a/tests/test_release_packs.py +++ b/tests/test_release_packs.py @@ -314,7 +314,7 @@ class EveryPlatformHasAPermanentPage(unittest.TestCase): page = generate_site.generate_get_page(name) pack = release_record.pack_for(name, record) with self.subTest(platform=name): - self.assertRegex(page, r"\n# .+ BIOS (pack|files)\n") + self.assertRegex(page, r"\n# (.+ )?BIOS (pack|files)( for .+)?\n") if name in RELEASED and pack: for asset in pack["assets"]: self.assertIn( diff --git a/tests/test_site_r5_entry.py b/tests/test_site_r5_entry.py index c59f4783..c4df0ac7 100644 --- a/tests/test_site_r5_entry.py +++ b/tests/test_site_r5_entry.py @@ -171,8 +171,12 @@ class GetPagesSayWhatTheyHold(unittest.TestCase): display = _display(name) text = sitepages.page(f"get/{name}.md").read_text(encoding="utf-8") kind = "pack" if REGISTRY[name].get("release_pack") is True else "files" + title = (f"BIOS {kind} for {display}" + if (REPO_ROOT / "emulators" / f"{name}.yml").is_file() + else f"{display} BIOS {kind}") with self.subTest(setup=name): - self.assertIn(f"title: {display} BIOS {kind}\n", text) + self.assertEqual(generate_site.get_page_title(name, display), title) + self.assertIn(f"title: {title}\n", text) self.assertNotIn("Download ", text.split("\n---\n", 1)[0].split("title:", 1)[1] .split("\n", 1)[0]) self.assertIn(f"link: /platforms/{name}/", text) @@ -185,7 +189,8 @@ class GetPagesSayWhatTheyHold(unittest.TestCase): if REGISTRY[name].get("release_pack") is True: continue with self.subTest(setup=name): - self.assertIn(f"Link to share: [{_display(name)} BIOS files](/retrobios/get/{name}/)", + title = generate_site.get_page_title(name, _display(name)) + self.assertIn(f"Link to share: [{title}](/retrobios/get/{name}/)", _page(f"platforms/{name}.md")) def test_a_relative_folder_is_named_as_the_setups(self):