150 lines
5.0 KiB
TypeScript
150 lines
5.0 KiB
TypeScript
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);
|