Review can search a chosen database: BGG or RPGGeek, by hand

The automatic cascade only reaches RPGGeek when BGG's board-game search
comes up empty — so every D&D box, which BGG does list as board games,
can never find its RPGGeek entry no matter how many times it is
reopened. Eric hit exactly that and settled for keeping them local.

Match cards now carry an editable query with two buttons, "search BGG"
and "search RPGGeek", which replace the row's ballot with whatever the
chosen database returns (owned counts and ranks attached when
available; if that stats call fails the results still stand and the
degradation is reported). The TUI's (f) re-search falls back to
RPGGeek automatically when the board-game search is empty.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016jXZFSTZQKzAC8fqpWSz9g
This commit is contained in:
Eric Wagoner
2026-08-05 23:58:58 -04:00
co-authored by Claude Fable 5
parent 50a710ce99
commit 9663f29702
6 changed files with 123 additions and 6 deletions
+27
View File
@@ -671,3 +671,30 @@ def test_local_rows_can_be_looked_up_again_on_rpggeek(tmp_path):
candidates = json.loads(row["candidates_json"])
assert any(c["type"] == "rpgitem" for c in candidates)
assert any("Alice is Missing" in c["name"] for c in candidates)
def test_research_can_target_rpggeek_explicitly(tmp_path):
"""BGG has board games called "Dungeons & Dragons", so the automatic
cascade never reaches RPGGeek for them — only an explicit search can."""
cfg = _setup(tmp_path, [_row(title_raw="Wingspan", match_status="unmatched")])
session = ReviewSession(
cfg, console=quiet_console(), input_fn=scripted(), client=fixture_client()
)
row = session.rows[0]
# cached search, but the stats batch for these results was never
# recorded: losing the decoration must not lose the search
session.client = BGGClient(
cache_dir=FIXTURES,
transport=httpx.MockTransport(
lambda req: httpx.Response(401, text="Unauthorized")
),
)
found = session.research(row, "Citadels")
assert found and row["match_status"] == "ambiguous"
ids = {c["bgg_id"] for c in json.loads(row["candidates_json"])}
assert {478, 205398} <= ids
assert session.warnings # the missing stats are reported, not swallowed
# a fresh ballot supersedes the previous verdict
assert row["bgg_id"] == ""
with pytest.raises(ValueError, match="needs some text"):
session.research(row, " ")