import { expect, test } from '@playwright/test'; test('login password can be shown and hidden', async ({ page }) => { await page.goto('/login'); const password = page.locator('#login-password'); await password.fill('secret-password'); await expect(password).toHaveAttribute('type', 'password'); await page.getByRole('button', { name: 'نمایش رمز عبور' }).click(); await expect(password).toHaveAttribute('type', 'text'); await page.getByRole('button', { name: 'مخفی کردن رمز عبور' }).click(); await expect(password).toHaveAttribute('type', 'password'); }); test('dashboard command surfaces and settings render without runtime errors', async ({ page }, testInfo) => { const runtimeErrors = []; page.on('pageerror', (error) => runtimeErrors.push(error.message)); page.on('console', (message) => { if (message.type() === 'error') runtimeErrors.push(message.text()); }); const user = { id: 1, name: 'مدیر تست رابط', email: 'ui@example.test', permissions: ['reports.view', 'settings.view', 'notifications.view'] }; await page.addInitScript(({ testUser }) => { localStorage.setItem('token', 'visual-smoke-token'); localStorage.setItem('user', JSON.stringify(testUser)); }, { testUser: user }); await page.route('**/api/**', async (route) => { const url = new URL(route.request().url()); const path = url.pathname; if (path === '/api/user') return route.fulfill({ json: { success: true, data: user } }); if (path === '/api/dashboard/monitoring') return route.fulfill({ json: { success: true, data: { generated_at: new Date().toISOString(), summary: { active_projects: 4, projects_at_risk: 1, open_tasks: 18, overdue_tasks: 3, blocked_tasks: 2, active_sprints: 2, meetings_today: 3, overdue_action_items: 1, open_blockers: 2 }, projects: [{ id: 1, title: 'پروژه نمونه رابط', status: 'in_progress', health: 'at_risk', progress: 62, total_tasks: 14, completed_tasks: 8, overdue_tasks: 2, blocked_tasks: 1 }], sprints: [{ id: 1, title: 'Sprint رابط', project: 'پروژه نمونه رابط', progress: 58, expected_progress: 65, remaining_days: 5, health: 'on_track', blocked_tasks: 0 }], workload: [{ id: 1, name: 'کاربر نمونه', open_tasks: 7, overdue_tasks: 1, load: 'high' }], attention: [], upcoming_meetings: [], trends: [{ month: '2026-06', created: 12, completed: 9 }, { month: '2026-07', created: 14, completed: 13 }], } } }); if (path === '/api/calendar/events') return route.fulfill({ json: { success: true, data: [] } }); if (path === '/api/notifications') return route.fulfill({ json: { success: true, data: [], meta: { unread_count: 0, archived_count: 0 } } }); if (path === '/api/settings') return route.fulfill({ json: { success: true, data: [ { id: 1, key: 'working_days', value: ['saturday', 'sunday'], group: 'calendar', type: 'list' }, { id: 2, key: 'default_meeting_reminder_minutes', value: 30, group: 'meeting', type: 'number' }, ] } }); return route.fulfill({ json: { success: true, data: [] } }); }); await page.goto('/'); await expect(page.getByText('مانیتورینگ عملیاتی')).toBeVisible(); await expect(page.locator('img.sidebar-brand-mark')).toBeVisible(); await page.getByRole('button', { name: 'تقویم رویدادها' }).click(); await expect(page.getByRole('region', { name: 'تقویم رویدادها' })).toBeVisible(); await expect(page.getByText('برنامه روز')).toBeVisible(); await page.mouse.click(900, 760); await expect(page.locator('.calendar-popover')).toBeHidden(); await page.getByRole('button', { name: 'اعلان‌ها' }).click(); await expect(page.getByLabel('مرکز اعلان‌ها')).toBeVisible(); await expect(page.getByText(/برای آرشیو به راست/)).toBeVisible(); await page.mouse.click(900, 760); await expect(page.locator('.notification-center')).toBeHidden(); await page.getByRole('button', { name: 'باز کردن پروفایل کاربری' }).click(); await expect(page.getByRole('dialog', { name: 'پروفایل کاربری' })).toBeVisible(); await expect(page.getByRole('button', { name: 'ذخیره هویت' })).toBeVisible(); await page.getByRole('tab', { name: 'اطلاعات کاری' }).click(); await expect(page.getByRole('button', { name: 'ذخیره اطلاعات کاری' })).toBeVisible(); const desktopModalMetrics = await page.getByRole('dialog', { name: 'پروفایل کاربری' }).evaluate((element) => { const body = element.querySelector('.modal-body'); const styles = getComputedStyle(element); return { overflow: styles.overflowY, bodyOverflow: getComputedStyle(body).overflowY, radius: [styles.borderTopLeftRadius, styles.borderTopRightRadius, styles.borderBottomRightRadius, styles.borderBottomLeftRadius], }; }); expect(desktopModalMetrics.overflow).toBe('hidden'); expect(desktopModalMetrics.bodyOverflow).toBe('hidden'); expect(desktopModalMetrics.radius.every((value) => parseFloat(value) > 0)).toBe(true); await page.getByRole('button', { name: 'بستن', exact: true }).click(); await expect(page.getByRole('dialog', { name: 'پروفایل کاربری' })).toBeHidden(); await page.goto('/settings'); await expect(page.getByRole('heading', { name: 'مرکز تنظیمات' })).toBeVisible(); await expect(page.getByText('شخصی‌سازی')).toBeVisible(); await page.screenshot({ path: testInfo.outputPath('settings-command-center.png'), fullPage: true }); await page.setViewportSize({ width: 390, height: 844 }); await page.evaluate(() => localStorage.setItem('preferredAppMode', 'desktop')); await page.goto('/'); await expect(page.getByText('مانیتورینگ عملیاتی')).toBeVisible(); expect(await page.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth)).toBe(true); await page.getByRole('button', { name: 'باز کردن منوی اصلی' }).click(); await expect(page.locator('.app-sidebar.mobile-open')).toBeVisible(); await expect(page.locator('.app-sidebar.mobile-open').getByText('پروژه‌ها')).toBeVisible(); await page.locator('.app-sidebar.mobile-open').getByRole('button', { name: 'بستن منوی اصلی' }).click(); await expect(page.locator('.app-sidebar.mobile-open')).toHaveCount(0); await page.getByRole('button', { name: 'باز کردن پروفایل کاربری' }).click(); await expect(page.getByRole('dialog', { name: 'پروفایل کاربری' })).toBeVisible(); expect(await page.getByRole('dialog', { name: 'پروفایل کاربری' }).evaluate((element) => element.getBoundingClientRect().height <= window.innerHeight)).toBe(true); await page.getByRole('button', { name: 'بستن', exact: true }).click(); await page.screenshot({ path: testInfo.outputPath('mobile-dashboard.png'), fullPage: true }); expect(runtimeErrors).toEqual([]); });