Files
goodgo-platform/e2e/web/search.spec.ts
Ho Ngoc Hai 8e82d346aa test(e2e): add 14 new web E2E test files for critical user flows
Cover auth (login, register, OAuth callbacks), search with filters,
listing detail, dashboard, analytics, create listing form, admin
dashboard/users/moderation/KYC, navigation routing, and responsive
design. Total 91 test cases using Playwright with API route mocking.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 13:14:17 +07:00

172 lines
5.0 KiB
TypeScript

import { test, expect } from '@playwright/test';
const mockListings = {
data: [
{
id: 'listing-1',
transactionType: 'SALE',
priceVND: '5000000000',
pricePerM2: 66666667,
rentPriceMonthly: null,
commissionPct: null,
status: 'ACTIVE',
viewCount: 120,
saveCount: 15,
inquiryCount: 8,
publishedAt: '2026-01-15T00:00:00Z',
property: {
id: 'prop-1',
propertyType: 'APARTMENT',
title: 'Căn hộ cao cấp Quận 1',
description: 'Căn hộ đẹp view sông',
address: '123 Nguyễn Huệ',
ward: 'Bến Nghé',
district: 'Quận 1',
city: 'Hồ Chí Minh',
latitude: 10.7769,
longitude: 106.7009,
areaM2: 75,
bedrooms: 2,
bathrooms: 2,
floors: 1,
direction: 'SOUTH',
yearBuilt: null,
legalStatus: null,
projectName: null,
amenities: [],
media: [],
},
seller: { id: 's1', fullName: 'Nguyen Van A', phone: '0912345678' },
agent: null,
},
{
id: 'listing-2',
transactionType: 'RENT',
priceVND: '15000000',
pricePerM2: null,
rentPriceMonthly: '15000000',
commissionPct: null,
status: 'ACTIVE',
viewCount: 50,
saveCount: 5,
inquiryCount: 3,
publishedAt: '2026-02-01T00:00:00Z',
property: {
id: 'prop-2',
propertyType: 'HOUSE',
title: 'Nhà phố Quận 7',
description: 'Nhà phố đẹp khu an ninh',
address: '456 Nguyễn Thị Thập',
ward: 'Tân Phú',
district: 'Quận 7',
city: 'Hồ Chí Minh',
latitude: 10.7385,
longitude: 106.7218,
areaM2: 120,
bedrooms: 4,
bathrooms: 3,
floors: 3,
direction: 'EAST',
yearBuilt: 2020,
legalStatus: null,
projectName: null,
amenities: [],
media: [],
},
seller: { id: 's2', fullName: 'Tran Thi B', phone: '0987654321' },
agent: null,
},
],
total: 2,
page: 1,
limit: 12,
totalPages: 1,
};
test.describe('Search Page', () => {
test.beforeEach(async ({ page }) => {
// Mock the listings API to return consistent data
await page.route('**/listings**', (route) => {
if (route.request().method() === 'GET') {
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(mockListings),
});
}
return route.continue();
});
});
test('renders search page with title and filters', async ({ page }) => {
await page.goto('/search');
await expect(page.getByRole('heading', { name: 'Tìm kiếm bất động sản' })).toBeVisible();
await expect(
page.getByText('Tìm bất động sản phù hợp với nhu cầu của bạn'),
).toBeVisible();
});
test('displays view mode toggle buttons', async ({ page }) => {
await page.goto('/search');
await expect(page.getByRole('button', { name: /Danh sách/i })).toBeVisible();
await expect(page.getByRole('button', { name: /Bản đồ/i })).toBeVisible();
});
test('displays listing results', async ({ page }) => {
await page.goto('/search');
await expect(page.getByText('Căn hộ cao cấp Quận 1')).toBeVisible({ timeout: 10000 });
await expect(page.getByText('Nhà phố Quận 7')).toBeVisible();
});
test('switches to map view mode', async ({ page }) => {
await page.goto('/search');
await page.getByRole('button', { name: /Bản đồ/i }).click();
// Map view should be active — list results should not be visible
await expect(page.getByRole('button', { name: /Bản đồ/i })).toHaveAttribute(
'data-state',
/.*/,
);
});
test('syncs filters to URL query parameters', async ({ page }) => {
await page.goto('/search?transactionType=SALE');
// The URL should contain the filter
await expect(page).toHaveURL(/transactionType=SALE/);
});
test('shows error state on API failure', async ({ page }) => {
await page.route('**/listings**', (route) =>
route.fulfill({ status: 500, body: 'Internal Server Error' }),
);
await page.goto('/search');
// Should show some error indication
await page.waitForTimeout(2000);
// The page should still be navigable (not crash)
await expect(page.getByRole('heading', { name: 'Tìm kiếm bất động sản' })).toBeVisible();
});
test('shows loading spinner initially', async ({ page }) => {
await page.route('**/listings**', async (route) => {
await new Promise((r) => setTimeout(r, 2000));
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(mockListings),
});
});
await page.goto('/search');
// Should show loading indication (spinner or skeleton)
const spinner = page.locator('.animate-spin, .animate-pulse');
await expect(spinner.first()).toBeVisible({ timeout: 3000 });
});
});