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>
This commit is contained in:
107
e2e/web/auth-login.spec.ts
Normal file
107
e2e/web/auth-login.spec.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Login Page', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/login');
|
||||
});
|
||||
|
||||
test('renders login form with all elements', async ({ page }) => {
|
||||
await expect(page.getByRole('heading', { name: 'Đăng nhập' })).toBeVisible();
|
||||
await expect(page.getByText('Nhập số điện thoại và mật khẩu để đăng nhập')).toBeVisible();
|
||||
|
||||
await expect(page.getByLabel('Số điện thoại')).toBeVisible();
|
||||
await expect(page.getByLabel('Mật khẩu')).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Đăng nhập' })).toBeVisible();
|
||||
|
||||
// OAuth buttons
|
||||
await expect(page.getByRole('button', { name: /Google/i })).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: /Zalo/i })).toBeVisible();
|
||||
|
||||
// Register link
|
||||
await expect(page.getByText('Chưa có tài khoản?')).toBeVisible();
|
||||
await expect(page.getByRole('link', { name: 'Đăng ký' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('shows validation errors for empty submission', async ({ page }) => {
|
||||
await page.getByRole('button', { name: 'Đăng nhập' }).click();
|
||||
|
||||
// Form validation should show error messages
|
||||
const alerts = page.locator('[role="alert"]');
|
||||
await expect(alerts.first()).toBeVisible();
|
||||
});
|
||||
|
||||
test('validates phone number format', async ({ page }) => {
|
||||
await page.getByLabel('Số điện thoại').fill('123');
|
||||
await page.getByLabel('Mật khẩu').fill('Test@1234!');
|
||||
await page.getByRole('button', { name: 'Đăng nhập' }).click();
|
||||
|
||||
const alerts = page.locator('[role="alert"]');
|
||||
await expect(alerts.first()).toBeVisible();
|
||||
});
|
||||
|
||||
test('toggles password visibility', async ({ page }) => {
|
||||
const passwordInput = page.getByLabel('Mật khẩu');
|
||||
await expect(passwordInput).toHaveAttribute('type', 'password');
|
||||
|
||||
// Click "Hiện" button to show password
|
||||
await page.getByRole('button', { name: 'Hiện' }).click();
|
||||
await expect(passwordInput).toHaveAttribute('type', 'text');
|
||||
|
||||
// Click "Ẩn" button to hide password
|
||||
await page.getByRole('button', { name: 'Ẩn' }).click();
|
||||
await expect(passwordInput).toHaveAttribute('type', 'password');
|
||||
});
|
||||
|
||||
test('navigates to register page', async ({ page }) => {
|
||||
await page.getByRole('link', { name: 'Đăng ký' }).click();
|
||||
await expect(page).toHaveURL(/\/register/);
|
||||
});
|
||||
|
||||
test('shows OAuth error message from query params', async ({ page }) => {
|
||||
await page.goto('/login?error=oauth_failed');
|
||||
await expect(
|
||||
page.getByText('Đăng nhập bằng mạng xã hội thất bại'),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('shows access denied OAuth error', async ({ page }) => {
|
||||
await page.goto('/login?error=access_denied');
|
||||
await expect(
|
||||
page.getByText('Bạn đã từ chối quyền truy cập'),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('submit button shows loading state during submission', async ({ page }) => {
|
||||
// Fill valid-looking data
|
||||
await page.getByLabel('Số điện thoại').fill('0912345678');
|
||||
await page.getByLabel('Mật khẩu').fill('Test@1234!');
|
||||
|
||||
// Intercept the API call to delay response
|
||||
await page.route('**/auth/login', async (route) => {
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
await route.fulfill({ status: 401, body: JSON.stringify({ message: 'Invalid credentials' }) });
|
||||
});
|
||||
|
||||
await page.getByRole('button', { name: 'Đăng nhập' }).click();
|
||||
|
||||
// Button should be disabled during loading
|
||||
await expect(page.getByRole('button', { name: 'Đăng nhập' })).toBeDisabled();
|
||||
});
|
||||
|
||||
test('displays server error on failed login', async ({ page }) => {
|
||||
await page.route('**/auth/login', (route) =>
|
||||
route.fulfill({
|
||||
status: 401,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ message: 'Sai số điện thoại hoặc mật khẩu' }),
|
||||
}),
|
||||
);
|
||||
|
||||
await page.getByLabel('Số điện thoại').fill('0912345678');
|
||||
await page.getByLabel('Mật khẩu').fill('WrongPass1!');
|
||||
await page.getByRole('button', { name: 'Đăng nhập' }).click();
|
||||
|
||||
const errorAlert = page.locator('[role="alert"]').filter({ hasNotText: /Số điện thoại|Mật khẩu/ });
|
||||
await expect(errorAlert.first()).toBeVisible({ timeout: 5000 });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user