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.
162 lines
5.2 KiB
TypeScript
162 lines
5.2 KiB
TypeScript
import { expect, test, type Page } from '@playwright/test'
|
|
|
|
import { createHostEvent, hostInsights } from '@/e2e/fixtures/hostEvent'
|
|
import { authenticateAs } from '@/e2e/fixtures/session'
|
|
|
|
interface ReviewEventFixture {
|
|
[key: string]: unknown
|
|
status: string
|
|
publishedAt: string | null
|
|
adminApprovedAt: string | null
|
|
rejectionReason: string | null
|
|
}
|
|
|
|
function pendingReviewEvent(): ReviewEventFixture {
|
|
return createHostEvent({
|
|
title: 'رویداد در انتظار بررسی',
|
|
status: 'pending_review',
|
|
publishedAt: null,
|
|
adminApprovedAt: null,
|
|
rejectionReason: null,
|
|
organizerId: 'host-1',
|
|
organizer: { id: 'host-1', firstName: 'میزبان', lastName: 'تست', mobile: '989121234567' },
|
|
settings: {
|
|
isDiscoverable: false,
|
|
autoCreateGroup: true,
|
|
addressVisibility: 'public',
|
|
generalArea: null,
|
|
waitlistAutoOffer: true,
|
|
sendReviewRequestSms: false,
|
|
},
|
|
})
|
|
}
|
|
|
|
async function mockReviewEndpoints(page: Page) {
|
|
let current = pendingReviewEvent()
|
|
const requests: { path: string; payload: unknown }[] = []
|
|
|
|
await page.route('**/api/v1/**', async (route) => {
|
|
const request = route.request()
|
|
const url = new URL(request.url())
|
|
const { pathname } = url
|
|
|
|
if (pathname.endsWith('/users/me')) {
|
|
await route.fulfill({ json: { success: true, data: { id: 'admin-id', role: 'admin', status: 'active' } } })
|
|
|
|
return
|
|
}
|
|
|
|
if (pathname.endsWith('/admin/events/event-1/approve') && request.method() === 'PATCH') {
|
|
requests.push({ path: pathname, payload: request.postDataJSON() })
|
|
current = {
|
|
...current,
|
|
status: 'published',
|
|
publishedAt: '2030-01-01T10:00:00.000Z',
|
|
adminApprovedAt: '2030-01-01T10:00:00.000Z',
|
|
}
|
|
await route.fulfill({ json: { success: true, data: current } })
|
|
|
|
return
|
|
}
|
|
|
|
if (pathname.endsWith('/admin/events/event-1/reject') && request.method() === 'PATCH') {
|
|
const payload = request.postDataJSON() as { rejectionReason: string }
|
|
|
|
requests.push({ path: pathname, payload })
|
|
current = {
|
|
...current,
|
|
status: 'rejected',
|
|
publishedAt: null,
|
|
adminApprovedAt: null,
|
|
rejectionReason: payload.rejectionReason,
|
|
}
|
|
await route.fulfill({ json: { success: true, data: current } })
|
|
|
|
return
|
|
}
|
|
|
|
if (pathname.endsWith('/admin/events/event-1') && request.method() === 'GET') {
|
|
await route.fulfill({ json: { success: true, data: current } })
|
|
|
|
return
|
|
}
|
|
|
|
if (pathname.endsWith('/admin/events/event-1/insights')) {
|
|
await route.fulfill({ json: { success: true, data: hostInsights } })
|
|
|
|
return
|
|
}
|
|
|
|
if (pathname.endsWith('/event-categories') || pathname.includes('/event-categories?')) {
|
|
await route.fulfill({ json: { success: true, data: [] } })
|
|
|
|
return
|
|
}
|
|
|
|
if (pathname.endsWith('/geography/cities') || pathname.includes('/geography/cities?')) {
|
|
await route.fulfill({ json: { success: true, data: [] } })
|
|
|
|
return
|
|
}
|
|
|
|
if (pathname.endsWith('/geography/provinces') || pathname.includes('/geography/provinces?')) {
|
|
await route.fulfill({ json: { success: true, data: [] } })
|
|
|
|
return
|
|
}
|
|
|
|
if (pathname.endsWith('/events/event-1/media') || pathname.endsWith('/events/event-1/faqs')) {
|
|
await route.fulfill({ json: { success: true, data: [] } })
|
|
|
|
return
|
|
}
|
|
|
|
await route.fulfill({ json: { success: true, data: { items: [], response: { page: 1, pageSize: 20, totalItemsCount: 0 } } } })
|
|
})
|
|
|
|
return requests
|
|
}
|
|
|
|
test.beforeEach(async ({ context, page }) => {
|
|
await authenticateAs(context, page, 'admin')
|
|
})
|
|
|
|
test('admin approval publishes a pending-review event exactly once', async ({ page }) => {
|
|
const requests = await mockReviewEndpoints(page)
|
|
|
|
await page.goto('/manage-events/event-1')
|
|
await expect(page.getByRole('button', { name: 'تأیید و انتشار' })).toBeEnabled()
|
|
await page.getByRole('button', { name: 'تأیید و انتشار' }).click()
|
|
await page.getByRole('button', { name: 'تأیید' }).click()
|
|
|
|
await expect.poll(() => requests).toEqual([{ path: '/api/v1/admin/events/event-1/approve', payload: null }])
|
|
await expect(page.getByRole('button', { name: 'تأیید و انتشار' })).toHaveCount(0)
|
|
await expect(page.getByRole('button', { name: 'رد' })).toHaveCount(0)
|
|
})
|
|
|
|
test('admin rejection requires a reason and marks the event as rejected', async ({ page }) => {
|
|
const requests = await mockReviewEndpoints(page)
|
|
|
|
await page.goto('/manage-events/event-1')
|
|
await page.getByRole('button', { name: 'رد' }).click()
|
|
|
|
const reject = page.getByRole('button', { name: 'رد رویداد', exact: true })
|
|
|
|
await expect(reject).toBeDisabled()
|
|
|
|
await page.getByLabel('دلیل رد').fill(' زمان و مکان رویداد را اصلاح کنید ')
|
|
await expect(reject).toBeEnabled()
|
|
await reject.click()
|
|
|
|
await expect
|
|
.poll(() => requests)
|
|
.toEqual([
|
|
{
|
|
path: '/api/v1/admin/events/event-1/reject',
|
|
payload: { rejectionReason: 'زمان و مکان رویداد را اصلاح کنید' },
|
|
},
|
|
])
|
|
await expect(page.getByRole('button', { name: 'تأیید برای انتشار' })).toBeEnabled()
|
|
await expect(page.getByRole('button', { name: 'رد' })).toHaveCount(0)
|
|
})
|