New_Micro_Learning/frontend/e2e/ui-phase2-app-shell.spec.ts

99 خطوط
5.1 KiB
TypeScript

import { expect, test } from '@playwright/test'
async function login(page: import('@playwright/test').Page, email = 'designer@microlearn.test') {
await page.goto('http://127.0.0.1:5173/login')
await page.getByLabel(/ایمیل|Email/).fill(email)
await page.getByLabel(/رمز عبور|Password/).fill('password')
await page.getByRole('button', { name: /ورود|Sign in/ }).click()
await expect(page).toHaveURL(/\/(app\/dashboard|admin\/dashboard|manager\/overview)$/)
}
async function expectWorkspaceWithinViewport(page: import('@playwright/test').Page) {
const bounds = await page.locator('.workspace').evaluate(element => {
const workspace = element.getBoundingClientRect()
const body = element.querySelector('.workspace__body')?.getBoundingClientRect()
return {
workspaceLeft: workspace.left,
workspaceRight: workspace.right,
bodyLeft: body?.left ?? 0,
bodyRight: body?.right ?? 0,
viewportWidth: window.innerWidth,
scrollWidth: document.documentElement.scrollWidth,
}
})
expect(bounds.workspaceLeft).toBeGreaterThanOrEqual(-1)
expect(bounds.bodyLeft).toBeGreaterThanOrEqual(-1)
expect(bounds.workspaceRight).toBeLessThanOrEqual(bounds.viewportWidth + 1)
expect(bounds.bodyRight).toBeLessThanOrEqual(bounds.viewportWidth + 1)
expect(bounds.scrollWidth).toBeLessThanOrEqual(bounds.viewportWidth)
}
test('desktop shell groups navigation, exposes context and preserves RTL/dark mode', async ({ page }) => {
await page.setViewportSize({ width: 1440, height: 900 })
await login(page)
await expectWorkspaceWithinViewport(page)
const primary = page.getByRole('navigation', { name: 'ناوبری اصلی' })
const create = primary.getByRole('button', { name: 'ساخت' })
await expect(create).toHaveAttribute('aria-expanded', 'true')
await create.click()
await expect(primary.getByRole('link', { name: 'دوره‌ها' })).toBeHidden()
await create.click()
const collapse = page.getByRole('button', { name: 'جمع‌کردن نوار کناری' })
await collapse.click()
await expect(page.locator('.workspace')).toHaveClass(/workspace--collapsed/)
await expectWorkspaceWithinViewport(page)
const courseLink = primary.getByRole('link', { name: 'دوره‌ها' })
await expect(courseLink).toHaveAttribute('data-tooltip', 'دوره‌ها')
await page.goto('http://127.0.0.1:5173/app/courses/course-1')
const breadcrumb = page.getByRole('navigation', { name: 'مسیر صفحه' })
await expect(breadcrumb).toContainText('دوره‌ها')
await expect(breadcrumb).toContainText('فضای دوره')
await page.getByRole('button', { name: 'انتخاب زبان و تقویم' }).click()
await page.getByRole('menuitemradio', { name: 'English' }).click()
await page.getByRole('button', { name: 'Choose appearance' }).click()
await page.getByRole('menuitemradio', { name: 'Dark' }).click()
await expect(page.locator('html')).toHaveAttribute('dir', 'ltr')
await expect(page.locator('html')).toHaveAttribute('data-theme', 'dark')
expect(await page.evaluate(() => document.documentElement.scrollWidth <= document.documentElement.clientWidth)).toBe(true)
})
test('mobile drawer announces state, traps focus and restores its trigger', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 812 })
await login(page)
for (const width of [375, 430, 768, 1024]) {
await page.setViewportSize({ width, height: width < 768 ? 812 : 900 })
const trigger = page.getByRole('button', { name: 'باز کردن منو' })
await expect(trigger).toBeVisible()
await expect(trigger).toHaveAttribute('aria-expanded', 'false')
await trigger.click()
await expect(trigger).toHaveAttribute('aria-expanded', 'true')
const sidebar = page.locator('.sidebar')
await expect(sidebar).toBeVisible()
await expect(sidebar.getByRole('button', { name: 'بستن منو' })).toBeFocused()
await page.keyboard.press('Escape')
await expect(sidebar).toBeHidden()
await expect(trigger).toBeFocused()
await expect(trigger).toHaveAttribute('aria-expanded', 'false')
expect(await page.evaluate(() => document.body.style.overflow), `${width}px body lock`).toBe('')
expect(await page.evaluate(() => document.documentElement.scrollWidth <= document.documentElement.clientWidth), `${width}px overflow`).toBe(true)
}
})
test('admin and manager receive distinct role-aware navigation', async ({ page }) => {
await login(page, 'admin@microlearn.test')
await expect(page.getByRole('navigation', { name: 'ناوبری اصلی' }).getByRole('link', { name: 'سازمان‌ها' })).toBeVisible()
await expect(page.getByRole('link', { name: 'دوره‌ها' })).toHaveCount(0)
await page.getByRole('button', { name: 'بازکردن حساب کاربری' }).click()
await page.getByRole('menuitem', { name: 'خروج از حساب' }).click()
await expect(page).toHaveURL(/\/login$/)
await login(page, 'manager@microlearn.test')
await expect(page.getByRole('navigation', { name: 'ناوبری اصلی' }).getByRole('link', { name: 'تیم من' })).toBeVisible()
await expect(page.getByRole('link', { name: 'استودیوی هوش مصنوعی' })).toHaveCount(0)
})