AI_UIAutomation/scripts/run-ios-controls.sh

115 lines
7.3 KiB
Bash

#!/bin/bash
# iOS 控制用例批量:每个用例前用 WDA terminate/launch 复位到首页,跑完记录结果。失败不阻塞。
# 对齐 Android run-p0-all 的 CONTROL,iOS 适配:① 复位走 WDA(无 adb)② 不做 BLE/WiFi 切换双跑(iOS 无 adb svc,
# 控制走当前连接即可)③ plug 在 iOS 改名为 "Plug JP",PLUG_CTRL_DEVICE 用子串 "Plug"。
# 设备依赖:控制类用例依赖添加阶段(run-ios-adds.sh)已加的设备 + 账号保留的 摄像头/门铃。
# 注:本 iOS 账号当前无 Lock/Blind Tilt 实体 → lock_card/blind_tilt 多半无设备(失败隔离,不影响其它)。
# WDA 须已在 localhost:8100。
set -u
cd "$(dirname "$0")/.."
export PLATFORM=ios SOAK_MODE=1 SKIP_PROTO_NET=1 VITEST_RETRY=1 # 控制阶段:单个 it 失败自动重跑一次(对齐 Android)
export LOCK_DEVICE="Lock 6D" LOCK_PRO_DEVICE="Lock Pro DE" BT_DEVICE="Blind Tilt 42"
# PLUG_CTRL_DEVICE 不导出:plug 控制走 getDeviceName('plug') → 注册表实际名(iOS 当前 "Plug EU"),不写死
BUNDLE=com.wohand.wohand
LOG=reports/ios-controls.log
: > "$LOG"
# WDA 健康检查 + 恢复:/status 不通则重启 iproxy 端口转发(覆盖过夜端口转发断开;设备上 WDA 进程仍在即恢复)。
ensure_wda(){
for t in 1 2 3; do
curl -s --max-time 5 http://localhost:8100/status 2>/dev/null | grep -q '"ready"' && return 0
echo "[wda] /status 不通,重启 iproxy(第 $t 次)..." | tee -a "$LOG"
pkill -f "iproxy 8100" 2>/dev/null; sleep 1
local udid; udid=$(idevice_id -l 2>/dev/null | head -1)
nohup iproxy 8100 8100 -u "$udid" >/dev/null 2>&1 &
sleep 5
done
curl -s --max-time 5 http://localhost:8100/status 2>/dev/null | grep -q '"ready"' && return 0
echo "[wda] !! WDA 仍不可达(设备上 WDA 进程可能已退出,需手动重启 WDA)" | tee -a "$LOG"; return 1
}
reset_home(){
ensure_wda || return 1
local sid
sid=$(curl -s --max-time 5 http://localhost:8100/status 2>/dev/null | grep -oE '"sessionId" *: *"[^"]*"' | sed 's/.*"\([^"]*\)"$/\1/')
[ -z "$sid" ] && { echo "[reset] 无 WDA session(WDA 掉了?)" | tee -a "$LOG"; return 1; }
curl -s -X POST "http://localhost:8100/session/$sid/wda/apps/terminate" -H 'Content-Type: application/json' -d "{\"bundleId\":\"$BUNDLE\"}" >/dev/null 2>&1
sleep 1
curl -s -X POST "http://localhost:8100/session/$sid/wda/apps/launch" -H 'Content-Type: application/json' -d "{\"bundleId\":\"$BUNDLE\"}" >/dev/null 2>&1
sleep 3
}
CONTROLS=(
"action_panel|npx vitest run tests/platform/action_panel_settings.test.ts"
"meter|npx vitest run tests/meter/meter_control.test.ts"
"bot_card|npx vitest run tests/bot/bot_card.test.ts"
"lock_card|npx vitest run tests/lock/lock_card.test.ts"
"curtain|npx vitest run tests/curtain/curtain_control.test.ts"
"curtain3|CURTAIN_DEVICE='Curtain3 Auto' npx vitest run tests/curtain/curtain_control.test.ts"
"curtain3_2025|CURTAIN_DEVICE='Curtain3 2025 Auto' npx vitest run tests/curtain/curtain_control.test.ts"
"plug_jp|PLUG_CTRL_DEVICE='Plug JP' npx vitest run tests/plug/plug_mini_control.test.ts"
"plug_us|PLUG_CTRL_DEVICE='Plug US' npx vitest run tests/plug/plug_mini_control.test.ts"
"plug_eu|PLUG_CTRL_DEVICE='Plug EU' npx vitest run tests/plug/plug_mini_control.test.ts"
"blind_tilt|npx vitest run tests/curtain/blind_tilt_control.test.ts"
"humidifier2|npx vitest run tests/humidifier/humidifier2_card.test.ts"
"air_purifier|npx vitest run tests/air_purifier/air_purifier_card.test.ts"
# 灯类首页卡片控制(电源+亮度+色温):通用用例,按 LIGHT_CARD 覆盖每个灯
"light_eave|LIGHT_REG=eaveLight LIGHT_CARD='Permanent Outdoor Lights' npx vitest run tests/ceiling_light/eave_light_control.test.ts"
"light_color_bulb|LIGHT_REG=colorBulb LIGHT_CARD='Color Bulb' npx vitest run tests/ceiling_light/eave_light_control.test.ts"
"light_ceiling_pro|LIGHT_REG=ceilingLight LIGHT_CARD='Ceiling Light Pro' npx vitest run tests/ceiling_light/eave_light_control.test.ts"
"light_color_floor|LIGHT_REG=colorFloorLamp LIGHT_CARD='RGBICWW Floor Lamp' npx vitest run tests/ceiling_light/eave_light_control.test.ts"
"light_floor|LIGHT_REG=floorLamp LIGHT_CARD='RGBWW Floor Lamp' npx vitest run tests/ceiling_light/eave_light_control.test.ts"
"light_strip|LIGHT_REG=stripLight LIGHT_CARD='Strip Light SB' npx vitest run tests/ceiling_light/eave_light_control.test.ts"
"light_strip3|LIGHT_REG=stripLight3 LIGHT_CARD='RGBWW Strip Light 3' npx vitest run tests/ceiling_light/eave_light_control.test.ts"
"light_neon|LIGHT_REG=neonLight LIGHT_CARD='RGBIC Neon Rope Light' npx vitest run tests/ceiling_light/eave_light_control.test.ts"
# 摄像头拉流(iOS 3/3 已验证;依赖保留的摄像头)
"camera_stream|STREAM_HOLD_MS=60000 npx vitest run tests/camera/camera_stream.test.ts"
# ===== TAIL:keypad 闭环 + 平台 + 账号(对齐 Android run-p0-all 的 TAIL,顺序一致)=====
# keypad 功能页闭环(绑锁+加密码+解绑);依赖账号保留的 Lock。账号注销前跑。
"keypad_lock_passcode|npx vitest run tests/keypad/keypad_lock_passcode.test.ts"
"feedback|npx vitest run tests/platform/feedback.test.ts"
"rn_plugin|npx vitest run tests/platform/rn_plugin.test.ts"
"create_room|npx vitest run tests/platform/create_room.test.ts"
"message_center|npx vitest run tests/platform/message_center.test.ts"
"scene_operation|npx vitest run tests/platform/scene_operation.test.ts"
# 账号:delete_account 注册临时号再删临时号(不碰主账号);login 最后重新登录主账号收尾。third_party iOS→SKIP。
"third_party_login|npx vitest run tests/auth/third_party_login.test.ts"
"eu_login|npx vitest run tests/auth/eu_login.test.ts"
"register|npx vitest run tests/auth/register.test.ts"
"forgot_password|npx vitest run tests/auth/forgot_password.test.ts"
"delete_account|npx vitest run tests/auth/delete_account.test.ts"
"login|npx vitest run tests/auth/login.test.ts"
)
echo "===== $(date '+%F %T') iOS 控制批量开始 =====" | tee -a "$LOG"
# 跑单条:复位→执行→打印结果;含 "✗ [FAIL]" 返回 1(SKIP/无设备不算失败,不重试)。
run_ctrl_one() {
local name="$1" cmd="$2"
echo "----- $(date +%T) [$name] -----" | tee -a "$LOG"
reset_home
eval "$cmd" > /tmp/ios-ctrl-one.log 2>&1
grep -E '✓ \[PASS\]|✗ \[FAIL\]|○ \[SKIP\]|结果:|未找到|not found|cannot' /tmp/ios-ctrl-one.log | grep -ivE "deprecat" | tail -6 | tee -a "$LOG"
grep -q '✗ \[FAIL\]' /tmp/ios-ctrl-one.log && return 1 || return 0
}
FAILED=()
for entry in "${CONTROLS[@]}"; do
name="${entry%%|*}"; cmd="${entry#*|}"
run_ctrl_one "$name" "$cmd" || FAILED+=("$entry")
done
# 控制失败重试一轮(控制偶发性高:首页卡片漂移/浮层/同步延迟;失败常为环境抖动)
if [ ${#FAILED[@]} -gt 0 ]; then
echo "===== iOS 控制失败 ${#FAILED[@]} 个,重试一轮 =====" | tee -a "$LOG"
for entry in "${FAILED[@]}"; do
name="${entry%%|*}"; cmd="${entry#*|}"
run_ctrl_one "${name}-retry" "$cmd" && echo "[CTRL-RETRY-OK] $name" | tee -a "$LOG" || echo "[CTRL-RETRY-GIVEUP] $name" | tee -a "$LOG"
done
fi
echo "===== $(date '+%F %T') iOS 控制完成 =====" | tee -a "$LOG"
# 汇总 iOS 全量(添加+控制,SOAK_MODE 累计在 reports/.results.json)逐用例报告
TS=$(date +%Y%m%d-%H%M%S)
npx ts-node scripts/gen-combined.ts "iOSAll_$TS" >> "$LOG" 2>&1 \
&& echo "iOS 逐用例报告: reports/iOSAll_${TS}_*.html" | tee -a "$LOG" \
|| echo "报告生成失败(见 $LOG)" | tee -a "$LOG"