import { test, expect } from './fixtures'; test.describe('I. Core & Authentication', () => { test.beforeEach(async ({ page }) => { // Console logs for debugging page.on('console', msg => console.log('PAGE LOG:', msg.text())); page.on('pageerror', exception => console.log(`PAGE ERROR: ${exception}`)); await page.goto('/'); }); // Helper to handle first login if needed async function handleFirstLogin(page: any) { // Wait for either Free Workout (already logged in/not first time) // OR Change Password heading // OR Error message try { const heading = page.getByRole('heading', { name: /Change Password/i }); const dashboard = page.getByText('Free Workout'); const loginButton = page.getByRole('button', { name: 'Login' }); // Race condition: wait for one of these to appear // We use a small polling or just wait logic. // Playwright doesn't have "race" for locators easily without Promise.race // Simple approach: Check if Change Password appears within 5s await expect(heading).toBeVisible({ timeout: 5000 }); // If we are here, Change Password is visible console.log('Change Password screen detected. Handling...'); await page.getByLabel('New Password').fill('StrongNewPass123!'); await page.getByRole('button', { name: /Save|Change/i }).click(); // Now expect dashboard await expect(dashboard).toBeVisible(); console.log('Password changed. Dashboard visible.'); } catch (e) { // If Change Password didn't appear, maybe we are already at dashboard? if (await page.getByText('Free Workout').isVisible()) { console.log('Already at Dashboard.'); return; } // Check for login error const error = page.locator('.text-error'); if (await error.isVisible()) { console.log('Login Error detected:', await error.textContent()); throw new Error(`Login failed: ${await error.textContent()}`); } console.log('Failed to handle first login. Dumping page content...'); console.log(await page.content()); throw e; } } // 1.1. A. Login - Successful Authentication test('1.1 Login - Successful Authentication', async ({ page, createUniqueUser }) => { const user = await createUniqueUser(); await page.getByLabel('Email').fill(user.email); await page.getByLabel('Password').fill(user.password); await page.getByRole('button', { name: 'Login' }).click(); await handleFirstLogin(page); // Expect redirection to dashboard await expect(page).not.toHaveURL(/\/login/); await expect(page.getByText('Free Workout')).toBeVisible(); }); // 1.2. A. Login - Invalid Credentials test('1.2 Login - Invalid Credentials', async ({ page }) => { await page.getByLabel('Email').fill('invalid@user.com'); await page.getByLabel('Password').fill('wrongpassword'); await page.getByRole('button', { name: 'Login' }).click(); await expect(page.getByText('Invalid credentials')).toBeVisible(); await expect(page.getByRole('button', { name: 'Login' })).toBeVisible(); }); test('1.3 & 1.4 Login - First-Time Password Change', async ({ page, createUniqueUser }) => { const user = await createUniqueUser(); await page.getByLabel('Email').fill(user.email); await page.getByLabel('Password').fill(user.password); await page.getByRole('button', { name: 'Login' }).click(); await expect(page.getByRole('heading', { name: /Change Password/i }).first()).toBeVisible({ timeout: 10000 }); // 1.4 Test short password await page.getByLabel('New Password').fill('123'); await page.getByRole('button', { name: /Save|Change/i }).click(); await expect(page.getByText('Password too short')).toBeVisible(); // 1.3 Test successful change await page.getByLabel('New Password').fill('StrongNewPass123!'); await page.getByRole('button', { name: /Save|Change/i }).click(); // Now we should be logged in await expect(page.getByText('Free Workout')).toBeVisible(); }); // 1.5. A. Login - Language Selection (English) test('1.5 Login - Language Selection (English)', async ({ page }) => { await page.getByRole('combobox').selectOption('en'); await expect(page.getByLabel('Email')).toBeVisible(); await expect(page.getByRole('button', { name: 'Login' })).toBeVisible(); }); // 1.6. A. Login - Language Selection (Russian) test('1.6 Login - Language Selection (Russian)', async ({ page }) => { await page.getByRole('combobox').selectOption('ru'); await expect(page.getByRole('button', { name: 'Войти' })).toBeVisible(); }); // 1.7. B. Navigation - Desktop Navigation Rail test('1.7 Navigation - Desktop Navigation Rail', async ({ page, createUniqueUser }) => { const user = await createUniqueUser(); await page.getByLabel('Email').fill(user.email); await page.getByLabel('Password').fill(user.password); await page.getByRole('button', { name: 'Login' }).click(); await handleFirstLogin(page); // Set viewport to desktop await page.setViewportSize({ width: 1280, height: 720 }); await expect(page.getByRole('button', { name: 'Tracker' }).first()).toBeVisible(); await expect(page.getByRole('button', { name: 'Plans' }).first()).toBeVisible(); }); // 1.8. B. Navigation - Mobile Bottom Navigation Bar test('1.8 Navigation - Mobile Bottom Navigation Bar', async ({ page, createUniqueUser }) => { const user = await createUniqueUser(); await page.getByLabel('Email').fill(user.email); await page.getByLabel('Password').fill(user.password); await page.getByRole('button', { name: 'Login' }).click(); await handleFirstLogin(page); // Set viewport to mobile await page.setViewportSize({ width: 375, height: 667 }); await page.waitForTimeout(500); // Allow layout transition // Verify visibility of mobile nav items await expect(page.getByRole('button', { name: 'Tracker' }).last()).toBeVisible(); }); });