import { render, screen } from '@testing-library/react'; import { describe, expect, it, vi } from 'vitest'; vi.mock('next/dynamic', () => ({ __esModule: true, default: () => { const Stub = () =>
; Stub.displayName = 'DynamicStub'; return Stub; }, })); vi.mock('next/image', () => ({ __esModule: true, default: (props: Record) => , })); vi.mock('@/lib/analytics-api', () => ({ analyticsApi: { getNearbyPOIs: vi.fn().mockResolvedValue({ pois: [] }), getProjectAiAdvice: vi.fn(), }, })); vi.mock('@/lib/listings-api', () => ({ listingsApi: { getNeighborhoodScore: vi.fn().mockRejectedValue(new Error('noop')) }, })); vi.mock('@/lib/du-an-api', () => ({ PROJECT_PROPERTY_TYPE_LABELS: { APARTMENT: 'Căn hộ', VILLA: 'Biệt thự' }, PROJECT_STATUS_COLORS: { PRE_SALE: 'bg-blue-100 text-blue-800', SELLING: 'bg-green-100 text-green-800' }, PROJECT_STATUS_LABELS: { PRE_SALE: 'Mở bán sắp tới', SELLING: 'Đang bán' }, duAnApi: { submitInquiry: vi.fn() }, })); vi.mock('@/lib/currency', () => ({ formatPrice: (v: string | number) => `${v} VNĐ`, })); vi.mock('@/lib/project-personas', () => ({ composeWhyThisProject: () => null, deriveProjectPersonas: () => [], })); vi.mock('@/components/du-an/project-ai-advice-card', () => ({ ProjectAiAdviceCard: () =>
, })); vi.mock('@/components/listings/image-gallery', () => ({ ImageGallery: () =>
, })); import { DuAnDetailClient } from '../du-an-detail-client'; const project = { id: 'p1', name: 'Vinhomes Grand Park', slug: 'vinhomes-grand-park', status: 'SELLING' as const, propertyTypes: ['APARTMENT' as const], address: '128 Nguyễn Xiển', district: 'Quận 9', city: 'Hồ Chí Minh', latitude: 10.84, longitude: 106.83, description: 'Dự án lớn nhất TP.HCM', totalArea: 271000, totalUnits: 43000, minPrice: '2000000000', completionDate: '2025-12-01', developer: { name: 'Vingroup', logoUrl: null, totalProjects: 12 }, blocks: [{ id: 'b1', name: 'S1', totalUnits: 500, availableUnits: 20, floors: 35 }], amenities: [{ id: 'a1', name: 'Hồ bơi', category: 'Thể thao' }], priceRanges: [], priceHistory: [], media: [], linkedListingCount: 5, pois: [], neighborhoodScores: [], documents: [], suitableFor: [], whyThisLocation: null, } as never; describe('DuAnDetailClient', () => { it('renders project name', () => { render(); expect(screen.getByText('Vinhomes Grand Park')).toBeInTheDocument(); }); it('renders status badge', () => { render(); expect(screen.getByText('Đang bán')).toBeInTheDocument(); }); it('renders property type badge', () => { render(); expect(screen.getByText('Căn hộ')).toBeInTheDocument(); }); it('renders developer name', () => { render(); expect(screen.getAllByText('Vingroup').length).toBeGreaterThan(0); }); it('renders quick stats', () => { render(); expect(screen.getByText(/271\.000/)).toBeInTheDocument(); // total area expect(screen.getByText('43000')).toBeInTheDocument(); // total units }); it('renders blocks section', () => { render(); expect(screen.getByText('Phân khu / Block')).toBeInTheDocument(); expect(screen.getByText('S1')).toBeInTheDocument(); }); it('renders inquiry form', () => { render(); expect(screen.getAllByText('Nhận tư vấn').length).toBeGreaterThan(0); expect(screen.getByLabelText('Họ tên')).toBeInTheDocument(); expect(screen.getByLabelText('Số điện thoại')).toBeInTheDocument(); }); it('renders tabs', () => { render(); expect(screen.getByRole('tab', { name: 'Tiện ích' })).toBeInTheDocument(); expect(screen.getByRole('tab', { name: 'Vị trí' })).toBeInTheDocument(); expect(screen.getByRole('tab', { name: 'Giá' })).toBeInTheDocument(); }); });