# Instructions

- Following Playwright test failed.
- Explain why, be concise, respect Playwright best practices.
- Provide a snippet of code with the fix, if possible.

# Test info

- Name: sprite-state.e2e.test.ts >> sprite-state machine (D-35) + nametag (D-27a) >> player sprite frame switches to Run<R> on rightward movement, back to Stand on stop
- Location: test/e2e/sprite-state.e2e.test.ts:16:3

# Error details

```
TypeError: expect(received).toMatch(expected)

Matcher error: received value must be a string

Received has value: undefined
```

# Page snapshot

```yaml
- generic [active] [ref=e1]:
  - generic:
    - generic [ref=e5]: Press T or Enter to chat
    - generic: uat_a
    - generic: uat_a
    - generic: uat_a
    - generic: uat_a
    - generic: uat_a
    - generic: uat_a
    - generic: uat_a
    - generic: uat_a
    - generic: uat_a
    - generic: uat_b
    - generic: uat_a
    - generic: uat_a
    - generic: uat_a
    - generic: uat_b
    - generic: uat_a
    - generic: uat_a
    - generic: uat_a
    - generic: uat_a
    - generic: uat_a
    - generic: uat_a
```

# Test source

```ts
  1  | // apps/client/test/e2e/sprite-state.e2e.test.ts
  2  | // [int->REQ-CLI-04] [int->REQ-CLI-07]
  3  | // Plan 06-16 D-35 + D-27a — Playwright e2e assertions for sprite-state machine
  4  | // and nametag rendering.
  5  | //
  6  | // D-35: frame state is asserted via window.__rebno.localFrame (set per simulation
  7  | // tick by PlayerRenderer.onSimulationTickLocal in dev mode). No canvas pixel
  8  | // sampling — deterministic and driver-independent (T-06-16-05 mitigated).
  9  | //
  10 | // D-27a: nameplate DOM mirror ([data-nameplate]) asserts nametag visibility.
  11 | 
  12 | import { test, expect } from './fixtures.js';
  13 | import { loginAs, waitForGameReady } from './fixtures.js';
  14 | 
  15 | test.describe('sprite-state machine (D-35) + nametag (D-27a)', () => {
  16 |   test('player sprite frame switches to Run<R> on rightward movement, back to Stand on stop', async ({
  17 |     page,
  18 |     accountA,
  19 |     inviteSuffix,
  20 |   }) => {
  21 |     await loginAs(page, accountA, inviteSuffix);
  22 |     await waitForGameReady(page);
  23 | 
  24 |     // Press right arrow and hold for 500ms
  25 |     await page.keyboard.down('ArrowRight');
  26 |     await page.waitForTimeout(600);
  27 | 
  28 |     // D-35: read frame state from __rebno hook (not canvas pixel sampling)
  29 |     const frameWhileRunning = await page.evaluate(
  30 |       () => (window as unknown as Record<string, Record<string, string>>).__rebno?.localFrame,
  31 |     );
  32 | 
  33 |     // Frame key must match Run R pattern: '0028-NaviRunR_NNN'
> 34 |     expect(frameWhileRunning).toMatch(/^0028-NaviRunR_\d{3}$/);
     |                               ^ TypeError: expect(received).toMatch(expected)
  35 | 
  36 |     // Release right arrow and wait for stop
  37 |     await page.keyboard.up('ArrowRight');
  38 |     await page.waitForTimeout(300);
  39 | 
  40 |     const frameAfterStop = await page.evaluate(
  41 |       () => (window as unknown as Record<string, Record<string, string>>).__rebno?.localFrame,
  42 |     );
  43 | 
  44 |     // Stand R (facing preserved) or Stand D (default) after stop
  45 |     expect(frameAfterStop).toMatch(/^(0029-NaviStandR_000|0000-NaviStandD_000)$/);
  46 |   });
  47 | 
  48 |   test('nameplate DOM mirror is visible for self (count >= 1)', async ({
  49 |     page,
  50 |     accountA,
  51 |     inviteSuffix,
  52 |   }) => {
  53 |     await loginAs(page, accountA, inviteSuffix);
  54 |     await waitForGameReady(page);
  55 | 
  56 |     // D-27a: DOM mirror [data-nameplate] must exist for at least self
  57 |     const count = await page.locator('[data-nameplate]').count();
  58 |     expect(count).toBeGreaterThanOrEqual(1);
  59 |   });
  60 | 
  61 |   test('nameplate text content matches logged-in username', async ({
  62 |     page,
  63 |     accountA,
  64 |     inviteSuffix,
  65 |   }) => {
  66 |     await loginAs(page, accountA, inviteSuffix);
  67 |     await waitForGameReady(page);
  68 | 
  69 |     // The nameplate DOM mirror should contain the logged-in username
  70 |     const nameplateEl = page.locator('[data-nameplate]').first();
  71 |     await expect(nameplateEl).toBeAttached({ timeout: 5_000 });
  72 |     const text = await nameplateEl.textContent();
  73 |     // The username is from accountA (default 'alice' or UAT_ACCOUNT_A env)
  74 |     expect(text?.trim()).toBeTruthy();
  75 |   });
  76 | });
  77 | 
```