fix: stabilize web e2e locale and timeout
This commit is contained in:
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -149,7 +149,7 @@ jobs:
|
|||||||
name: E2E Tests
|
name: E2E Tests
|
||||||
needs: ci
|
needs: ci
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 20
|
timeout-minutes: 45
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
|
|||||||
2
.github/workflows/e2e.yml
vendored
2
.github/workflows/e2e.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
|||||||
e2e:
|
e2e:
|
||||||
name: Playwright E2E
|
name: Playwright E2E
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 20
|
timeout-minutes: 45
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
|
|||||||
@@ -3,6 +3,14 @@ const createNextIntlPlugin = require('next-intl/plugin');
|
|||||||
|
|
||||||
const withNextIntl = createNextIntlPlugin('./i18n/request.ts');
|
const withNextIntl = createNextIntlPlugin('./i18n/request.ts');
|
||||||
|
|
||||||
|
function getPublicApiOrigin() {
|
||||||
|
try {
|
||||||
|
return process.env.NEXT_PUBLIC_API_URL ? new URL(process.env.NEXT_PUBLIC_API_URL).origin : '';
|
||||||
|
} catch {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
@@ -52,7 +60,7 @@ const nextConfig = {
|
|||||||
"style-src 'self' 'unsafe-inline' https://api.mapbox.com",
|
"style-src 'self' 'unsafe-inline' https://api.mapbox.com",
|
||||||
"img-src 'self' data: blob: https://*.mapbox.com https://*.tiles.mapbox.com https:",
|
"img-src 'self' data: blob: https://*.mapbox.com https://*.tiles.mapbox.com https:",
|
||||||
"font-src 'self' data:",
|
"font-src 'self' data:",
|
||||||
`connect-src 'self' https://*.mapbox.com https://api.mapbox.com https://events.mapbox.com https://api.goodgo.vn${process.env.NODE_ENV !== 'production' ? ' http://localhost:3001 http://localhost:3011 http://localhost:3200 http://localhost:3201 http://localhost:9000 ws://localhost:3001 ws://localhost:3011 ws://localhost:3200 ws://localhost:3201' : ''}`,
|
`connect-src 'self' https://*.mapbox.com https://api.mapbox.com https://events.mapbox.com https://api.goodgo.vn${process.env.NODE_ENV !== 'production' ? ` ${getPublicApiOrigin()} http://localhost:3001 http://localhost:3011 http://localhost:3200 http://localhost:3201 http://localhost:9000 ws://localhost:3001 ws://localhost:3011 ws://localhost:3200 ws://localhost:3201` : ''}`,
|
||||||
"worker-src 'self' blob:",
|
"worker-src 'self' blob:",
|
||||||
"child-src 'self' blob:",
|
"child-src 'self' blob:",
|
||||||
"frame-ancestors 'none'",
|
"frame-ancestors 'none'",
|
||||||
|
|||||||
@@ -1,4 +1,20 @@
|
|||||||
import { test, expect } from '@playwright/test';
|
import { test, expect, type Route } from '@playwright/test';
|
||||||
|
|
||||||
|
async function fulfillJson(route: Route, status: number, body: unknown) {
|
||||||
|
const origin = route.request().headers()['origin'] ?? '*';
|
||||||
|
|
||||||
|
await route.fulfill({
|
||||||
|
status,
|
||||||
|
contentType: 'application/json',
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin': origin,
|
||||||
|
'Access-Control-Allow-Credentials': 'true',
|
||||||
|
'Access-Control-Allow-Headers': 'content-type,x-csrf-token',
|
||||||
|
'Access-Control-Allow-Methods': 'GET,POST,OPTIONS',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
test.describe('Register Page', () => {
|
test.describe('Register Page', () => {
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
@@ -6,12 +22,12 @@ test.describe('Register Page', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('renders registration form with all fields', async ({ page }) => {
|
test('renders registration form with all fields', async ({ page }) => {
|
||||||
await expect(page.getByRole('heading', { name: 'Tạo tài khoản' })).toBeVisible();
|
await expect(page.getByRole('heading', { name: 'Đăng ký' })).toBeVisible();
|
||||||
await expect(page.getByText('Nhập thông tin để đăng ký tài khoản GoodGo')).toBeVisible();
|
await expect(page.getByText('Tạo tài khoản mới để bắt đầu sử dụng GoodGo')).toBeVisible();
|
||||||
|
|
||||||
await expect(page.getByLabel('Họ và tên')).toBeVisible();
|
await expect(page.getByLabel('Họ và tên')).toBeVisible();
|
||||||
await expect(page.getByLabel('Số điện thoại')).toBeVisible();
|
await expect(page.getByLabel('Số điện thoại')).toBeVisible();
|
||||||
await expect(page.getByLabel('Email (tùy chọn)')).toBeVisible();
|
await expect(page.getByLabel('Email')).toBeVisible();
|
||||||
await expect(page.getByLabel('Mật khẩu', { exact: false }).first()).toBeVisible();
|
await expect(page.getByLabel('Mật khẩu', { exact: false }).first()).toBeVisible();
|
||||||
await expect(page.getByLabel('Xác nhận mật khẩu')).toBeVisible();
|
await expect(page.getByLabel('Xác nhận mật khẩu')).toBeVisible();
|
||||||
await expect(page.getByRole('button', { name: 'Đăng ký' })).toBeVisible();
|
await expect(page.getByRole('button', { name: 'Đăng ký' })).toBeVisible();
|
||||||
@@ -73,13 +89,19 @@ test.describe('Register Page', () => {
|
|||||||
|
|
||||||
test('successful registration redirects to home', async ({ page }) => {
|
test('successful registration redirects to home', async ({ page }) => {
|
||||||
await page.route('**/auth/register', (route) =>
|
await page.route('**/auth/register', (route) =>
|
||||||
route.fulfill({
|
fulfillJson(route, 201, { message: 'Registered successfully' }),
|
||||||
status: 201,
|
);
|
||||||
contentType: 'application/json',
|
await page.route('**/auth/profile', (route) =>
|
||||||
body: JSON.stringify({
|
fulfillJson(route, 200, {
|
||||||
accessToken: 'fake-access-token',
|
id: 'test-user-id',
|
||||||
refreshToken: 'fake-refresh-token',
|
email: null,
|
||||||
}),
|
phone: '0912345678',
|
||||||
|
fullName: 'Test User',
|
||||||
|
avatarUrl: null,
|
||||||
|
role: 'USER',
|
||||||
|
kycStatus: 'NOT_SUBMITTED',
|
||||||
|
isActive: true,
|
||||||
|
createdAt: new Date().toISOString(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -94,11 +116,7 @@ test.describe('Register Page', () => {
|
|||||||
|
|
||||||
test('displays server error on failed registration', async ({ page }) => {
|
test('displays server error on failed registration', async ({ page }) => {
|
||||||
await page.route('**/auth/register', (route) =>
|
await page.route('**/auth/register', (route) =>
|
||||||
route.fulfill({
|
fulfillJson(route, 409, { message: 'Số điện thoại đã được đăng ký' }),
|
||||||
status: 409,
|
|
||||||
contentType: 'application/json',
|
|
||||||
body: JSON.stringify({ message: 'Số điện thoại đã được đăng ký' }),
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
await page.getByLabel('Họ và tên').fill('Test User');
|
await page.getByLabel('Họ và tên').fill('Test User');
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ const API_PORT = process.env.API_PORT ?? '3001';
|
|||||||
const WEB_PORT = process.env.WEB_PORT ?? '3000';
|
const WEB_PORT = process.env.WEB_PORT ?? '3000';
|
||||||
|
|
||||||
const SERVER_STARTUP_TIMEOUT_MS = process.env.CI ? 300_000 : 60_000;
|
const SERVER_STARTUP_TIMEOUT_MS = process.env.CI ? 300_000 : 60_000;
|
||||||
|
const VIETNAMESE_BROWSER_CONTEXT = {
|
||||||
|
locale: 'vi-VN',
|
||||||
|
extraHTTPHeaders: {
|
||||||
|
'Accept-Language': 'vi-VN,vi;q=0.9,en;q=0.8',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Playwright E2E configuration for Goodgo Platform.
|
* Playwright E2E configuration for Goodgo Platform.
|
||||||
@@ -57,6 +63,7 @@ export default defineConfig({
|
|||||||
testDir: './e2e/web',
|
testDir: './e2e/web',
|
||||||
use: {
|
use: {
|
||||||
...devices['Desktop Chrome'],
|
...devices['Desktop Chrome'],
|
||||||
|
...VIETNAMESE_BROWSER_CONTEXT,
|
||||||
baseURL: process.env.WEB_BASE_URL ?? `http://localhost:${WEB_PORT}`,
|
baseURL: process.env.WEB_BASE_URL ?? `http://localhost:${WEB_PORT}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -75,6 +82,7 @@ export default defineConfig({
|
|||||||
grep: /@smoke/,
|
grep: /@smoke/,
|
||||||
use: {
|
use: {
|
||||||
...devices['Desktop Chrome'],
|
...devices['Desktop Chrome'],
|
||||||
|
...VIETNAMESE_BROWSER_CONTEXT,
|
||||||
baseURL: process.env.WEB_BASE_URL ?? `http://localhost:${WEB_PORT}`,
|
baseURL: process.env.WEB_BASE_URL ?? `http://localhost:${WEB_PORT}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -84,6 +92,7 @@ export default defineConfig({
|
|||||||
testDir: './e2e/a11y',
|
testDir: './e2e/a11y',
|
||||||
use: {
|
use: {
|
||||||
...devices['Desktop Chrome'],
|
...devices['Desktop Chrome'],
|
||||||
|
...VIETNAMESE_BROWSER_CONTEXT,
|
||||||
baseURL: process.env.WEB_BASE_URL ?? `http://localhost:${WEB_PORT}`,
|
baseURL: process.env.WEB_BASE_URL ?? `http://localhost:${WEB_PORT}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user