CRM/frontend/e2e/lead-layout.spec.ts

99 خطوط
4.2 KiB
TypeScript

import { expect, test } from './fixtures'
test.beforeEach(async ({ page }) => {
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: 1,
name: 'مدیر تست',
email: 'admin@example.test',
roles: ['admin'],
permissions: ['view_leads', 'create_calls', 'assign_leads'],
is_active: true,
} } })
}
if (url.pathname === '/api/leads/1') {
return route.fulfill({ json: {
id: 1,
company: 'شرکت تست چیدمان',
first_name: 'مینا',
last_name: 'احمدی',
phone: '09120000000',
notes: [],
contacts: [],
contactRelations: [],
callLogs: [],
call_attempts: 2,
assignee: { id: 2, name: 'کارشناس تست' },
} })
}
if (url.pathname === '/api/calls' || url.pathname === '/api/follow-ups') {
return route.fulfill({ json: { data: [], meta: { current_page: 1, last_page: 1, per_page: 50, total: 0 } } })
}
if (url.pathname === '/api/call-results') return route.fulfill({ json: [] })
if (url.pathname === '/api/timeline' || url.pathname === '/api/attachments') return route.fulfill({ json: { data: [] } })
if (url.pathname === '/api/users/referral-targets') return route.fulfill({ json: [] })
if (url.pathname === '/api/users') return route.fulfill({ json: { data: [] } })
if (url.pathname === '/api/notifications/unread-count') return route.fulfill({ json: { data: 0 } })
if (url.pathname === '/api/settings/public') return route.fulfill({ json: { data: {} } })
return route.fulfill({ json: { data: [] } })
})
})
test('lead header stays compact and does not cover content in a short desktop viewport', async ({ page }) => {
await page.setViewportSize({ width: 1917, height: 375 })
await page.goto('/leads/1')
const appHeader = page.getByTestId('app-header')
const actionBar = page.getByTestId('lead-action-bar')
const scrollContainer = page.getByTestId('app-scroll-container')
const summaryLabel = page.getByText('مخاطب اصلی برای تماس بعدی')
await expect(page.getByRole('heading', { name: 'شرکت تست چیدمان' })).toBeVisible()
await actionBar.evaluate(async (element) => {
const animations = element.parentElement?.getAnimations() ?? []
await Promise.all(animations.map((animation) => animation.finished))
})
const initialHeaderBox = await appHeader.boundingBox()
const initialActionBox = await actionBar.boundingBox()
const initialSummaryBox = await summaryLabel.boundingBox()
expect(initialHeaderBox).not.toBeNull()
expect(initialActionBox).not.toBeNull()
expect(initialSummaryBox).not.toBeNull()
expect(initialHeaderBox!.height).toBeLessThanOrEqual(65)
expect(initialActionBox!.height).toBeLessThanOrEqual(65)
expect(Math.abs(initialActionBox!.y - (initialHeaderBox!.y + initialHeaderBox!.height))).toBeLessThanOrEqual(1)
expect(initialSummaryBox!.y).toBeGreaterThanOrEqual(initialActionBox!.y + initialActionBox!.height)
await scrollContainer.evaluate((element) => { element.scrollTop = 320 })
await expect.poll(async () => (await actionBar.boundingBox())?.y).toBe(initialHeaderBox!.y + initialHeaderBox!.height)
const stickyActionBox = await actionBar.boundingBox()
const followupsBox = await page.getByTestId('lead-followups').boundingBox()
expect(stickyActionBox).not.toBeNull()
expect(followupsBox).not.toBeNull()
expect(followupsBox!.y).toBeGreaterThanOrEqual(stickyActionBox!.y + stickyActionBox!.height + 15)
})
test('lead actions remain in normal flow on mobile', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 812 })
await page.goto('/leads/1')
const actionBar = page.getByTestId('lead-action-bar')
const scrollContainer = page.getByTestId('app-scroll-container')
const initialY = (await actionBar.boundingBox())?.y
expect(initialY).toBeDefined()
await scrollContainer.evaluate((element) => { element.scrollTop = 240 })
await expect.poll(async () => (await actionBar.boundingBox())?.y).toBeLessThan(initialY!)
})