128 خطوط
7.8 KiB
TypeScript
128 خطوط
7.8 KiB
TypeScript
import { expect, test } from './fixtures'
|
||
|
||
test.use({ viewport: { width: 390, height: 844 } })
|
||
|
||
test('mobile shell exposes floating navigation, notification sheet, calendar and date picker', async ({ page }) => {
|
||
const now = new Date().toISOString()
|
||
await page.route('**/api/**', async (route) => {
|
||
const request = route.request()
|
||
const url = new URL(request.url())
|
||
if (!url.pathname.startsWith('/api/')) return route.continue()
|
||
if (url.pathname === '/api/auth/me') return route.fulfill({ json: { data: {
|
||
id: 11, name: 'کارشناس موبایل', email: 'agent@example.test', phone: null, avatar: null,
|
||
roles: ['agent'], permissions: ['view_agent_dashboard', 'view_leads', 'view_own_tasks', 'create_tasks'],
|
||
is_active: true, team_id: 2, created_at: '', updated_at: '',
|
||
} } })
|
||
if (url.pathname === '/api/settings/public') return route.fulfill({ json: { data: {} } })
|
||
if (url.pathname === '/api/notifications/unread-count') return route.fulfill({ json: { data: 1 } })
|
||
if (url.pathname === '/api/notifications') return route.fulfill({ json: paginated([{
|
||
id: 81, type: 'task_assigned', title: 'کار جدید', message: 'پیگیری قرارداد', data: { url: '/tasks' },
|
||
is_read: false, read_at: null, created_at: now,
|
||
}]) })
|
||
if (url.pathname === '/api/calendar/events') return route.fulfill({ json: { events: [{
|
||
id: 'task-31', entity_id: 31, type: 'task', title: 'پیگیری قرارداد', starts_at: now,
|
||
status: 'open', priority: 'normal', assignee: { id: 11, name: 'کارشناس موبایل' }, related: null, url: '/tasks',
|
||
}] } })
|
||
if (url.pathname === '/api/tasks') return route.fulfill({ json: paginated([]) })
|
||
if (url.pathname === '/api/users/assignable') return route.fulfill({ json: { data: [] } })
|
||
return route.fulfill({ json: { data: {} } })
|
||
})
|
||
|
||
await page.goto('/tasks')
|
||
await expect(page.getByRole('navigation', { name: 'ناوبری اصلی موبایل' })).toBeVisible()
|
||
await expect(page.locator('aside')).toBeHidden()
|
||
await expect(page.getByRole('button', { name: 'تقویم کارها و پیگیریها' })).toBeVisible()
|
||
await page.getByRole('button', { name: 'تقویم کارها و پیگیریها' }).click()
|
||
await expect(page).toHaveURL(/\/calendar$/)
|
||
await page.getByRole('tab', { name: 'برنامه روز' }).click()
|
||
await expect(page.getByRole('button').filter({ hasText: 'پیگیری قرارداد' }).last()).toBeVisible()
|
||
await expect.poll(() => page.evaluate(() => document.documentElement.scrollWidth === document.documentElement.clientWidth)).toBe(true)
|
||
|
||
const calendarDialog = page.getByRole('dialog', { name: 'تقویم کارها و پیگیریها' })
|
||
await calendarDialog.getByRole('button', { name: 'بستن' }).click()
|
||
await expect(calendarDialog).toBeHidden()
|
||
await expect(page).toHaveURL(/\/tasks$/)
|
||
|
||
await page.getByRole('button', { name: /اعلان خواندهنشده/ }).click()
|
||
const notificationDialog = page.getByRole('dialog', { name: 'اعلانها' })
|
||
await expect(notificationDialog).toBeVisible()
|
||
await expect(notificationDialog.getByText('کار جدید')).toBeVisible()
|
||
const notificationBox = await notificationDialog.boundingBox()
|
||
expect(notificationBox?.x).toBeGreaterThanOrEqual(12)
|
||
expect(notificationBox ? 390 - notificationBox.x - notificationBox.width : 0).toBeGreaterThanOrEqual(12)
|
||
await page.keyboard.press('Escape')
|
||
await expect(page.getByRole('dialog', { name: 'اعلانها' })).toBeHidden()
|
||
|
||
await expect(page.getByRole('heading', { name: 'مرکز کارها' })).toBeVisible()
|
||
await page.getByRole('button', { name: 'کار جدید' }).click()
|
||
await page.getByLabel('موضوع کار').fill('کار آزمایشی')
|
||
await page.getByRole('button', { name: 'ادامه' }).click()
|
||
await page.getByRole('button', { name: /^موعد:/ }).click()
|
||
await expect(page.getByRole('dialog', { name: 'موعد' })).toBeVisible()
|
||
await expect.poll(() => page.evaluate(() => document.documentElement.scrollWidth === document.documentElement.clientWidth)).toBe(true)
|
||
await page.getByRole('button', { name: 'امروز' }).click()
|
||
await expect(page.getByRole('button', { name: /^موعد:/ })).not.toContainText('انتخاب تاریخ و ساعت')
|
||
})
|
||
|
||
test('selected calendar day number stays visible in dark mode', async ({ page }) => {
|
||
await page.addInitScript(() => localStorage.setItem('theme', 'dark'))
|
||
await page.route('**/api/**', async (route) => {
|
||
const url = new URL(route.request().url())
|
||
if (!url.pathname.startsWith('/api/')) return route.continue()
|
||
if (url.pathname === '/api/auth/me') return route.fulfill({ json: { data: {
|
||
id: 11, name: 'کارشناس موبایل', email: 'agent@example.test', roles: ['agent'],
|
||
permissions: ['view_agent_dashboard', 'view_leads', 'view_own_tasks'], is_active: true,
|
||
} } })
|
||
if (url.pathname === '/api/settings/public') return route.fulfill({ json: { data: {} } })
|
||
if (url.pathname === '/api/notifications/unread-count') return route.fulfill({ json: { data: 0 } })
|
||
if (url.pathname === '/api/calendar/events') return route.fulfill({ json: { events: [] } })
|
||
return route.fulfill({ json: { data: [] } })
|
||
})
|
||
|
||
await page.goto('/calendar')
|
||
const selectedNumber = page.locator('button[aria-pressed="true"] > span').first()
|
||
await expect(selectedNumber).toBeVisible()
|
||
const colors = await selectedNumber.evaluate((element) => {
|
||
const style = getComputedStyle(element)
|
||
return { foreground: style.color, background: style.backgroundColor, text: element.textContent?.trim() }
|
||
})
|
||
expect(colors.text).toBeTruthy()
|
||
expect(colors.background).not.toBe('rgba(0, 0, 0, 0)')
|
||
expect(colors.foreground).not.toBe(colors.background)
|
||
})
|
||
|
||
test('desktop calendar keeps the first event readable inside its day cell', async ({ page }) => {
|
||
await page.setViewportSize({ width: 1440, height: 820 })
|
||
const now = new Date().toISOString()
|
||
await page.route('**/api/**', async (route) => {
|
||
const url = new URL(route.request().url())
|
||
if (!url.pathname.startsWith('/api/')) return route.continue()
|
||
if (url.pathname === '/api/auth/me') return route.fulfill({ json: { data: {
|
||
id: 11, name: 'کارشناس تقویم', email: 'agent@example.test', roles: ['agent'],
|
||
permissions: ['view_agent_dashboard', 'view_leads', 'view_own_tasks'], is_active: true,
|
||
} } })
|
||
if (url.pathname === '/api/settings/public') return route.fulfill({ json: { data: {} } })
|
||
if (url.pathname === '/api/notifications/unread-count') return route.fulfill({ json: { data: 0 } })
|
||
if (url.pathname === '/api/calendar/events') return route.fulfill({ json: { events: [
|
||
{ id: 'task-1', entity_id: 1, type: 'task', title: 'رویداد قابل خواندن', starts_at: now, status: 'open', priority: 'normal', assignee: null, related: null, url: '/tasks' },
|
||
{ id: 'follow-2', entity_id: 2, type: 'follow_up', title: 'پیگیری دوم', starts_at: now, status: 'pending', assignee: null, related: null, url: '/follow-ups' },
|
||
] } })
|
||
return route.fulfill({ json: { data: [] } })
|
||
})
|
||
|
||
await page.goto('/calendar')
|
||
const event = page.locator('span[title="رویداد قابل خواندن"]')
|
||
await expect(event).toBeVisible()
|
||
await expect(page.getByText('+۱ مورد دیگر')).toBeVisible()
|
||
const cell = event.locator('xpath=ancestor::button[1]')
|
||
const eventBox = await event.boundingBox()
|
||
const cellBox = await cell.boundingBox()
|
||
expect(eventBox?.height).toBeGreaterThanOrEqual(12)
|
||
expect(eventBox?.y).toBeGreaterThanOrEqual(cellBox?.y ?? 0)
|
||
expect((eventBox?.y ?? 0) + (eventBox?.height ?? 0)).toBeLessThanOrEqual((cellBox?.y ?? 0) + (cellBox?.height ?? 0))
|
||
})
|
||
|
||
function paginated(items: Record<string, unknown>[]) {
|
||
return { data: items, meta: { current_page: 1, last_page: 1, per_page: 20, total: items.length, from: items.length ? 1 : 0, to: items.length } }
|
||
}
|