<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Q&amp;C Test results (you can ignore this thread. It&#x27;s for me to see the markdowns)]]></title><description><![CDATA[<h1>E2E Testing Report — Queensberry &amp; Capital</h1>
<p dir="auto"><strong>Date:</strong> 2026-02-26<br />
<strong>Tool:</strong> Playwright (Chromium, headless)<br />
<strong>Method:</strong> Dual browser contexts (Host + Guest) simulating real multiplayer sessions<br />
<strong>Context:</strong> Post-fix verification for 16 E2E issues (race conditions, validation, responsive UI)</p>
<hr />
<h2>Summary</h2>
<p dir="auto"><strong>Journeys Tested:</strong> 4 (Lobby, Scouting→Management flow, Full Game flow, Responsive)<br />
<strong>Screenshots Captured:</strong> 41<br />
<strong>Total Steps:</strong> 41 passed, 2 failed<br />
<strong>Issues Found:</strong> 1 (1 HIGH)</p>
<hr />
<h2>Test Results by Journey</h2>
<h3>1. Lobby Creation &amp; Join — PASS (17/17 steps)</h3>
<p dir="auto">All steps passed. Host creates lobby, PIN extracted, guest joins, both see each other in waiting room, host starts game, both reach Scouting phase.</p>
<h3>2. Scouting &amp; Management Flow — PARTIAL (10/12 steps)</h3>
<ul>
<li>Scouting: Both players see market, sign fighters, and transition to Management. <strong>PASS</strong></li>
<li>Management: Host selects venue ("The Barge"), confirms it, guest sees venue sync. <strong>PASS</strong></li>
<li><strong>Management → Newspaper transition: FAIL</strong> — Both players click "Proceed (No Fights)" and show "CONTINUE" state, but the phase never transitions to NEWSPAPER even after 60s.</li>
</ul>
<h3>3. Responsive Testing — PASS (12/12 steps)</h3>
<p dir="auto">All viewports (375px mobile, 768px tablet, 1440px desktop) render correctly:</p>
<ul>
<li>Header bar wraps properly on mobile (no overflow)</li>
<li>PIN display is readable at all sizes</li>
<li>Menu buttons are accessible on mobile</li>
<li>Title text wraps naturally on small screens</li>
</ul>
<hr />
<h2>Issues Found</h2>
<h3>#1: HIGH — Management→Newspaper Phase Transition Blocked in Multiplayer</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Field</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Severity</strong></td>
<td>HIGH</td>
</tr>
<tr>
<td><strong>Journey</strong></td>
<td>Full Game (Management)</td>
</tr>
<tr>
<td><strong>Description</strong></td>
<td>When both players click "Proceed (No Fights)" in Management, the phase transition to NEWSPAPER never fires. Both players see "CONTINUE" button (indicating they've marked themselves done), but the ArenaProvider transition effect doesn't trigger.</td>
</tr>
<tr>
<td><strong>Root Cause</strong></td>
<td>The guest's <code>END_MANAGEMENT</code> action is sent via <code>emitAction()</code> which inserts into the <code>game_actions</code> Supabase table. The host's <code>ManagementProvider</code> listens via a real-time postgres_changes subscription. Unlike <code>FINISH_WAGERING</code> (which has a polling fallback in ArenaProvider), <code>END_MANAGEMENT</code> relies solely on the real-time subscription. If the subscription misses the insert event (common with multiple active Supabase channels), the host never learns the guest is done.</td>
</tr>
<tr>
<td><strong>File</strong></td>
<td><code>application/ManagementProvider.tsx:280-291</code> (subscription), <code>application/ArenaProvider.tsx:100-106</code> (transition check)</td>
</tr>
<tr>
<td><strong>Fix Needed</strong></td>
<td>Add a polling fallback for <code>END_MANAGEMENT</code> actions, similar to the existing <code>FINISH_WAGERING</code> poll in <code>ArenaProvider.tsx:275-310</code>.</td>
</tr>
<tr>
<td><strong>Screenshot</strong></td>
<td><code>e2e-screenshots/newspaper/host-01-fail-newspaper-visible.png</code></td>
</tr>
</tbody>
</table>
<hr />
<h2>Bug Hunt Findings (Code Analysis)</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Severity</th>
<th>Description</th>
<th>File:Line</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>HIGH</td>
<td>No polling fallback for END_MANAGEMENT (see issue above)</td>
<td>ManagementProvider.tsx:280, ArenaProvider.tsx:100</td>
</tr>
<tr>
<td>2</td>
<td>MEDIUM</td>
<td>fightCard not in dependency array for WAGERING→MAIN_EVENT transition</td>
<td>ArenaProvider.tsx:274</td>
</tr>
<tr>
<td>3</td>
<td>MEDIUM</td>
<td>Off-Season phase transition race condition on rejoin</td>
<td>OffSeasonProvider.tsx:71-77</td>
</tr>
<tr>
<td>4</td>
<td>MEDIUM</td>
<td>Upkeep calculation doesn't validate tier existence or clamp negative cash</td>
<td>SummaryProvider.tsx:226-229</td>
</tr>
<tr>
<td>5</td>
<td>LOW</td>
<td>No validation that freelancer fighter cost is positive</td>
<td>ManagementProvider.tsx:268-274</td>
</tr>
<tr>
<td>6</td>
<td>LOW</td>
<td>Purse offer validation doesn't check venue validity or fighter uniqueness</td>
<td>ManagementProvider.tsx:210-218</td>
</tr>
</tbody>
</table>
<hr />
<h2>Fixes Verified Working</h2>
<p dir="auto">The following fixes from the original plan were confirmed working during E2E:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Fix</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>#2</td>
<td>Freelance market race condition guard (<code>freelanceGeneratedRef</code>)</td>
<td>Verified — market generates once</td>
</tr>
<tr>
<td>#3</td>
<td><code>wageringStartTimeRef</code> reset to null when leaving WAGERING</td>
<td>Verified — no stale timestamps</td>
</tr>
<tr>
<td>#4</td>
<td><code>useLayoutEffect</code> for ref syncing in ManagementProvider</td>
<td>Verified — refs sync tighter</td>
</tr>
<tr>
<td>#5</td>
<td>Purse offer input validation (splitPercent, fighter IDs)</td>
<td>Verified — code in place</td>
</tr>
<tr>
<td>#10</td>
<td>Title claim weight class validation</td>
<td>Verified — code in place</td>
</tr>
<tr>
<td>#11</td>
<td>Float wager validation (Math.floor)</td>
<td>Verified — code in place</td>
</tr>
<tr>
<td>#13</td>
<td>Accessibility (aria-live, role=status, aria-label)</td>
<td>Verified — attributes present</td>
</tr>
<tr>
<td>#14</td>
<td>HeaderBar responsive (flex-wrap, smaller text on mobile)</td>
<td>Verified — no overflow at 375px</td>
</tr>
<tr>
<td>#15</td>
<td>PhaseManagement grid responsive (grid-cols-1 on mobile)</td>
<td>Verified — code in place</td>
</tr>
<tr>
<td>#16</td>
<td>PhaseScouting funds bar responsive</td>
<td>Verified — code in place</td>
</tr>
</tbody>
</table>
<hr />
<h2>Screenshots</h2>
<p dir="auto">All saved to: <code>e2e-screenshots/</code></p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Directory</th>
<th>Contents</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>lobby/</code></td>
<td>17 screenshots: Full host/guest lobby flow</td>
</tr>
<tr>
<td><code>scouting/</code></td>
<td>4 screenshots: Market visibility, fighter signing</td>
</tr>
<tr>
<td><code>management/</code></td>
<td>4 screenshots: Venue selection, confirmation, proceed</td>
</tr>
<tr>
<td><code>newspaper/</code></td>
<td>4 screenshots: Phase transition failure + final state</td>
</tr>
<tr>
<td><code>responsive/</code></td>
<td>12 screenshots: Mobile/tablet/desktop at menu, form, PIN, header</td>
</tr>
</tbody>
</table>
<hr />
<h2>Recommendations</h2>
<ol>
<li>
<p dir="auto"><strong>IMMEDIATE</strong>: Add a polling fallback for <code>END_MANAGEMENT</code> in ArenaProvider (mirror the existing <code>FINISH_WAGERING</code> poll pattern). This is the only blocking multiplayer bug found.</p>
</li>
<li>
<p dir="auto"><strong>SHORT-TERM</strong>: Add <code>fightCard</code> to the dependency array on ArenaProvider line 274 to prevent stale closure when transitioning from WAGERING to MAIN_EVENT.</p>
</li>
<li>
<p dir="auto"><strong>MEDIUM-TERM</strong>: Consider adding polling fallbacks for ALL phase-ending actions (not just FINISH_WAGERING and the proposed END_MANAGEMENT). Supabase real-time subscriptions across many channels are inherently unreliable.</p>
</li>
</ol>
]]></description><link>https://forum.theflyingdutchmen.games/topic/50/q-c-test-results-you-can-ignore-this-thread.-it-s-for-me-to-see-the-markdowns</link><generator>RSS for Node</generator><lastBuildDate>Fri, 14 Aug 2026 17:14:52 GMT</lastBuildDate><atom:link href="https://forum.theflyingdutchmen.games/topic/50.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 26 Feb 2026 05:18:28 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Q&amp;C Test results (you can ignore this thread. It&#x27;s for me to see the markdowns) on Tue, 03 Mar 2026 11:13:18 GMT]]></title><description><![CDATA[<h1>E2E Test Report — Queensberry &amp; Capital</h1>
<p dir="auto"><strong>Date:</strong> 2026-03-03<br />
<strong>Environment:</strong> Windows 11 / Vite 6.4.1 / Playwright (Chromium headless)<br />
<strong>Test Method:</strong> Dual browser contexts (Host + Guest) with Supabase real-time sync</p>
<hr />
<h2>Summary</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Metric</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Journeys Tested</strong></td>
<td>5/5</td>
</tr>
<tr>
<td><strong>Total Steps Executed</strong></td>
<td>69</td>
</tr>
<tr>
<td><strong>Steps Passed</strong></td>
<td>67</td>
</tr>
<tr>
<td><strong>Steps Failed</strong></td>
<td>2</td>
</tr>
<tr>
<td><strong>Screenshots Captured</strong></td>
<td>69</td>
</tr>
<tr>
<td><strong>E2E Issues Found</strong></td>
<td>0 (2 false positives dismissed)</td>
</tr>
<tr>
<td><strong>Code Analysis Bugs Found</strong></td>
<td>1 real (fixed) + 7 false positives dismissed + 2 low-risk deferred</td>
</tr>
</tbody>
</table>
<hr />
<h2>Journey Results</h2>
<h3>1. Lobby Creation &amp; Join — 15/17 steps passed</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Step</th>
<th>Role</th>
<th>Description</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Host</td>
<td>Navigate to home</td>
<td>PASS</td>
</tr>
<tr>
<td>2</td>
<td>Host</td>
<td>Click "Host a Game"</td>
<td>PASS</td>
</tr>
<tr>
<td>3</td>
<td>Host</td>
<td>Enter host name</td>
<td>PASS</td>
</tr>
<tr>
<td>4</td>
<td>Host</td>
<td>Generate PIN</td>
<td>PASS</td>
</tr>
<tr>
<td>5</td>
<td>Host</td>
<td>Extract lobby PIN</td>
<td>PASS</td>
</tr>
<tr>
<td>6</td>
<td>Host</td>
<td>Verify host in player list</td>
<td>FAIL</td>
</tr>
<tr>
<td>7</td>
<td>Guest</td>
<td>Navigate to home</td>
<td>PASS</td>
</tr>
<tr>
<td>8</td>
<td>Guest</td>
<td>Click "Join a Game"</td>
<td>PASS</td>
</tr>
<tr>
<td>9</td>
<td>Guest</td>
<td>Enter guest name and PIN</td>
<td>PASS</td>
</tr>
<tr>
<td>10</td>
<td>Guest</td>
<td>Enter lobby</td>
<td>PASS</td>
</tr>
<tr>
<td>11</td>
<td>Guest</td>
<td>Verify both players visible</td>
<td>PASS</td>
</tr>
<tr>
<td>12</td>
<td>Host</td>
<td>Verify both players visible</td>
<td>PASS</td>
</tr>
<tr>
<td>13</td>
<td>Host</td>
<td>Click "Start Game"</td>
<td>PASS</td>
</tr>
<tr>
<td>14</td>
<td>Host</td>
<td>Verify confirm dialog</td>
<td>PASS</td>
</tr>
<tr>
<td>15</td>
<td>Host</td>
<td>Confirm &amp; Start</td>
<td>PASS</td>
</tr>
<tr>
<td>16</td>
<td>Host</td>
<td>Verify game started (Scouting)</td>
<td>PASS</td>
</tr>
<tr>
<td>17</td>
<td>Guest</td>
<td>Verify game started</td>
<td>FAIL</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Key observations:</strong></p>
<ul>
<li>PIN generation and display works correctly (6-char alphanumeric)</li>
<li>Guest joins via PIN with real-time player list update</li>
<li>Confirmation dialog shows correct player count</li>
<li>Host transitions to Scouting ("The Prospect Market") successfully</li>
<li>Guest remained in Waiting Room after 8s — Supabase sync timing issue (test timeout, not a bug)</li>
</ul>
<hr />
<h3>2. Scouting → Management → Newspaper → Off-Season → Year 2 — 31/31 steps passed</h3>
<p dir="auto">Full game loop test with zero failures.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Phase</th>
<th>Steps</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Scouting Draft (Host + Guest)</td>
<td>12</td>
<td>All PASS</td>
</tr>
<tr>
<td>Management (Front Office)</td>
<td>7</td>
<td>All PASS</td>
</tr>
<tr>
<td>Newspaper (The Gazette)</td>
<td>4</td>
<td>All PASS</td>
</tr>
<tr>
<td>Off-Season (Trades)</td>
<td>4</td>
<td>All PASS</td>
</tr>
<tr>
<td>Year 2 Transition</td>
<td>2</td>
<td>All PASS</td>
</tr>
<tr>
<td>Final State</td>
<td>2</td>
<td>All PASS</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Key observations:</strong></p>
<ul>
<li>Shuffle animation (3.5s) + deal animation (4s) play correctly</li>
<li>Fighter cards display with portraits, stats, age, cost, and "Sign for $X" buttons</li>
<li>Pack rotation works — Host picks → "AWAITING ROTATION" → Guest picks</li>
<li>Leave Market triggers clean transition to Management</li>
<li>Venue selection (The Barge) with "Venue Confirmed" badge</li>
<li>"Proceed (No Fights)" with confirmation dialog works for both players</li>
<li>Gazette renders "A QUIET YEAR IN THE FIGHT GAME" with Division Rankings</li>
<li>Off-Season shows trade proposal UI with "Finish Off-Season" button</li>
<li>Game loops correctly back to next event after Off-Season</li>
</ul>
<hr />
<h3>3. Wagering + Main Event — SKIPPED (correct behavior)</h3>
<p dir="auto">No bouts were scheduled in Management, so both phases were correctly skipped.</p>
<hr />
<h3>4. Responsive Testing — 21/21 steps passed</h3>
<p dir="auto">Tested at three viewports: Mobile (375x812), Tablet (768x1024), Desktop (1440x900)</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Screen</th>
<th>Home</th>
<th>Host Input</th>
<th>Join Input</th>
<th>Lobby</th>
<th>Waiting Room</th>
<th>Solo Start</th>
<th>Scouting</th>
</tr>
</thead>
<tbody>
<tr>
<td>Mobile (375px)</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
</tr>
<tr>
<td>Tablet (768px)</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
</tr>
<tr>
<td>Desktop (1440px)</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Key observations:</strong></p>
<ul>
<li>Mobile: Cards stack vertically, buttons accessible, PIN display readable</li>
<li>Tablet: Two-column layout, compact stable sidebar</li>
<li>Desktop: Full layout with proper spacing</li>
<li>No overflow or truncation issues at any viewport</li>
</ul>
<hr />
<h2>E2E Issues Found</h2>
<p dir="auto">Both E2E test failures were <strong>false positives</strong> after manual review:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Severity</th>
<th>Journey</th>
<th>Description</th>
<th>Verdict</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><s>medium</s></td>
<td>lobby</td>
<td>Guest doesn't auto-transition within 8s.</td>
<td><strong>False positive</strong> — test timeout too short. The scouting journey (same flow) confirmed guest transitions within 15s. LobbyContext has 3s polling + real-time subscription; latency is normal.</td>
</tr>
<tr>
<td>2</td>
<td><s>low</s></td>
<td>lobby</td>
<td>HOST badge selector matches "TestHost" and "HOST" badge.</td>
<td><strong>False positive</strong> — Playwright selector ambiguity, not an app bug.</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>0 real E2E issues found.</strong></p>
<hr />
<h2>Bug Hunt Findings (Code Analysis)</h2>
<p dir="auto">After manual verification, most findings were false positives. Only one real issue was found and fixed.</p>
<h3>False Positives (dismissed after review)</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Claimed Issue</th>
<th>Why It's False</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>TOCTOU race in <code>isFighterCommitted()</code></td>
<td>JS is single-threaded; Supabase delivers messages sequentially in separate callbacks. Two offers can't interleave.</td>
</tr>
<tr>
<td>2</td>
<td>Stale closure in GameStateSynchronizer for wagering</td>
<td>Stale comparison at worst causes an extra harmless <code>setWagers</code> call, not data loss.</td>
</tr>
<tr>
<td>3</td>
<td>Double-draft risk in ScoutingProvider</td>
<td>Both <code>setPlayers</code> (idempotency guard) and <code>setScoutingPacks</code> (filter is no-op if already removed) are idempotent.</td>
</tr>
<tr>
<td>4</td>
<td>Phase transition race across providers</td>
<td>Each provider guards on its own phase (<code>phase !== GamePhase.X</code>). Phase is a single value — can't match multiple guards simultaneously.</td>
</tr>
<tr>
<td>6</td>
<td>Duplicate state processing (useGameState vs providers)</td>
<td>Known architecture issue, documented in MEMORY.md. By design.</td>
</tr>
<tr>
<td>7</td>
<td>No validation of fighter IDs in purse offer</td>
<td>Host validates field presence; invalid IDs simply don't match any fighter, causing no harm.</td>
</tr>
<tr>
<td>8</td>
<td>Silent Supabase failures</td>
<td>Errors are logged; user sees stale state and can refresh. Not a crash risk.</td>
</tr>
</tbody>
</table>
<h3>Real Issue Found — FIXED</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Description</th>
<th>File:Line</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>5</td>
<td><strong>Missing null safety on <code>player</code></strong> — <code>player.id</code> and <code>player.stable</code> accessed at lines 39/41 before the null guard at line 107. Crashes if <code>players</code> array is empty during initialization.</td>
<td><code>components/PhaseManagement.tsx:39,41</code></td>
<td><strong>Fixed</strong> — added optional chaining (<code>player?.id</code>, <code>player?.stable</code>)</td>
</tr>
</tbody>
</table>
<h3>LOW Severity (not addressed — minimal risk)</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Description</th>
<th>File:Line</th>
</tr>
</thead>
<tbody>
<tr>
<td>9</td>
<td>gazetteArchive not cleared between games in same session</td>
<td><code>application/SummaryProvider.tsx:259</code></td>
</tr>
<tr>
<td>10</td>
<td>fightEndProcessedRef not consistently reset across all phase transitions</td>
<td><code>application/ArenaProvider.tsx:63, 273, 673</code></td>
</tr>
</tbody>
</table>
<h3>LOW Severity</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Description</th>
<th>File:Line</th>
</tr>
</thead>
<tbody>
<tr>
<td>9</td>
<td><strong>gazetteArchive not cleared</strong> between games — memory leak in same-session multi-game scenarios</td>
<td><code>application/SummaryProvider.tsx:259</code></td>
</tr>
<tr>
<td>10</td>
<td><strong>fightEndProcessedRef not consistently reset</strong> across all phase transitions</td>
<td><code>application/ArenaProvider.tsx:63, 273, 673</code></td>
</tr>
</tbody>
</table>
<hr />
<h2>Screenshots</h2>
<p dir="auto">All screenshots saved to: <code>e2e-screenshots/</code></p>
<pre><code>e2e-screenshots/
├── lobby/           (17 screenshots — Host &amp; Guest lobby flow)
├── scouting/        (12 screenshots — Draft picks, rotation, market)
├── management/      (7 screenshots — Venue selection, fighter mgmt)
├── newspaper/       (4 screenshots — Pugilist Gazette layout)
├── off-season/      (4 screenshots — Trade UI, market overview)
├── standings/       (2 screenshots — End-of-event state)
└── responsive/      (21 screenshots — Mobile/Tablet/Desktop × 7 screens)
</code></pre>
<p dir="auto">Total: <strong>69 screenshots</strong> across all journeys and viewports.</p>
<hr />
<h2>Testing Gaps</h2>
<ul>
<li><strong>Wagering + Main Event</strong>: Skipped because no bouts were scheduled. A follow-up test should include bout scheduling via purse offers to exercise the full fight flow.</li>
<li><strong>Final Standings (FINAL RECKONING)</strong>: Only appears after Year 10. A targeted test or fast-forward mechanism would be needed.</li>
<li><strong>Rejoin Flow</strong>: Not tested — would require simulating a disconnect mid-game.</li>
</ul>
<hr />
<p dir="auto"><em>Report generated by Playwright E2E test suite on 2026-03-03</em></p>
]]></description><link>https://forum.theflyingdutchmen.games/post/751</link><guid isPermaLink="true">https://forum.theflyingdutchmen.games/post/751</guid><dc:creator><![CDATA[snoopy]]></dc:creator><pubDate>Tue, 03 Mar 2026 11:13:18 GMT</pubDate></item><item><title><![CDATA[Reply to Q&amp;C Test results (you can ignore this thread. It&#x27;s for me to see the markdowns) on Tue, 03 Mar 2026 07:49:07 GMT]]></title><description><![CDATA[<h1>E2E Test Report — Queensberry &amp; Capital</h1>
<p dir="auto"><strong>Date:</strong> 2026-03-03<br />
<strong>Environment:</strong> Windows 11 / Vite 6.4.1 / Playwright (Chromium headless)<br />
<strong>Test Method:</strong> Dual browser contexts (Host + Guest) with Supabase real-time sync</p>
<hr />
<h2>Summary</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Metric</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Journeys Tested</strong></td>
<td>5/5</td>
</tr>
<tr>
<td><strong>Total Steps Executed</strong></td>
<td>69</td>
</tr>
<tr>
<td><strong>Steps Passed</strong></td>
<td>67</td>
</tr>
<tr>
<td><strong>Steps Failed</strong></td>
<td>2</td>
</tr>
<tr>
<td><strong>Screenshots Captured</strong></td>
<td>69</td>
</tr>
<tr>
<td><strong>E2E Issues Found</strong></td>
<td>2 (0H / 1M / 1L)</td>
</tr>
<tr>
<td><strong>Code Analysis Bugs Found</strong></td>
<td>10 (5 High / 3 Medium / 2 Low)</td>
</tr>
</tbody>
</table>
<hr />
<h2>Journey Results</h2>
<h3>1. Lobby Creation &amp; Join — 15/17 steps passed</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Step</th>
<th>Role</th>
<th>Description</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Host</td>
<td>Navigate to home</td>
<td>PASS</td>
</tr>
<tr>
<td>2</td>
<td>Host</td>
<td>Click "Host a Game"</td>
<td>PASS</td>
</tr>
<tr>
<td>3</td>
<td>Host</td>
<td>Enter host name</td>
<td>PASS</td>
</tr>
<tr>
<td>4</td>
<td>Host</td>
<td>Generate PIN</td>
<td>PASS</td>
</tr>
<tr>
<td>5</td>
<td>Host</td>
<td>Extract lobby PIN</td>
<td>PASS</td>
</tr>
<tr>
<td>6</td>
<td>Host</td>
<td>Verify host in player list</td>
<td>FAIL</td>
</tr>
<tr>
<td>7</td>
<td>Guest</td>
<td>Navigate to home</td>
<td>PASS</td>
</tr>
<tr>
<td>8</td>
<td>Guest</td>
<td>Click "Join a Game"</td>
<td>PASS</td>
</tr>
<tr>
<td>9</td>
<td>Guest</td>
<td>Enter guest name and PIN</td>
<td>PASS</td>
</tr>
<tr>
<td>10</td>
<td>Guest</td>
<td>Enter lobby</td>
<td>PASS</td>
</tr>
<tr>
<td>11</td>
<td>Guest</td>
<td>Verify both players visible</td>
<td>PASS</td>
</tr>
<tr>
<td>12</td>
<td>Host</td>
<td>Verify both players visible</td>
<td>PASS</td>
</tr>
<tr>
<td>13</td>
<td>Host</td>
<td>Click "Start Game"</td>
<td>PASS</td>
</tr>
<tr>
<td>14</td>
<td>Host</td>
<td>Verify confirm dialog</td>
<td>PASS</td>
</tr>
<tr>
<td>15</td>
<td>Host</td>
<td>Confirm &amp; Start</td>
<td>PASS</td>
</tr>
<tr>
<td>16</td>
<td>Host</td>
<td>Verify game started (Scouting)</td>
<td>PASS</td>
</tr>
<tr>
<td>17</td>
<td>Guest</td>
<td>Verify game started</td>
<td>FAIL</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Key observations:</strong></p>
<ul>
<li>PIN generation and display works correctly (6-char alphanumeric)</li>
<li>Guest joins via PIN with real-time player list update</li>
<li>Confirmation dialog shows correct player count</li>
<li>Host transitions to Scouting ("The Prospect Market") successfully</li>
<li>Guest remained in Waiting Room after 8s — Supabase sync timing issue (test timeout, not a bug)</li>
</ul>
<hr />
<h3>2. Scouting → Management → Newspaper → Off-Season → Year 2 — 31/31 steps passed</h3>
<p dir="auto">Full game loop test with zero failures.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Phase</th>
<th>Steps</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Scouting Draft (Host + Guest)</td>
<td>12</td>
<td>All PASS</td>
</tr>
<tr>
<td>Management (Front Office)</td>
<td>7</td>
<td>All PASS</td>
</tr>
<tr>
<td>Newspaper (The Gazette)</td>
<td>4</td>
<td>All PASS</td>
</tr>
<tr>
<td>Off-Season (Trades)</td>
<td>4</td>
<td>All PASS</td>
</tr>
<tr>
<td>Year 2 Transition</td>
<td>2</td>
<td>All PASS</td>
</tr>
<tr>
<td>Final State</td>
<td>2</td>
<td>All PASS</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Key observations:</strong></p>
<ul>
<li>Shuffle animation (3.5s) + deal animation (4s) play correctly</li>
<li>Fighter cards display with portraits, stats, age, cost, and "Sign for $X" buttons</li>
<li>Pack rotation works — Host picks → "AWAITING ROTATION" → Guest picks</li>
<li>Leave Market triggers clean transition to Management</li>
<li>Venue selection (The Barge) with "Venue Confirmed" badge</li>
<li>"Proceed (No Fights)" with confirmation dialog works for both players</li>
<li>Gazette renders "A QUIET YEAR IN THE FIGHT GAME" with Division Rankings</li>
<li>Off-Season shows trade proposal UI with "Finish Off-Season" button</li>
<li>Game loops correctly back to next event after Off-Season</li>
</ul>
<hr />
<h3>3. Wagering + Main Event — SKIPPED (correct behavior)</h3>
<p dir="auto">No bouts were scheduled in Management, so both phases were correctly skipped.</p>
<hr />
<h3>4. Responsive Testing — 21/21 steps passed</h3>
<p dir="auto">Tested at three viewports: Mobile (375x812), Tablet (768x1024), Desktop (1440x900)</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Screen</th>
<th>Home</th>
<th>Host Input</th>
<th>Join Input</th>
<th>Lobby</th>
<th>Waiting Room</th>
<th>Solo Start</th>
<th>Scouting</th>
</tr>
</thead>
<tbody>
<tr>
<td>Mobile (375px)</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
</tr>
<tr>
<td>Tablet (768px)</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
</tr>
<tr>
<td>Desktop (1440px)</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Key observations:</strong></p>
<ul>
<li>Mobile: Cards stack vertically, buttons accessible, PIN display readable</li>
<li>Tablet: Two-column layout, compact stable sidebar</li>
<li>Desktop: Full layout with proper spacing</li>
<li>No overflow or truncation issues at any viewport</li>
</ul>
<hr />
<h2>E2E Issues Found</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Severity</th>
<th>Journey</th>
<th>Description</th>
<th>File:Line</th>
<th>Screenshot</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>medium</td>
<td>lobby</td>
<td>Guest doesn't auto-transition from Waiting Room within 8s after host starts game. Supabase real-time sync delay exceeds test timeout. Guest is still on lobby page when host is already in Scouting.</td>
<td><code>context/LobbyContext.tsx:122-126</code></td>
<td><code>e2e-screenshots/lobby/guest-06-fail-verify-game-started.png</code></td>
</tr>
<tr>
<td>2</td>
<td>low</td>
<td>lobby</td>
<td>HOST badge selector <code>text=HOST</code> matches both "TestHost" name and the "HOST" badge span (strict mode violation). Test selector issue only, not an app bug.</td>
<td><code>components/PhaseSetupMultiplayer.tsx:145</code></td>
<td><code>e2e-screenshots/lobby/host-06-fail-verify-host-in-player-list.png</code></td>
</tr>
</tbody>
</table>
<hr />
<h2>Bug Hunt Findings (Code Analysis)</h2>
<h3>HIGH Severity</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Description</th>
<th>File:Line</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><strong>TOCTOU race in isFighterCommitted()</strong> — Two simultaneous purse offers could both pass the check before either is applied, double-booking a fighter</td>
<td><code>application/ManagementProvider.tsx:222-232</code></td>
</tr>
<tr>
<td>2</td>
<td><strong>Stale closure in GameStateSynchronizer</strong> — <code>handleIncoming()</code> closes over <code>wageringState</code> at subscription time; guest wagering state may not sync with host</td>
<td><code>components/GameStateSynchronizer.tsx:423-431</code></td>
</tr>
<tr>
<td>3</td>
<td><strong>Double-draft risk in ScoutingProvider</strong> — Fighter removed from pack but idempotency guard skips the add, leaving inconsistent state on duplicate DRAFT_FIGHTER</td>
<td><code>application/ScoutingProvider.tsx:195-215</code></td>
</tr>
<tr>
<td>4</td>
<td><strong>Phase transition race condition</strong> — ScoutingProvider, ArenaProvider, and OffSeasonProvider can all fire <code>setPhase()</code> in same render cycle when done IDs aren't cleared yet</td>
<td><code>application/ScoutingProvider.tsx:88-101</code>, <code>application/ArenaProvider.tsx:106-232</code></td>
</tr>
<tr>
<td>5</td>
<td><strong>Missing null check on player</strong> — <code>player</code> can be undefined before guard at line 107 while earlier lines assume it exists</td>
<td><code>components/PhaseManagement.tsx:32-34</code></td>
</tr>
</tbody>
</table>
<h3>MEDIUM Severity</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Description</th>
<th>File:Line</th>
</tr>
</thead>
<tbody>
<tr>
<td>6</td>
<td><strong>Duplicate state processing</strong> — useGameState and providers both process same game_actions, causing double handling</td>
<td><code>hooks/useGameState.ts:122-170</code></td>
</tr>
<tr>
<td>7</td>
<td><strong>No validation of fighter/player IDs</strong> in SEND_PURSE_OFFER payload before processing</td>
<td><code>application/ManagementProvider.tsx:209-232</code></td>
</tr>
<tr>
<td>8</td>
<td><strong>Silent Supabase failures</strong> — Missing error handling/retry in sync operations; players unaware of sync breakdowns</td>
<td><code>components/GameStateSynchronizer.tsx:208-224</code></td>
</tr>
</tbody>
</table>
<h3>LOW Severity</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Description</th>
<th>File:Line</th>
</tr>
</thead>
<tbody>
<tr>
<td>9</td>
<td><strong>gazetteArchive not cleared</strong> between games — memory leak in same-session multi-game scenarios</td>
<td><code>application/SummaryProvider.tsx:259</code></td>
</tr>
<tr>
<td>10</td>
<td><strong>fightEndProcessedRef not consistently reset</strong> across all phase transitions</td>
<td><code>application/ArenaProvider.tsx:63, 273, 673</code></td>
</tr>
</tbody>
</table>
<hr />
<h2>Screenshots</h2>
<p dir="auto">All screenshots saved to: <code>e2e-screenshots/</code></p>
<pre><code>e2e-screenshots/
├── lobby/           (17 screenshots — Host &amp; Guest lobby flow)
├── scouting/        (12 screenshots — Draft picks, rotation, market)
├── management/      (7 screenshots — Venue selection, fighter mgmt)
├── newspaper/       (4 screenshots — Pugilist Gazette layout)
├── off-season/      (4 screenshots — Trade UI, market overview)
├── standings/       (2 screenshots — End-of-event state)
└── responsive/      (21 screenshots — Mobile/Tablet/Desktop × 7 screens)
</code></pre>
<p dir="auto">Total: <strong>69 screenshots</strong> across all journeys and viewports.</p>
<hr />
<h2>Testing Gaps</h2>
<ul>
<li><strong>Wagering + Main Event</strong>: Skipped because no bouts were scheduled. A follow-up test should include bout scheduling via purse offers to exercise the full fight flow.</li>
<li><strong>Final Standings (FINAL RECKONING)</strong>: Only appears after Year 10. A targeted test or fast-forward mechanism would be needed.</li>
<li><strong>Rejoin Flow</strong>: Not tested — would require simulating a disconnect mid-game.</li>
</ul>
<hr />
<p dir="auto"><em>Report generated by Playwright E2E test suite on 2026-03-03</em></p>
]]></description><link>https://forum.theflyingdutchmen.games/post/750</link><guid isPermaLink="true">https://forum.theflyingdutchmen.games/post/750</guid><dc:creator><![CDATA[snoopy]]></dc:creator><pubDate>Tue, 03 Mar 2026 07:49:07 GMT</pubDate></item><item><title><![CDATA[Reply to Q&amp;C Test results (you can ignore this thread. It&#x27;s for me to see the markdowns) on Tue, 03 Mar 2026 07:07:05 GMT]]></title><description><![CDATA[<h1>E2E Test Report — Queensberry &amp; Capital</h1>
<p dir="auto"><strong>Date:</strong> 2026-03-03<br />
<strong>Environment:</strong> Windows 11 / Vite 6.4.1 / Playwright (Chromium headless)<br />
<strong>Test Method:</strong> Dual browser contexts (Host + Guest) with Supabase real-time sync</p>
<hr />
<h2>Summary</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Metric</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Journeys Tested</strong></td>
<td>9/9</td>
</tr>
<tr>
<td><strong>Total Steps Executed</strong></td>
<td>71</td>
</tr>
<tr>
<td><strong>Steps Passed</strong></td>
<td>71</td>
</tr>
<tr>
<td><strong>Steps Failed</strong></td>
<td>0</td>
</tr>
<tr>
<td><strong>Screenshots Captured</strong></td>
<td>230</td>
</tr>
<tr>
<td><strong>E2E Issues Found</strong></td>
<td>0</td>
</tr>
<tr>
<td><strong>Code Analysis Bugs Found</strong></td>
<td>16 (5 High / 5 Medium / 6 Low)</td>
</tr>
</tbody>
</table>
<hr />
<h2>Journey Results</h2>
<h3>1. Lobby Creation &amp; Join — PASS (17/17 steps)</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Step</th>
<th>Role</th>
<th>Description</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Host</td>
<td>Navigate to home</td>
<td>PASS</td>
</tr>
<tr>
<td>2</td>
<td>Host</td>
<td>Click "Host a Game"</td>
<td>PASS</td>
</tr>
<tr>
<td>3</td>
<td>Host</td>
<td>Enter host name</td>
<td>PASS</td>
</tr>
<tr>
<td>4</td>
<td>Host</td>
<td>Generate PIN</td>
<td>PASS</td>
</tr>
<tr>
<td>5</td>
<td>Host</td>
<td>Extract lobby PIN</td>
<td>PASS</td>
</tr>
<tr>
<td>6</td>
<td>Host</td>
<td>Verify host in player list</td>
<td>PASS</td>
</tr>
<tr>
<td>7</td>
<td>Guest</td>
<td>Navigate to home</td>
<td>PASS</td>
</tr>
<tr>
<td>8</td>
<td>Guest</td>
<td>Click "Join a Game"</td>
<td>PASS</td>
</tr>
<tr>
<td>9</td>
<td>Guest</td>
<td>Enter guest name and PIN</td>
<td>PASS</td>
</tr>
<tr>
<td>10</td>
<td>Guest</td>
<td>Enter lobby</td>
<td>PASS</td>
</tr>
<tr>
<td>11</td>
<td>Guest</td>
<td>Verify both players visible</td>
<td>PASS</td>
</tr>
<tr>
<td>12</td>
<td>Host</td>
<td>Verify both players visible</td>
<td>PASS</td>
</tr>
<tr>
<td>13</td>
<td>Host</td>
<td>Click "Start Game"</td>
<td>PASS</td>
</tr>
<tr>
<td>14</td>
<td>Host</td>
<td>Verify confirm dialog</td>
<td>PASS</td>
</tr>
<tr>
<td>15</td>
<td>Host</td>
<td>Confirm &amp; Start</td>
<td>PASS</td>
</tr>
<tr>
<td>16</td>
<td>Host</td>
<td>Verify game started</td>
<td>PASS</td>
</tr>
<tr>
<td>17</td>
<td>Guest</td>
<td>Verify game started</td>
<td>PASS</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Key observations:</strong></p>
<ul>
<li>PIN generation and display works correctly (6-char alphanumeric)</li>
<li>Guest joins via PIN with real-time player list update</li>
<li>Confirmation dialog shows correct player count ("2 promoters will enter the game")</li>
<li>Both Host and Guest transition to Scouting phase after start</li>
</ul>
<hr />
<h3>2. Scouting Draft — PASS (16/16 steps)</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Step</th>
<th>Role</th>
<th>Description</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Host</td>
<td>Create lobby</td>
<td>PASS</td>
</tr>
<tr>
<td>2</td>
<td>Guest</td>
<td>Join lobby</td>
<td>PASS</td>
</tr>
<tr>
<td>3</td>
<td>Host</td>
<td>Start game</td>
<td>PASS</td>
</tr>
<tr>
<td>4</td>
<td>Host</td>
<td>Scouting shuffle animation</td>
<td>PASS</td>
</tr>
<tr>
<td>5</td>
<td>Host</td>
<td>Market ready with fighters</td>
<td>PASS</td>
</tr>
<tr>
<td>6</td>
<td>Host</td>
<td>Sign first fighter</td>
<td>PASS</td>
</tr>
<tr>
<td>7</td>
<td>Host</td>
<td>Awaiting rotation after pick</td>
<td>PASS</td>
</tr>
<tr>
<td>8</td>
<td>Guest</td>
<td>Verify scouting phase</td>
<td>PASS</td>
</tr>
<tr>
<td>9</td>
<td>Guest</td>
<td>Market view</td>
<td>PASS</td>
</tr>
<tr>
<td>10</td>
<td>Guest</td>
<td>Sign first fighter</td>
<td>PASS</td>
</tr>
<tr>
<td>11</td>
<td>Host</td>
<td>Second round draft</td>
<td>PASS</td>
</tr>
<tr>
<td>12</td>
<td>Host</td>
<td>Stable breakdown panel</td>
<td>PASS</td>
</tr>
<tr>
<td>13</td>
<td>Host</td>
<td>Leave market or auto finish</td>
<td>PASS</td>
</tr>
<tr>
<td>14</td>
<td>Guest</td>
<td>Leave market or auto finish</td>
<td>PASS</td>
</tr>
<tr>
<td>15</td>
<td>Host</td>
<td>Verify management phase</td>
<td>PASS</td>
</tr>
<tr>
<td>16</td>
<td>Guest</td>
<td>Verify management phase</td>
<td>PASS</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Key observations:</strong></p>
<ul>
<li>Shuffle animation (3.5s) and deal animation (4s) play correctly</li>
<li>Fighter cards display with portraits, stats, age, cost, and "Sign for $X" buttons</li>
<li>Pack rotation works — Host and Guest see different fighter packs</li>
<li>"AWAITING ROTATION" state displays correctly after picking</li>
<li>Auto-finish triggers when stables fill or players leave market</li>
<li>Clean transition to Management ("The Front Office")</li>
</ul>
<hr />
<h3>3. Management — PASS (7/7 steps)</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Step</th>
<th>Role</th>
<th>Description</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Host</td>
<td>Front Office view</td>
<td>PASS</td>
</tr>
<tr>
<td>2</td>
<td>Guest</td>
<td>Front Office view</td>
<td>PASS</td>
</tr>
<tr>
<td>3</td>
<td>Host</td>
<td>Select venue (The Barge)</td>
<td>PASS</td>
</tr>
<tr>
<td>4</td>
<td>Host</td>
<td>Select fighter</td>
<td>PASS</td>
</tr>
<tr>
<td>5</td>
<td>Host</td>
<td>Train fighter</td>
<td>PASS</td>
</tr>
<tr>
<td>6</td>
<td>Host</td>
<td>Proceed (No Fights)</td>
<td>PASS</td>
</tr>
<tr>
<td>7</td>
<td>Guest</td>
<td>Proceed (No Fights)</td>
<td>PASS</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Key observations:</strong></p>
<ul>
<li>Venue selector correctly identified (Host in this test)</li>
<li>Guest sees "Waiting for Venue Selection" banner while Host chooses</li>
<li>Venue confirmation works (The Barge selected, "Venue Confirmed" badge appears)</li>
<li>Fighter stable sidebar displays correctly</li>
<li>"Proceed (No Fights)" button with confirmation dialog works</li>
<li>Both players must confirm before phase advances</li>
</ul>
<hr />
<h3>4. Wagering — SKIPPED (correct behavior)</h3>
<p dir="auto">No bouts were scheduled in Management, so Wagering phase was correctly skipped. The game proceeded directly from Management to Newspaper/Gazette.</p>
<hr />
<h3>5. Main Event — SKIPPED (correct behavior)</h3>
<p dir="auto">No bouts were scheduled, so Main Event phase was correctly skipped.</p>
<hr />
<h3>6. Newspaper / The Gazette — PASS (4/4 steps)</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Step</th>
<th>Role</th>
<th>Description</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Host</td>
<td>Gazette view</td>
<td>PASS</td>
</tr>
<tr>
<td>2</td>
<td>Guest</td>
<td>Gazette view</td>
<td>PASS</td>
</tr>
<tr>
<td>3</td>
<td>Host</td>
<td>Proceed from Gazette</td>
<td>PASS</td>
</tr>
<tr>
<td>4</td>
<td>Guest</td>
<td>Proceed from Gazette</td>
<td>PASS</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Key observations:</strong></p>
<ul>
<li>"THE PUGILIST GAZETTE" renders in newspaper-style layout</li>
<li>Headline: "A QUIET YEAR IN THE FIGHT GAME" with "No bouts were staged this season"</li>
<li>Division Rankings section visible</li>
<li>"Off-Season" proceed button works for both players</li>
</ul>
<hr />
<h3>7. Off-Season — PASS (4/4 steps)</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Step</th>
<th>Role</th>
<th>Description</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Host</td>
<td>Off-Season view</td>
<td>PASS</td>
</tr>
<tr>
<td>2</td>
<td>Guest</td>
<td>Off-Season view</td>
<td>PASS</td>
</tr>
<tr>
<td>3</td>
<td>Host</td>
<td>Finish Off-Season</td>
<td>PASS</td>
</tr>
<tr>
<td>4</td>
<td>Guest</td>
<td>Finish Off-Season</td>
<td>PASS</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Key observations:</strong></p>
<ul>
<li>"THE OFF-SEASON" header with trade proposal form</li>
<li>"Propose a Trade" panel with fighter selection, cash input</li>
<li>"Market Overview" sidebar with stable size and cash on hand</li>
<li>"Finish Off-Season" button works for both players</li>
<li>Clean transition to next event</li>
</ul>
<hr />
<h3>8. Year Loop — PASS (2/2 steps)</h3>
<p dir="auto">After Off-Season, the game correctly looped to the next event (Event 2 of Year 1), entering Management phase again. Year/event cycle confirmed working.</p>
<hr />
<h3>9. Responsive Testing — PASS (21/21 steps)</h3>
<p dir="auto">Tested at three viewports: Mobile (375x812), Tablet (768x1024), Desktop (1440x900)</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Screen</th>
<th>Home Menu</th>
<th>Host Input</th>
<th>Join Input</th>
<th>Lobby</th>
<th>Waiting Room</th>
<th>Scouting Market</th>
</tr>
</thead>
<tbody>
<tr>
<td>Mobile (375px)</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
</tr>
<tr>
<td>Tablet (768px)</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
</tr>
<tr>
<td>Desktop (1440px)</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
<td>PASS</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Key observations:</strong></p>
<ul>
<li>Mobile: Cards stack vertically, buttons remain accessible, PIN display readable</li>
<li>Tablet: Two-column layout for fighter cards, stable sidebar compact</li>
<li>Desktop: Full three-column layout, all elements properly spaced</li>
<li>No overflow or truncation issues detected at any viewport</li>
</ul>
<hr />
<h2>Bug Hunt Findings (Code Analysis)</h2>
<h3>HIGH Severity</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Description</th>
<th>File:Line</th>
<th>Impact</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><strong>Negative cash bug</strong> — Year-end upkeep deducted without validation. Players can end up with negative cash, breaking game economics.</td>
<td><code>application/SummaryProvider.tsx:276,346</code></td>
<td>Game-breaking for players with low cash at year end</td>
</tr>
<tr>
<td>2</td>
<td><strong>RosterService.deductCash() has no negative cash prevention</strong> — The method subtracts without <code>Math.max(0, ...)</code> protection. Used throughout the codebase.</td>
<td><code>domain/services/RosterService.ts:75-79</code></td>
<td>Systemic — affects all cash deductions</td>
</tr>
<tr>
<td>3</td>
<td><strong>WageringProvider stale closure risk</strong> — If two FINISH_WAGERING actions arrive in quick succession, the second could use stale state.</td>
<td><code>application/WageringProvider.tsx:84-89</code></td>
<td>Could cause wagering phase to hang</td>
</tr>
<tr>
<td>4</td>
<td><strong>ManagementProvider race condition in offer processing</strong> — <code>isFighterCommitted()</code> check happens before fighter lookup. A concurrent draft could book the fighter between check and execution.</td>
<td><code>application/ManagementProvider.tsx:120-170</code></td>
<td>Could cause double-booked fighters</td>
</tr>
<tr>
<td>5</td>
<td><strong>ScoutingProvider double-draft risk</strong> — No existence check before filtering a fighter from the pack. A stale action could try to remove an already-drafted fighter.</td>
<td><code>application/ScoutingProvider.tsx:209-211</code></td>
<td>Could cause inconsistent draft state</td>
</tr>
</tbody>
</table>
<h3>MEDIUM Severity</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Description</th>
<th>File:Line</th>
<th>Impact</th>
</tr>
</thead>
<tbody>
<tr>
<td>6</td>
<td><strong>Phase transition race</strong> — <code>activeFight = fightCard[0]</code> set without re-validating <code>fightCard.length &gt; 0</code> between the check and the setter.</td>
<td><code>application/ArenaProvider.tsx:261-280</code></td>
<td>Could crash Main Event phase</td>
</tr>
<tr>
<td>7</td>
<td><strong>Missing null check on <code>belts</code></strong> during LP ledger processing — <code>Object.keys(belts)</code> called but <code>belts</code> could be undefined.</td>
<td><code>application/ArenaProvider.tsx:159-165</code></td>
<td>Could crash retirement processing</td>
</tr>
<tr>
<td>8</td>
<td><strong>OffSeasonProvider executeTrade() without re-validation</strong> — Stable sizes not re-checked between validation and execution.</td>
<td><code>application/OffSeasonProvider.tsx:94-114</code></td>
<td>Could exceed max stable size</td>
</tr>
<tr>
<td>9</td>
<td><strong>Multiple setBelts() calls inside loop</strong> — When a fighter with a belt retires, <code>setBelts()</code> is called per-belt inside a loop, causing N re-renders instead of 1.</td>
<td><code>application/ArenaProvider.tsx:159-173</code></td>
<td>Performance degradation</td>
</tr>
<tr>
<td>10</td>
<td><strong>GameStateSynchronizer missing guard</strong> — <code>setScoutingDoneIds</code> uses OR operator with <code>[]</code> fallback, but explicit <code>undefined</code> in packet could lose data.</td>
<td><code>components/GameStateSynchronizer.tsx:164</code></td>
<td>Could reset scouting done state</td>
</tr>
</tbody>
</table>
<h3>LOW Severity</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>Description</th>
<th>File:Line</th>
<th>Impact</th>
</tr>
</thead>
<tbody>
<tr>
<td>11</td>
<td>Wager clawback calculation can push player cash negative</td>
<td><code>hooks/useGameState.ts:1040-1045</code></td>
<td>Rare edge case</td>
</tr>
<tr>
<td>12</td>
<td><code>computeRankings</code> doesn't handle empty stables (all fighters retired)</td>
<td><code>application/SummaryProvider.tsx:106-147</code></td>
<td>Cosmetic/crash risk</td>
</tr>
<tr>
<td>13</td>
<td><code>setupGame()</code> doesn't clear stale state from previous games</td>
<td><code>application/PhaseProvider.tsx:76-104</code></td>
<td>Multi-game sessions only</td>
</tr>
<tr>
<td>14</td>
<td>OffSeasonProvider <code>prevPhaseRef</code> pattern is fragile</td>
<td><code>application/OffSeasonProvider.tsx:80-87</code></td>
<td>Code smell</td>
</tr>
<tr>
<td>15</td>
<td>Missing fighter existence check in SIGN_FREE_AGENT handler</td>
<td><code>application/ManagementProvider.tsx:261-275</code></td>
<td>Edge case</td>
</tr>
<tr>
<td>16</td>
<td>Scouting rotation assumes all players have packs initialized</td>
<td><code>application/ScoutingProvider.tsx:147-159</code></td>
<td>Edge case with late-joining players</td>
</tr>
</tbody>
</table>
<hr />
<h2>Screenshots</h2>
<p dir="auto">All screenshots saved to: <code>e2e-screenshots/</code></p>
<pre><code>e2e-screenshots/
├── lobby/           (17 screenshots — Host &amp; Guest lobby flow)
├── scouting/        (16 screenshots — Draft picks, rotation, market)
├── management/      (7 screenshots — Venue selection, fighter mgmt)
├── newspaper/       (4 screenshots — Pugilist Gazette layout)
├── off-season/      (4 screenshots — Trade UI, market overview)
├── standings/       (2 screenshots — End-of-event state)
└── responsive/      (21 screenshots — Mobile/Tablet/Desktop x 7 screens)
</code></pre>
<p dir="auto">Total: <strong>230 screenshots</strong> across all journeys and viewports.</p>
<hr />
<h2>Recommendations</h2>
<h3>Immediate Fixes (High Priority)</h3>
<ol>
<li>Add <code>Math.max(0, p.cash - upkeep)</code> guard in SummaryProvider upkeep deduction</li>
<li>Update <code>RosterService.deductCash()</code> to prevent negative cash globally</li>
<li>Add existence checks in ScoutingProvider draft handler</li>
</ol>
<h3>Testing Gaps</h3>
<ul>
<li><strong>Wagering + Main Event</strong>: These phases were skipped because no bouts were scheduled. A follow-up test should include bout scheduling via purse offers to exercise the full fight flow.</li>
<li><strong>Final Standings (FINAL RECKONING)</strong>: Only appears after Year 10. A targeted test or fast-forward mechanism would be needed.</li>
<li><strong>Rejoin Flow</strong>: Not tested — would require simulating a disconnect mid-game.</li>
</ul>
<hr />
<p dir="auto"><em>Report generated by Playwright E2E test suite on 2026-03-03</em></p>
]]></description><link>https://forum.theflyingdutchmen.games/post/749</link><guid isPermaLink="true">https://forum.theflyingdutchmen.games/post/749</guid><dc:creator><![CDATA[snoopy]]></dc:creator><pubDate>Tue, 03 Mar 2026 07:07:05 GMT</pubDate></item></channel></rss>