CRM/frontend/e2e/task-center.spec.ts

205 خطوط
10 KiB
TypeScript

import { expect, test } from './fixtures'
test('supervisor creates an assigned task from Task Center', async ({ page }) => {
let createdTask: Record<string, unknown> | null = null
const pageErrors: string[] = []
page.on('pageerror', (error) => pageErrors.push(error.message))
page.on('console', (message) => { if (message.type() === 'error') pageErrors.push(message.text()) })
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: 7, name: 'سرپرست تست', email: 'supervisor@example.test', phone: null,
voip_extension: null, avatar: null, is_active: true, last_login_at: null,
roles: ['supervisor'], team_id: 2, created_at: '', updated_at: '',
permissions: ['view_team_tasks', 'create_tasks', 'assign_tasks', 'bulk_manage_tasks'],
} } })
}
if (url.pathname === '/api/users/assignable') {
return route.fulfill({ json: { data: [{
id: 11, name: 'کارشناس تیم', avatar: null, role_label: 'کارشناس',
team_label: 'فروش', is_active: true, open_tasks_count: 2,
}] } })
}
if (url.pathname === '/api/tasks' && request.method() === 'POST') {
const body = request.postDataJSON()
createdTask = task({ id: 31, subject: body.subject, assigned_to: body.assigned_to })
return route.fulfill({ status: 201, json: { data: createdTask } })
}
if (url.pathname === '/api/tasks') {
const tasks = createdTask ? [createdTask] : []
return route.fulfill({ json: { data: tasks, meta: {
current_page: 1, last_page: 1, per_page: 20, total: tasks.length,
from: tasks.length ? 1 : 0, to: tasks.length,
} } })
}
if (url.pathname === '/api/notifications/unread-count') return route.fulfill({ json: { data: { count: 0 } } })
if (url.pathname === '/api/settings/public') return route.fulfill({ json: { data: {} } })
return route.fulfill({ json: { data: [] } })
})
await page.goto('/tasks')
await page.waitForTimeout(500)
expect(pageErrors, `Browser errors: ${pageErrors.join(' | ')}`).toEqual([])
await expect(page).toHaveURL(/\/tasks$/)
expect(await page.locator('body').innerText()).toContain('مرکز کارها')
await page.getByRole('button', { name: 'کار جدید' }).click()
await page.getByLabel('موضوع کار').fill('پیگیری قرارداد آزمایشی')
await page.getByText('کارشناس تیم').click()
await page.getByRole('button', { name: 'ادامه' }).click()
await page.getByRole('button', { name: 'ایجاد کار' }).click()
await expect(page.getByText('پیگیری قرارداد آزمایشی')).toBeVisible()
})
test('agent opens an assignment notification, starts and completes the task, then supervisor sees it', async ({ page }) => {
let role: 'agent' | 'supervisor' = 'agent'
let status: 'open' | 'in_progress' | 'done' = 'open'
let version = 1
let notificationRead = false
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: user(role, role === 'agent'
? ['view_own_tasks', 'edit_own_tasks', 'complete_tasks']
: ['view_team_tasks', 'edit_team_tasks', 'complete_tasks']) } })
}
if (url.pathname === '/api/notifications') {
return route.fulfill({ json: paginated([{
id: 81, title: 'کار جدید به شما تخصیص یافت', message: 'پیگیری مشتری',
type: 'task_assigned', data: { url: '/tasks?task=31', task_id: 31 },
is_read: notificationRead, read_at: notificationRead ? new Date().toISOString() : null,
created_at: new Date().toISOString(),
}]) })
}
if (url.pathname === '/api/notifications/81/read') {
notificationRead = true
return route.fulfill({ json: { data: { read_at: new Date().toISOString() } } })
}
if (url.pathname === '/api/notifications/unread-count') {
return route.fulfill({ json: { data: notificationRead ? 0 : 1 } })
}
if (url.pathname === '/api/tasks/31/start') {
status = 'in_progress'; version += 1
return route.fulfill({ json: { data: task({ id: 31, subject: 'پیگیری مشتری', status, version }) } })
}
if (url.pathname === '/api/tasks/31/complete') {
status = 'done'; version += 1
return route.fulfill({ json: { data: task({ id: 31, subject: 'پیگیری مشتری', status, version }) } })
}
if (url.pathname === '/api/tasks/31') {
return route.fulfill({ json: { data: task({ id: 31, subject: 'پیگیری مشتری', status, version }) } })
}
if (url.pathname === '/api/tasks') {
return route.fulfill({ json: paginated([task({ id: 31, subject: 'پیگیری مشتری', status, version })]) })
}
if (url.pathname === '/api/users/assignable') return route.fulfill({ json: { data: [] } })
return route.fulfill({ json: { data: {} } })
})
await page.goto('/notifications')
await expect(page.getByText('کار جدید به شما تخصیص یافت')).toBeVisible()
await page.getByRole('link', { name: 'باز کردن' }).click()
await expect(page.getByRole('dialog', { name: 'کار: پیگیری مشتری' })).toBeVisible()
await page.getByRole('button', { name: 'شروع کار' }).click()
await expect(page.getByRole('cell', { name: 'در حال انجام' })).toBeVisible()
await page.getByRole('button', { name: 'مشاهده' }).click()
await page.getByRole('button', { name: 'تکمیل کار' }).click()
await page.getByRole('button', { name: 'ادامه و بررسی نهایی' }).click()
await page.getByRole('button', { name: 'اجرای تغییر وضعیت' }).click()
await expect(page.getByRole('cell', { name: 'انجام‌شده' })).toBeVisible()
role = 'supervisor'
await page.reload()
await expect(page.getByRole('cell', { name: 'انجام‌شده' })).toBeVisible()
})
test('agent adds a call note while out-of-scope task and call details stay closed', async ({ page }) => {
let notes: Record<string, unknown>[] = []
let denyDirectAccess = false
const call = {
id: 51, user_id: 11, lead_id: 21, direction: 'outbound', status: 'completed',
duration_seconds: 45, result: 'answered', notes: null, started_at: null,
created_at: new Date().toISOString(), updated_at: new Date().toISOString(),
agent: { id: 11, name: 'کارشناس تیم' }, lead: { id: 21, first_name: 'رضا', last_name: 'محمدی' },
}
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: user('agent', ['view_own_calls', 'view_own_tasks', 'manage_call_notes']) } })
if (url.pathname === '/api/calls' && !denyDirectAccess) return route.fulfill({ json: paginated([call]) })
if (url.pathname === '/api/calls/51' && !denyDirectAccess) return route.fulfill({ json: { data: call } })
if (url.pathname === '/api/calls/51/notes' && request.method() === 'POST') {
const body = request.postDataJSON()
notes = [{ id: 91, content: body.content, type: body.type, visibility: body.visibility,
is_pinned: false, author: { id: 11, name: 'کارشناس تیم' }, edited_at: null,
created_at: new Date().toISOString(), updated_at: new Date().toISOString(),
capabilities: { edit: true, delete: true, pin: false } }]
return route.fulfill({ status: 201, json: { data: notes[0] } })
}
if (url.pathname === '/api/calls/51/notes') return route.fulfill({ json: { data: notes } })
if (url.pathname === '/api/tasks/999' || url.pathname === '/api/calls/999') {
return route.fulfill({ status: 403, json: { message: 'Forbidden' } })
}
if (url.pathname === '/api/tasks') return route.fulfill({ json: paginated([]) })
if (url.pathname === '/api/calls' && denyDirectAccess) return route.fulfill({ json: paginated([{ ...call, id: 999 }]) })
if (url.pathname === '/api/notifications/unread-count') return route.fulfill({ json: { data: 0 } })
return route.fulfill({ json: { data: {} } })
})
await page.goto('/calls')
await page.getByText('رضا محمدی').click()
await page.getByLabel('یادداشت جدید تماس').fill('تعهد به ارسال قرارداد')
await page.getByRole('button', { name: 'ثبت یادداشت' }).click()
await expect(page.getByText('تعهد به ارسال قرارداد')).toBeVisible()
denyDirectAccess = true
await page.goto('/tasks?task=999')
await expect(page.getByRole('dialog')).toHaveCount(0)
await page.goto('/calls')
await page.getByText('رضا محمدی').click()
await expect(page.getByRole('dialog')).toHaveCount(0)
})
function task(overrides: Record<string, unknown>) {
return {
id: 1, subject: 'کار', description: null, taskable_type: null, taskable_id: null,
taskable: null, assigned_to: null, assignee: { id: 11, name: 'کارشناس تیم' },
assigned_by: 7, assigner: { id: 7, name: 'سرپرست تست' }, created_by: 7,
creator: { id: 7, name: 'سرپرست تست' }, priority: 'normal', status: 'open',
due_at: null, started_at: null, completed_at: null, reminder_at: null,
parent_task_id: null, parent: null, estimated_minutes: null, visibility: 'team',
version: 1, is_overdue: false,
capabilities: { update: true, assign: true, transition: true, delete: true },
created_at: new Date().toISOString(), updated_at: new Date().toISOString(),
...overrides,
}
}
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 } }
}
function user(role: 'agent' | 'supervisor', permissions: string[]) {
return {
id: role === 'agent' ? 11 : 7, name: role === 'agent' ? 'کارشناس تیم' : 'سرپرست تست',
email: `${role}@example.test`, phone: null, voip_extension: null, avatar: null,
is_active: true, last_login_at: null, roles: [role], permissions, team_id: 2,
created_at: '', updated_at: '',
}
}