AI_UIAutomation/scripts/wda_find_bot.ts

150 lines
5.0 KiB
TypeScript
Raw Permalink 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 * as http from 'http';
import * as dotenv from 'dotenv';
import * as path from 'path';
dotenv.config({ path: path.resolve(__dirname, '../.env') });
function wdaRequest(method: string, urlPath: string, body?: any): Promise<any> {
return new Promise((resolve, reject) => {
const options = {
hostname: 'localhost',
port: 8100,
path: urlPath,
method: method,
headers: { 'Content-Type': 'application/json' },
};
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => (data += chunk));
res.on('end', () => {
try { resolve(JSON.parse(data)); } catch { resolve(data); }
});
});
req.on('error', reject);
if (body) req.write(JSON.stringify(body));
req.end();
});
}
async function main() {
console.log('=== WDA原生API点击Bot 0F + 探索设置页 ===\n');
// 创建session
const sessionRes = await wdaRequest('POST', '/session', {
capabilities: {
alwaysMatch: {
platformName: 'iOS',
automationName: 'XCUITest',
shouldUseSingletonTestManager: false,
},
},
});
const sessionId = sessionRes.value?.sessionId || sessionRes.sessionId;
console.log('Session:', sessionId);
// 启动APP
await wdaRequest('POST', `/session/${sessionId}/wda/apps/launch`, {
bundleId: 'com.wohand.wohand',
});
await new Promise((r) => setTimeout(r, 5000));
// 找到Bot 0F Cell元素
const findRes = await wdaRequest('POST', `/session/${sessionId}/element`, {
using: 'name',
value: 'Bot 0FOff',
});
let botElemId = findRes.value?.ELEMENT || findRes.value?.['element-6066-11e4-a52e-4f735466cecf'];
if (!botElemId) {
// 可能状态是On
const findRes2 = await wdaRequest('POST', `/session/${sessionId}/element`, {
using: 'name',
value: 'Bot 0FOn',
});
botElemId = findRes2.value?.ELEMENT || findRes2.value?.['element-6066-11e4-a52e-4f735466cecf'];
}
if (!botElemId) {
// 尝试partial match
const findRes3 = await wdaRequest('POST', `/session/${sessionId}/elements`, {
using: 'predicate string',
value: 'name CONTAINS "Bot 0F"',
});
console.log('Predicate查找结果:', JSON.stringify(findRes3.value?.length || 0), '个元素');
if (findRes3.value?.length > 0) {
botElemId = findRes3.value[0].ELEMENT || findRes3.value[0]['element-6066-11e4-a52e-4f735466cecf'];
}
}
if (!botElemId) {
console.log('找不到Bot 0F元素');
await wdaRequest('DELETE', `/session/${sessionId}`);
return;
}
// 获取元素位置
const rectRes = await wdaRequest('GET', `/session/${sessionId}/element/${botElemId}/rect`);
const rect = rectRes.value;
console.log('Bot 0F元素位置:', rect);
// 点击元素中心
const centerX = rect.x + rect.width / 2;
const centerY = rect.y + rect.height / 2;
console.log(`\n点击Bot 0F中心坐标: (${centerX}, ${centerY})`);
await wdaRequest('POST', `/session/${sessionId}/wda/tap`, { x: centerX, y: centerY });
await new Promise((r) => setTimeout(r, 3000));
// 获取点击后的页面source看是否有弹框
console.log('\n检查点击后状态...');
const afterSource = await wdaRequest('GET', `/session/${sessionId}/source`);
const afterXml = afterSource.value as string;
// 查找弹框/菜单相关元素
const sheetMatch = afterXml.match(/<XCUIElementTypeSheet[^>]*>/g);
const alertMatch = afterXml.match(/<XCUIElementTypeAlert[^>]*>/g);
const popoverMatch = afterXml.match(/<XCUIElementTypePopover[^>]*>/g);
const menuMatch = afterXml.match(/name="[^"]*[Ss]etting[^"]*"/g);
console.log('Sheet元素:', sheetMatch?.length || 0);
console.log('Alert元素:', alertMatch?.length || 0);
console.log('Popover元素:', popoverMatch?.length || 0);
console.log('Setting相关:', menuMatch);
// 搜索所有包含 "Setting" 的元素
const settingElements = afterXml.match(/[^<]*[Ss]etting[^<]*/gi);
if (settingElements) {
console.log('\nSetting相关元素:');
settingElements.slice(0, 5).forEach((m, i) => console.log(` ${i + 1}. ${m.substring(0, 200)}`));
}
// 搜索所有按钮
const buttons = afterXml.match(/<XCUIElementTypeButton[^>]*name="[^"]*"[^>]*/g);
if (buttons) {
console.log('\n当前页面所有按钮:');
buttons.slice(0, 20).forEach((b, i) => {
const nameMatch = b.match(/name="([^"]*)"/);
const visMatch = b.match(/visible="([^"]*)"/);
if (visMatch && visMatch[1] === 'true') {
console.log(` ${i + 1}. ${nameMatch?.[1] || 'unnamed'}`);
}
});
}
// 搜索所有可见的Cell和StaticText
const visibleCells = afterXml.match(/<XCUIElementTypeCell[^>]*visible="true"[^>]*/g);
if (visibleCells) {
console.log('\n可见的Cell元素:');
visibleCells.slice(0, 10).forEach((c, i) => {
const nameMatch = c.match(/name="([^"]*)"/);
console.log(` ${i + 1}. ${nameMatch?.[1] || 'unnamed'}`);
});
}
// 清理
await wdaRequest('DELETE', `/session/${sessionId}`);
console.log('\n=== 完成 ===');
}
main().catch(console.error);