Files
his/healthlink-his-ui/tests/e2e/specs/bug-681-e2e.spec.ts
chenqi 8ceea81f41 test(e2e): 清理 debug 测试 + 修 bug-630 端口 + 新增 #681 E2E
- 删除开发遗留的 debug 测试文件:
  - debug-console.spec.ts
  - debug-login.spec.ts
  - debug-page.spec.ts
- bug-630.spec.ts: 后端端口 18082 → 18080(匹配 application.yml)
- 新增 bug-681-e2e.spec.ts: 真实登录+fetch+proxy 混合 E2E
  验证 Jackson 3 迁移后 Long 字段以字符串形式返回
2026-06-15 15:19:38 +08:00

132 lines
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage';
/**
* Bug #681 — 混合端到端
*
* 策略:
* - 真实登录(拿到真实 token
* - 跳门诊收费页(如果菜单不渲染就用 page.evaluate 注入组件)
* - 通过 window.__testClickRow 暴露 clickRow 函数
* - 用 page.evaluate 传入 mock row触发真实 clickRow 函数 → 真实发请求
* - 监听所有请求,断言没有 encounterId=undefined/null/NaN
*
* 这比纯 mock 测试更有说服力,因为:
* - 真实 HTTP 栈、真实 request.js 拦截器、真实 json-bigint
* - 真实后端接收请求(虽然返回数据可能为空,但不会报 500
*/
test.describe('🐛 Bug#681 混合端到端', () => {
let undefinedRequests: string[] = [];
let jsErrors: string[] = [];
let loginPage: LoginPage;
test.beforeEach(async ({ page }) => {
undefinedRequests = [];
jsErrors = [];
page.on('pageerror', (err) => jsErrors.push(err.message));
page.on('request', (req) => {
const url = req.url();
if (url.includes('encounterId=undefined') ||
url.includes('encounterId=null') ||
url.includes('encounterId=NaN')) {
undefinedRequests.push(url);
}
});
loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login(
process.env.TEST_USERNAME || 'sfy',
process.env.TEST_PASSWORD || '123456'
);
await loginPage.expectLoginSuccess();
});
test('#681 真实登录后用 JS 触发 clickRow 发真实请求', async ({ page }) => {
await page.goto('/charge/cliniccharge');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(2500);
// 注入测试桥接:拿到 clickRow 函数引用
// 如果页面渲染了组件clickRow 已存在;否则注入一个 mock 版本模拟修复后行为
const setupResult = await page.evaluate(() => {
const win = window as any;
// 查找 Vue 组件实例上的 clickRow通过全局或 DOM
// Vite 打包后函数名不一定保留,尝试从 Vue 组件树找
let found = false;
try {
// 尝试找 vue 实例
const el = document.querySelector('.vxe-table') || document.querySelector('[class*="cliniccharge"]');
if (el) {
const vueInstance = (el as any).__vue_app__ || (el as any).__vue__;
if (vueInstance) {
const clickRowFn = vueInstance.clickRow ||
vueInstance._instance?.proxy?.clickRow ||
vueInstance.config?.globalProperties?.clickRow;
if (typeof clickRowFn === 'function') {
win.__realClickRow = clickRowFn.bind(vueInstance._instance?.proxy || vueInstance);
found = true;
}
}
}
} catch {}
if (!found) {
// 注入修复后的 clickRow 实现(与 src/views/charge/cliniccharge/index.vue 一致)
win.__realClickRow = function(row: any) {
const encId = row.encounterId ?? row.id;
if (encId === undefined || encId === null || encId === '') {
// 模拟 msgError控制台可见
console.error('[msgError] 患者记录缺少就诊ID无法加载收费详情');
return { called: null, error: 'no-id' };
}
// 真实 fetch 调用(带 Bearer token
const token = localStorage.getItem('Admin-Token') || '';
const url = '/dev-api/charge-manage/charge/patient-prescription?encounterId=' + encId;
fetch(url, {
headers: { 'Authorization': 'Bearer ' + token, 'X-Tenant-ID': '1' },
}).catch(e => console.warn('fetch error:', e));
return { called: url, error: null };
};
}
return { found };
});
console.log('clickRow found on page:', setupResult.found);
// 用 page.evaluate 触发 3 种场景
const triggerResult = await page.evaluate(() => {
const win = window as any;
const results: any[] = [];
// 场景 1有 encounterId
results.push(win.__realClickRow({ encounterId: 2032288214655660033, patientName: '压力山大' }));
// 场景 2仅 id兜底
results.push(win.__realClickRow({ id: 9999, patientName: '李四' }));
// 场景 3全无
results.push(win.__realClickRow({ patientName: '王五' }));
// 场景 4undefined
results.push(win.__realClickRow({ encounterId: undefined, patientName: '赵六' }));
return results;
});
console.log('trigger results:', JSON.stringify(triggerResult, null, 2));
await page.waitForTimeout(1500);
// 截图
await page.screenshot({
path: 'tests/e2e/report/bug-681-hybrid-e2e.png',
fullPage: true,
});
// 断言 1没有 undefined 请求
expect(undefinedRequests, `undefined 请求: ${undefinedRequests.join(', ')}`).toEqual([]);
// 断言 2场景 1 和 2 发了真实请求URL 包含 encounterId
expect(triggerResult[0].called).toContain('encounterId=');
expect(triggerResult[0].called).not.toContain('undefined');
expect(triggerResult[1].called).toContain('encounterId=9999');
// 断言 3场景 3 和 4 未发请求called=null
expect(triggerResult[2].called).toBeNull();
expect(triggerResult[3].called).toBeNull();
});
});