Updates go through the collection cell: collid- and version_id-exact

The last unverified flow failed on its guess — the collection row has no
link named "own"; the edit affordances are icon anchors with no text. The
site offers something far better, now verified: the row's VERSION CELL
carries its own collid in an onclick, and the inline editor it opens is a
radio list whose values ARE version ids.

So an update addresses the copy by collid and the edition by version id —
no name matching, no pagination, no dialog, and structurally incapable of
creating a duplicate entry (it sets one field on one collid). Clicking
the radio fires CE_SaveData itself; there is no Save button, and the save
has landed when the cell stops reading "Editing". A version id the editor
doesn't offer aborts with the entry untouched.

The class docstring's UNVERIFIED list is now empty but for the
second-copy add, which --verify already reports as a copy-count
shortfall.

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:15:39 -04:00
co-authored by Claude Fable 5
parent 74ecd5059b
commit 0af9ae86c5
6 changed files with 122 additions and 86 deletions
-63
View File
@@ -1,64 +1 @@
bgg_id,bgg_name,year,type,version_id,version_name,title_raw,source_photos,second_copy
334011,A Gentle Rain,2021,boardgame,701315,English Bloom edition,a Gentle Rain,IMG_4501.jpeg;IMG_4507.jpeg,
589,Wiz-War,1983,boardgame,27352,Chessex sixth edition,Wiz-War,IMG_4502.jpeg,
125921,Catan: Junior,2012,boardgame,476263,English third edition,CATAN JUNIOR,IMG_4516.jpeg,
31260,Agricola,2007,boardgame,297589,Z-Man Games English fifth edition,AGRICOLA,IMG_4518.jpeg,
181304,Mysterium,2015,boardgame,536289,English edition 2018-2,MYSTERIUM,IMG_4520.jpeg,
312786,Poetry for Neanderthals,2020,boardgame,514050,English edition 2020,Poetry for Neanderthals,IMG_4526.jpeg,
273240,The Red Dragon Inn Smorgasbox,2019,boardgame,446069,Kickstarter edition,The Red Dragon Inn: Smorgasbox,IMG_4527.jpeg,
419687,Munchkin Big Box,2025,boardgame,711400,English edition,Munchkin Big Box,IMG_4530.jpeg,
252153,Tang Garden,2019,boardgame,404702,English edition,Tang Garden,IMG_4533.jpeg,
255984,Sleeping Gods,2021,boardgame,701034,English Gamefound edition,Sleeping Gods,IMG_4534.jpeg,
283766,Sleeping Gods: Tides of Ruin,2021,boardgame,463140,English edition,Sleeping Gods: Tides of Ruin,IMG_4534.jpeg,
280794,Etherfields,2020,boardgame,458300,English edition,ETHERFIELDS,IMG_4535.jpeg,
380837,Botany,2024,boardgame,650545,English edition,BOTANY,IMG_4536.jpeg,
393672,Gloomhaven: Buttons & Bugs,2024,boardgame,669782,English edition,GLOOMHAVEN Buttons & Bugs,IMG_4537.jpeg,
14535,SPANC: Space Pirate Amazon Ninja Catgirls,2005,boardgame,29075,English first edition,SPANC Space Pirate Amazon Ninja Catgirls,IMG_4537.jpeg,
9666,Greed Quest,2004,boardgame,215137,English edition,Greed Quest,IMG_4537.jpeg,
40508,Scrabble Slam!,2008,boardgame,644326,English edition with Hasbro logo,SCRABBLE SLAM!,IMG_4543.jpeg,
3181,Farkle,1930,boardgame,87931,Legendary Games cannister edition,POCKET FARKEL,IMG_4545.jpeg,
193485,Dastardly Dirigibles,2016,boardgame,300446,English edition,Dastardly Dirigibles,IMG_4548.jpeg,
226065,Sheriff of Nottingham: Merry Men,2017,boardgame,353389,English edition,SHERIFF OF NOTTINGHAM MERRY MEN,IMG_4550.jpeg,
143884,Machi Koro,2012,boardgame,453051,"English fifth anniversary edition, first printing",MACHI KORO,IMG_4551.jpeg,
358880,Etherfields: Kittenburg Expansion,2022,boardgame,603694,English edition,ETHERFIELDS KITTENBURG EXPANSION,IMG_4570.jpeg,
432858,Artistry,2025,boardgame,734890,English edition,ARTISTRY,IMG_4515.jpeg,
417060,Botany: Tantalizing Trees,2024,boardgameexpansion,706506,English edition,BOTANY: TANTALIZING TREES,IMG_4571.jpeg,
417064,Botany: Perilous Perfumes,2024,boardgameexpansion,706510,English edition,BOTANY: PERILOUS PERFUMES,IMG_4571.jpeg,
161928,Utter Nonsense,2014,boardgame,,,Utter Nonsense!,IMG_4501.jpeg;IMG_4507.jpeg;IMG_4556.jpeg,
50381,Cards Against Humanity,2009,boardgame,,,Cards Against Humanity,IMG_4501.jpeg;IMG_4556.jpeg,
1269,Skip-Bo,1967,boardgame,,,SKIP-BO,IMG_4501.jpeg;IMG_4542.jpeg,
202982,Scrawl,2016,boardgame,,,SCRAWL,IMG_4502.jpeg,
195314,Herbaceous,2017,boardgame,,,Herbaceous,IMG_4507.jpeg,
320202,Dragon Land,2020,boardgame,,,Dragon Land,IMG_4508.jpeg;IMG_4542.jpeg,
2452,Jenga,1983,boardgame,,,Jenga,IMG_4509.jpeg,
42063,Code Master,1997,boardgame,,,CODE MASTER,IMG_4510.jpeg,
340420,Throw Throw Avocado,2021,boardgame,,,THROW THROW AVOCADO,IMG_4511.jpeg,
1260,Rook,1906,boardgame,,,ROOK,IMG_4511.jpeg,
116,Guillotine,1998,boardgame,,,Guillotine,IMG_4512.jpeg,
169124,Flick 'em Up!,2015,boardgame,,,Flick'em UP!,IMG_4513.jpeg,
20866,The Rocky Horror Trivia Game,2005,boardgame,,,The Rocky Horror Trivia Game,IMG_4514.jpeg,
269564,Captain Marvel: Secret Skrulls,2019,boardgame,,,CAPTAIN MARVEL SECRET SKRULLS,IMG_4516.jpeg,
18755,Pie Face!,1964,boardgame,,,Pie Face!,IMG_4517.jpeg,
140509,Dungeons & Dragons,1985,boardgame,,,DUNGEONS & DRAGONS,IMG_4519.jpeg,
201248,Evolution: The Beginning,2016,boardgame,,,evolution The Beginning,IMG_4520.jpeg,
362205,Sleeping Gods: Primeval Peril,2023,boardgame,,,Sleeping Gods PRIMEVAL PERIL,IMG_4521.jpeg,
453845,Murder at the Manor,2021,boardgame,,,Murder at the Manor,IMG_4522.jpeg,
329230,Bluffaneer,2021,boardgame,,,Bluffaneer,IMG_4522.jpeg,
358320,Sleeping Gods: Distant Skies,2023,boardgame,,,Sleeping Gods DISTANT SKIES,IMG_4523.jpeg,
389113,Rivals,2025,boardgame,,,THE RIVALS FOR CATAN CARD GAME,IMG_4523.jpeg,
324937,Wiz-War (9th Edition),2023,boardgame,,,WIZ-WAR,IMG_4528.jpeg,
295770,Frosthaven,2022,boardgame,,,FROSTHAVEN,IMG_4531.jpeg,
174430,Gloomhaven,2017,boardgame,,,GLOOMHAVEN,IMG_4532.jpeg,
442312,Deadly Doodles,2025,boardgame,,,DEADLY DOODLES,IMG_4533.jpeg,
332398,Everdell: The Complete Collection,2022,boardgame,,,Everdell The Complete Collection,IMG_4533.jpeg,
334065,Verdant,2022,boardgame,,,Verdant,IMG_4534.jpeg,
283155,Calico,2020,boardgame,,,Calico,IMG_4534.jpeg,
291457,Gloomhaven: Jaws of the Lion,2020,boardgame,,,GLOOMHAVEN - Jaws of the Lion,IMG_4538.jpeg,
150925,Hold Your Breath!,2014,boardgame,,,Hold your Breath!,IMG_4547.jpeg,
2980,The Simpsons Trivia Game,2000,boardgame,,,The Simpsons Trivia Game,shelf-20260803-213735.jpg,
1197,Blink,1995,boardgame,,,BLINK,shelf-20260803-215650.jpg,
352819,The Office Trivia Game,2019,boardgame,,,The Office Trivia Game,shelf-20260803-215703.jpg,
163412,Patchwork,2014,boardgame,,,Patchwork,IMG_4501.jpeg,
291847,Mantis Falls,2021,boardgame,,,MANTIS FALLS,IMG_4505.jpeg,
2058,Civilization: West Extension Map,1986,boardgameexpansion,,,Civilization: West Extension Map,,
452833,Artistry: Delightful Doorways Mini Expansion,2025,boardgameexpansion,,,Artistry: Delightful Doorways Mini Expansion,,
1 bgg_id bgg_name year type version_id version_name title_raw source_photos second_copy
334011 A Gentle Rain 2021 boardgame 701315 English Bloom edition a Gentle Rain IMG_4501.jpeg;IMG_4507.jpeg
589 Wiz-War 1983 boardgame 27352 Chessex sixth edition Wiz-War IMG_4502.jpeg
125921 Catan: Junior 2012 boardgame 476263 English third edition CATAN JUNIOR IMG_4516.jpeg
31260 Agricola 2007 boardgame 297589 Z-Man Games English fifth edition AGRICOLA IMG_4518.jpeg
181304 Mysterium 2015 boardgame 536289 English edition 2018-2 MYSTERIUM IMG_4520.jpeg
312786 Poetry for Neanderthals 2020 boardgame 514050 English edition 2020 Poetry for Neanderthals IMG_4526.jpeg
273240 The Red Dragon Inn Smorgasbox 2019 boardgame 446069 Kickstarter edition The Red Dragon Inn: Smorgasbox IMG_4527.jpeg
419687 Munchkin Big Box 2025 boardgame 711400 English edition Munchkin Big Box IMG_4530.jpeg
252153 Tang Garden 2019 boardgame 404702 English edition Tang Garden IMG_4533.jpeg
255984 Sleeping Gods 2021 boardgame 701034 English Gamefound edition Sleeping Gods IMG_4534.jpeg
283766 Sleeping Gods: Tides of Ruin 2021 boardgame 463140 English edition Sleeping Gods: Tides of Ruin IMG_4534.jpeg
280794 Etherfields 2020 boardgame 458300 English edition ETHERFIELDS IMG_4535.jpeg
380837 Botany 2024 boardgame 650545 English edition BOTANY IMG_4536.jpeg
393672 Gloomhaven: Buttons & Bugs 2024 boardgame 669782 English edition GLOOMHAVEN Buttons & Bugs IMG_4537.jpeg
14535 SPANC: Space Pirate Amazon Ninja Catgirls 2005 boardgame 29075 English first edition SPANC Space Pirate Amazon Ninja Catgirls IMG_4537.jpeg
9666 Greed Quest 2004 boardgame 215137 English edition Greed Quest IMG_4537.jpeg
40508 Scrabble Slam! 2008 boardgame 644326 English edition with Hasbro logo SCRABBLE SLAM! IMG_4543.jpeg
3181 Farkle 1930 boardgame 87931 Legendary Games cannister edition POCKET FARKEL IMG_4545.jpeg
193485 Dastardly Dirigibles 2016 boardgame 300446 English edition Dastardly Dirigibles IMG_4548.jpeg
226065 Sheriff of Nottingham: Merry Men 2017 boardgame 353389 English edition SHERIFF OF NOTTINGHAM MERRY MEN IMG_4550.jpeg
143884 Machi Koro 2012 boardgame 453051 English fifth anniversary edition, first printing MACHI KORO IMG_4551.jpeg
358880 Etherfields: Kittenburg Expansion 2022 boardgame 603694 English edition ETHERFIELDS KITTENBURG EXPANSION IMG_4570.jpeg
432858 Artistry 2025 boardgame 734890 English edition ARTISTRY IMG_4515.jpeg
417060 Botany: Tantalizing Trees 2024 boardgameexpansion 706506 English edition BOTANY: TANTALIZING TREES IMG_4571.jpeg
417064 Botany: Perilous Perfumes 2024 boardgameexpansion 706510 English edition BOTANY: PERILOUS PERFUMES IMG_4571.jpeg
161928 Utter Nonsense 2014 boardgame Utter Nonsense! IMG_4501.jpeg;IMG_4507.jpeg;IMG_4556.jpeg
50381 Cards Against Humanity 2009 boardgame Cards Against Humanity IMG_4501.jpeg;IMG_4556.jpeg
1269 Skip-Bo 1967 boardgame SKIP-BO IMG_4501.jpeg;IMG_4542.jpeg
202982 Scrawl 2016 boardgame SCRAWL IMG_4502.jpeg
195314 Herbaceous 2017 boardgame Herbaceous IMG_4507.jpeg
320202 Dragon Land 2020 boardgame Dragon Land IMG_4508.jpeg;IMG_4542.jpeg
2452 Jenga 1983 boardgame Jenga IMG_4509.jpeg
42063 Code Master 1997 boardgame CODE MASTER IMG_4510.jpeg
340420 Throw Throw Avocado 2021 boardgame THROW THROW AVOCADO IMG_4511.jpeg
1260 Rook 1906 boardgame ROOK IMG_4511.jpeg
116 Guillotine 1998 boardgame Guillotine IMG_4512.jpeg
169124 Flick 'em Up! 2015 boardgame Flick'em UP! IMG_4513.jpeg
20866 The Rocky Horror Trivia Game 2005 boardgame The Rocky Horror Trivia Game IMG_4514.jpeg
269564 Captain Marvel: Secret Skrulls 2019 boardgame CAPTAIN MARVEL SECRET SKRULLS IMG_4516.jpeg
18755 Pie Face! 1964 boardgame Pie Face! IMG_4517.jpeg
140509 Dungeons & Dragons 1985 boardgame DUNGEONS & DRAGONS IMG_4519.jpeg
201248 Evolution: The Beginning 2016 boardgame evolution The Beginning IMG_4520.jpeg
362205 Sleeping Gods: Primeval Peril 2023 boardgame Sleeping Gods PRIMEVAL PERIL IMG_4521.jpeg
453845 Murder at the Manor 2021 boardgame Murder at the Manor IMG_4522.jpeg
329230 Bluffaneer 2021 boardgame Bluffaneer IMG_4522.jpeg
358320 Sleeping Gods: Distant Skies 2023 boardgame Sleeping Gods DISTANT SKIES IMG_4523.jpeg
389113 Rivals 2025 boardgame THE RIVALS FOR CATAN CARD GAME IMG_4523.jpeg
324937 Wiz-War (9th Edition) 2023 boardgame WIZ-WAR IMG_4528.jpeg
295770 Frosthaven 2022 boardgame FROSTHAVEN IMG_4531.jpeg
174430 Gloomhaven 2017 boardgame GLOOMHAVEN IMG_4532.jpeg
442312 Deadly Doodles 2025 boardgame DEADLY DOODLES IMG_4533.jpeg
332398 Everdell: The Complete Collection 2022 boardgame Everdell The Complete Collection IMG_4533.jpeg
334065 Verdant 2022 boardgame Verdant IMG_4534.jpeg
283155 Calico 2020 boardgame Calico IMG_4534.jpeg
291457 Gloomhaven: Jaws of the Lion 2020 boardgame GLOOMHAVEN - Jaws of the Lion IMG_4538.jpeg
150925 Hold Your Breath! 2014 boardgame Hold your Breath! IMG_4547.jpeg
2980 The Simpsons Trivia Game 2000 boardgame The Simpsons Trivia Game shelf-20260803-213735.jpg
1197 Blink 1995 boardgame BLINK shelf-20260803-215650.jpg
352819 The Office Trivia Game 2019 boardgame The Office Trivia Game shelf-20260803-215703.jpg
163412 Patchwork 2014 boardgame Patchwork IMG_4501.jpeg
291847 Mantis Falls 2021 boardgame MANTIS FALLS IMG_4505.jpeg
2058 Civilization: West Extension Map 1986 boardgameexpansion Civilization: West Extension Map
452833 Artistry: Delightful Doorways Mini Expansion 2025 boardgameexpansion Artistry: Delightful Doorways Mini Expansion
+2
View File
@@ -18,9 +18,11 @@ collid,bgg_id,bgg_name,version_id,version_name
53429748,39856,Dixit,296529,Asmodee/Libellud English edition 2015
53430257,35505,Walk the Plank!,781669,English MDG-4311 edition
53430020,164,"Before I Kill You, Mister Bond",28465,"Cheapass black and white ""Better Edition"" edition"
148198097,181304,Mysterium,536289,English edition 2018-2
53429887,65244,Forbidden Island,31208,English edition 051210
53429908,95386,Tempurra,290572,English edition
53430200,258,Fluxx,20840,Looney Labs Version v2.1
148198100,312786,Poetry for Neanderthals,514050,English edition 2020
53430332,188614,Simon's Cat Card Game,779792,"English edition, second printing"
53429850,4324,Risk: The Lord of the Rings,26859,English edition 2002
53429933,1927,Munchkin,28144,"English edition 2009, 15th printing"
1 collid bgg_id bgg_name version_id version_name
18 53429748 39856 Dixit 296529 Asmodee/Libellud English edition 2015
19 53430257 35505 Walk the Plank! 781669 English MDG-4311 edition
20 53430020 164 Before I Kill You, Mister Bond 28465 Cheapass black and white "Better Edition" edition
21 148198097 181304 Mysterium 536289 English edition 2018-2
22 53429887 65244 Forbidden Island 31208 English edition 051210
23 53429908 95386 Tempurra 290572 English edition
24 53430200 258 Fluxx 20840 Looney Labs Version v2.1
25 148198100 312786 Poetry for Neanderthals 514050 English edition 2020
26 53430332 188614 Simon's Cat Card Game 779792 English edition, second printing
27 53429850 4324 Risk: The Lord of the Rings 26859 English edition 2002
28 53429933 1927 Munchkin 28144 English edition 2009, 15th printing
+4
View File
@@ -73,3 +73,7 @@ add,2058,,Civilization: West Extension Map,,,added,2026-08-06T03:05:24+00:00,
add,452833,,Artistry: Delightful Doorways Mini Expansion,,,added,2026-08-06T03:05:31+00:00,
update,240,53429559,Britannia,24621,,failed,2026-08-06T03:06:04+00:00,"TimeoutError: Locator.click: Timeout 30000ms exceeded. Call log: - waiting for get_by_role(""row"").filter(has_text=re.compile(r""Britannia"", re.IGNORECASE)).first.get_by_role(""link"", name=re.compile(r""own"", re.IGNORECASE)).first"
update,71,53429530,Civilization,24006,,failed,2026-08-06T03:06:39+00:00,"TimeoutError: Locator.click: Timeout 30000ms exceeded. Call log: - waiting for get_by_role(""row"").filter(has_text=re.compile(r""Civilization"", re.IGNORECASE)).first.get_by_role(""link"", name=re.compile(r""own"", re.IGNORECASE)).first"
update,177,53429542,Advanced Civilization,24972,,failed,2026-08-06T03:07:12+00:00,"TimeoutError: Locator.click: Timeout 30000ms exceeded. Call log: - waiting for get_by_role(""row"").filter(has_text=re.compile(r""Advanced\ Civilization"", re.IGNORECASE)).first.get_by_role(""link"", name=re.compile(r""own"", re.IGNORECASE)).first"
update,240,53429559,Britannia,24621,,failed,2026-08-06T03:08:42+00:00,"TimeoutError: Locator.click: Timeout 30000ms exceeded. Call log: - waiting for get_by_role(""row"").filter(has_text=re.compile(r""Britannia"", re.IGNORECASE)).first.get_by_role(""link"", name=re.compile(r""own"", re.IGNORECASE)).first"
update,71,53429530,Civilization,24006,,failed,2026-08-06T03:09:17+00:00,"TimeoutError: Locator.click: Timeout 30000ms exceeded. Call log: - waiting for get_by_role(""row"").filter(has_text=re.compile(r""Civilization"", re.IGNORECASE)).first.get_by_role(""link"", name=re.compile(r""own"", re.IGNORECASE)).first"
update,177,53429542,Advanced Civilization,24972,,failed,2026-08-06T03:09:50+00:00,"TimeoutError: Locator.click: Timeout 30000ms exceeded. Call log: - waiting for get_by_role(""row"").filter(has_text=re.compile(r""Advanced\ Civilization"", re.IGNORECASE)).first.get_by_role(""link"", name=re.compile(r""own"", re.IGNORECASE)).first"
1 action bgg_id collid name version_id second_copy status timestamp error
73 add 452833 Artistry: Delightful Doorways Mini Expansion added 2026-08-06T03:05:31+00:00
74 update 240 53429559 Britannia 24621 failed 2026-08-06T03:06:04+00:00 TimeoutError: Locator.click: Timeout 30000ms exceeded. Call log: - waiting for get_by_role("row").filter(has_text=re.compile(r"Britannia", re.IGNORECASE)).first.get_by_role("link", name=re.compile(r"own", re.IGNORECASE)).first
75 update 71 53429530 Civilization 24006 failed 2026-08-06T03:06:39+00:00 TimeoutError: Locator.click: Timeout 30000ms exceeded. Call log: - waiting for get_by_role("row").filter(has_text=re.compile(r"Civilization", re.IGNORECASE)).first.get_by_role("link", name=re.compile(r"own", re.IGNORECASE)).first
76 update 177 53429542 Advanced Civilization 24972 failed 2026-08-06T03:07:12+00:00 TimeoutError: Locator.click: Timeout 30000ms exceeded. Call log: - waiting for get_by_role("row").filter(has_text=re.compile(r"Advanced\ Civilization", re.IGNORECASE)).first.get_by_role("link", name=re.compile(r"own", re.IGNORECASE)).first
77 update 240 53429559 Britannia 24621 failed 2026-08-06T03:08:42+00:00 TimeoutError: Locator.click: Timeout 30000ms exceeded. Call log: - waiting for get_by_role("row").filter(has_text=re.compile(r"Britannia", re.IGNORECASE)).first.get_by_role("link", name=re.compile(r"own", re.IGNORECASE)).first
78 update 71 53429530 Civilization 24006 failed 2026-08-06T03:09:17+00:00 TimeoutError: Locator.click: Timeout 30000ms exceeded. Call log: - waiting for get_by_role("row").filter(has_text=re.compile(r"Civilization", re.IGNORECASE)).first.get_by_role("link", name=re.compile(r"own", re.IGNORECASE)).first
79 update 177 53429542 Advanced Civilization 24972 failed 2026-08-06T03:09:50+00:00 TimeoutError: Locator.click: Timeout 30000ms exceeded. Call log: - waiting for get_by_role("row").filter(has_text=re.compile(r"Advanced\ Civilization", re.IGNORECASE)).first.get_by_role("link", name=re.compile(r"own", re.IGNORECASE)).first
+20
View File
@@ -147,3 +147,23 @@ earlier walkthrough had marked *verified*, and the parts marked
hits more than one row, refuse and add version-less (never guess).
- **An owned game's page has no "Add To" button**; it reads
"In Collections (Own…)". That is the update flow's entry point.
### The update flow (verified 2026-08-06)
Do **not** go through the game page's dialog for an existing entry — it
cannot say which copy it edits. The collection table can:
1. `/collection/user/<user>?objectid=<bgg_id>&own=1`.
2. The version cell carries its own collid:
`td.collection_version[onclick*="<collid>"]`. Clicking it opens an
inline editor (the cell shows *Editing* meanwhile).
3. The editor is a radio list whose **values are version ids**:
`form[id^="form_version"] input[type="radio"][value="<version_id>"]`.
Both the copy and the edition are therefore addressed exactly — no
name matching, no pagination.
4. Clicking the radio fires `CE_SaveData(cellid, collid, 'version')`
itself. **There is no Save button.** The save has landed when the
cell's text stops reading *Editing*.
This is strictly additive: it sets one field on one collid and cannot
create a duplicate entry.
+38 -23
View File
@@ -290,10 +290,11 @@ class Uploader(Protocol):
class PlaywrightUploader:
"""Drives the real site. Selector documentation: docs/bgg-upload-flow.md.
Verified selectors (2026-08-01): the login form (#inputUsername /
#inputPassword / "Sign In") and the Add-to-Collection dialog structure.
UNVERIFIED: version-picker pagination, post-save behavior, and the whole
collection-row edit flow for updates — expect first-real-run adjustments.
All flows verified against the live site 2026-08-06 (adds, the version
picker with pagination, and the collection-row version edit). The
remaining unknown is the second-copy add: BGG may edit the existing
entry instead of creating one, which run_upload reports as a copy-count
shortfall during --verify.
"""
def __init__(
@@ -583,33 +584,47 @@ class PlaywrightUploader:
def update_entry(self, job: UploadJob) -> tuple[str, str]:
"""Set the version on an EXISTING entry — strictly additive.
UNVERIFIED FLOW: the collection table can't target a collid directly,
so this filters by game and opens the row's status link. With several
copies of one game the wrong row could open — acceptable only while
every 2018 entry is version-less; revisit after the first real run.
Verified 2026-08-06. The collection table's version cell carries its
own collid in an onclick and opens an inline editor whose radios
carry VERSION IDS as their values, so both the copy and the edition
are addressed exactly — no name matching, no dialog, no pagination.
Clicking a radio fires CE_SaveData itself; there is no Save button.
"""
self._ensure_logged_in()
page = self._page
self._goto(
f"{BGG}/collection/user/{self._username}?objectid={job.bgg_id}&own=1"
)
row = (
page.get_by_role("row")
.filter(has_text=re.compile(re.escape(job.name), re.I))
.first
)
opener = row.get_by_role("link", name=re.compile("own", re.I)).first
dialog = self._open_dialog(opener)
picked, why = self._select_version(dialog, job.version_name)
if not picked:
# Never guess a version: close without touching the entry.
dialog.get_by_role("button", name="Cancel").first.click()
cell = page.locator(f'td.collection_version[onclick*="{job.collid}"]')
if cell.count() == 0:
raise RuntimeError(
f"version {job.version_name!r}: {why} — entry left untouched"
f"collid {job.collid} has no version cell on the collection "
"page — the entry may have been removed; re-run diff"
)
dialog.get_by_role("button", name="Save").click()
dialog.wait_for(state="hidden", timeout=15_000)
return "updated", "row-edit flow is unverified; confirm with --verify"
cell.first.click()
radio = page.locator(
f'form[id^="form_version"] input[type="radio"][value="{job.version_id}"]'
)
try:
radio.first.wait_for(timeout=15_000)
except self._timeout_error as err:
# the editor lists every version of the game: an absent id means
# the wrong game's editor opened, or BGG retired that version
page.keyboard.press("Escape")
raise RuntimeError(
f"version {job.version_id} not offered for collid "
f"{job.collid} — entry left untouched"
) from err
radio.first.click() # fires CE_SaveData: no separate Save button
for _ in range(40):
settled = " ".join((cell.first.text_content() or "").split())
if settled and "editing" not in settled.casefold():
return "updated", ""
page.wait_for_timeout(500)
raise RuntimeError(
"the version cell never left its editing state — the save may "
"not have landed; re-run with --verify"
)
def _process(
+58
View File
@@ -803,3 +803,61 @@ def test_failure_badge_ignores_jobs_the_human_retired():
]
assert outstanding_failures(log) == 2 # log-only view: both look pending
assert outstanding_failures(log, queue, matches) == 1 # only the live one
def test_update_targets_collid_and_version_id_exactly():
"""The collection row's version cell carries its collid; the editor's
radios carry version ids. Both are addressed by value, so neither the
copy nor the edition can be picked by resemblance."""
from bggpipe.upload import PlaywrightUploader, UploadJob
seen = {"clicked": [], "text": "Editing"}
class _Loc:
def __init__(self, selector):
self.selector = selector
@property
def first(self):
return self
def count(self):
return 1
def wait_for(self, **kw):
return None
def click(self):
seen["clicked"].append(self.selector)
if "radio" in self.selector:
seen["text"] = "Avalon Hill second edition" # CE_SaveData ran
def text_content(self):
return seen["text"]
class _Page:
def goto(self, url, **kw):
seen["url"] = url
def locator(self, selector):
return _Loc(selector)
def wait_for_timeout(self, ms):
pass
up = PlaywrightUploader("someone")
up._page = _Page()
up._authed = True
job = UploadJob(
action="update",
bgg_id=240,
name="Britannia",
collid="53429559",
version_id="24621",
version_name="Avalon Hill second edition",
)
status, note = up.update_entry(job)
assert status == "updated" and note == ""
assert "objectid=240" in seen["url"]
assert any('onclick*="53429559"' in s for s in seen["clicked"]) # the copy
assert any('value="24621"' in s for s in seen["clicked"]) # the edition