Files
Mana-Loop/playwright-report/data/6408809a17a0a92b06e5cc75fcee95e9778138c4.md
T
2026-05-13 12:16:11 +02:00

285 lines
13 KiB
Markdown

# 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 navigate to Crafting tab
- Location: e2e/enchanting.spec.ts:28:7
# Error details
```
Error: expect(locator).toBeVisible() failed
Locator: getByRole('button')
Expected: visible
Error: strict mode violation: getByRole('button') resolved to 6 elements:
1) <button data-slot="button" class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive text-primary-foreground shad…>…</button> aka getByRole('button', { name: 'Gather +1 Mana' })
2) <button class="flex items-center justify-between w-full text-xs text-gray-400 hover:text-gray-300 mb-2">…</button> aka getByRole('button', { name: 'Elemental Mana (1)' })
3) <button data-slot="button" class="inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive text-primary-foreground shadow-xs hover…>…</button> aka getByRole('button', { name: 'Climb the Spire' })
4) <button data-slot="action-button" class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-[var(--radius)] text-sm font-medium transition-all duration-100 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:ring-2 focus-visible:ring-[var(--border-focus)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--bg-base)] bg-[var(--interactive-primary)] text-white …>…</button> aka getByRole('button', { name: 'Fabricate' })
5) <button data-slot="action-button" class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-[var(--radius)] text-sm font-medium transition-all duration-100 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:ring-2 focus-visible:ring-[var(--border-focus)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--bg-base)] bg-[var(--interactive-secondary)] text-[var…>…</button> aka getByRole('button', { name: 'Enchant' })
6) <button id="next-logo" aria-haspopup="menu" data-next-mark="true" aria-expanded="false" aria-label="Open Next.js Dev Tools" data-nextjs-dev-tools-button="true" aria-controls="nextjs-dev-tools-menu">…</button> aka getByRole('button', { name: 'Open Next.js Dev Tools' })
Call log:
- Expect "toBeVisible" with timeout 5000ms
- 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]: 00:55
- 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]: "11"
- generic [ref=e21]: / 100
- generic [ref=e22]:
- text: +2.4 mana/hr
- generic [ref=e23]: (1.2x 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();
| ^ Error: expect(locator).toBeVisible() failed
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();
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 | });
```