test(e2e): align web specs with current app routes

This commit is contained in:
Ho Ngoc Hai
2026-05-04 20:11:09 +07:00
parent f112045826
commit 39156fc107
21 changed files with 334 additions and 458 deletions

View File

@@ -1,4 +1,5 @@
import { test, expect } from '@playwright/test';
import { mockAuthenticatedUser } from './support/auth';
const mockMarketReport = {
districts: [
@@ -35,15 +36,17 @@ const mockListings = {
};
test.describe('Dashboard Page', () => {
test.beforeEach(async ({ page }) => {
test.beforeEach(async ({ page, context, baseURL }) => {
await mockAuthenticatedUser(page, context, baseURL, { role: 'AGENT' });
// Mock all API calls
await page.route('**/analytics/market-report**', (route) =>
await page.route('**/api/v1/analytics/market-report**', (route) =>
route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(mockMarketReport) }),
);
await page.route('**/analytics/heatmap**', (route) =>
await page.route('**/api/v1/analytics/heatmap**', (route) =>
route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(mockHeatmap) }),
);
await page.route('**/listings**', (route) =>
await page.route('**/api/v1/listings**', (route) =>
route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(mockListings) }),
);
});
@@ -51,67 +54,68 @@ test.describe('Dashboard Page', () => {
test('renders dashboard with title and post button', async ({ page }) => {
await page.goto('/dashboard');
await expect(page.getByRole('heading', { name: 'Bang dieu khien' })).toBeVisible();
await expect(page.getByText('Tong quan thi truong va tin dang cua ban')).toBeVisible();
await expect(page.getByRole('link', { name: /Dang tin moi/i })).toBeVisible();
await expect(page.getByRole('heading', { name: 'Bng điều khin' })).toBeVisible();
await expect(page.getByText('Tng quan th trường và tin đăng ca bn')).toBeVisible();
await expect(page.getByRole('link', { name: /Đăng tin mi/i })).toBeVisible();
});
test('displays stat cards', async ({ page }) => {
await page.goto('/dashboard');
await expect(page.getByText('Tin dang cua toi')).toBeVisible({ timeout: 10000 });
await expect(page.getByText('Luot xem')).toBeVisible();
await expect(page.getByText('Lien he')).toBeVisible();
await expect(page.getByText('Gia TB thi truong')).toBeVisible();
const main = page.getByRole('main');
await expect(main.getByText('Tin đăng của tôi', { exact: true })).toBeVisible({ timeout: 10000 });
await expect(main.getByText('Lượt xem', { exact: true })).toBeVisible();
await expect(main.getByText('Liên hệ', { exact: true })).toBeVisible();
await expect(main.getByText('Giá TB thị trường', { exact: true })).toBeVisible();
});
test('shows market summary card', async ({ page }) => {
await page.goto('/dashboard');
await expect(page.getByText('Tin dang cua toi')).toBeVisible({ timeout: 10000 });
await expect(page.getByText('Tong tin dang')).toBeVisible();
await expect(page.getByText('Gia TB/m2')).toBeVisible();
await expect(page.getByText('Ngay TB de ban')).toBeVisible();
await expect(page.getByText('So quan')).toBeVisible();
await expect(page.getByText('Tin đăng ca tôi')).toBeVisible({ timeout: 10000 });
await expect(page.getByText('Tng tin đăng')).toBeVisible();
await expect(page.getByText('Giá TB/m²')).toBeVisible();
await expect(page.getByText('Ngày TB để bán')).toBeVisible();
await expect(page.getByText('S qun')).toBeVisible();
});
test('shows recent listings section', async ({ page }) => {
await page.goto('/dashboard');
await expect(page.getByText('Tin dang gan day')).toBeVisible({ timeout: 10000 });
await expect(page.getByText('Tin đăng gn đây')).toBeVisible({ timeout: 10000 });
await expect(page.getByText('Căn hộ test')).toBeVisible();
});
test('navigates to create listing page', async ({ page }) => {
await page.goto('/dashboard');
await expect(page.getByRole('heading', { name: 'Bang dieu khien' })).toBeVisible();
await expect(page.getByRole('heading', { name: 'Bng điều khin' })).toBeVisible();
await page.getByRole('link', { name: /Dang tin moi/i }).click();
await expect(page).toHaveURL(/\/listings\/new/);
await page.getByRole('link', { name: /Đăng tin mi/i }).click();
await expect(page).toHaveURL(/\/my-listings\/new/);
});
test('navigates to analytics page', async ({ page }) => {
await page.goto('/dashboard');
await expect(page.getByText('Xem phan tich chi tiet')).toBeVisible({ timeout: 10000 });
await expect(page.getByText('Xem phân tích chi tiết')).toBeVisible({ timeout: 10000 });
await page.getByText('Xem phan tich chi tiet').click();
await page.getByText('Xem phân tích chi tiết').click();
await expect(page).toHaveURL(/\/analytics/);
});
test('handles API failures gracefully', async ({ page }) => {
await page.route('**/analytics/market-report**', (route) =>
await page.route('**/api/v1/analytics/market-report**', (route) =>
route.fulfill({ status: 500, body: 'Error' }),
);
await page.route('**/analytics/heatmap**', (route) =>
await page.route('**/api/v1/analytics/heatmap**', (route) =>
route.fulfill({ status: 500, body: 'Error' }),
);
await page.route('**/listings**', (route) =>
await page.route('**/api/v1/listings**', (route) =>
route.fulfill({ status: 500, body: 'Error' }),
);
await page.goto('/dashboard');
// Page should still render (with fallback states)
await expect(page.getByRole('heading', { name: 'Bang dieu khien' })).toBeVisible();
await expect(page.getByRole('heading', { name: 'Bng điều khin' })).toBeVisible();
});
});