"""Pages a phone can open: split pages, light navigation, short tables of contents. systems/game-engines/ was one 10.5 MB page, emulators/mame/ 3 MB, and each of 600 emulator pages carried 65 KB of navigation. A large page is now a summary with pages of its own, and every address cited before the split still lands: a console's heading stays on the summary, a card's sha1 anchor is looked up by content, an emulator card's anchor sits on its row. """ from __future__ import annotations import sys import unittest from pathlib import Path from types import SimpleNamespace REPO_ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(REPO_ROOT / "scripts")) import generate_site # noqa: E402 import sitestarlight # noqa: E402 import siterender # noqa: E402 import sitemarkup as markup # noqa: E402 from cross_reference import FileConsumers # noqa: E402 def _file(name: str, index: int, console: str, maker: str = "Maker") -> dict: sha1 = f"{index:012x}" + "0" * 28 return {"name": name, "sha1": sha1, "md5": f"{index:032x}", "size": 10, "path": f"bios/{maker}/{console}/{name}"} class ASystemPageOverItsBudgetIsSplit(unittest.TestCase): def setUp(self) -> None: siterender.reset_console_pages() self.addCleanup(siterender.reset_console_pages) self.consoles = { "Big": [_file(f"big{i:03d}.bin", i, "Big") for i in range(60)], "Small": [_file("small.bin", 900, "Small")], } def _pages(self, budget: int) -> dict: return generate_site.system_pages( "Maker", self.consoles, FileConsumers({"files": {}}), budget=budget) def test_a_page_within_its_budget_stays_whole(self): pages = self._pages(10_000_000) self.assertEqual(list(pages), ["maker"]) self.assertIn("## Big", pages["maker"][0]) def test_the_largest_section_moves_and_is_cut_in_parts(self): pages = self._pages(20_000) summary = pages["maker"][0] # Both headings stay on the summary: systems/maker/#big still lands. self.assertIn("## Big", summary) self.assertIn("## Small", summary) # The small section keeps its cards in place. self.assertIn('id="sha1-' + f"{900:012x}", summary) parts = [stem for stem in pages if stem.startswith("maker-big")] self.assertGreater(len(parts), 1) self.assertEqual(parts[0], "maker-big") for stem in parts: self.assertIn(f"]({stem}.md)", summary) self.assertLessEqual(len(pages[stem][0]), 20_000 + 5_000) self.assertIn("## Files", pages[stem][0]) # Each card is on exactly one part, and the links follow it. held = [f["sha1"] for stem in parts for f in pages[stem][1]["Big"]] self.assertEqual(sorted(held), sorted(f["sha1"] for f in self.consoles["Big"])) last = self.consoles["Big"][-1] self.assertEqual(siterender.card_page(last["path"], last["sha1"]), parts[-1]) small = self.consoles["Small"][0] self.assertEqual(siterender.card_page(small["path"], small["sha1"]), "maker") self.assertEqual(siterender.console_href("maker", "Big"), "systems/maker.md#big") def test_a_console_on_one_page_is_linked_directly(self): self.consoles["Big"] = self.consoles["Big"][:12] # The budget is measured in the Markdown it was set on. with markup.using("mkdocs"): whole = self._pages(10**9)["maker"][0] pages = self._pages(len(whole) - 1) self.assertIn("maker-big", pages) self.assertNotIn("maker-big-2", pages) self.assertEqual(siterender.console_href("maker", "Big", "../"), "../systems/maker-big.md") class AnEmulatorWithTooManyCardsIsSplit(unittest.TestCase): def test_parts_are_balanced_and_rows_keep_the_anchors(self): files = [{"name": f"set{i:04d}.zip", "required": i % 2 == 0, "category": "bios_zip"} for i in range(generate_site.EMULATOR_CARDS_PER_PAGE * 2 + 1)] parts = generate_site.emulator_parts("big", files) self.assertEqual([stem for stem, _ in parts], ["big-files-1", "big-files-2", "big-files-3"]) sizes = [len(entries) for _, entries in parts] self.assertLessEqual(max(sizes) - min(sizes), 1) self.assertEqual(generate_site.emulator_parts("small", files[:3]), []) pages = generate_site.emulator_pages( "big", {"emulator": "Big", "type": "standalone", "files": files}, {"files": {}}) self.assertEqual(sorted(pages), ["big", "big-files-1", "big-files-2", "big-files-3"]) main = pages["big"] anchors = generate_site.emulator_file_anchors(files) for anchor in anchors: self.assertIn(f'