Files
goodgo-platform/e2e/web/agents.spec.ts
2026-05-04 20:11:09 +07:00

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
});
}
});