Files
railwaysystem/scripts/qa/browser_regression.js
T
buliping 1def568f24 refactor(iot): 移除 MQTT 传输层,仅保留设备开放接口与门禁写操作策略
- 依赖:删除根 pom 的 paho.version 与 org.eclipse.paho.client.mqttv3 依赖声明,
  同步移除 ruoyi-iot 模块中的 Paho 依赖,模块描述改为“iot设备数据与开放接口”
- MQTT 协议栈整体删除:IotMqttConfig、IotMqttProperties、MqttClientManager、
  MqttMessageDispatcher、MqttCallbackHandler、MqttConnectionCallback、
  IMqttMessageListener、MqttMessageDTO、MqttPublishRequest、MqttMessageEvent、
  IMqttService/MqttServiceImpl、IotMqttController,以及 lock 侧 topic 订阅与
  LockMessageListener、AccessRecordHandler、CommandRespHandler、
  GatewayOnlineHandler、LockSignalHandler
- MQTT 报文留痕链路删除:LockMqttLog 实体、LockMqttLogMapper(+XML)、
  ILockMqttLogService/LockMqttLogServiceImpl、LockMqttLogController,
  以及对应的前端页面 build_ui/src/views/iot/mqttlog 与 API build_ui/src/api/iot/mqttlog.js
- 命令下发改为仅落库:LockCommandServiceImpl 派发时直接置 TRANSPORT_DISABLED 失败,
  retryPending 返回 0;删除 GatewayOfflineCheckTask、LockCommandRetryTask、
  LockDeviceOfflineCheckTask 等依赖 MQTT 的补偿与离线检查定时任务
- 保留与传输无关的门禁写操作策略:新增 IotLockSecurityProperties(iot.lock-security),
  RealIotSecurityGate 及其测试改用该配置类
- 配置与调用处清理:application*.yml 中 iot.mqtt 段迁移为 iot.lock-security,
  删除 broker-url/client-id/username/password/topics/will/qos 等连接参数,
  修正 iot.face 环境标识注释引用;QA 工具启动参数改用 --iot.lock-security.*,
  并移除 browser_regression.js 的 mqttlog 路由
- 测试同步:删除依赖 MQTT 与传输层的 CommandRespHandlerMockTest、
  Round5sEgressIsolationTest、Round5sExecutionIntegrationTest、
  Round5v4BrowserFixture、Round5v4KingbaseIntegrationTest;
  更新 RealIotSecurityGateTest、FaceExtractClientMockTest、
  TrainIotLockAuthBridgeMockTest

说明:数据库侧 lock_mqtt_log 表结构与历史验收文档保留,未做数据迁移;
前端若仍配置了“MQTT报文日志”菜单,需在后台菜单管理中一并移除。
2026-11-10 16:06:23 +08:00

42 lines
2.7 KiB
JavaScript

async (page) => {
if (!page.__qaEvidence) throw new Error('Run the protected Chrome login driver first');
const blockedHosts=new Set(),requestHosts=new Set();
// Real pages/API only; never substitute responses or allow a stored photo URL to contact a device service.
await page.route('**/*',async route=>{
const url=route.request().url(),host=url.match(/^https?:\/\/([^/]+)/)?.[1];
if(host)requestHosts.add(host);
if(host&&host!=='127.0.0.1:18088'){blockedHosts.add(host);await route.abort('blockedbyclient');}
else await route.continue();
});
const routes = [
['/index', null], ['/person/student', 'Student'], ['/person/teacher', null],
['/coursemgr/plan', null], ['/equip/dormitory', null], ['/equip/accommodation', 'Accommodation'],
...Object.entries({group:'Group',gateway:'Gateway',device:'Device',face:'Face',auth:'Auth',
accesslog:'AccessLog',command:'Command',config:'ServiceConfig'}).map(([r,c])=>['/iot/'+r,c])
];
const results=[];
for (const [path,expected] of routes) {
const start=page.__qaEvidence.responses.length;
await page.goto('http://127.0.0.1:18088'+path);
await page.waitForLoadState('networkidle');
const components=await page.locator('.app-main').evaluate(e=>{
function names(v){return v?[v.$options.name||v.$options._componentTag||'',...v.$children.flatMap(names)]:[];}
return names(e.__vue__).filter(n=>n&&!n.startsWith('El'));
});
const api=[...new Map(page.__qaEvidence.responses.slice(start).map(r=>[JSON.stringify(r),r])).values()];
const tables=await page.locator('.app-main .el-table').count();
const pass=page.url()==='http://127.0.0.1:18088'+path&&
(await page.title()).includes('SYFJGYD')&&(!expected||components.includes(expected))&&
!components.some(n=>/404|401|ErrorPage/i.test(n))&&api.length>0&&
api.every(r=>r.status===200&&(r.code==null||r.code===200))&&page.__qaEvidence.errors.length===0&&blockedHosts.size===0&&
(path==='/index'?await page.locator('canvas').count()===4:tables>0);
results.push({path,pass,components:[...new Set(components)],tables,api});
if(!pass)throw new Error('Actual component/API regression failed: '+JSON.stringify(results.at(-1)));
if(path==='/index')await page.screenshot({path:'output/playwright/round5v4-home-final.png',fullPage:true});
if(path.startsWith('/iot/'))await page.screenshot({path:'output/playwright/round5v4-'+path.split('/').at(-1)+'-headers.png',
mask:[page.locator('.el-table__body-wrapper'),page.locator('.avatar-container')]});
}
return {pass:true,chrome:page.context().browser().version(),results,errors:page.__qaEvidence.errors,
requestHosts:[...requestHosts],blockedExternalHosts:[...blockedHosts]};
}