import { render, screen } from '@testing-library/react'; import { describe, expect, it, vi } from 'vitest'; import type { ListingDetail } from '@/lib/listings-api'; import { PropertyCard } from '../property-card'; // Mock next/image vi.mock('next/image', () => ({ default: (props: Record) => { return ; }, })); // Mock next/link vi.mock('next/link', () => ({ default: ({ children, href }: { children: React.ReactNode; href: string }) => ( {children} ), })); // Mock AddToCompareButton vi.mock('@/components/comparison/add-to-compare-button', () => ({ AddToCompareButton: ({ listingId }: { listingId: string }) => ( ), })); // Mock image-blur vi.mock('@/lib/image-blur', () => ({ shimmerBlurDataURL: () => 'data:image/svg+xml;base64,mock', })); function makeListing(overrides: Partial = {}): ListingDetail { return { id: 'listing-1', status: 'ACTIVE', transactionType: 'SALE', priceVND: '3500000000', pricePerM2: 40_000_000, rentPriceMonthly: null, commissionPct: null, viewCount: 100, saveCount: 10, inquiryCount: 5, publishedAt: '2026-01-01T00:00:00Z', createdAt: '2025-12-01T00:00:00Z', property: { id: 'prop-1', propertyType: 'APARTMENT', title: 'Căn hộ 2PN Vinhomes Central Park', description: 'Căn hộ đẹp view sông', address: '208 Nguyễn Hữu Cảnh', ward: 'Phường 22', district: 'Quận Bình Thạnh', city: 'Hồ Chí Minh', areaM2: 75, bedrooms: 2, bathrooms: 2, floors: null, direction: 'SOUTH', yearBuilt: 2020, legalStatus: null, amenities: [], projectName: 'Vinhomes Central Park', latitude: 10.7975, longitude: 106.721, media: [ { id: 'media-1', type: 'image', url: 'https://example.com/img1.jpg', order: 0, caption: null }, { id: 'media-2', type: 'image', url: 'https://example.com/img2.jpg', order: 1, caption: null }, ], }, seller: { id: 'seller-1', fullName: 'Nguyen Van B', phone: '0912345678', }, agent: null, ...overrides, }; } describe('PropertyCard', () => { it('renders property title', () => { render(); expect(screen.getByText('Căn hộ 2PN Vinhomes Central Park')).toBeInTheDocument(); }); it('renders formatted price', () => { render(); expect(screen.getByText(/3\.5 tỷ/)).toBeInTheDocument(); }); it('renders property address', () => { render(); expect(screen.getByText(/208 Nguyễn Hữu Cảnh/)).toBeInTheDocument(); }); it('renders transaction type badge for SALE', () => { render(); expect(screen.getByText('Bán')).toBeInTheDocument(); }); it('renders transaction type badge for RENT', () => { render(); expect(screen.getByText('Cho thuê')).toBeInTheDocument(); }); it('renders property type badge', () => { render(); expect(screen.getByText('Căn hộ')).toBeInTheDocument(); }); it('renders area badge', () => { render(); expect(screen.getByText('75 m²')).toBeInTheDocument(); }); it('renders bedrooms badge', () => { render(); expect(screen.getByText('2 PN')).toBeInTheDocument(); }); it('renders bathrooms badge', () => { render(); expect(screen.getByText('2 PT')).toBeInTheDocument(); }); it('renders direction badge when set', () => { render(); expect(screen.getByText('Hướng Nam')).toBeInTheDocument(); }); it('does not render direction badge when null', () => { const listing = makeListing(); listing.property.direction = null; render(); expect(screen.queryByText(/Hướng/)).not.toBeInTheDocument(); }); it('shows photo count badge when multiple images', () => { render(); expect(screen.getByText('2 ảnh')).toBeInTheDocument(); }); it('does not show photo count when single image', () => { const listing = makeListing(); listing.property.media = [{ id: 'media-1', type: 'image', url: 'https://example.com/img1.jpg', order: 0, caption: null }]; render(); expect(screen.queryByText(/\d+ ảnh/)).not.toBeInTheDocument(); }); it('shows "Chưa có ảnh" placeholder when no media', () => { const listing = makeListing(); listing.property.media = []; render(); expect(screen.getByText('Chưa có ảnh')).toBeInTheDocument(); }); it('links to listing detail page', () => { render(); const link = screen.getByRole('link'); expect(link).toHaveAttribute('href', '/listings/listing-1'); }); it('renders article with descriptive aria-label', () => { render(); expect(screen.getByRole('article')).toHaveAttribute( 'aria-label', expect.stringContaining('Căn hộ 2PN Vinhomes Central Park'), ); }); it('does not render bedrooms badge when null', () => { const listing = makeListing(); listing.property.bedrooms = null; render(); expect(screen.queryByText(/^\d+ PN$/)).not.toBeInTheDocument(); }); it('does not render bathrooms badge when 0', () => { const listing = makeListing(); listing.property.bathrooms = 0; render(); expect(screen.queryByText(/PT/)).not.toBeInTheDocument(); }); it('renders compare button', () => { render(); expect(screen.getByTestId('compare-btn-listing-1')).toBeInTheDocument(); }); it('shows rent price suffix for rental listings', () => { const listing = makeListing({ transactionType: 'RENT', rentPriceMonthly: '15000000', }); render(); expect(screen.getByText('/tháng')).toBeInTheDocument(); }); });