119 lines
4.1 KiB
TypeScript
119 lines
4.1 KiB
TypeScript
/**
|
|
* Agents Page E2E Tests
|
|
*
|
|
* Tests the agent profile page at /agents/[id].
|
|
* The app does not have a public agent listing page, only individual agent profiles.
|
|
* Tests use route mocking to avoid API dependency.
|
|
*/
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
import { mockAuthenticatedUser } from './support/auth';
|
|
|
|
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, context, baseURL }) => {
|
|
await mockAuthenticatedUser(page, context, baseURL, { role: 'AGENT' });
|
|
});
|
|
|
|
test('renders agent name and verified badge', async ({ page }) => {
|
|
await page.goto(`/agents/${seededAgentId}`);
|
|
|
|
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/${seededAgentId}`);
|
|
|
|
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 listings and reviews sections', async ({ page }) => {
|
|
await page.goto(`/agents/${seededAgentId}`);
|
|
|
|
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/${seededAgentId}`);
|
|
|
|
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 }) => {
|
|
const criticalErrors: string[] = [];
|
|
page.on('console', (msg) => {
|
|
if (msg.type() === 'error') {
|
|
const text = msg.text();
|
|
if (
|
|
text.includes('mapbox') ||
|
|
text.includes('NEXT_PUBLIC') ||
|
|
text.includes('net::ERR') ||
|
|
text.includes('Failed to load resource')
|
|
) {
|
|
return;
|
|
}
|
|
criticalErrors.push(text);
|
|
}
|
|
});
|
|
|
|
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 }) => {
|
|
const res = await page.goto('/agents/nonexistent-agent-id');
|
|
const status = res?.status();
|
|
if (status && status >= 500) {
|
|
throw new Error(`Agent page returned ${status} for unknown ID (expected 404 or redirect)`);
|
|
}
|
|
});
|
|
});
|
|
|
|
test.describe('Agent Profile — Responsive', () => {
|
|
const viewports = [
|
|
{ label: '375px (mobile)', width: 375, height: 667 },
|
|
{ label: '768px (tablet)', width: 768, height: 1024 },
|
|
{ label: '1280px (laptop)', width: 1280, height: 800 },
|
|
{ label: '1920px (desktop)', width: 1920, height: 1080 },
|
|
];
|
|
|
|
for (const vp of viewports) {
|
|
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/${seededAgentId}`);
|
|
|
|
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);
|
|
const viewportWidth = await page.evaluate(() => window.innerWidth);
|
|
expect(bodyWidth).toBeLessThanOrEqual(viewportWidth + 2); // 2px tolerance
|
|
});
|
|
}
|
|
});
|