admin/e2e/admin/event-management.spec.ts
alisaza 96603d31f7 feat(alert-modal): integrate alert modal for confirmation actions
Enhanced various components to utilize the alert modal for user confirmations before executing critical actions. This includes marking messages as read, saving notification rules, restoring reviews, sending replies, changing ticket statuses, and managing event commissions. The integration improves user experience by ensuring actions are intentional and provides clear feedback on the outcomes.
2026-09-13 10:14:18 +03:30

164 lines
6.1 KiB
TypeScript

import { expect, test } from '@playwright/test'
import { createHostEvent, hostInsights } from '@/e2e/fixtures/hostEvent'
import { authenticateAs } from '@/e2e/fixtures/session'
const event = createHostEvent({
title: 'رویداد تست مدیریت',
status: 'draft',
settings: {
isDiscoverable: false,
autoCreateGroup: true,
addressVisibility: 'public',
generalArea: null,
waitlistAutoOffer: true,
sendReviewRequestSms: false,
},
organizerId: 'admin-id',
capacity: 20,
bookedCount: 2,
price: 0,
isFree: true,
})
test.beforeEach(async ({ context, page }) => {
await authenticateAs(context, page, 'admin')
await page.route('**/api/v1/**', async (route) => {
const url = new URL(route.request().url())
if (url.pathname.endsWith('/users/me')) {
await route.fulfill({ json: { success: true, data: { id: 'admin-id', role: 'admin', status: 'active' } } })
return
}
if (url.pathname.endsWith('/api/v1/admin/events/event-1')) {
if (route.request().method() === 'GET') {
await route.fulfill({ json: { success: true, data: { ...event, bookmarkCount: 0 } } })
return
}
if (route.request().method() === 'PATCH') {
const payload = route.request().postDataJSON() as { settings?: Record<string, unknown> }
await route.fulfill({
json: { success: true, data: { ...event, settings: { ...event.settings, ...payload.settings } } },
})
return
}
}
if (url.pathname.endsWith('/admin/events/event-1/insights')) {
await route.fulfill({ json: { success: true, data: hostInsights } })
return
}
if (url.pathname.endsWith('/admin/events/event-1/publish') && route.request().method() === 'PATCH') {
await route.fulfill({ json: { success: true, data: { ...event, status: 'published' } } })
return
}
if (url.pathname.endsWith('/event-categories') || url.pathname.includes('/event-categories?')) {
await route.fulfill({ json: { success: true, data: [] } })
return
}
if (url.pathname.endsWith('/geography/cities') || url.pathname.includes('/geography/cities?')) {
await route.fulfill({ json: { success: true, data: [] } })
return
}
if (url.pathname.endsWith('/geography/provinces') || url.pathname.includes('/geography/provinces?')) {
await route.fulfill({ json: { success: true, data: [] } })
return
}
if (url.pathname.endsWith('/events/event-1/media') || url.pathname.endsWith('/events/event-1/faqs')) {
await route.fulfill({ json: { success: true, data: [] } })
return
}
await route.fulfill({ json: { success: true, data: { items: [], meta: { total: 0 } } } })
})
})
test('admin lists events with their main management fields and can open create flow', async ({ page }) => {
const adminEvent = {
id: 'admin-event-1',
title: 'کارگاه مدیریت محصول',
status: 'published',
isDiscoverable: true,
isFree: false,
price: 450_000,
startsAt: '2030-02-01T10:00:00.000Z',
category: { id: 10, name: 'آموزشی' },
province: { id: 1, name: 'تهران' },
city: { id: 2, name: 'تهران' },
organizer: { id: 'organizer-1', firstName: 'سارا', lastName: 'احمدی' },
}
let listRequestUrl: URL | undefined
await page.route('**/api/v1/admin/events**', async (route) => {
listRequestUrl = new URL(route.request().url())
await route.fulfill({
json: {
success: true,
data: {
events: [adminEvent],
response: { page: 1, pageSize: 20, totalItemsCount: 1 },
},
},
})
})
await page.route('**/api/v1/admin/event-categories/flat', (route) =>
route.fulfill({ json: { success: true, data: [{ id: 10, name: 'آموزشی' }] } })
)
await page.route('**/api/v1/geography/cities**', (route) =>
route.fulfill({ json: { success: true, data: [{ id: 2, provinceId: 1, name: 'تهران', slug: 'tehran', lat: 35.7, lng: 51.4 }] } })
)
await page.goto('/manage-events')
await expect(page.getByText('رویدادها', { exact: true }).last()).toBeVisible()
await expect(page.getByRole('grid', { name: 'فهرست صفحه‌بندی‌شده' })).toBeVisible()
const eventRow = page.getByRole('row').filter({ hasText: adminEvent.title })
await expect(eventRow.getByText(adminEvent.title, { exact: true })).toBeVisible()
await expect(eventRow.getByRole('link', { name: 'مشاهده رویداد' })).toHaveAttribute('href', '/manage-events/admin-event-1')
await expect(eventRow.getByText('منتشر‌شده', { exact: true })).toBeVisible()
await expect(eventRow.getByText('آموزشی', { exact: true })).toBeVisible()
await expect(eventRow.getByText('سارا احمدی', { exact: true })).toBeVisible()
await expect(eventRow.getByText('۴۵۰٬۰۰۰ تومان')).toBeVisible()
expect(listRequestUrl?.pathname).toBe('/api/v1/admin/events')
})
test('edits discoverability and publishes a draft event', async ({ page }) => {
await page.goto('/manage-events/event-1')
await expect(page.getByText(event.title, { exact: true })).toBeVisible()
await expect(page.getByText('پیش‌نویس', { exact: true })).toBeVisible()
const [updateRequest] = await Promise.all([
page.waitForRequest((request) => request.method() === 'PATCH' && new URL(request.url()).pathname.endsWith('/admin/events/event-1')),
(async () => {
await page.getByRole('switch', { name: 'نمایش در جستجو' }).click({ force: true })
await page.getByRole('button', { name: 'تأیید' }).click()
})(),
])
expect(updateRequest.postDataJSON()).toEqual({ settings: { isDiscoverable: true } })
const publishRequest = page.waitForRequest(
(request) => request.method() === 'PATCH' && new URL(request.url()).pathname.endsWith('/admin/events/event-1/publish')
)
await page.getByRole('button', { name: 'انتشار فوری' }).click()
await page.getByRole('button', { name: 'تأیید' }).click()
await publishRequest
await expect(page.getByText('منتشر‌شده', { exact: true })).toBeVisible()
await expect(page.getByRole('button', { name: 'انتشار فوری' })).toHaveCount(0)
})