96 lines
4.4 KiB
TypeScript
96 lines
4.4 KiB
TypeScript
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;
|
||
}
|