Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
100 lines
3.5 KiB
TypeScript
100 lines
3.5 KiB
TypeScript
import { cleanup, render, screen } from '@testing-library/react'
|
|
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
import { AdminUserContactInfo, AdminUserOverview } from '@/features/admin-users/adminUserDetailUi'
|
|
import type { AdminUserDetail } from '@/services/adminUserDetail'
|
|
|
|
vi.mock('@/components/heroui/Card', () => ({
|
|
Card: ({ children }: { children: React.ReactNode }) => <section>{children}</section>,
|
|
CardBody: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
|
|
CardHeader: ({ children }: { children: React.ReactNode }) => <h2>{children}</h2>,
|
|
}))
|
|
vi.mock('@/components/heroui/Chip', () => ({
|
|
Chip: ({ children }: { children: React.ReactNode }) => <span>{children}</span>,
|
|
}))
|
|
vi.mock('@/components/ui/StatusChip', () => ({
|
|
default: ({ children, label }: { children?: React.ReactNode; label?: string }) => <span>{children ?? label}</span>,
|
|
}))
|
|
vi.mock('@/constants/status', () => ({
|
|
getBooleanStatus: (value: boolean, labels?: { true: string; false: string }) => ({
|
|
label: value ? (labels?.true ?? 'بله') : (labels?.false ?? 'خیر'),
|
|
}),
|
|
getIdentityStatus: () => ({ label: 'تأییدشده', chipColor: 'success' }),
|
|
getUserAccountStatus: () => ({ label: 'فعال', chipColor: 'success' }),
|
|
getUserRole: () => ({ label: 'کاربر', chipColor: 'default' }),
|
|
}))
|
|
vi.mock('@/lib/formatters', () => ({
|
|
formatIranianMobile: (mobile: string) => mobile,
|
|
formatPersianDate: () => 'تاریخ',
|
|
}))
|
|
vi.mock('@/helpers', () => ({
|
|
formatNumber: (value: number) => String(value),
|
|
}))
|
|
|
|
const detail = {
|
|
bio: 'درباره میزبان',
|
|
defaultAddress: 'تهران، خیابان ولیعصر',
|
|
contactLinks: [
|
|
{
|
|
id: 'link-1',
|
|
channel: 'instagram',
|
|
label: 'اینستاگرام',
|
|
value: 'public_host',
|
|
url: 'https://instagram.com/public_host',
|
|
isPublic: true,
|
|
displayOrder: 1,
|
|
},
|
|
{
|
|
id: 'link-2',
|
|
channel: 'telegram',
|
|
label: 'تلگرام',
|
|
value: 'private_host',
|
|
url: 'https://t.me/private_host',
|
|
isPublic: false,
|
|
displayOrder: 2,
|
|
},
|
|
],
|
|
} as AdminUserDetail
|
|
|
|
const overviewDetail = {
|
|
mobile: '09121234567',
|
|
cityName: 'مشهد',
|
|
role: 'user',
|
|
status: 'active',
|
|
identityStatus: 'verified',
|
|
walletBalance: 0,
|
|
lastLoginAt: null,
|
|
createdAt: '2024-01-01T00:00:00.000Z',
|
|
dateOfBirth: null,
|
|
} as AdminUserDetail
|
|
|
|
describe('AdminUserContactInfo', () => {
|
|
afterEach(cleanup)
|
|
|
|
it('shows all user contact links to admins, including private links', () => {
|
|
render(<AdminUserContactInfo detail={detail} />)
|
|
|
|
expect(screen.getByRole('link', { name: 'public_host' })).toHaveAttribute('href', 'https://instagram.com/public_host')
|
|
expect(screen.getByRole('link', { name: 'private_host' })).toHaveAttribute('href', 'https://t.me/private_host')
|
|
expect(screen.getByText('عمومی')).toBeInTheDocument()
|
|
expect(screen.getByText('فقط شرکتکنندگان')).toBeInTheDocument()
|
|
})
|
|
|
|
it('shows the empty state when no contact information exists', () => {
|
|
render(<AdminUserContactInfo detail={{ ...detail, bio: null, defaultAddress: null, contactLinks: [] }} />)
|
|
|
|
expect(screen.getByText('هنوز آدرس ثابت یا لینک تماسی ثبت نشده است.')).toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('AdminUserOverview', () => {
|
|
afterEach(cleanup)
|
|
|
|
it('shows profile city next to mobile', () => {
|
|
render(<AdminUserOverview detail={overviewDetail} />)
|
|
|
|
expect(screen.getByText('09121234567')).toBeInTheDocument()
|
|
expect(screen.getByText('مشهد')).toBeInTheDocument()
|
|
})
|
|
})
|