# 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: enchanting.spec.ts >> Enchanting Flow >> can switch to Enchant sub-tab and see design UI - Location: e2e/enchanting.spec.ts:41:7 # Error details ``` Error: locator.click: Error: strict mode violation: getByRole('button') resolved to 6 elements: 1) aka getByRole('button', { name: 'Elemental Mana (1)' }) 3) aka getByRole('button', { name: 'Open Next.js Dev Tools' }) Call log: - waiting for getByRole('button') ``` # Page snapshot ```yaml - generic [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]: 01: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]: "12" - generic [ref=e21]: / 100 - generic [ref=e22]: - text: +2.3 mana/hr - generic [ref=e23]: (1.1x 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 - button "Climb the Spire" [ref=e40]: - img - text: Climb the Spire - generic [ref=e42]: - generic [ref=e43]: - img [ref=e44] - generic [ref=e46]: Current Activity - generic [ref=e47]: Meditating - generic [ref=e48]: - generic [ref=e49]: "1" - generic [ref=e50]: "2" - generic [ref=e51]: "3" - generic [ref=e52]: "4" - generic [ref=e53]: "5" - generic [ref=e54]: "6" - generic [ref=e55]: "7" - generic [ref=e56]: "8" - generic [ref=e57]: "9" - generic [ref=e58]: "10" - generic [ref=e59]: "11" - generic [ref=e60]: "12" - generic [ref=e61]: "13" - generic [ref=e62]: "14" - generic [ref=e63]: "15" - generic [ref=e64]: "16" - generic [ref=e65]: "17" - generic [ref=e66]: "18" - generic [ref=e67]: "19" - generic [ref=e68]: "20" - generic [ref=e69]: "21" - generic [ref=e70]: "22" - generic [ref=e71]: "23" - generic [ref=e72]: "24" - generic [ref=e73]: "25" - generic [ref=e74]: "26" - generic [ref=e75]: "27" - generic [ref=e76]: "28" - generic [ref=e77]: "29" - generic [ref=e78]: "30" - generic [ref=e80]: - tablist [ref=e81]: - tab "⚔️ Spire" [ref=e82] - tab "✨ Attune" [ref=e83] - tab "🗿 Golems" [ref=e84] - tab "📚 Skills" [ref=e85] - tab "🔮 Spells" [ref=e86] - tab "🛡️ Gear" [ref=e87] - tab "🔧 Craft" [active] [selected] [ref=e88] - tab "💎 Loot" [ref=e89] - tab "🏆 Achieve" [ref=e90] - tab "📊 Stats" [ref=e91] - tab "🐛 Debug" [ref=e92] - tab "📖 Grimoire" [ref=e93] - tabpanel "🔧 Craft" [ref=e94]: - generic [ref=e95]: - generic [ref=e97]: - button "Fabricate" [ref=e98]: - img - text: Fabricate - button "Enchant" [ref=e99]: - img - text: Enchant - generic [ref=e100]: - generic [ref=e101]: - generic [ref=e103]: - img [ref=e104] - text: Available Blueprints - generic [ref=e113]: - img [ref=e114] - paragraph [ref=e118]: No blueprints discovered yet. - paragraph [ref=e119]: Defeat guardians to find blueprints! - generic [ref=e120]: - generic [ref=e122]: - img [ref=e123] - text: Materials (0) - generic [ref=e131]: - img [ref=e132] - paragraph [ref=e134]: No materials collected yet. - paragraph [ref=e135]: Defeat floors to gather materials! - region "Notifications (F8)": - list - region "Notifications (F8)": - list - button "Open Next.js Dev Tools" [ref=e141] [cursor=pointer]: - img [ref=e142] - alert [ref=e145] ``` # Test source ```ts 1 | import { test, expect } from '@playwright/test'; 2 | 3 | /** 4 | * E2E tests for the 3-step enchantment flow: 5 | * Design → Prepare → Apply 6 | * 7 | * These tests validate the core crafting loop works end-to-end. 8 | */ 9 | 10 | test.describe('Enchanting Flow', () => { 11 | /** 12 | * Before each test, ensure we start with a clean state. 13 | * The game persists state in localStorage, so we clear it. 14 | */ 15 | test.beforeEach(async ({ page }) => { 16 | await page.goto('/'); 17 | // Clear game state to ensure a fresh start 18 | await page.evaluate(() => { 19 | Object.keys(localStorage) 20 | .filter((k) => k.startsWith('mana-loop-')) 21 | .forEach((k) => localStorage.removeItem(k)); 22 | }); 23 | await page.reload(); 24 | // Wait for the game to initialize 25 | await page.waitForLoadState('networkidle'); 26 | }); 27 | 28 | test('can navigate to Crafting tab', async ({ page }) => { 29 | // The tab bar contains a "Craft" tab 30 | const craftTab = page.getByRole('tab', { name: /🔧 Craft/ }); 31 | await expect(craftTab).toBeVisible(); 32 | await craftTab.click(); 33 | 34 | // Verify we're on the crafting tab by checking for sub-tabs 35 | const fabricateBtn = page.getByRole('button', { hasText: 'Fabricate' }); 36 | const enchantBtn = page.getByRole('button', { hasText: 'Enchant' }); 37 | await expect(fabricateBtn).toBeVisible(); 38 | await expect(enchantBtn).toBeVisible(); 39 | }); 40 | 41 | test('can switch to Enchant sub-tab and see design UI', async ({ page }) => { 42 | await page.goto('/'); 43 | await page.evaluate(() => { 44 | Object.keys(localStorage) 45 | .filter((k) => k.startsWith('mana-loop-')) 46 | .forEach((k) => localStorage.removeItem(k)); 47 | }); 48 | await page.reload(); 49 | await page.waitForLoadState('networkidle'); 50 | 51 | // Navigate to Crafting tab 52 | await page.getByRole('tab', { name: /🔧 Craft/ }).click(); 53 | 54 | // Click Enchant sub-tab 55 | const enchantBtn = page.getByRole('button', { hasText: 'Enchant' }); > 56 | await enchantBtn.click(); | ^ Error: locator.click: Error: strict mode violation: getByRole('button') resolved to 6 elements: 57 | 58 | // Should see the design stage UI 59 | const designBtn = page.getByRole('button', { hasText: 'Design' }); 60 | const prepareBtn = page.getByRole('button', { hasText: 'Prepare' }); 61 | const applyBtn = page.getByRole('button', { hasText: 'Apply' }); 62 | await expect(designBtn).toBeVisible(); 63 | await expect(prepareBtn).toBeVisible(); 64 | await expect(applyBtn).toBeVisible(); 65 | }); 66 | 67 | test('can select equipment type and effect in Design stage', async ({ page }) => { 68 | await page.goto('/'); 69 | await page.evaluate(() => { 70 | Object.keys(localStorage) 71 | .filter((k) => k.startsWith('mana-loop-')) 72 | .forEach((k) => localStorage.removeItem(k)); 73 | }); 74 | await page.reload(); 75 | await page.waitForLoadState('networkidle'); 76 | 77 | // Navigate to Crafting > Enchant > Design 78 | await page.getByRole('tab', { name: /🔧 Craft/ }).click(); 79 | await page.getByRole('button', { hasText: 'Enchant' }).click(); 80 | 81 | // The design section should show effect selectors once an equipment type is chosen 82 | // Look for any element matching equipment type buttons and effect-related content 83 | const equipmentButtons = page.locator('button:has-text("Basic Staff"), button:has-text("Apprentice Wand"), button:has-text("Oak Staff"), button:has-text("Crystal Wand")'); 84 | const count = await equipmentButtons.count(); 85 | expect(count).toBeGreaterThan(0); 86 | }); 87 | 88 | test('can navigate through all 3 enchant stages', async ({ page }) => { 89 | await page.goto('/'); 90 | await page.evaluate(() => { 91 | Object.keys(localStorage) 92 | .filter((k) => k.startsWith('mana-loop-')) 93 | .forEach((k) => localStorage.removeItem(k)); 94 | }); 95 | await page.reload(); 96 | await page.waitForLoadState('networkidle'); 97 | 98 | // Navigate to Crafting > Enchant 99 | await page.getByRole('tab', { name: /🔧 Craft/ }).click(); 100 | await page.getByRole('button', { hasText: 'Enchant' }).click(); 101 | 102 | // Verify Design stage is active 103 | const designBtn = page.getByRole('button', { hasText: 'Design' }); 104 | await expect(designBtn).toBeVisible(); 105 | 106 | // Switch to Prepare stage 107 | const prepareBtn = page.getByRole('button', { hasText: 'Prepare' }); 108 | await prepareBtn.click(); 109 | 110 | // Should see preparation UI 111 | const prepareHeading = page.locator('text=Select Equipment to Prepare'); 112 | await expect(prepareHeading).toBeVisible({ timeout: 5000 }); 113 | 114 | // Switch to Apply stage 115 | const applyBtn = page.getByRole('button', { hasText: 'Apply' }); 116 | await applyBtn.click(); 117 | 118 | // Should see application UI 119 | const applyHeading = page.locator('text=Select Equipment & Design'); 120 | await expect(applyHeading).toBeVisible({ timeout: 5000 }); 121 | }); 122 | }); ```