test(web): increase frontend test coverage to ~70% page coverage

- Fix vitest config to include [locale] directory tests (was excluded)
- Fix register.spec.tsx: use getByRole('heading') to avoid duplicate text match
- Fix search.spec.tsx: add QueryClientProvider wrapper and mock saved searches hook
- Add 12 new page test files covering dashboard, admin, public, and OAuth pages:
  - dashboard (main, profile, payments, subscription, KYC)
  - admin (dashboard, users)
  - public (landing, pricing)
  - analytics
  - OAuth callbacks (Google, Zalo)
- 29 test files, 174 tests, 16/23 pages covered (69.6%)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-10 23:14:16 +07:00
parent d62eb5f164
commit 68b65cb848
15 changed files with 1122 additions and 7 deletions

View File

@@ -0,0 +1,78 @@
/* eslint-disable import-x/order */
import { render, screen, waitFor } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
vi.mock('next/dynamic', () => ({
default: () => {
const Mock = () => <div data-testid="chart-placeholder">Chart</div>;
Mock.displayName = 'MockChart';
return Mock;
},
}));
const mockMarketReport = {
districts: [
{ district: 'Quan 1', totalListings: 100, avgPriceM2: 120000000, medianPrice: '15000000000', daysOnMarket: 45, yoyChange: 5.2, inventoryLevel: 50 },
],
};
const mockHeatmap = {
dataPoints: [
{ district: 'Quan 1', avgPriceM2: 120000000, totalListings: 100, lat: 10.77, lng: 106.7 },
],
};
const mockDistrictStats = {
districts: [
{ district: 'Quan 1', propertyType: 'APARTMENT', medianPrice: '15000000000', avgPriceM2: 120000000, totalListings: 100, daysOnMarket: 45, yoyChange: 5.2 },
],
};
const mockPriceTrend = {
trend: [
{ period: '2025-Q4', avgPriceM2: 115000000, totalListings: 90 },
{ period: '2026-Q1', avgPriceM2: 120000000, totalListings: 100 },
],
};
vi.mock('@/lib/hooks/use-analytics', () => ({
useMarketReport: vi.fn(() => ({ data: mockMarketReport, isLoading: false, error: null })),
useHeatmap: vi.fn(() => ({ data: mockHeatmap, isLoading: false })),
useDistrictStats: vi.fn(() => ({ data: mockDistrictStats, isLoading: false })),
usePriceTrend: vi.fn(() => ({ data: mockPriceTrend, isLoading: false })),
}));
import AnalyticsPage from '../page';
describe('AnalyticsPage', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('renders analytics page heading', () => {
render(<AnalyticsPage />);
expect(screen.getByText('Phân tích thị trường')).toBeInTheDocument();
});
it('renders summary cards', () => {
render(<AnalyticsPage />);
expect(screen.getByText('Tổng tin đăng')).toBeInTheDocument();
expect(screen.getByText('Giá TB/m²')).toBeInTheDocument();
expect(screen.getByText('Ngày trung bình để bán')).toBeInTheDocument();
});
it('renders city selection buttons', () => {
render(<AnalyticsPage />);
expect(screen.getByRole('button', { name: 'Ho Chi Minh' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Ha Noi' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Da Nang' })).toBeInTheDocument();
});
it('renders tab navigation', () => {
render(<AnalyticsPage />);
expect(screen.getByText('Tổng quan')).toBeInTheDocument();
expect(screen.getByText('Xu hướng giá')).toBeInTheDocument();
expect(screen.getByText('Chi tiết quận')).toBeInTheDocument();
expect(screen.getByText('Hiệu suất')).toBeInTheDocument();
});
});