test(web): add component tests for 10 untested frontend components (GOO-54)
Cover critical-path and feature components that were missing tests: - charts: district-heatmap - chuyen-nhuong: detail-client, transfer-wizard-client - du-an: detail-client, project-ai-advice-card, project-map - khu-cong-nghiep: detail-client, listing-search-client, park-compare-client, park-map All 49 new tests pass with Vitest + React Testing Library. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import type { HeatmapPoint } from '../district-heatmap';
|
||||
|
||||
vi.mock('mapbox-gl', () => {
|
||||
class MockMap {
|
||||
addControl = vi.fn();
|
||||
fitBounds = vi.fn();
|
||||
setStyle = vi.fn();
|
||||
remove = vi.fn();
|
||||
on = vi.fn();
|
||||
}
|
||||
class MockNavigationControl {}
|
||||
class MockMarker {
|
||||
setLngLat() { return this; }
|
||||
setPopup() { return this; }
|
||||
addTo() { return this; }
|
||||
remove() {}
|
||||
}
|
||||
class MockPopup {
|
||||
setHTML() { return this; }
|
||||
setLngLat() { return this; }
|
||||
addTo() { return this; }
|
||||
remove() {}
|
||||
}
|
||||
class MockLngLatBounds {
|
||||
extend() { return this; }
|
||||
isEmpty() { return false; }
|
||||
}
|
||||
return {
|
||||
default: {
|
||||
accessToken: '',
|
||||
Map: MockMap,
|
||||
NavigationControl: MockNavigationControl,
|
||||
Marker: MockMarker,
|
||||
Popup: MockPopup,
|
||||
LngLatBounds: MockLngLatBounds,
|
||||
},
|
||||
};
|
||||
});
|
||||
vi.mock('mapbox-gl/dist/mapbox-gl.css', () => ({}));
|
||||
vi.mock('@/lib/mapbox-style', () => ({
|
||||
useMapboxStyle: () => 'mapbox://styles/mapbox/light-v11',
|
||||
MAPBOX_STYLE_DARK: 'mapbox://styles/mapbox/dark-v11',
|
||||
}));
|
||||
|
||||
import { DistrictHeatmap } from '../district-heatmap';
|
||||
|
||||
const sampleData: HeatmapPoint[] = [
|
||||
{ district: 'Quan 1', avgPriceM2: 80_000_000, totalListings: 120, medianPrice: '7500000000' },
|
||||
{ district: 'Quan 7', avgPriceM2: 45_000_000, totalListings: 85, medianPrice: '4500000000' },
|
||||
];
|
||||
|
||||
describe('DistrictHeatmap', () => {
|
||||
it('renders the map container', () => {
|
||||
render(<DistrictHeatmap data={sampleData} city="Ho Chi Minh" />);
|
||||
// Legend is always visible
|
||||
expect(screen.getByText('Giá trung bình/m²')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows token missing fallback when NEXT_PUBLIC_MAPBOX_TOKEN is absent', () => {
|
||||
delete (process.env as Record<string, string | undefined>)['NEXT_PUBLIC_MAPBOX_TOKEN'];
|
||||
render(<DistrictHeatmap data={[]} city="Ho Chi Minh" />);
|
||||
expect(screen.getByText(/NEXT_PUBLIC_MAPBOX_TOKEN/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders legend labels', () => {
|
||||
render(<DistrictHeatmap data={sampleData} city="Ho Chi Minh" />);
|
||||
expect(screen.getByText('Thấp')).toBeInTheDocument();
|
||||
expect(screen.getByText('Cao')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('accepts optional className', () => {
|
||||
const { container } = render(
|
||||
<DistrictHeatmap data={sampleData} city="Ho Chi Minh" className="h-[600px]" />,
|
||||
);
|
||||
expect(container.firstChild).toHaveClass('h-[600px]');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user