import { test, expect } from '@playwright/test'; test.describe('Quasar E2E Tests - Full User Journey', () => { // All tests assume backend runs on http://localhost:3000 // and frontend runs on http://localhost:5173 (with proxy to /api) test('E2E: Navigate to home page and verify layout', async ({ page }) => { // Navigate to home page await page.goto('http://localhost:5173/'); // Verify page loads without errors await expect(page).toHaveTitle(/Quasar|Games/i); // Verify navigation links exist const gamesLink = page.locator('a:has-text("Games")').first(); const romsLink = page.locator('a:has-text("ROMs")').first(); await expect(gamesLink).toBeVisible(); await expect(romsLink).toBeVisible(); }); test('E2E: Create a game manually via form', async ({ page }) => { // Navigate to games page await page.goto('http://localhost:5173/games'); // Wait for page to load await page.waitForLoadState('networkidle'); // Click "Add Game" button const addGameBtn = page.locator('button:has-text("Add Game")'); await expect(addGameBtn).toBeVisible(); await addGameBtn.click(); // Wait for form to appear const titleInput = page.locator('#title'); await expect(titleInput).toBeVisible(); // Fill form: title and platform await titleInput.fill('The Legend of Zelda'); const platformInput = page.locator('#platformId'); await platformInput.fill('Nintendo 64'); // Submit form - look for button with Submit/Save/Create text const submitBtn = page.locator('button[type="submit"]').first(); await submitBtn.click(); // Wait for API response and refresh await page.waitForTimeout(1000); // Verify game appears in table const gameInTable = page.locator('text=The Legend of Zelda'); await expect(gameInTable).toBeVisible(); }); test('E2E: Search metadata for a game', async ({ page }) => { // Navigate to ROMs page (metadata search trigger) await page.goto('http://localhost:5173/roms'); // Wait for page to load await page.waitForLoadState('networkidle'); // Click "Scan Directory" or find metadata search button const scanBtn = page.locator('button:has-text("Scan Directory")'); if (await scanBtn.isVisible()) { // If there's a scan button, we'd click it, but for this test // we'll focus on metadata search dialog // In real scenario, would fill scan path and trigger } // Alternative: Create a game first, then search metadata for it // For now, we'll just verify the metadata search dialog can be triggered const linkMetadataBtn = page.locator('button:has-text("Link Metadata")').first(); // Skip if no ROMs yet if (!(await linkMetadataBtn.isVisible())) { // Create a game first so we have something to link await page.goto('http://localhost:5173/games'); await page.locator('button:has-text("Add Game")').click(); await page.locator('#title').fill('Super Mario'); await page.locator('#platformId').fill('Nintendo'); await page.locator('button[type="submit"]').first().click(); // Go back to ROMs await page.goto('http://localhost:5173/roms'); await page.waitForLoadState('networkidle'); } // Verify metadata search dialog can be opened const linkBtns = page.locator('button:has-text("Link Metadata")'); if ((await linkBtns.count()) > 0) { await linkBtns.first().click(); // Wait for metadata dialog to appear const dialog = page.locator('[role="dialog"]').or(page.locator('.modal')).first(); await expect(dialog).toBeVisible({ timeout: 5000 }); } }); test('E2E: Link ROM to game', async ({ page }) => { // This test requires: // 1. At least one game created // 2. At least one ROM in the system // First, create a game await page.goto('http://localhost:5173/games'); await page.waitForLoadState('networkidle'); const addGameBtn = page.locator('button:has-text("Add Game")'); if (await addGameBtn.isVisible()) { await addGameBtn.click(); await page.locator('#title').fill('Zelda'); await page.locator('#platformId').fill('Nintendo'); await page.locator('button[type="submit"]').first().click(); await page.waitForTimeout(1000); } // Now go to ROMs and try to link await page.goto('http://localhost:5173/roms'); await page.waitForLoadState('networkidle'); const linkBtns = page.locator('button:has-text("Link Metadata")'); const linkCount = await linkBtns.count(); if (linkCount > 0) { // Click first "Link Metadata" button await linkBtns.first().click(); // Wait for dialog with game selection const dialog = page.locator('[role="dialog"], .modal').first(); await expect(dialog).toBeVisible({ timeout: 5000 }); // Try to select "Zelda" game from results const zelda = page.locator('text=Zelda').nth(1); // nth(1) to skip the header if (await zelda.isVisible()) { await zelda.click(); // Wait for link to complete await page.waitForTimeout(1500); // Verify ROM now shows "Zelda" in Game column const gameCell = page.locator('td:has-text("Zelda")'); await expect(gameCell).toBeVisible(); } } }); test('E2E: Full user journey - create, search, link, view', async ({ page }) => { // Step 1: Create game "Hades" await page.goto('http://localhost:5173/games'); await page.waitForLoadState('networkidle'); await page.locator('button:has-text("Add Game")').click(); await page.locator('#title').fill('Hades'); await page.locator('#platformId').fill('Nintendo Switch'); await page.locator('button[type="submit"]').first().click(); await page.waitForTimeout(1000); // Verify game appears in games list let hadesInGames = page.locator('text=Hades').first(); await expect(hadesInGames).toBeVisible(); // Step 2: Navigate to ROMs and verify we can search metadata await page.goto('http://localhost:5173/roms'); await page.waitForLoadState('networkidle'); // If there are ROMs, try to link one to Hades const linkBtns = page.locator('button:has-text("Link Metadata")'); if ((await linkBtns.count()) > 0) { // Open metadata search await linkBtns.first().click(); // Wait for dialog const dialog = page.locator('[role="dialog"], .modal').first(); await expect(dialog).toBeVisible({ timeout: 5000 }); // Try to find and select Hades const hadesOption = page.locator('text=Hades'); const count = await hadesOption.count(); if (count > 1) { // Select second occurrence (avoiding button text, if any) await hadesOption.nth(1).click(); await page.waitForTimeout(1000); } } // Step 3: Verify in games view await page.goto('http://localhost:5173/games'); await page.waitForLoadState('networkidle'); hadesInGames = page.locator('text=Hades'); await expect(hadesInGames).toBeVisible(); }); });