You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1229 lines
44 KiB
1229 lines
44 KiB
/**
|
|
* 健康档案完整功能测试脚本
|
|
* 测试内容:
|
|
* 1. 基础信息 - 所有9个字段的编辑和保存
|
|
* 2. 生活习惯 - 所有10个字段的编辑和保存
|
|
* 3. 病史记录 - 添加新记录(5个字段)
|
|
* 4. 家族病史 - 添加新记录(3个字段)
|
|
* 5. 过敏记录 - 添加新记录(4个字段)
|
|
* 6. 验证保存后数据是否正确显示
|
|
*/
|
|
const { chromium } = require('playwright');
|
|
|
|
const APP_URL = 'http://localhost:8081';
|
|
const TEST_PHONE = '13800138000';
|
|
const TEST_CODE = '123456';
|
|
|
|
// 测试数据
|
|
const TEST_DATA = {
|
|
basicInfo: {
|
|
name: '测试用户' + Date.now().toString().slice(-4),
|
|
gender: 'female', // 改为女
|
|
birth_date: '1990-05-15',
|
|
height: '175',
|
|
weight: '68',
|
|
blood_type: 'A',
|
|
occupation: '软件工程师',
|
|
marital_status: 'married', // 改为已婚
|
|
region: '北京市海淀区',
|
|
},
|
|
lifestyle: {
|
|
sleep_time: '23:00',
|
|
wake_time: '07:30',
|
|
sleep_quality: 'good', // 良好
|
|
meal_regularity: 'regular', // 规律
|
|
diet_preference: '清淡饮食',
|
|
daily_water_ml: '2000',
|
|
exercise_frequency: 'often', // 经常
|
|
exercise_type: '跑步、游泳',
|
|
is_smoker: false,
|
|
alcohol_frequency: 'sometimes', // 偶尔
|
|
},
|
|
medicalHistory: {
|
|
disease_name: '高血压',
|
|
disease_type: 'chronic', // 慢性病
|
|
diagnosed_date: '2020-03',
|
|
status: 'controlled', // 已控制
|
|
notes: '定期服药控制中',
|
|
},
|
|
familyHistory: {
|
|
relation: 'father', // 父亲
|
|
disease_name: '糖尿病',
|
|
notes: '2型糖尿病',
|
|
},
|
|
allergyRecord: {
|
|
allergy_type: 'drug', // 药物
|
|
allergen: '青霉素',
|
|
severity: 'severe', // 重度
|
|
reaction_desc: '全身过敏反应,需立即就医',
|
|
}
|
|
};
|
|
|
|
// 测试结果统计
|
|
const testResults = {
|
|
passed: 0,
|
|
failed: 0,
|
|
tests: []
|
|
};
|
|
|
|
function logTest(name, passed, detail = '') {
|
|
const status = passed ? '✓' : '✗';
|
|
const msg = `${status} ${name}${detail ? ': ' + detail : ''}`;
|
|
console.log(msg);
|
|
testResults.tests.push({ name, passed, detail });
|
|
if (passed) testResults.passed++;
|
|
else testResults.failed++;
|
|
}
|
|
|
|
// 使用坐标点击元素
|
|
async function clickByText(page, text) {
|
|
const pos = await page.evaluate((searchText) => {
|
|
const allElements = document.querySelectorAll('*');
|
|
for (const el of allElements) {
|
|
if (el.textContent?.trim() === searchText && el.children.length === 0) {
|
|
const rect = el.getBoundingClientRect();
|
|
if (rect.width > 0 && rect.height > 0) {
|
|
return { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}, text);
|
|
|
|
if (pos) {
|
|
await page.mouse.click(pos.x, pos.y);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 等待并检查提示消息
|
|
async function waitForToast(page, text, timeout = 3000) {
|
|
try {
|
|
const toast = page.locator(`text=${text}`).first();
|
|
return await toast.isVisible({ timeout });
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// 关闭所有弹窗
|
|
async function closeAllModals(page) {
|
|
for (let i = 0; i < 5; i++) {
|
|
const cancelClicked = await clickByText(page, '取消');
|
|
if (cancelClicked) {
|
|
await page.waitForTimeout(500);
|
|
continue;
|
|
}
|
|
|
|
const closeBtn = page.locator('[aria-label="Close"]').first();
|
|
if (await closeBtn.isVisible({ timeout: 300 }).catch(() => false)) {
|
|
await closeBtn.click({ force: true });
|
|
await page.waitForTimeout(500);
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 填写 TextInput 输入框
|
|
async function fillInput(page, label, value) {
|
|
// 方式1: 通过 label 属性查找
|
|
let input = page.locator(`input[label="${label}"]`).first();
|
|
if (await input.isVisible({ timeout: 500 }).catch(() => false)) {
|
|
await input.clear();
|
|
await input.fill(value);
|
|
return true;
|
|
}
|
|
|
|
// 方式2: 通过 placeholder 查找
|
|
input = page.locator(`input[placeholder*="${label}"]`).first();
|
|
if (await input.isVisible({ timeout: 500 }).catch(() => false)) {
|
|
await input.clear();
|
|
await input.fill(value);
|
|
return true;
|
|
}
|
|
|
|
// 方式3: 通过文本标签位置查找附近的输入框
|
|
const inputPos = await page.evaluate((labelText) => {
|
|
const allElements = document.querySelectorAll('*');
|
|
for (const el of allElements) {
|
|
const text = el.textContent?.trim();
|
|
if (text && (text === labelText || text.startsWith(labelText))) {
|
|
const rect = el.getBoundingClientRect();
|
|
// 找到标签后,查找附近的输入框
|
|
const inputs = document.querySelectorAll('input:not([type="checkbox"]):not([role="switch"])');
|
|
let closestInput = null;
|
|
let minDistance = Infinity;
|
|
|
|
for (const inp of inputs) {
|
|
const inpRect = inp.getBoundingClientRect();
|
|
// 输入框在标签下方或右侧
|
|
const distance = Math.abs(inpRect.y - rect.y) + Math.abs(inpRect.x - rect.x);
|
|
if (distance < minDistance && inpRect.y >= rect.y - 50) {
|
|
minDistance = distance;
|
|
closestInput = inp;
|
|
}
|
|
}
|
|
|
|
if (closestInput) {
|
|
return { found: true };
|
|
}
|
|
}
|
|
}
|
|
return { found: false };
|
|
}, label);
|
|
|
|
return false;
|
|
}
|
|
|
|
// 点击 SegmentedButtons 中的选项
|
|
async function clickSegmentOption(page, optionText) {
|
|
const clicked = await page.evaluate((text) => {
|
|
const buttons = document.querySelectorAll('*');
|
|
for (const btn of buttons) {
|
|
if (btn.textContent?.trim() === text && btn.children.length === 0) {
|
|
const rect = btn.getBoundingClientRect();
|
|
if (rect.width > 20 && rect.height > 15) {
|
|
btn.click();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}, optionText);
|
|
|
|
if (!clicked) {
|
|
// 备用: 使用 Playwright 定位器
|
|
const btn = page.locator(`text=${optionText}`).first();
|
|
if (await btn.isVisible({ timeout: 500 }).catch(() => false)) {
|
|
await btn.click({ force: true });
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return clicked;
|
|
}
|
|
|
|
async function login(page) {
|
|
console.log('\n【准备工作】登录账号...');
|
|
|
|
const loginBtn = page.locator('text=登录').first();
|
|
if (!(await loginBtn.isVisible({ timeout: 2000 }).catch(() => false))) {
|
|
logTest('已登录状态', true, '跳过登录流程');
|
|
return true;
|
|
}
|
|
|
|
await page.locator('input').first().fill(TEST_PHONE);
|
|
await page.waitForTimeout(300);
|
|
|
|
const getCodeBtn = page.locator('text=获取验证码').first();
|
|
if (await getCodeBtn.isVisible()) {
|
|
await getCodeBtn.click();
|
|
await page.waitForTimeout(1000);
|
|
}
|
|
|
|
await page.locator('input').nth(1).fill(TEST_CODE);
|
|
await page.waitForTimeout(300);
|
|
|
|
await loginBtn.click();
|
|
await page.waitForTimeout(3000);
|
|
|
|
const homeVisible = await page.locator('text=/.*好,.*$/').first().isVisible({ timeout: 5000 }).catch(() => false);
|
|
logTest('登录', homeVisible);
|
|
|
|
return homeVisible;
|
|
}
|
|
|
|
async function navigateToHealthProfile(page) {
|
|
console.log('\n【步骤1】导航到健康档案页面...');
|
|
|
|
// 点击"我的" Tab
|
|
const tabPos = await page.evaluate(() => {
|
|
const allElements = document.querySelectorAll('*');
|
|
for (const el of allElements) {
|
|
if (el.textContent?.trim() === '我的' && el.children.length === 0) {
|
|
const rect = el.getBoundingClientRect();
|
|
if (rect.y > 500) {
|
|
return { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
});
|
|
|
|
if (tabPos) {
|
|
await page.mouse.click(tabPos.x, tabPos.y);
|
|
await page.waitForTimeout(1500);
|
|
}
|
|
|
|
// 滚动到顶部
|
|
await page.evaluate(() => window.scrollTo(0, 0));
|
|
await page.waitForTimeout(500);
|
|
|
|
// 点击健康档案菜单
|
|
const healthMenuPos = await page.evaluate(() => {
|
|
const allElements = document.querySelectorAll('*');
|
|
for (const el of allElements) {
|
|
const text = el.textContent;
|
|
if (text?.includes('健康档案') &&
|
|
text?.includes('查看和管理') &&
|
|
!text?.includes('用药/治疗记录')) {
|
|
const rect = el.getBoundingClientRect();
|
|
if (rect.width > 100 && rect.height > 30 && rect.height < 100) {
|
|
return { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
});
|
|
|
|
if (healthMenuPos) {
|
|
await page.mouse.click(healthMenuPos.x, healthMenuPos.y);
|
|
await page.waitForTimeout(2000);
|
|
} else {
|
|
// 备用方法
|
|
const healthItem = page.locator('text=健康档案').first();
|
|
if (await healthItem.isVisible()) {
|
|
await healthItem.click({ force: true });
|
|
await page.waitForTimeout(2000);
|
|
}
|
|
}
|
|
|
|
// 验证进入健康档案页面
|
|
const basicInfo = await page.locator('text=基础信息').first().isVisible({ timeout: 3000 }).catch(() => false);
|
|
const backBtn = await page.locator('text=← 返回').first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
|
|
const success = basicInfo && backBtn;
|
|
logTest('导航到健康档案页面', success);
|
|
await page.screenshot({ path: 'tests/screenshots/hp-initial.png' });
|
|
|
|
return success;
|
|
}
|
|
|
|
async function testBasicInfoEdit(page) {
|
|
console.log('\n【步骤2】测试基础信息编辑(9个字段)...');
|
|
|
|
await page.evaluate(() => window.scrollTo(0, 0));
|
|
await page.waitForTimeout(500);
|
|
|
|
// 点击基础信息的编辑按钮
|
|
const editPos = await page.evaluate(() => {
|
|
const basicTitle = Array.from(document.querySelectorAll('*')).find(
|
|
el => el.textContent?.trim() === '基础信息'
|
|
);
|
|
if (basicTitle) {
|
|
const rect = basicTitle.getBoundingClientRect();
|
|
return { x: window.innerWidth - 50, y: rect.y };
|
|
}
|
|
return null;
|
|
});
|
|
|
|
if (!editPos) {
|
|
logTest('打开基础信息编辑弹窗', false, '未找到编辑按钮');
|
|
return false;
|
|
}
|
|
|
|
await page.mouse.click(editPos.x, editPos.y);
|
|
await page.waitForTimeout(1000);
|
|
|
|
const modalOpened = await page.locator('text=编辑基础信息').first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('打开基础信息编辑弹窗', modalOpened);
|
|
|
|
if (!modalOpened) return false;
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-basic-edit-before.png' });
|
|
|
|
// 获取所有输入框
|
|
const inputs = page.locator('input:not([type="checkbox"]):not([role="switch"])');
|
|
const inputCount = await inputs.count();
|
|
console.log(` 找到 ${inputCount} 个输入框`);
|
|
|
|
// 测试1: 填写姓名
|
|
let nameInput = inputs.first();
|
|
if (await nameInput.isVisible()) {
|
|
await nameInput.clear();
|
|
await nameInput.fill(TEST_DATA.basicInfo.name);
|
|
console.log(` 填写姓名: ${TEST_DATA.basicInfo.name}`);
|
|
logTest('基础信息-姓名输入', true);
|
|
} else {
|
|
logTest('基础信息-姓名输入', false, '未找到输入框');
|
|
}
|
|
|
|
// 测试2: 选择性别 - 女
|
|
const genderClicked = await clickSegmentOption(page, '女');
|
|
logTest('基础信息-性别选择', genderClicked);
|
|
await page.waitForTimeout(300);
|
|
|
|
// 测试3: 填写出生日期 - 找到第二个输入框
|
|
if (inputCount >= 2) {
|
|
const birthInput = inputs.nth(1);
|
|
if (await birthInput.isVisible()) {
|
|
await birthInput.clear();
|
|
await birthInput.fill(TEST_DATA.basicInfo.birth_date);
|
|
console.log(` 填写出生日期: ${TEST_DATA.basicInfo.birth_date}`);
|
|
logTest('基础信息-出生日期输入', true);
|
|
}
|
|
}
|
|
|
|
// 测试4 & 5: 填写身高和体重 - 找到第三、四个输入框
|
|
if (inputCount >= 4) {
|
|
const heightInput = inputs.nth(2);
|
|
const weightInput = inputs.nth(3);
|
|
|
|
if (await heightInput.isVisible()) {
|
|
await heightInput.clear();
|
|
await heightInput.fill(TEST_DATA.basicInfo.height);
|
|
console.log(` 填写身高: ${TEST_DATA.basicInfo.height}cm`);
|
|
logTest('基础信息-身高输入', true);
|
|
}
|
|
|
|
if (await weightInput.isVisible()) {
|
|
await weightInput.clear();
|
|
await weightInput.fill(TEST_DATA.basicInfo.weight);
|
|
console.log(` 填写体重: ${TEST_DATA.basicInfo.weight}kg`);
|
|
logTest('基础信息-体重输入', true);
|
|
}
|
|
}
|
|
|
|
// 测试6: 填写血型
|
|
if (inputCount >= 5) {
|
|
const bloodInput = inputs.nth(4);
|
|
if (await bloodInput.isVisible()) {
|
|
await bloodInput.clear();
|
|
await bloodInput.fill(TEST_DATA.basicInfo.blood_type);
|
|
console.log(` 填写血型: ${TEST_DATA.basicInfo.blood_type}`);
|
|
logTest('基础信息-血型输入', true);
|
|
}
|
|
}
|
|
|
|
// 测试7: 填写职业
|
|
if (inputCount >= 6) {
|
|
const occupationInput = inputs.nth(5);
|
|
if (await occupationInput.isVisible()) {
|
|
await occupationInput.clear();
|
|
await occupationInput.fill(TEST_DATA.basicInfo.occupation);
|
|
console.log(` 填写职业: ${TEST_DATA.basicInfo.occupation}`);
|
|
logTest('基础信息-职业输入', true);
|
|
}
|
|
}
|
|
|
|
// 测试8: 选择婚姻状况 - 已婚
|
|
const maritalClicked = await clickSegmentOption(page, '已婚');
|
|
logTest('基础信息-婚姻状况选择', maritalClicked);
|
|
await page.waitForTimeout(300);
|
|
|
|
// 测试9: 填写地区
|
|
if (inputCount >= 7) {
|
|
const regionInput = inputs.nth(6);
|
|
if (await regionInput.isVisible()) {
|
|
await regionInput.clear();
|
|
await regionInput.fill(TEST_DATA.basicInfo.region);
|
|
console.log(` 填写地区: ${TEST_DATA.basicInfo.region}`);
|
|
logTest('基础信息-地区输入', true);
|
|
}
|
|
}
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-basic-edit-after.png' });
|
|
|
|
// 点击保存按钮
|
|
const saveClicked = await clickByText(page, '保存');
|
|
if (!saveClicked) {
|
|
logTest('基础信息-点击保存', false, '未找到保存按钮');
|
|
await closeAllModals(page);
|
|
return false;
|
|
}
|
|
|
|
await page.waitForTimeout(2500);
|
|
|
|
// 验证保存结果
|
|
const saveSuccess = await waitForToast(page, '保存成功', 3000);
|
|
const modalClosed = !(await page.locator('text=编辑基础信息').first().isVisible({ timeout: 500 }).catch(() => false));
|
|
|
|
logTest('基础信息-保存成功', saveSuccess || modalClosed, saveSuccess ? '显示保存成功提示' : (modalClosed ? '弹窗已关闭' : ''));
|
|
|
|
// 等待数据刷新
|
|
await page.waitForTimeout(1500);
|
|
|
|
// 验证保存后的数据是否正确显示
|
|
await page.evaluate(() => window.scrollTo(0, 0));
|
|
await page.waitForTimeout(500);
|
|
|
|
const nameDisplayed = await page.locator(`text=${TEST_DATA.basicInfo.name}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('基础信息-保存后姓名显示', nameDisplayed);
|
|
|
|
const regionDisplayed = await page.locator(`text=${TEST_DATA.basicInfo.region}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('基础信息-保存后地区显示', regionDisplayed);
|
|
|
|
const occupationDisplayed = await page.locator(`text=${TEST_DATA.basicInfo.occupation}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('基础信息-保存后职业显示', occupationDisplayed);
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-basic-saved.png' });
|
|
|
|
return saveSuccess || modalClosed;
|
|
}
|
|
|
|
async function testLifestyleEdit(page) {
|
|
console.log('\n【步骤3】测试生活习惯编辑(10个字段)...');
|
|
|
|
await page.evaluate(() => window.scrollTo(0, 300));
|
|
await page.waitForTimeout(500);
|
|
|
|
// 点击生活习惯的编辑按钮
|
|
const editPos = await page.evaluate(() => {
|
|
const title = Array.from(document.querySelectorAll('*')).find(
|
|
el => el.textContent?.trim() === '生活习惯'
|
|
);
|
|
if (title) {
|
|
const rect = title.getBoundingClientRect();
|
|
return { x: window.innerWidth - 50, y: rect.y };
|
|
}
|
|
return null;
|
|
});
|
|
|
|
if (!editPos) {
|
|
logTest('打开生活习惯编辑弹窗', false, '未找到编辑按钮');
|
|
return false;
|
|
}
|
|
|
|
await page.mouse.click(editPos.x, editPos.y);
|
|
await page.waitForTimeout(1000);
|
|
|
|
const modalOpened = await page.locator('text=编辑生活习惯').first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('打开生活习惯编辑弹窗', modalOpened);
|
|
|
|
if (!modalOpened) return false;
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-lifestyle-edit-before.png' });
|
|
|
|
// 获取所有输入框
|
|
const inputs = page.locator('input:not([type="checkbox"]):not([role="switch"])');
|
|
const inputCount = await inputs.count();
|
|
console.log(` 找到 ${inputCount} 个输入框`);
|
|
|
|
// 测试1 & 2: 填写入睡时间和起床时间
|
|
if (inputCount >= 2) {
|
|
const sleepInput = inputs.first();
|
|
const wakeInput = inputs.nth(1);
|
|
|
|
if (await sleepInput.isVisible()) {
|
|
await sleepInput.clear();
|
|
await sleepInput.fill(TEST_DATA.lifestyle.sleep_time);
|
|
console.log(` 填写入睡时间: ${TEST_DATA.lifestyle.sleep_time}`);
|
|
logTest('生活习惯-入睡时间输入', true);
|
|
}
|
|
|
|
if (await wakeInput.isVisible()) {
|
|
await wakeInput.clear();
|
|
await wakeInput.fill(TEST_DATA.lifestyle.wake_time);
|
|
console.log(` 填写起床时间: ${TEST_DATA.lifestyle.wake_time}`);
|
|
logTest('生活习惯-起床时间输入', true);
|
|
}
|
|
}
|
|
|
|
// 测试3: 选择睡眠质量 - 良好
|
|
const sleepQualityClicked = await clickSegmentOption(page, '良好');
|
|
logTest('生活习惯-睡眠质量选择', sleepQualityClicked);
|
|
await page.waitForTimeout(300);
|
|
|
|
// 测试4: 选择三餐规律 - 规律
|
|
const mealClicked = await clickSegmentOption(page, '规律');
|
|
logTest('生活习惯-三餐规律选择', mealClicked);
|
|
await page.waitForTimeout(300);
|
|
|
|
// 测试5: 填写饮食偏好
|
|
if (inputCount >= 3) {
|
|
const dietInput = inputs.nth(2);
|
|
if (await dietInput.isVisible()) {
|
|
await dietInput.clear();
|
|
await dietInput.fill(TEST_DATA.lifestyle.diet_preference);
|
|
console.log(` 填写饮食偏好: ${TEST_DATA.lifestyle.diet_preference}`);
|
|
logTest('生活习惯-饮食偏好输入', true);
|
|
}
|
|
}
|
|
|
|
// 测试6: 填写日饮水量
|
|
if (inputCount >= 4) {
|
|
const waterInput = inputs.nth(3);
|
|
if (await waterInput.isVisible()) {
|
|
await waterInput.clear();
|
|
await waterInput.fill(TEST_DATA.lifestyle.daily_water_ml);
|
|
console.log(` 填写日饮水量: ${TEST_DATA.lifestyle.daily_water_ml}ml`);
|
|
logTest('生活习惯-日饮水量输入', true);
|
|
}
|
|
}
|
|
|
|
// 测试7: 选择运动频率 - 经常
|
|
const exerciseClicked = await clickSegmentOption(page, '经常');
|
|
logTest('生活习惯-运动频率选择', exerciseClicked);
|
|
await page.waitForTimeout(300);
|
|
|
|
// 测试8: 填写运动类型
|
|
if (inputCount >= 5) {
|
|
const exerciseTypeInput = inputs.nth(4);
|
|
if (await exerciseTypeInput.isVisible()) {
|
|
await exerciseTypeInput.clear();
|
|
await exerciseTypeInput.fill(TEST_DATA.lifestyle.exercise_type);
|
|
console.log(` 填写运动类型: ${TEST_DATA.lifestyle.exercise_type}`);
|
|
logTest('生活习惯-运动类型输入', true);
|
|
}
|
|
}
|
|
|
|
// 测试9: 选择是否吸烟 - 否
|
|
const smokerClicked = await clickSegmentOption(page, '否');
|
|
logTest('生活习惯-吸烟选择', smokerClicked);
|
|
await page.waitForTimeout(300);
|
|
|
|
// 测试10: 选择饮酒频率 - 偶尔
|
|
const alcoholClicked = await clickSegmentOption(page, '偶尔');
|
|
logTest('生活习惯-饮酒频率选择', alcoholClicked);
|
|
await page.waitForTimeout(300);
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-lifestyle-edit-after.png' });
|
|
|
|
// 点击保存按钮
|
|
const saveClicked = await clickByText(page, '保存');
|
|
if (!saveClicked) {
|
|
logTest('生活习惯-点击保存', false, '未找到保存按钮');
|
|
await closeAllModals(page);
|
|
return false;
|
|
}
|
|
|
|
await page.waitForTimeout(2500);
|
|
|
|
// 验证保存结果
|
|
const saveSuccess = await waitForToast(page, '保存成功', 3000);
|
|
const modalClosed = !(await page.locator('text=编辑生活习惯').first().isVisible({ timeout: 500 }).catch(() => false));
|
|
|
|
logTest('生活习惯-保存成功', saveSuccess || modalClosed, saveSuccess ? '显示保存成功提示' : (modalClosed ? '弹窗已关闭' : ''));
|
|
|
|
// 等待数据刷新
|
|
await page.waitForTimeout(1500);
|
|
|
|
// 验证保存后的数据是否正确显示
|
|
await page.evaluate(() => {
|
|
const lifestyleTitle = Array.from(document.querySelectorAll('*')).find(
|
|
el => el.textContent?.trim() === '生活习惯'
|
|
);
|
|
if (lifestyleTitle) {
|
|
lifestyleTitle.scrollIntoView({ behavior: 'instant', block: 'center' });
|
|
}
|
|
});
|
|
await page.waitForTimeout(500);
|
|
|
|
const sleepTimeDisplayed = await page.locator(`text=${TEST_DATA.lifestyle.sleep_time}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('生活习惯-保存后入睡时间显示', sleepTimeDisplayed);
|
|
|
|
const dietDisplayed = await page.locator(`text=${TEST_DATA.lifestyle.diet_preference}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('生活习惯-保存后饮食偏好显示', dietDisplayed);
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-lifestyle-saved.png' });
|
|
|
|
return saveSuccess || modalClosed;
|
|
}
|
|
|
|
async function testMedicalHistoryAdd(page) {
|
|
console.log('\n【步骤4】测试添加病史记录(5个字段)...');
|
|
|
|
// 滚动到病史记录卡片
|
|
await page.evaluate(() => {
|
|
const medicalTitle = Array.from(document.querySelectorAll('*')).find(
|
|
el => el.textContent?.trim() === '病史记录'
|
|
);
|
|
if (medicalTitle) {
|
|
medicalTitle.scrollIntoView({ behavior: 'instant', block: 'center' });
|
|
}
|
|
});
|
|
await page.waitForTimeout(800);
|
|
|
|
// 点击添加按钮
|
|
const addPos = await page.evaluate(() => {
|
|
const medicalTitle = Array.from(document.querySelectorAll('*')).find(
|
|
el => el.textContent?.trim() === '病史记录'
|
|
);
|
|
if (medicalTitle) {
|
|
const rect = medicalTitle.getBoundingClientRect();
|
|
return { x: window.innerWidth - 50, y: Math.min(rect.y, window.innerHeight - 100) };
|
|
}
|
|
return null;
|
|
});
|
|
|
|
if (!addPos) {
|
|
logTest('打开添加病史记录弹窗', false, '未找到添加按钮');
|
|
return false;
|
|
}
|
|
|
|
await page.mouse.click(addPos.x, addPos.y);
|
|
await page.waitForTimeout(1000);
|
|
|
|
const modalOpened = await page.locator('text=添加病史记录').first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('打开添加病史记录弹窗', modalOpened);
|
|
|
|
if (!modalOpened) return false;
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-medical-add-before.png' });
|
|
|
|
// 获取所有输入框
|
|
const inputs = page.locator('input:not([type="checkbox"]):not([role="switch"])');
|
|
|
|
// 测试1: 填写疾病名称
|
|
const diseaseInput = inputs.first();
|
|
if (await diseaseInput.isVisible()) {
|
|
await diseaseInput.click();
|
|
await page.waitForTimeout(200);
|
|
await diseaseInput.fill(TEST_DATA.medicalHistory.disease_name);
|
|
console.log(` 填写疾病名称: ${TEST_DATA.medicalHistory.disease_name}`);
|
|
logTest('病史记录-疾病名称输入', true);
|
|
}
|
|
|
|
// 测试2: 选择疾病类型 - 慢性病
|
|
const diseaseTypeClicked = await clickSegmentOption(page, '慢性病');
|
|
logTest('病史记录-疾病类型选择', diseaseTypeClicked);
|
|
await page.waitForTimeout(300);
|
|
|
|
// 测试3: 填写诊断日期
|
|
const dateInput = inputs.nth(1);
|
|
if (await dateInput.isVisible({ timeout: 500 }).catch(() => false)) {
|
|
await dateInput.click();
|
|
await page.waitForTimeout(200);
|
|
await dateInput.fill(TEST_DATA.medicalHistory.diagnosed_date);
|
|
console.log(` 填写诊断日期: ${TEST_DATA.medicalHistory.diagnosed_date}`);
|
|
logTest('病史记录-诊断日期输入', true);
|
|
}
|
|
|
|
// 测试4: 选择治疗状态 - 已控制
|
|
const statusClicked = await clickSegmentOption(page, '已控制');
|
|
logTest('病史记录-治疗状态选择', statusClicked);
|
|
await page.waitForTimeout(300);
|
|
|
|
// 测试5: 填写备注 (多行输入框)
|
|
const textAreas = page.locator('textarea');
|
|
const textAreaCount = await textAreas.count();
|
|
if (textAreaCount > 0) {
|
|
const notesInput = textAreas.first();
|
|
if (await notesInput.isVisible({ timeout: 500 }).catch(() => false)) {
|
|
await notesInput.click();
|
|
await page.waitForTimeout(200);
|
|
await notesInput.fill(TEST_DATA.medicalHistory.notes);
|
|
console.log(` 填写备注: ${TEST_DATA.medicalHistory.notes}`);
|
|
logTest('病史记录-备注输入', true);
|
|
}
|
|
}
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-medical-add-after.png' });
|
|
|
|
// 点击添加按钮
|
|
const addClicked = await clickByText(page, '添加');
|
|
if (!addClicked) {
|
|
logTest('病史记录-点击添加', false, '未找到添加按钮');
|
|
await closeAllModals(page);
|
|
return false;
|
|
}
|
|
|
|
await page.waitForTimeout(2500);
|
|
|
|
// 验证添加结果
|
|
const addSuccess = await waitForToast(page, '添加成功', 3000);
|
|
const modalClosed = !(await page.locator('text=添加病史记录').first().isVisible({ timeout: 500 }).catch(() => false));
|
|
|
|
logTest('病史记录-添加成功', addSuccess || modalClosed, addSuccess ? '显示添加成功提示' : (modalClosed ? '弹窗已关闭' : ''));
|
|
|
|
// 等待数据刷新
|
|
await page.waitForTimeout(1500);
|
|
|
|
// 验证添加后的数据是否正确显示
|
|
await page.evaluate(() => {
|
|
const medicalTitle = Array.from(document.querySelectorAll('*')).find(
|
|
el => el.textContent?.trim() === '病史记录'
|
|
);
|
|
if (medicalTitle) {
|
|
medicalTitle.scrollIntoView({ behavior: 'instant', block: 'center' });
|
|
}
|
|
});
|
|
await page.waitForTimeout(500);
|
|
|
|
const diseaseDisplayed = await page.locator(`text=${TEST_DATA.medicalHistory.disease_name}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('病史记录-添加后疾病名称显示', diseaseDisplayed);
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-medical-saved.png' });
|
|
|
|
return addSuccess || modalClosed;
|
|
}
|
|
|
|
async function testFamilyHistoryAdd(page) {
|
|
console.log('\n【步骤5】测试添加家族病史(3个字段)...');
|
|
|
|
// 滚动到家族病史卡片
|
|
await page.evaluate(() => {
|
|
const familyTitle = Array.from(document.querySelectorAll('*')).find(
|
|
el => el.textContent?.trim() === '家族病史'
|
|
);
|
|
if (familyTitle) {
|
|
familyTitle.scrollIntoView({ behavior: 'instant', block: 'center' });
|
|
}
|
|
});
|
|
await page.waitForTimeout(800);
|
|
|
|
// 点击添加按钮
|
|
const addPos = await page.evaluate(() => {
|
|
const familyTitle = Array.from(document.querySelectorAll('*')).find(
|
|
el => el.textContent?.trim() === '家族病史'
|
|
);
|
|
if (familyTitle) {
|
|
const rect = familyTitle.getBoundingClientRect();
|
|
return { x: window.innerWidth - 50, y: Math.min(rect.y, window.innerHeight - 100) };
|
|
}
|
|
return null;
|
|
});
|
|
|
|
if (!addPos) {
|
|
logTest('打开添加家族病史弹窗', false, '未找到添加按钮');
|
|
return false;
|
|
}
|
|
|
|
await page.mouse.click(addPos.x, addPos.y);
|
|
await page.waitForTimeout(1000);
|
|
|
|
const modalOpened = await page.locator('text=添加家族病史').first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('打开添加家族病史弹窗', modalOpened);
|
|
|
|
if (!modalOpened) return false;
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-family-add-before.png' });
|
|
|
|
// 测试1: 选择亲属关系 - 父亲
|
|
const relationClicked = await clickSegmentOption(page, '父亲');
|
|
logTest('家族病史-亲属关系选择', relationClicked);
|
|
await page.waitForTimeout(300);
|
|
|
|
// 测试2: 填写疾病名称
|
|
const inputs = page.locator('input:not([type="checkbox"]):not([role="switch"])');
|
|
const diseaseInput = inputs.first();
|
|
if (await diseaseInput.isVisible()) {
|
|
await diseaseInput.click();
|
|
await page.waitForTimeout(200);
|
|
await diseaseInput.fill(TEST_DATA.familyHistory.disease_name);
|
|
console.log(` 填写疾病名称: ${TEST_DATA.familyHistory.disease_name}`);
|
|
logTest('家族病史-疾病名称输入', true);
|
|
}
|
|
|
|
// 测试3: 填写备注
|
|
const textAreas = page.locator('textarea');
|
|
if (await textAreas.first().isVisible({ timeout: 500 }).catch(() => false)) {
|
|
await textAreas.first().click();
|
|
await page.waitForTimeout(200);
|
|
await textAreas.first().fill(TEST_DATA.familyHistory.notes);
|
|
console.log(` 填写备注: ${TEST_DATA.familyHistory.notes}`);
|
|
logTest('家族病史-备注输入', true);
|
|
}
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-family-add-after.png' });
|
|
|
|
// 点击添加按钮
|
|
const addClicked = await clickByText(page, '添加');
|
|
if (!addClicked) {
|
|
logTest('家族病史-点击添加', false, '未找到添加按钮');
|
|
await closeAllModals(page);
|
|
return false;
|
|
}
|
|
|
|
await page.waitForTimeout(2500);
|
|
|
|
// 验证添加结果
|
|
const addSuccess = await waitForToast(page, '添加成功', 3000);
|
|
const modalClosed = !(await page.locator('text=添加家族病史').first().isVisible({ timeout: 500 }).catch(() => false));
|
|
|
|
logTest('家族病史-添加成功', addSuccess || modalClosed, addSuccess ? '显示添加成功提示' : (modalClosed ? '弹窗已关闭' : ''));
|
|
|
|
// 等待数据刷新
|
|
await page.waitForTimeout(1500);
|
|
|
|
// 验证添加后的数据是否正确显示
|
|
const diseaseDisplayed = await page.locator(`text=${TEST_DATA.familyHistory.disease_name}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('家族病史-添加后疾病名称显示', diseaseDisplayed);
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-family-saved.png' });
|
|
|
|
return addSuccess || modalClosed;
|
|
}
|
|
|
|
async function testAllergyRecordAdd(page) {
|
|
console.log('\n【步骤6】测试添加过敏记录(4个字段)...');
|
|
|
|
// 滚动到过敏记录卡片
|
|
await page.evaluate(() => {
|
|
const allergyTitle = Array.from(document.querySelectorAll('*')).find(
|
|
el => el.textContent?.trim() === '过敏记录'
|
|
);
|
|
if (allergyTitle) {
|
|
allergyTitle.scrollIntoView({ behavior: 'instant', block: 'center' });
|
|
}
|
|
});
|
|
await page.waitForTimeout(800);
|
|
|
|
// 点击添加按钮
|
|
const addPos = await page.evaluate(() => {
|
|
const allergyTitle = Array.from(document.querySelectorAll('*')).find(
|
|
el => el.textContent?.trim() === '过敏记录'
|
|
);
|
|
if (allergyTitle) {
|
|
const rect = allergyTitle.getBoundingClientRect();
|
|
return { x: window.innerWidth - 50, y: Math.min(rect.y, window.innerHeight - 100) };
|
|
}
|
|
return null;
|
|
});
|
|
|
|
if (!addPos) {
|
|
logTest('打开添加过敏记录弹窗', false, '未找到添加按钮');
|
|
return false;
|
|
}
|
|
|
|
await page.mouse.click(addPos.x, addPos.y);
|
|
await page.waitForTimeout(1000);
|
|
|
|
const modalOpened = await page.locator('text=添加过敏记录').first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('打开添加过敏记录弹窗', modalOpened);
|
|
|
|
if (!modalOpened) return false;
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-allergy-add-before.png' });
|
|
|
|
// 测试1: 选择过敏类型 - 药物
|
|
const typeClicked = await clickSegmentOption(page, '药物');
|
|
logTest('过敏记录-过敏类型选择', typeClicked);
|
|
await page.waitForTimeout(300);
|
|
|
|
// 测试2: 填写过敏原
|
|
const inputs = page.locator('input:not([type="checkbox"]):not([role="switch"])');
|
|
const allergenInput = inputs.first();
|
|
if (await allergenInput.isVisible()) {
|
|
await allergenInput.click();
|
|
await page.waitForTimeout(200);
|
|
await allergenInput.fill(TEST_DATA.allergyRecord.allergen);
|
|
console.log(` 填写过敏原: ${TEST_DATA.allergyRecord.allergen}`);
|
|
logTest('过敏记录-过敏原输入', true);
|
|
}
|
|
|
|
// 测试3: 选择严重程度 - 重度
|
|
const severityClicked = await clickSegmentOption(page, '重度');
|
|
logTest('过敏记录-严重程度选择', severityClicked);
|
|
await page.waitForTimeout(300);
|
|
|
|
// 测试4: 填写过敏反应描述
|
|
const textAreas = page.locator('textarea');
|
|
if (await textAreas.first().isVisible({ timeout: 500 }).catch(() => false)) {
|
|
await textAreas.first().click();
|
|
await page.waitForTimeout(200);
|
|
await textAreas.first().fill(TEST_DATA.allergyRecord.reaction_desc);
|
|
console.log(` 填写过敏反应描述: ${TEST_DATA.allergyRecord.reaction_desc}`);
|
|
logTest('过敏记录-过敏反应描述输入', true);
|
|
}
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-allergy-add-after.png' });
|
|
|
|
// 点击添加按钮
|
|
const addClicked = await clickByText(page, '添加');
|
|
if (!addClicked) {
|
|
logTest('过敏记录-点击添加', false, '未找到添加按钮');
|
|
await closeAllModals(page);
|
|
return false;
|
|
}
|
|
|
|
await page.waitForTimeout(2500);
|
|
|
|
// 验证添加结果
|
|
const addSuccess = await waitForToast(page, '添加成功', 3000);
|
|
const modalClosed = !(await page.locator('text=添加过敏记录').first().isVisible({ timeout: 500 }).catch(() => false));
|
|
|
|
logTest('过敏记录-添加成功', addSuccess || modalClosed, addSuccess ? '显示添加成功提示' : (modalClosed ? '弹窗已关闭' : ''));
|
|
|
|
// 等待数据刷新
|
|
await page.waitForTimeout(1500);
|
|
|
|
// 验证添加后的数据是否正确显示
|
|
const allergenDisplayed = await page.locator(`text=${TEST_DATA.allergyRecord.allergen}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('过敏记录-添加后过敏原显示', allergenDisplayed);
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-allergy-saved.png' });
|
|
|
|
return addSuccess || modalClosed;
|
|
}
|
|
|
|
async function testMedicalHistoryDelete(page) {
|
|
console.log('\n【步骤7】测试病史记录删除功能...');
|
|
|
|
// 滚动到病史记录区域
|
|
await page.evaluate(() => {
|
|
const medicalTitle = Array.from(document.querySelectorAll('*')).find(
|
|
el => el.textContent?.trim() === '病史记录'
|
|
);
|
|
if (medicalTitle) {
|
|
medicalTitle.scrollIntoView({ behavior: 'instant', block: 'center' });
|
|
}
|
|
});
|
|
await page.waitForTimeout(800);
|
|
|
|
// 检查是否有病史记录可以删除
|
|
const diseaseVisible = await page.locator(`text=${TEST_DATA.medicalHistory.disease_name}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
|
|
if (!diseaseVisible) {
|
|
logTest('病史记录-删除测试', false, '未找到可删除的记录');
|
|
return false;
|
|
}
|
|
|
|
// 长按病史记录项
|
|
const diseasePos = await page.evaluate((diseaseName) => {
|
|
const diseaseEl = Array.from(document.querySelectorAll('*')).find(
|
|
el => el.textContent?.trim() === diseaseName && el.children.length === 0
|
|
);
|
|
if (diseaseEl) {
|
|
const rect = diseaseEl.getBoundingClientRect();
|
|
return { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };
|
|
}
|
|
return null;
|
|
}, TEST_DATA.medicalHistory.disease_name);
|
|
|
|
if (!diseasePos) {
|
|
logTest('病史记录-找到删除目标', false, '未找到记录位置');
|
|
return false;
|
|
}
|
|
|
|
logTest('病史记录-找到删除目标', true);
|
|
|
|
// 长按触发删除
|
|
console.log(' 长按记录...');
|
|
await page.mouse.move(diseasePos.x, diseasePos.y);
|
|
await page.mouse.down();
|
|
await page.waitForTimeout(800); // 长按时间
|
|
await page.mouse.up();
|
|
await page.waitForTimeout(1000);
|
|
|
|
// 检查确认弹窗是否出现
|
|
const confirmVisible = await page.locator('text=确认删除').first().isVisible({ timeout: 3000 }).catch(() => false);
|
|
logTest('病史记录-删除确认弹窗显示', confirmVisible);
|
|
|
|
if (!confirmVisible) {
|
|
// 尝试点击方式触发 onLongPress
|
|
const touchEl = page.locator(`text=${TEST_DATA.medicalHistory.disease_name}`).first();
|
|
if (await touchEl.isVisible()) {
|
|
// 使用 JavaScript 触发 long press
|
|
await page.evaluate((diseaseName) => {
|
|
const el = Array.from(document.querySelectorAll('*')).find(
|
|
e => e.textContent?.trim() === diseaseName && e.children.length === 0
|
|
);
|
|
if (el) {
|
|
// 尝试找到父级 TouchableOpacity 并触发长按
|
|
let parent = el.parentElement;
|
|
for (let i = 0; i < 5 && parent; i++) {
|
|
if (parent.onclick || parent.onlongpress) {
|
|
const event = new Event('longpress', { bubbles: true });
|
|
parent.dispatchEvent(event);
|
|
break;
|
|
}
|
|
parent = parent.parentElement;
|
|
}
|
|
}
|
|
}, TEST_DATA.medicalHistory.disease_name);
|
|
await page.waitForTimeout(1000);
|
|
}
|
|
|
|
// 再次检查
|
|
const confirmAgain = await page.locator('text=确认删除').first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
if (!confirmAgain) {
|
|
logTest('病史记录-删除功能', false, '无法触发长按删除');
|
|
await page.screenshot({ path: 'tests/screenshots/hp-medical-delete-fail.png' });
|
|
return false;
|
|
}
|
|
}
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-medical-delete-confirm.png' });
|
|
|
|
// 点击删除按钮
|
|
const deleteClicked = await clickByText(page, '删除');
|
|
if (!deleteClicked) {
|
|
logTest('病史记录-点击删除按钮', false, '未找到删除按钮');
|
|
await closeAllModals(page);
|
|
return false;
|
|
}
|
|
|
|
logTest('病史记录-点击删除按钮', true);
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 验证删除结果
|
|
const deleteSuccess = await waitForToast(page, '删除成功', 3000);
|
|
logTest('病史记录-删除成功', deleteSuccess, deleteSuccess ? '显示删除成功提示' : '');
|
|
|
|
// 验证记录已从页面移除
|
|
await page.waitForTimeout(1000);
|
|
const diseaseStillVisible = await page.locator(`text=${TEST_DATA.medicalHistory.disease_name}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('病史记录-记录已删除', !diseaseStillVisible, diseaseStillVisible ? '记录仍然显示' : '');
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-medical-delete-done.png' });
|
|
|
|
return deleteSuccess || !diseaseStillVisible;
|
|
}
|
|
|
|
async function verifyAllSavedData(page) {
|
|
console.log('\n【步骤8】验证所有保存的数据...');
|
|
|
|
// 刷新页面获取最新数据
|
|
await page.reload();
|
|
await page.waitForTimeout(3000);
|
|
|
|
// 重新导航到健康档案
|
|
await navigateToHealthProfile(page);
|
|
|
|
// 验证基础信息
|
|
await page.evaluate(() => window.scrollTo(0, 0));
|
|
await page.waitForTimeout(500);
|
|
|
|
const nameVerified = await page.locator(`text=${TEST_DATA.basicInfo.name}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('验证-基础信息姓名', nameVerified);
|
|
|
|
const regionVerified = await page.locator(`text=${TEST_DATA.basicInfo.region}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('验证-基础信息地区', regionVerified);
|
|
|
|
// 验证生活习惯
|
|
await page.evaluate(() => window.scrollTo(0, 300));
|
|
await page.waitForTimeout(500);
|
|
|
|
const sleepTimeVerified = await page.locator(`text=${TEST_DATA.lifestyle.sleep_time}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('验证-生活习惯入睡时间', sleepTimeVerified);
|
|
|
|
// 验证病史记录
|
|
await page.evaluate(() => window.scrollTo(0, 600));
|
|
await page.waitForTimeout(500);
|
|
|
|
const diseaseVerified = await page.locator(`text=${TEST_DATA.medicalHistory.disease_name}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('验证-病史记录疾病名称', diseaseVerified);
|
|
|
|
// 验证家族病史
|
|
const familyDiseaseVerified = await page.locator(`text=${TEST_DATA.familyHistory.disease_name}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('验证-家族病史疾病名称', familyDiseaseVerified);
|
|
|
|
// 验证过敏记录
|
|
const allergenVerified = await page.locator(`text=${TEST_DATA.allergyRecord.allergen}`).first().isVisible({ timeout: 2000 }).catch(() => false);
|
|
logTest('验证-过敏记录过敏原', allergenVerified);
|
|
|
|
await page.screenshot({ path: 'tests/screenshots/hp-final-verification.png' });
|
|
|
|
return nameVerified || sleepTimeVerified;
|
|
}
|
|
|
|
async function runTests() {
|
|
console.log('═══════════════════════════════════════════════════════════');
|
|
console.log(' 健康档案完整功能自动化测试');
|
|
console.log('═══════════════════════════════════════════════════════════');
|
|
console.log('\n测试范围:');
|
|
console.log(' - 基础信息: 9个字段(姓名、性别、出生日期、身高、体重、血型、职业、婚姻、地区)');
|
|
console.log(' - 生活习惯: 10个字段(入睡时间、起床时间、睡眠质量、三餐规律、饮食偏好、');
|
|
console.log(' 日饮水量、运动频率、运动类型、吸烟、饮酒)');
|
|
console.log(' - 病史记录: 添加(5个字段)+ 长按删除');
|
|
console.log(' - 家族病史: 3个字段(亲属关系、疾病名称、备注)');
|
|
console.log(' - 过敏记录: 4个字段(过敏类型、过敏原、严重程度、过敏反应描述)');
|
|
console.log('');
|
|
|
|
const browser = await chromium.launch({ headless: false });
|
|
const context = await browser.newContext({
|
|
viewport: { width: 1280, height: 800 }
|
|
});
|
|
const page = await context.newPage();
|
|
|
|
// 监听错误
|
|
page.on('console', msg => {
|
|
if (msg.type() === 'error') {
|
|
console.log(' [Console Error]', msg.text());
|
|
}
|
|
});
|
|
|
|
page.on('pageerror', error => {
|
|
console.log(' [Page Error]', error.message);
|
|
});
|
|
|
|
try {
|
|
console.log('\n打开应用...');
|
|
await page.goto(APP_URL);
|
|
await page.waitForTimeout(2000);
|
|
|
|
// 执行测试步骤
|
|
const loginOk = await login(page);
|
|
if (!loginOk) throw new Error('登录失败');
|
|
|
|
const navOk = await navigateToHealthProfile(page);
|
|
if (!navOk) throw new Error('导航失败');
|
|
|
|
await testBasicInfoEdit(page);
|
|
await testLifestyleEdit(page);
|
|
await testMedicalHistoryAdd(page);
|
|
await testFamilyHistoryAdd(page);
|
|
await testAllergyRecordAdd(page);
|
|
await testMedicalHistoryDelete(page);
|
|
await verifyAllSavedData(page);
|
|
|
|
} catch (error) {
|
|
console.error('\n测试中断:', error.message);
|
|
await page.screenshot({ path: 'tests/screenshots/hp-error.png' });
|
|
} finally {
|
|
// 打印测试摘要
|
|
console.log('\n═══════════════════════════════════════════════════════════');
|
|
console.log(' 测试结果摘要');
|
|
console.log('═══════════════════════════════════════════════════════════');
|
|
console.log(`通过: ${testResults.passed} 失败: ${testResults.failed}`);
|
|
console.log('───────────────────────────────────────────────────────────');
|
|
|
|
// 按类别分组显示
|
|
const categories = {
|
|
'导航': [],
|
|
'基础信息': [],
|
|
'生活习惯': [],
|
|
'病史记录': [],
|
|
'家族病史': [],
|
|
'过敏记录': [],
|
|
'验证': []
|
|
};
|
|
|
|
for (const test of testResults.tests) {
|
|
const icon = test.passed ? '✓' : '✗';
|
|
const line = `${icon} ${test.name}${test.detail ? ' - ' + test.detail : ''}`;
|
|
|
|
if (test.name.includes('导航') || test.name.includes('登录')) {
|
|
categories['导航'].push(line);
|
|
} else if (test.name.includes('基础信息')) {
|
|
categories['基础信息'].push(line);
|
|
} else if (test.name.includes('生活习惯')) {
|
|
categories['生活习惯'].push(line);
|
|
} else if (test.name.includes('病史记录')) {
|
|
categories['病史记录'].push(line);
|
|
} else if (test.name.includes('家族病史')) {
|
|
categories['家族病史'].push(line);
|
|
} else if (test.name.includes('过敏记录')) {
|
|
categories['过敏记录'].push(line);
|
|
} else if (test.name.includes('验证')) {
|
|
categories['验证'].push(line);
|
|
} else {
|
|
categories['导航'].push(line);
|
|
}
|
|
}
|
|
|
|
for (const [category, tests] of Object.entries(categories)) {
|
|
if (tests.length > 0) {
|
|
console.log(`\n【${category}】`);
|
|
for (const test of tests) {
|
|
console.log(` ${test}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log('\n═══════════════════════════════════════════════════════════');
|
|
|
|
await page.waitForTimeout(2000);
|
|
await browser.close();
|
|
|
|
// 返回退出码
|
|
process.exit(testResults.failed > 0 ? 1 : 0);
|
|
}
|
|
}
|
|
|
|
// 运行测试
|
|
runTests();
|
|
|