import { expect, test, type Page } from '@playwright/test'; async function login(page: Page, username = 'mobile-admin', target = '/') { await page.addInitScript(() => localStorage.setItem('pipu.locale', 'ru')); await page.goto(`/login?redirect=${encodeURIComponent(target)}`); await page.getByLabel('Логин', { exact: true }).fill(username); await page.getByRole('textbox', { name: 'Пароль', exact: true }).fill(`${username}-password`); await page.getByRole('button', { name: 'Войти', exact: true }).click(); await expect(page.getByRole('button', { name: 'Меню профиля' })).toBeVisible(); } test('admin groups related pages and remembers collapsed sections', async ({ page }, info) => { await login(page); const nav = page.getByRole('navigation', { name: 'Навигация' }); await nav.getByRole('button', { name: 'Админка', exact: true }).click(); await expect(nav.getByRole('link', { name: 'Пользователи', exact: true })).toBeVisible(); for (const title of ['Медиатека', 'Загрузки', 'Система']) { await expect(nav.getByRole('button', { name: title, exact: true })).toHaveAttribute('aria-expanded', 'false'); } await nav.getByRole('button', { name: 'Система', exact: true }).click(); const system = nav.getByRole('group', { name: 'Система', exact: true }); await expect(system.getByRole('link')).toHaveCount(4); for (const title of ['Обновления', 'Конфигурация', 'Настройки', 'Журнал']) { await expect(system.getByRole('link', { name: title, exact: true })).toBeVisible(); } await nav.screenshot({ path: info.outputPath('admin-groups.png') }); // The fake API resets authentication on a full document load; sign in again. await login(page); await expect(nav.getByRole('button', { name: 'Система', exact: true })).toHaveAttribute('aria-expanded', 'true'); await nav.getByRole('button', { name: 'Система', exact: true }).click(); await login(page); await expect(nav.getByRole('button', { name: 'Система', exact: true })).toHaveAttribute('aria-expanded', 'false'); await login(page, 'mobile-admin', '/admin/audit'); await expect(system.getByRole('link', { name: 'Журнал', exact: true })).toBeVisible(); await expect(system.getByRole('link', { name: 'Журнал', exact: true })).toHaveAttribute('data-status', 'active'); await nav.getByRole('button', { name: 'Медиатека', exact: true }).click(); await expect(nav.getByRole('group', { name: 'Медиатека', exact: true }).getByRole('link')).toHaveCount(2); await nav.getByRole('button', { name: 'Загрузки', exact: true }).click(); await expect(nav.getByRole('group', { name: 'Загрузки', exact: true }).getByRole('link')).toHaveCount(3); }); test('moderator sees only permitted groups and pages', async ({ page }) => { await login(page, 'moderator', '/admin/library'); const nav = page.getByRole('navigation', { name: 'Навигация' }); await expect(nav.getByRole('group', { name: 'Медиатека', exact: true }).getByRole('link', { name: 'Библиотека' })).toBeVisible(); await expect(nav.getByRole('button', { name: 'Система', exact: true })).toHaveCount(0); await expect(nav.getByRole('link', { name: 'Хранилища' })).toHaveCount(0); await nav.getByRole('button', { name: 'Загрузки', exact: true }).click(); await expect(nav.getByRole('group', { name: 'Загрузки', exact: true }).getByRole('link', { name: 'Очередь', exact: true })).toBeVisible(); }); test('mobile menu exposes grouped pages and closes after navigation', async ({ page }, info) => { await page.setViewportSize({ width: 390, height: 844 }); await login(page); await page.getByRole('button', { name: 'Ещё', exact: true }).click(); const dialog = page.getByRole('dialog', { name: 'Навигация' }); for (const title of ['Медиатека', 'Загрузки', 'Система']) { await expect(dialog.getByRole('heading', { name: title, exact: true })).toBeVisible(); } await dialog.screenshot({ path: info.outputPath('admin-groups-mobile.png') }); await dialog.getByRole('group', { name: 'Система', exact: true }).getByRole('link', { name: 'Обновления', exact: true }).click(); await expect(dialog).not.toBeVisible(); await expect(page).toHaveURL(/\/admin\/updates$/); }); test('tablet icon sidebar keeps all admin destinations accessible', async ({ page }) => { await page.setViewportSize({ width: 900, height: 900 }); await login(page); const nav = page.getByRole('navigation', { name: 'Навигация' }); for (const title of ['Библиотека', 'Хранилища', 'Предложить треки', 'Очередь', 'Журнал']) { await expect(nav.getByRole('link', { name: title, exact: true })).toBeVisible(); } });