"""Long lists read as a table first, details on demand (density round). MAME's card pages read 13,000 to 16,700 words, card after card, and GroovyMAME 14,400 before its last entry. The TOSEC wanted list was 46 closed blocks, one per DAT, opened one by one to find a name. Each entry is now a table row that opens to its card, and each wanted list one filtered table under its counts. Nothing the pages said is lost: the tests below read every name and hash back. """ from __future__ import annotations import re import sys import unittest from html.parser import HTMLParser from pathlib import Path import yaml REPO_ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(REPO_ROOT / "scripts")) import generate_site as gs # noqa: E402 import siteentries # noqa: E402 import validate_site # noqa: E402 EMPTY_DB = {"files": {}, "indexes": {"by_name": {}}} DIST = REPO_ROOT / "website" / "dist" def _archive(i: int, members: int = 3, **fields: object) -> dict: return { "name": f"set{i:04d}.zip", "required": True, "category": "bios_zip", "contents": [{"name": f"m{i}_{k}.rom", "size": 1024, "crc32": f"{i:04x}{k:04x}", "sha1": f"{i:04x}{k:04x}" * 5} for k in range(members)], **fields, } class TheEntryTable(unittest.TestCase): def _rows(self, count: int) -> list[siteentries.Row]: return [siteentries.Row(f'
{i}"])
for i in range(count)]
def test_a_long_table_has_its_filter_box_and_stacks(self):
lines = siteentries.entry_table(self._rows(25), gs.ENTRY_HEADS, "rb-entry-filter-x", "Required")
text = "\n".join(lines)
self.assertRegex(text, r'| File | Contents | ' 'Hash | ', text) self.assertNotIn("Status", text) self.assertEqual(text.count('1 | ', lines) def test_a_card_loses_only_its_wrapper(self): card = ['
|---|
| "), 31) for entry in self.missing: self.assertIn(f" | |
| {entry['name']} | ", self.page) self.assertIn(f'{entry["sha1"]} | ', self.page) self.assertIn("Sony - PlayStation 2 - BIOS Images, Nintendo - GameCube - BIOS Images", self.page) self.assertNotIn("made.bin", self.page) class TheBrowserSide(unittest.TestCase): CSS = (REPO_ROOT / "website" / "src" / "styles" / "retrobios.css").read_text(encoding="utf-8") TS = (REPO_ROOT / "website" / "src" / "scripts" / "site.ts").read_text(encoding="utf-8") def test_a_filtered_row_stays_hidden_on_a_phone(self): # A stacked row is `display: block`, which outweighed `hidden`. self.assertIn(".sl-markdown-content table[data-rb-stack] tr[hidden] { display: none; }", self.CSS) def test_a_box_above_a_closed_block_opens_it(self): self.assertIn("block?.previousElementSibling?.matches('.rb-table-filter')", self.TS) self.assertIn("if (block && query) block.open = true;", self.TS) def test_a_link_to_a_folded_card_opens_its_row(self): start = self.TS.index("const openTargetBlock = () =>") body = self.TS[start:self.TS.index("};", start)] self.assertIn("closest('details')", body) self.assertIn("block.open = true;", body) self.assertIn("addEventListener('hashchange', openTargetBlock);", self.TS) def test_an_open_card_takes_the_table_width(self): self.assertIn(".sl-markdown-content .rb-entries-wrap { container-type: inline-size; }", self.CSS) self.assertIn("details.rb-entry[open] > :not(summary) { width: 100cqi; }", self.CSS) class _Visible(HTMLParser): """Words in