# 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: combat.spec.ts >> Combat System >> shows floor information in spire mode - Location: e2e/combat.spec.ts:65:7 # Error details ``` Error: expect(locator).toBeVisible() failed Locator: locator('text="Floor"').first() Expected: visible Timeout: 5000ms Error: element(s) not found Call log: - Expect "toBeVisible" with timeout 5000ms - waiting for locator('text="Floor"').first() ``` # Page snapshot ```yaml - generic [active] [ref=e1]: - generic [ref=e2]: - banner [ref=e3]: - generic [ref=e4]: - heading "MANA LOOP" [level=1] [ref=e5] - generic [ref=e7]: - generic [ref=e8]: - generic [ref=e9]: Day 1 - generic [ref=e10]: 02:04 - generic [ref=e11]: - generic [ref=e12]: "0" - generic [ref=e13]: Insight - main [ref=e14]: - generic [ref=e15]: - generic [ref=e17]: - generic [ref=e18]: - generic [ref=e19]: - generic [ref=e20]: "15" - generic [ref=e21]: / 100 - generic [ref=e22]: - text: +3.0 mana/hr - generic [ref=e23]: (1.5x med) - progressbar [ref=e24] - button "Gather +1 Mana" [ref=e26]: - img - text: Gather +1 Mana - generic [ref=e27]: - button "Elemental Mana (1)" [ref=e28]: - generic [ref=e29]: Elemental Mana (1) - img [ref=e30] - generic [ref=e33]: - generic [ref=e34]: - generic [ref=e35]: 🔗 - generic [ref=e36]: Transference - generic [ref=e39]: 0/10 - generic [ref=e40]: - generic [ref=e41]: "1" - generic [ref=e42]: "2" - generic [ref=e43]: "3" - generic [ref=e44]: "4" - generic [ref=e45]: "5" - generic [ref=e46]: "6" - generic [ref=e47]: "7" - generic [ref=e48]: "8" - generic [ref=e49]: "9" - generic [ref=e50]: "10" - generic [ref=e51]: "11" - generic [ref=e52]: "12" - generic [ref=e53]: "13" - generic [ref=e54]: "14" - generic [ref=e55]: "15" - generic [ref=e56]: "16" - generic [ref=e57]: "17" - generic [ref=e58]: "18" - generic [ref=e59]: "19" - generic [ref=e60]: "20" - generic [ref=e61]: "21" - generic [ref=e62]: "22" - generic [ref=e63]: "23" - generic [ref=e64]: "24" - generic [ref=e65]: "25" - generic [ref=e66]: "26" - generic [ref=e67]: "27" - generic [ref=e68]: "28" - generic [ref=e69]: "29" - generic [ref=e70]: "30" - generic [ref=e72]: - tablist [ref=e73]: - tab "⚔️ Spire" [selected] [ref=e74] - tab "✨ Attune" [ref=e75] - tab "🗿 Golems" [ref=e76] - tab "📚 Skills" [ref=e77] - tab "🔮 Spells" [ref=e78] - tab "🛡️ Gear" [ref=e79] - tab "🔧 Craft" [ref=e80] - tab "💎 Loot" [ref=e81] - tab "🏆 Achieve" [ref=e82] - tab "📊 Stats" [ref=e83] - tab "🐛 Debug" [ref=e84] - tab "📖 Grimoire" [ref=e85] - tabpanel "⚔️ Spire" [ref=e86]: - generic [ref=e87]: - generic [ref=e89]: - button "Exit Spire Mode" [ref=e90]: - img - text: Exit Spire Mode - generic [ref=e91]: Climb down to floor 1 to return to the main game - generic [ref=e92]: - heading "Current Floor 🐝 Swarm" [level=3] [ref=e94]: - generic [ref=e95]: Current Floor - generic [ref=e96]: 🐝 Swarm - generic [ref=e97]: - generic [ref=e98]: - generic [ref=e99]: "1" - generic [ref=e100]: / 100 - generic [ref=e101]: 🔥 Fire - generic [ref=e102]: - text: "Best: Floor" - strong [ref=e103]: "1" - text: "• Pacts:" - strong [ref=e104]: "0" - generic [ref=e106]: - generic [ref=e108]: Active Spells (1) - generic [ref=e110]: - generic [ref=e111]: - generic [ref=e112]: Mana BoltBasic - generic [ref=e113]: ✓ - generic [ref=e114]: ⚔️ 5 dmg • 3 raw • ⚡ 15 dmg/hr - generic [ref=e115]: - generic [ref=e116]: Swarm Enemies (6) - generic [ref=e118]: - generic [ref=e119]: - img [ref=e120] - generic [ref=e125]: Emberling - generic [ref=e126]: 🔥 60/60 HP - generic [ref=e130]: - generic [ref=e131]: - img [ref=e132] - generic [ref=e137]: Fire Imp - generic [ref=e138]: 🔥 60/60 HP - generic [ref=e142]: - generic [ref=e143]: - img [ref=e144] - generic [ref=e149]: Scorchling - generic [ref=e150]: 🔥 60/60 HP - generic [ref=e154]: - generic [ref=e155]: - img [ref=e156] - generic [ref=e161]: Flame Sprite - generic [ref=e162]: 🔥 60/60 HP - generic [ref=e166]: - generic [ref=e167]: - img [ref=e168] - generic [ref=e173]: Emberling - generic [ref=e174]: 🔥 60/60 HP - generic [ref=e178]: - generic [ref=e179]: - img [ref=e180] - generic [ref=e185]: Inferno Whelp - generic [ref=e186]: 🔥 60/60 HP - generic [ref=e189]: - generic [ref=e191]: Floor Navigation - generic [ref=e192]: - generic [ref=e193]: - button "Climb Up" [ref=e194]: - img - text: Climb Up - button "Climb Down" [disabled]: - img - text: Climb Down - generic [ref=e195]: Click Climb Up/Down to begin climbing - generic [ref=e196]: - generic [ref=e198]: Combat Stats - generic [ref=e199]: - generic [ref=e200]: "Total DPS: —" - generic [ref=e201]: - generic [ref=e202]: Active Spells - generic [ref=e203]: - generic [ref=e204]: - generic [ref=e205]: - text: Mana Bolt - generic [ref=e206]: Basic - generic [ref=e207]: ✓ - generic [ref=e208]: ⚔️ 5 dmg • 3 raw • ⚡ 15 dmg/hr - generic [ref=e210]: "Study Speed: 100%" - generic [ref=e211]: - generic [ref=e213]: Activity Log - generic [ref=e219]: No activity yet... - region "Notifications (F8)": - list - region "Notifications (F8)": - list - button "Open Next.js Dev Tools" [ref=e225] [cursor=pointer]: - img [ref=e226] - alert [ref=e229] ``` # Test source ```ts 1 | import { test, expect } from '@playwright/test'; 2 | 3 | /** 4 | * E2E tests for combat system: 5 | * - Entering spire mode (climbing) 6 | * - Casting spells and seeing progress 7 | * - Enemy HP reduction 8 | * - Floor advancement 9 | */ 10 | 11 | test.describe('Combat System', () => { 12 | test.beforeEach(async ({ page }) => { 13 | await page.goto('/'); 14 | // Clear game state to ensure a fresh start 15 | await page.evaluate(() => { 16 | Object.keys(localStorage) 17 | .filter((k) => k.startsWith('mana-loop-')) 18 | .forEach((k) => localStorage.removeItem(k)); 19 | }); 20 | await page.reload(); 21 | await page.waitForLoadState('networkidle'); 22 | }); 23 | 24 | test('can see the Spire tab and "Climb the Spire" button', async ({ page }) => { 25 | // The Spire tab uses an icon + text, so match by the tab role 26 | const spireTab = page.getByRole('tab', { name: /⚔️ Spire/ }); 27 | await expect(spireTab).toBeVisible(); 28 | 29 | // Main page should show "Climb the Spire" button 30 | const climbBtn = page.getByRole('button', { name: 'Climb the Spire' }); 31 | await expect(climbBtn).toBeVisible(); 32 | }); 33 | 34 | test('can enter Spire mode by clicking Climb button', async ({ page }) => { 35 | // Click "Climb the Spire" button on the main page (via left panel) 36 | await page.getByRole('button', { name: 'Climb the Spire' }).click(); 37 | 38 | // Should now see Spire mode UI elements 39 | // The "Enter Spire Mode" button appears when on the Spire tab 40 | const enterBtn = page.getByRole('button', { name: 'Enter Spire Mode' }); 41 | await expect(enterBtn).toBeVisible({ timeout: 5000 }); 42 | }); 43 | 44 | test('can navigate to Spire tab', async ({ page }) => { 45 | // Click the Spire tab specifically (using role=tab to disambiguate) 46 | await page.getByRole('tab', { name: /⚔️ Spire/ }).click(); 47 | 48 | // Should see Spire-specific UI 49 | const enterSpireBtn = page.getByRole('button', { name: 'Enter Spire Mode' }); 50 | await expect(enterSpireBtn).toBeVisible({ timeout: 5000 }); 51 | }); 52 | 53 | test('can enter spire mode from the Spire tab', async ({ page }) => { 54 | await page.getByRole('tab', { name: /⚔️ Spire/ }).click(); 55 | 56 | const enterBtn = page.getByRole('button', { name: 'Enter Spire Mode' }); 57 | await expect(enterBtn).toBeEnabled(); 58 | await enterBtn.click(); 59 | 60 | // After entering, should see exit button 61 | const exitBtn = page.getByRole('button', { name: 'Exit Spire Mode' }); 62 | await expect(exitBtn).toBeVisible({ timeout: 5000 }); 63 | }); 64 | 65 | test('shows floor information in spire mode', async ({ page }) => { 66 | await page.getByRole('tab', { name: /⚔️ Spire/ }).click(); 67 | await page.getByRole('button', { name: 'Enter Spire Mode' }).click(); 68 | 69 | // Should display floor number - look for "Floor" label or the floor counter 70 | const floorDisplay = page.locator('text="Floor"').first(); > 71 | await expect(floorDisplay).toBeVisible({ timeout: 5000 }); | ^ Error: expect(locator).toBeVisible() failed 72 | }); 73 | }); ```