AI_UIAutomation/utils/common/feedback.helper.ts

96 lines
4.4 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 { DeviceDriver } from '../../drivers/types';
import { sleep, waitForSource } from './element.helper';
import { extractTicketId, setSharedTicketId } from './zendesk.helper';
async function tapText(driver: DeviceDriver, t: string): Promise<boolean> {
const el = driver.platform === 'android'
? await driver.findElementRaw('-android uiautomator', `new UiSelector().textContains("${t}")`)
: await driver.findElementRaw('name', t);
if (el) { await driver.tapElement(el); return true; }
return false;
}
/** Profile → Support → Feedback 页(我的反馈工单列表 + Create a New Ticket)。 */
export async function navigateToFeedback(driver: DeviceDriver): Promise<boolean> {
const prof = await driver.findElementRaw('-android uiautomator', 'new UiSelector().descriptionContains("Profile")');
if (prof) { await driver.tapElement(prof); await sleep(2000); }
if (!(await tapText(driver, 'Support'))) return false;
await sleep(2000);
if (!(await tapText(driver, 'Feedback'))) return false;
await sleep(2000);
return true;
}
/**
* 提交一条 feedback 工单(Android 实测 2026-06)。流程:
* Feedback 页 → Create a New Ticket → Question Type 滚轮(从 Product Issues 起第 typeIndex 个)
* → 填 Question Details → Submit → "My Feedback" 成功页(含 Ticket ID)。
*
* Question Type 滚轮选项无障碍不可见,只能盲滑:**先重置到顶(Product Issues),再上滑 typeIndex 格**。
* 顺序:0 Product Issues / 1 Order Tracking / 2 Buying Guide / 3 App issues / 4 Rapid Replacement / 5 B2B Enquiry。
* 坐标按 1080×2280;换机型需调。
* @returns 是否到达成功页
*/
export async function submitFeedback(
driver: DeviceDriver,
opts: { details?: string; typeIndex?: number } = {}
): Promise<boolean> {
const details = opts.details || '内测问题直接关闭插件热更校验';
const typeIndex = opts.typeIndex ?? 3; // App issues
if (!(await tapText(driver, 'Create a New Ticket'))) {
// 已无工单时按钮文案可能不同,兜底找 "Create"
if (!(await tapText(driver, 'Create'))) return false;
}
await waitForSource(driver, 'Question Type', 8000).catch(() => {});
// 选 Question Type:开 picker → 重置到顶 → 上滑 typeIndex 格 → Confirm
// 开选择器:优先点字段文字 "Please select"(跨分辨率稳),找不到再坐标兜底。
if (!(await tapText(driver, 'Please select'))) { await driver.tap(540, 460); }
await sleep(1200);
// 类型轮选项无障碍不可见,只能盲滑;与时间轮(automation.helper spinWheel)同一套方式:
// 单格慢滑 ~95px、duration 0.5、无惯性(1 次=1 格)。列居中 x≈540、选中带中心 y≈2090。
const COL_X = 540, MID = 2090, TOP = 1995;
for (let i = 0; i < 8; i++) { await driver.swipe(COL_X, TOP, COL_X, MID, 0.5); await sleep(250); } // 下滑到顶=Product Issues
await sleep(300);
for (let i = 0; i < typeIndex; i++) { await driver.swipe(COL_X, MID, COL_X, TOP, 0.5); await sleep(250); } // 上滑 N 格
await sleep(300);
// Confirm:文字定位(实测在 y≈1714,旧硬编码 y1511 点空),坐标兜底。
if (!(await tapText(driver, 'Confirm'))) { await driver.tap(947, 1714); }
await sleep(2000);
// 填 Question Details(末个 EditText)
const eds = await driver.findElementsRaw('-android uiautomator', 'new UiSelector().className("android.widget.EditText")');
if (!eds.length) return false;
await driver.typeText(eds[eds.length - 1], details);
await sleep(500);
try { await driver.goBack(); } catch { /* 收键盘 */ }
// Submit
if (!(await tapText(driver, 'Submit'))) return false;
await sleep(4000);
// 成功页:My Feedback / Ticket ID
return waitForSource(driver, 'Ticket ID', 8000).catch(() => false) as Promise<boolean>;
}
/**
* feedback 提交成功后,从结果页抓取工单号并持久化(供「获取RN插件 / 插件热更」用例消费)。
* 返回工单号;未抓到返回 null。
*/
export async function captureFeedbackTicketId(driver: DeviceDriver): Promise<string | null> {
let ticketId: string | null = null;
for (let i = 0; i < 3 && !ticketId; i++) {
const source = await driver.getSource();
ticketId = extractTicketId(source);
if (!ticketId) await sleep(1500);
}
if (ticketId) {
setSharedTicketId(ticketId);
console.log(`feedback 工单号已捕获并保存: ${ticketId}`);
} else {
console.log('feedback 提交页未解析到工单号(检查 extractTicketId 规则与实际 UI)');
}
return ticketId;
}