test(web+mp): E2E 测试全量实施 — Web 5 flow + MP 4 flow + 基础设施
Web 端 (Playwright): - fixtures: test-data 工厂 + API Client (乐观锁 version) + 增强 auth fixture - pages: LoginPage, PatientListPage, PatientDetailPage, HealthDataPage, AppointmentPage - flows: 患者全流程, 体征数据链路, 预约排班链路, 随访管理链路, 告警处理链路 - smoke tests 迁移到 smoke/ 目录,import 路径更新 - playwright.config.ts 更新: globalSetup 环境检查, 60s timeout, video retain 小程序端 (Vitest + miniprogram-automator): - helpers: AutomatorClient, MpApiClient, MpAuthHelper, MpNavigator - flows: 患者健康数据查看, 体征数据录入, 积分签到兑换, 积分商城浏览 - vitest.config.ts + check-readiness.ts - vitest 4.1.5 依赖安装 Playwright 发现 15 个测试 (5 flow + 10 smoke),全部就绪
This commit is contained in:
70
apps/miniprogram/e2e/helpers/api-client.ts
Normal file
70
apps/miniprogram/e2e/helpers/api-client.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
// apps/miniprogram/e2e/helpers/api-client.ts
|
||||
// 简化版 API Client,用于小程序 E2E 数据准备/清理
|
||||
|
||||
const API_BASE = process.env.E2E_API_URL || 'http://localhost:3000/api/v1';
|
||||
|
||||
export class MpApiClient {
|
||||
private token = '';
|
||||
|
||||
async login(username?: string, password?: string) {
|
||||
const res = await fetch(`${API_BASE}/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
username: username || process.env.E2E_ADMIN_USER || 'admin',
|
||||
password: password || process.env.E2E_ADMIN_PASS || 'Admin@2026',
|
||||
}),
|
||||
});
|
||||
const json = await res.json();
|
||||
if (!json.success) throw new Error('Login failed');
|
||||
this.token = json.data.access_token;
|
||||
return json.data;
|
||||
}
|
||||
|
||||
getToken() { return this.token; }
|
||||
|
||||
async createPatient(overrides?: Record<string, unknown>) {
|
||||
return this.post('/health/patients', overrides ?? {});
|
||||
}
|
||||
|
||||
async deletePatient(id: string, version: number) {
|
||||
await this.del(`/health/patients/${id}`, { version });
|
||||
}
|
||||
|
||||
async createVitalSigns(patientId: string, overrides?: Record<string, unknown>) {
|
||||
return this.post(`/health/patients/${patientId}/vital-signs`, overrides ?? {});
|
||||
}
|
||||
|
||||
async deleteVitalSigns(patientId: string, id: string, version: number) {
|
||||
await this.del(`/health/patients/${patientId}/vital-signs/${id}`, { version });
|
||||
}
|
||||
|
||||
async listPointsProducts() {
|
||||
return this.get('/health/points/products');
|
||||
}
|
||||
|
||||
private async headers() {
|
||||
return { 'Content-Type': 'application/json', Authorization: `Bearer ${this.token}` };
|
||||
}
|
||||
|
||||
private async get(path: string) {
|
||||
const res = await fetch(`${API_BASE}${path}`, { headers: await this.headers() });
|
||||
const json = await res.json();
|
||||
return json.data;
|
||||
}
|
||||
|
||||
private async post(path: string, body: unknown) {
|
||||
const res = await fetch(`${API_BASE}${path}`, {
|
||||
method: 'POST', headers: await this.headers(), body: JSON.stringify(body),
|
||||
});
|
||||
const json = await res.json();
|
||||
if (!json.success) throw new Error(`POST ${path} failed`);
|
||||
return json.data;
|
||||
}
|
||||
|
||||
private async del(path: string, body?: unknown) {
|
||||
await fetch(`${API_BASE}${path}`, {
|
||||
method: 'DELETE', headers: await this.headers(), body: body ? JSON.stringify(body) : undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user