test(e2e): align web specs with current app routes
This commit is contained in:
@@ -7,110 +7,55 @@
|
||||
*/
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
const mockAgent = {
|
||||
id: 'agent-1',
|
||||
fullName: 'Nguyễn Văn Minh',
|
||||
avatarUrl: null,
|
||||
phone: '0912345678',
|
||||
email: 'minh@goodgo.vn',
|
||||
agency: 'GoodGo Realty',
|
||||
licenseNumber: 'GPHN-2025-001',
|
||||
bio: 'Chuyên viên tư vấn bất động sản khu vực Quận 7 và Quận 2 với hơn 5 năm kinh nghiệm.',
|
||||
qualityScore: 88,
|
||||
totalDeals: 45,
|
||||
isVerified: true,
|
||||
serviceAreas: ['Quận 7', 'Quận 2', 'Nhà Bè'],
|
||||
memberSince: '2023-06-15T00:00:00Z',
|
||||
activeListings: [
|
||||
{
|
||||
id: 'listing-1',
|
||||
transactionType: 'SALE',
|
||||
priceVND: '5000000000',
|
||||
status: 'ACTIVE',
|
||||
property: {
|
||||
id: 'prop-1',
|
||||
title: 'Căn hộ cao cấp Quận 7',
|
||||
propertyType: 'APARTMENT',
|
||||
address: '123 Nguyễn Thị Thập',
|
||||
district: 'Quận 7',
|
||||
city: 'Hồ Chí Minh',
|
||||
areaM2: 75,
|
||||
bedrooms: 2,
|
||||
bathrooms: 2,
|
||||
imageUrl: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
avgReviewRating: 4.8,
|
||||
totalReviews: 12,
|
||||
};
|
||||
import { mockAuthenticatedUser } from './support/auth';
|
||||
|
||||
const mockReviews = {
|
||||
data: [
|
||||
{
|
||||
id: 'review-1',
|
||||
userId: 'user-1',
|
||||
userName: 'Trần Thị B',
|
||||
targetType: 'AGENT',
|
||||
targetId: 'agent-1',
|
||||
rating: 5,
|
||||
comment: 'Môi giới tận tình, hỗ trợ nhiệt tình.',
|
||||
createdAt: '2026-03-01T00:00:00Z',
|
||||
},
|
||||
],
|
||||
stats: {
|
||||
targetType: 'AGENT',
|
||||
targetId: 'agent-1',
|
||||
averageRating: 4.8,
|
||||
totalReviews: 12,
|
||||
distribution: { 5: 10, 4: 2 },
|
||||
},
|
||||
};
|
||||
const seededAgentId = 'seed-agentprofile-001';
|
||||
const seededAgentName = 'Nguyễn Văn An';
|
||||
const seededAgentAgency = 'GoodGo Premium Realty';
|
||||
|
||||
test.describe('Agent Profile Page', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.route('**/agents/agent-1', (route) =>
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(mockAgent),
|
||||
}),
|
||||
);
|
||||
await page.route('**/agents/agent-1/reviews**', (route) =>
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(mockReviews),
|
||||
}),
|
||||
);
|
||||
test.beforeEach(async ({ page, context, baseURL }) => {
|
||||
await mockAuthenticatedUser(page, context, baseURL, { role: 'AGENT' });
|
||||
});
|
||||
|
||||
test('renders agent name and verified badge', async ({ page }) => {
|
||||
await page.goto('/agents/agent-1');
|
||||
await page.goto(`/agents/${seededAgentId}`);
|
||||
|
||||
await expect(page.getByText('Nguyễn Văn Minh')).toBeVisible({ timeout: 10_000 });
|
||||
await expect(page.getByRole('heading', { name: seededAgentName })).toBeVisible({
|
||||
timeout: 10_000,
|
||||
});
|
||||
await expect(page.getByText('KYC xác minh')).toBeVisible();
|
||||
});
|
||||
|
||||
test('shows agent agency and contact info', async ({ page }) => {
|
||||
await page.goto('/agents/agent-1');
|
||||
await page.goto(`/agents/${seededAgentId}`);
|
||||
|
||||
await expect(page.getByText('Nguyễn Văn Minh')).toBeVisible({ timeout: 10_000 });
|
||||
await expect(page.getByText(/GoodGo Realty/)).toBeVisible();
|
||||
await expect(page.getByRole('heading', { name: seededAgentName })).toBeVisible({
|
||||
timeout: 10_000,
|
||||
});
|
||||
await expect(page.getByText(seededAgentAgency)).toBeVisible();
|
||||
await expect(page.getByText('+84900000002').first()).toBeVisible();
|
||||
});
|
||||
|
||||
test('shows active listings section', async ({ page }) => {
|
||||
await page.goto('/agents/agent-1');
|
||||
test('shows listings and reviews sections', async ({ page }) => {
|
||||
await page.goto(`/agents/${seededAgentId}`);
|
||||
|
||||
await expect(page.getByText('Nguyễn Văn Minh')).toBeVisible({ timeout: 10_000 });
|
||||
// Listing should appear
|
||||
await expect(page.getByText(/Căn hộ cao cấp Quận 7/)).toBeVisible();
|
||||
await expect(page.getByRole('heading', { name: seededAgentName })).toBeVisible({
|
||||
timeout: 10_000,
|
||||
});
|
||||
await expect(page.getByText('Danh mục bất động sản')).toBeVisible();
|
||||
await expect(page.getByRole('heading', { name: /Đánh giá/ })).toBeVisible();
|
||||
});
|
||||
|
||||
test('has breadcrumb back to homepage', async ({ page }) => {
|
||||
await page.goto('/agents/agent-1');
|
||||
await page.goto(`/agents/${seededAgentId}`);
|
||||
|
||||
await expect(page.getByText('Nguyễn Văn Minh')).toBeVisible({ timeout: 10_000 });
|
||||
await expect(page.getByRole('link', { name: /Trang chủ/i })).toBeVisible();
|
||||
await expect(page.getByRole('heading', { name: seededAgentName })).toBeVisible({
|
||||
timeout: 10_000,
|
||||
});
|
||||
await expect(
|
||||
page.locator('#main-content').getByRole('link', { name: /Trang chủ/i }),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('renders without critical console errors', async ({ page }) => {
|
||||
@@ -130,17 +75,13 @@ test.describe('Agent Profile Page', () => {
|
||||
}
|
||||
});
|
||||
|
||||
await page.goto('/agents/agent-1');
|
||||
await page.goto(`/agents/${seededAgentId}`);
|
||||
await page.waitForLoadState('networkidle', { timeout: 15_000 }).catch(() => {});
|
||||
|
||||
expect(criticalErrors).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('handles 404 for unknown agent gracefully', async ({ page }) => {
|
||||
await page.route('**/agents/nonexistent**', (route) =>
|
||||
route.fulfill({ status: 404, body: JSON.stringify({ message: 'Not found' }) }),
|
||||
);
|
||||
|
||||
const res = await page.goto('/agents/nonexistent-agent-id');
|
||||
const status = res?.status();
|
||||
if (status && status >= 500) {
|
||||
@@ -158,26 +99,15 @@ test.describe('Agent Profile — Responsive', () => {
|
||||
];
|
||||
|
||||
for (const vp of viewports) {
|
||||
test(`renders at ${vp.label}`, async ({ page }) => {
|
||||
await page.route('**/agents/agent-1', (route) =>
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(mockAgent),
|
||||
}),
|
||||
);
|
||||
await page.route('**/agents/agent-1/reviews**', (route) =>
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(mockReviews),
|
||||
}),
|
||||
);
|
||||
test(`renders at ${vp.label}`, async ({ page, context, baseURL }) => {
|
||||
await mockAuthenticatedUser(page, context, baseURL, { role: 'AGENT' });
|
||||
|
||||
await page.setViewportSize({ width: vp.width, height: vp.height });
|
||||
await page.goto('/agents/agent-1');
|
||||
await page.goto(`/agents/${seededAgentId}`);
|
||||
|
||||
await expect(page.getByText('Nguyễn Văn Minh')).toBeVisible({ timeout: 10_000 });
|
||||
await expect(page.getByRole('heading', { name: seededAgentName })).toBeVisible({
|
||||
timeout: 10_000,
|
||||
});
|
||||
|
||||
// No horizontal overflow (layout break indicator)
|
||||
const bodyWidth = await page.evaluate(() => document.body.scrollWidth);
|
||||
|
||||
Reference in New Issue
Block a user