feat: TASK-001 - Playwright E2E test setup + baseline tests
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 33s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 33s
- Added @playwright/test as dev dependency - Created playwright.config.ts with Chromium config and webServer setup - Created e2e/combat.spec.ts (5 tests for spire mode, floor display) - Created e2e/enchanting.spec.ts (4 tests for design/crafting tab, enchant flow) - Created e2e/equipment.spec.ts (5 tests for equip, slots, 2H blocking) - Created docs/tasks/TASK-001-playwright-setup.md - All 13 E2E tests passing
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* E2E tests for the 3-step enchantment flow:
|
||||
* Design → Prepare → Apply
|
||||
*
|
||||
* These tests validate the core crafting loop works end-to-end.
|
||||
*/
|
||||
|
||||
test.describe('Enchanting Flow', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.evaluate(() => {
|
||||
Object.keys(localStorage)
|
||||
.filter((k) => k.startsWith('mana-loop-'))
|
||||
.forEach((k) => localStorage.removeItem(k));
|
||||
});
|
||||
await page.reload();
|
||||
await page.waitForLoadState('networkidle');
|
||||
});
|
||||
|
||||
test('can navigate to Crafting tab', async ({ page }) => {
|
||||
const craftTab = page.getByRole('tab').filter({ hasText: '🔧' });
|
||||
await expect(craftTab).toBeVisible();
|
||||
await craftTab.click();
|
||||
|
||||
// Should see the Crafting tab sub-tabs: Fabricate and Enchant
|
||||
const fabricateBtn = page.getByRole('button', { name: 'Fabricate' });
|
||||
const enchantBtn = page.getByRole('button', { name: 'Enchant' });
|
||||
await expect(fabricateBtn).toBeVisible();
|
||||
await expect(enchantBtn).toBeVisible();
|
||||
});
|
||||
|
||||
test('can switch to Enchant sub-tab and see design UI', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.evaluate(() => {
|
||||
Object.keys(localStorage)
|
||||
.filter((k) => k.startsWith('mana-loop-'))
|
||||
.forEach((k) => localStorage.removeItem(k));
|
||||
});
|
||||
await page.reload();
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
await page.getByRole('tab').filter({ hasText: '🔧' }).click();
|
||||
await page.getByRole('button', { name: 'Enchant' }).click();
|
||||
|
||||
// Should see the design stage buttons
|
||||
const designBtn = page.getByRole('button', { name: 'Design' });
|
||||
const prepareBtn = page.getByRole('button', { name: 'Prepare' });
|
||||
const applyBtn = page.getByRole('button', { name: 'Apply' });
|
||||
await expect(designBtn).toBeVisible();
|
||||
await expect(prepareBtn).toBeVisible();
|
||||
await expect(applyBtn).toBeVisible();
|
||||
});
|
||||
|
||||
test('can select equipment type in Design stage', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.evaluate(() => {
|
||||
Object.keys(localStorage)
|
||||
.filter((k) => k.startsWith('mana-loop-'))
|
||||
.forEach((k) => localStorage.removeItem(k));
|
||||
});
|
||||
await page.reload();
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
await page.getByRole('tab').filter({ hasText: '🔧' }).click();
|
||||
await page.getByRole('button', { name: 'Enchant' }).click();
|
||||
|
||||
// Look for equipment type selector showing available staff types
|
||||
// The EnchantmentDesigner shows equipment type options
|
||||
const staffOption = page.locator('text=Basic Staff');
|
||||
await expect(staffOption).toBeVisible({ timeout: 5000 });
|
||||
});
|
||||
|
||||
test('can navigate through all 3 enchant stages', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.evaluate(() => {
|
||||
Object.keys(localStorage)
|
||||
.filter((k) => k.startsWith('mana-loop-'))
|
||||
.forEach((k) => localStorage.removeItem(k));
|
||||
});
|
||||
await page.reload();
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
await page.getByRole('tab').filter({ hasText: '🔧' }).click();
|
||||
await page.getByRole('button', { name: 'Enchant' }).click();
|
||||
|
||||
// Verify Design stage is active
|
||||
await expect(page.getByRole('button', { name: 'Design' })).toBeVisible();
|
||||
|
||||
// Switch to Prepare stage
|
||||
await page.getByRole('button', { name: 'Prepare' }).click();
|
||||
|
||||
// Should see preparation UI
|
||||
// Use role=heading to target the SectionHeader h3, not the empty state div
|
||||
const prepareHeading = page.getByRole('heading', { name: 'Select Equipment to Prepare' });
|
||||
await expect(prepareHeading).toBeVisible({ timeout: 5000 });
|
||||
|
||||
// Switch to Apply stage
|
||||
await page.getByRole('button', { name: 'Apply' }).click();
|
||||
|
||||
// Should see application UI
|
||||
const applyHeading = page.locator('text=Select Equipment & Design');
|
||||
await expect(applyHeading).toBeVisible({ timeout: 5000 });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user