feat: integrate Playwright for E2E testing and enhance testing framework
- Added Playwright for end-to-end testing in the `apps/web` module, including a new `login.spec.ts` for testing login functionality. - Updated package.json to include Playwright dependencies and new test commands for E2E testing. - Enhanced .gitignore to exclude Playwright test results and reports. - Modified existing documentation to reflect the integration of Playwright and updated testing guidelines. - Refactored test commands to streamline the testing process, including a dedicated command for E2E tests. These changes improve the testing framework by providing robust E2E testing capabilities, enhancing the reliability and quality of the application.
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
export const E2E_LOGIN = {
|
||||
username: 'administrator',
|
||||
password: 'password123',
|
||||
} as const;
|
||||
@@ -0,0 +1,11 @@
|
||||
export function createFakeJwt(expiresInSeconds = 3600): string {
|
||||
const header = Buffer.from(JSON.stringify({ alg: 'none', typ: 'JWT' })).toString('base64url');
|
||||
const payload = Buffer.from(
|
||||
JSON.stringify({
|
||||
sub: 'e2e-user',
|
||||
exp: Math.floor(Date.now() / 1000) + expiresInSeconds,
|
||||
}),
|
||||
).toString('base64url');
|
||||
|
||||
return `${header}.${payload}.e2e`;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import type { Page, Route } from '@playwright/test';
|
||||
import { E2E_LOGIN } from './credentials';
|
||||
import { createFakeJwt } from './fake-jwt';
|
||||
|
||||
const APP_HOSTS = new Set(['127.0.0.1', 'localhost']);
|
||||
const APP_PORT = Number(process.env.E2E_PORT ?? 4173);
|
||||
|
||||
const EMPTY_LIST = {
|
||||
data: [],
|
||||
meta: {
|
||||
currentPage: 1,
|
||||
itemsPerPage: 10,
|
||||
totalItems: 0,
|
||||
totalPages: 0,
|
||||
itemCount: 0,
|
||||
},
|
||||
};
|
||||
|
||||
const E2E_USER = {
|
||||
id: 'e2e-user-id',
|
||||
username: E2E_LOGIN.username,
|
||||
isSuperadmin: true,
|
||||
privilege: null,
|
||||
permissions: {},
|
||||
};
|
||||
|
||||
export type LoginApiOutcome = 'success' | 'unauthorized';
|
||||
|
||||
export async function mockBackend(page: Page, login: LoginApiOutcome = 'success'): Promise<void> {
|
||||
await page.route('**/*', async (route) => {
|
||||
const requestUrl = new URL(route.request().url());
|
||||
if (isAppRequest(requestUrl)) {
|
||||
await route.continue();
|
||||
return;
|
||||
}
|
||||
|
||||
await fulfillBackend(route, login);
|
||||
});
|
||||
}
|
||||
|
||||
function isAppRequest(requestUrl: URL): boolean {
|
||||
const port = Number(requestUrl.port || (requestUrl.protocol === 'https:' ? 443 : 80));
|
||||
return APP_HOSTS.has(requestUrl.hostname) && port === APP_PORT;
|
||||
}
|
||||
|
||||
async function fulfillBackend(route: Route, login: LoginApiOutcome): Promise<void> {
|
||||
const request = route.request();
|
||||
const pathname = new URL(request.url()).pathname.replace(/\/$/, '');
|
||||
|
||||
if (pathname.endsWith('/auth/login') && request.method() === 'POST') {
|
||||
if (login === 'unauthorized') {
|
||||
await route.fulfill({
|
||||
status: 401,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ statusCode: 401, message: 'Unauthorized' }),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
accessToken: createFakeJwt(),
|
||||
refreshToken: createFakeJwt(86_400),
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (pathname.endsWith('/auth/me') && request.method() === 'GET') {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(E2E_USER),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const resourceType = request.resourceType();
|
||||
if (resourceType === 'xhr' || resourceType === 'fetch') {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(EMPTY_LIST),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await route.abort();
|
||||
}
|
||||
Reference in New Issue
Block a user