diff --git a/examples/uitest/android_expert_test.json b/examples/uitest/android_expert_test.json new file mode 100644 index 00000000..97edc084 --- /dev/null +++ b/examples/uitest/android_expert_test.json @@ -0,0 +1,476 @@ +{ + "config": { + "name": "安卓专家用例", + "variables": { + "app_name": "抖音", + "bundle_id": "com.ss.android.ugc.aweme", + "device": "${ENV(SerialNumber)}", + "query": "${ENV(query)}" + }, + "android": [ + { + "serial": "$device", + "uia2": true, + "log_on": true + } + ] + }, + "teststeps": [ + { + "name": "app_launch 以及 ui_foreground_app equal 断言", + "android": { + "actions": [ + { + "method": "app_launch", + "params": "$bundle_id" + }, + { + "method": "sleep", + "params": 2 + } + ] + }, + "validate": [ + { + "check": "ui_foreground_app", + "assert": "equal", + "expect": "$bundle_id", + "msg": "app [$bundle_id] should be in foreground" + } + ] + }, + { + "name": "home 以及 swipe_to_tap_app 默认配置", + "android": { + "actions": [ + { + "method": "home" + }, + { + "method": "swipe_to_tap_app", + "params": "$app_name", + "options": {} + }, + { + "method": "sleep", + "params": 10 + } + ] + } + }, + { + "name": "处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言", + "android": { + "actions": [ + { + "method": "tap_ocr", + "params": "我知道了", + "options": { + "ignore_NotFoundError": true + } + } + ] + }, + "validate": [ + { + "check": "ui_ocr", + "assert": "exists", + "expect": "推荐", + "msg": "进入抖音失败" + } + ] + }, + { + "name": "【直播】feed头像或卡片进房 swipe_to_tap_texts 自定义配置", + "android": { + "actions": [ + { + "method": "swipe_to_tap_texts", + "params": [ + "直播", + "直播中", + "点击进入直播间" + ], + "options": { + "identifier": "click_live", + "max_retry_times": 50, + "interval": 1.5, + "direction": [ + 0.5, + 0.7, + 0.5, + 0.3 + ], + "scope": [ + 0.2, + 0.2, + 1, + 0.8 + ] + } + } + ] + } + }, + { + "name": "sleep 10s", + "android": { + "actions": [ + { + "method": "sleep", + "params": 10 + } + ] + } + }, + { + "name": "【直播】swipe 自定义配置 以及 back", + "android": { + "actions": [ + { + "method": "swipe", + "params": [ + 0.5, + 0.7, + 0.5, + 0.3 + ], + "options": { + "identifier": "slide_in_live" + } + }, + { + "method": "sleep", + "params": 5 + }, + { + "method": "back", + "options": {} + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "【搜索】点击放大镜 tap_xy 自定义配置", + "android": { + "actions": [ + { + "method": "tap_xy", + "params": [ + 0.9, + 0.08 + ], + "options": { + "identifier": "click_search_in_middle_page" + } + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "【搜索】输入query词 input", + "android": { + "actions": [ + { + "method": "input", + "params": "$query", + "options": { + "identifier": "input_query" + } + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "【搜索】点击搜索按钮 tap_ocr 自定义配置", + "android": { + "actions": [ + { + "method": "tap_ocr", + "params": "搜索", + "options": { + "identifier": "click_search_after_input_query" + } + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "选择直播页签 tap_ocr 默认配置", + "android": { + "actions": [ + { + "method": "tap_ocr", + "params": "直播", + "options": {} + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "【生活服务】进入直播间 tap_xy", + "android": { + "actions": [ + { + "method": "tap_xy", + "params": [ + 0.5, + 0.5 + ], + "options": {} + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "【生活服务】点击货架商品 tap_ocr 自定义配置", + "android": { + "actions": [ + { + "method": "tap_cv", + "options": { + "identifier": "click_sales_rack", + "screenshot_with_ui_types": [ + "dyhouse", + "shoppingbag" + ] + } + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "app_terminate 以及 ui_foreground_app not_equal 断言", + "android": { + "actions": [ + { + "method": "app_terminate", + "params": "$bundle_id" + }, + { + "method": "sleep", + "params": 2 + } + ] + }, + "validate": [ + { + "check": "ui_foreground_app", + "assert": "not_equal", + "expect": "$bundle_id", + "msg": "app [$bundle_id] should not be in foreground" + } + ] + }, + { + "name": "home 以及 swipe_to_tap_app 自定义配置", + "android": { + "actions": [ + { + "method": "home" + }, + { + "method": "swipe_to_tap_app", + "params": "$app_name", + "options": { + "max_retry_times": 5, + "interval": 1, + "offset": [ + 0, + -50 + ] + } + }, + { + "method": "sleep", + "params": 10 + } + ] + } + }, + { + "name": "处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言", + "android": { + "actions": [ + { + "method": "tap_ocr", + "params": "我知道了", + "options": { + "ignore_NotFoundError": true + } + } + ] + }, + "validate": [ + { + "check": "ui_ocr", + "assert": "exists", + "expect": "推荐", + "msg": "进入抖音失败" + } + ] + }, + { + "name": "【点播】滑动消费", + "android": { + "actions": [ + { + "method": "video_crawler", + "params": { + "feed": { + "sleep_random": [ + 0, + 5, + 0.6, + 5, + 15, + 0.2, + 15, + 50, + 0.2 + ], + "target_count": 10, + "target_labels": [ + { + "regex": true, + "scope": [ + 0, + 0.5, + 1, + 1 + ], + "text": "^广告$" + }, + { + "regex": true, + "scope": [ + 0, + 0.5, + 1, + 1 + ], + "text": "^图文$" + }, + { + "regex": true, + "scope": [ + 0, + 0.5, + 1, + 1 + ], + "text": "^特效\\|" + }, + { + "regex": true, + "scope": [ + 0, + 0.5, + 1, + 1 + ], + "text": "^模板\\|" + }, + { + "regex": true, + "scope": [ + 0, + 0.5, + 1, + 1 + ], + "text": "^购物\\|" + } + ] + }, + "live": { + "sleep_random": [ + 20, + 20 + ], + "target_count": 0 + }, + "timeout": 600 + } + } + ] + } + }, + { + "name": "返回主界面,并打开本地时间戳", + "android": { + "actions": [ + { + "method": "home" + }, + { + "method": "app_terminate", + "params": "$bundle_id" + }, + { + "method": "sleep", + "params": 3 + }, + { + "method": "swipe_to_tap_app", + "params": "local", + "options": { + "max_retry_times": 5 + } + }, + { + "method": "sleep", + "params": 10 + } + ] + } + }, + { + "name": "screeshot 以及 sleep_random", + "android": { + "actions": [ + { + "method": "screenshot", + "options": {} + }, + { + "method": "sleep_random", + "params": [ + 1, + 3 + ] + } + ] + }, + "loops": 3 + } + ] +} \ No newline at end of file diff --git a/examples/uitest/expert_test.go b/examples/uitest/expert_test.go new file mode 100644 index 00000000..0067f625 --- /dev/null +++ b/examples/uitest/expert_test.go @@ -0,0 +1,325 @@ +//go:build localtest + +package uitest + +import ( + "testing" + + "github.com/httprunner/httprunner/v4/hrp" + "github.com/httprunner/httprunner/v4/hrp/pkg/uixt" +) + +func TestAndroidExpertTest(t *testing.T) { + testCase := &hrp.TestCase{ + Config: hrp.NewConfig("安卓专家用例"). + WithVariables(map[string]interface{}{ + "device": "${ENV(SerialNumber)}", + "query": "${ENV(query)}", + "bundle_id": "com.ss.android.ugc.aweme", + "app_name": "抖音", + }). + SetAndroid( + uixt.WithSerialNumber("$device"), + uixt.WithAdbLogOn(true), + uixt.WithUIA2(true), + ), + TestSteps: []hrp.IStep{ + // 温启动 + hrp.NewStep("app_launch 以及 ui_foreground_app equal 断言"). + Android(). + AppLaunch("$bundle_id"). + Sleep(2). + Validate(). + AssertAppInForeground("$bundle_id"), + hrp.NewStep("home 以及 swipe_to_tap_app 默认配置"). + Android(). + Home(). + SwipeToTapApp("$app_name"). + Sleep(10), + hrp.NewStep("处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言"). + Android(). + TapByOCR( + "我知道了", + uixt.WithIgnoreNotFoundError(true), + ). + Validate(). + AssertOCRExists("推荐", "进入抖音失败"), + // 直播赛道 + hrp.NewStep("【直播】feed头像或卡片进房 swipe_to_tap_texts 自定义配置"). + Android(). + SwipeToTapTexts( + []string{"直播", "直播中", "点击进入直播间"}, + uixt.WithCustomDirection(0.5, 0.7, 0.5, 0.3), + uixt.WithScope(0.2, 0.2, 1, 0.8), + uixt.WithMaxRetryTimes(50), + uixt.WithWaitTime(1.5), + uixt.WithIdentifier("click_live"), + ), + hrp.NewStep("sleep 10s"). + Android(). + Sleep(10), + hrp.NewStep("【直播】swipe 自定义配置 以及 back"). + Android(). + Swipe( + 0.5, 0.7, 0.5, 0.3, + uixt.WithIdentifier("slide_in_live"), + ). + Sleep(5). + Back(). + Sleep(5), + // 搜索赛道 + hrp.NewStep("【搜索】点击放大镜 tap_xy 自定义配置"). + Android(). + TapXY( + 0.9, 0.08, + uixt.WithIdentifier("click_search_in_middle_page"), + ). + Sleep(5), + hrp.NewStep("【搜索】输入query词 input"). + Android(). + Input( + "$query", + uixt.WithIdentifier("input_query"), + ). + Sleep(5), + hrp.NewStep("【搜索】点击搜索按钮 tap_ocr 自定义配置"). + Android(). + TapByOCR( + "搜索", + uixt.WithIdentifier("click_search_after_input_query"), + uixt.WithIndex(0), + ). + Sleep(5), + hrp.NewStep("选择直播页签 tap_ocr 默认配置"). + Android(). + TapByOCR("直播"). + Sleep(5), + // 生活服务赛道 + hrp.NewStep("【生活服务】进入直播间 tap_xy"). + Android(). + TapXY(0.5, 0.5). + Sleep(5), + hrp.NewStep("【生活服务】点击货架商品 tap_ocr 自定义配置"). + Android(). + TapByUITypes( + uixt.WithScreenShotUITypes("dyhouse", "shoppingbag"), + uixt.WithIdentifier("click_sales_rack"), + ). + Sleep(5), + // 冷启动 + hrp.NewStep("app_terminate 以及 ui_foreground_app not_equal 断言"). + Android(). + AppTerminate("$bundle_id"). + Sleep(2). + Validate(). + AssertAppNotInForeground("$bundle_id"), + hrp.NewStep("home 以及 swipe_to_tap_app 自定义配置"). + Android(). + Home(). + SwipeToTapApp("$app_name", uixt.WithMaxRetryTimes(5), uixt.WithInterval(1), uixt.WithOffset(0, -50)). + Sleep(10), + hrp.NewStep("处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言"). + Android(). + TapByOCR( + "我知道了", + uixt.WithIgnoreNotFoundError(true), + ). + Validate(). + AssertOCRExists("推荐", "进入抖音失败"), + // 点播赛道 + hrp.NewStep("【点播】滑动消费"). + Android(). + VideoCrawler(map[string]interface{}{ + "timeout": 600, + "feed": map[string]interface{}{ + "target_count": 10, + "target_labels": []map[string]interface{}{ + {"text": "^广告$", "scope": []float64{0, 0.5, 1, 1}, "regex": true}, + {"text": "^图文$", "scope": []float64{0, 0.5, 1, 1}, "regex": true}, + {"text": `^特效\|`, "scope": []float64{0, 0.5, 1, 1}, "regex": true}, + {"text": `^模板\|`, "scope": []float64{0, 0.5, 1, 1}, "regex": true}, + {"text": `^购物\|`, "scope": []float64{0, 0.5, 1, 1}, "regex": true}, + }, + "sleep_random": []float64{0, 5, 0.6, 5, 15, 0.2, 15, 50, 0.2}, + }, + "live": map[string]interface{}{ + "target_count": 0, + "sleep_random": []float64{20, 20}, + }, + }), + // localtime 时间戳界面 + hrp.NewStep("返回主界面,并打开本地时间戳"). + Android(). + Home(). + AppTerminate("$bundle_id"). + Sleep(3). + SwipeToTapApp("local", uixt.WithMaxRetryTimes(5)).Sleep(10), + hrp.NewStep("screeshot 以及 sleep_random"). + Loop(3). + Android(). + ScreenShot(). + SleepRandom(1, 3), + }, + } + + if err := testCase.Dump2JSON("android_expert_test.json"); err != nil { + t.Fatal(err) + } +} + +func TestIOSExpertTest(t *testing.T) { + testCase := &hrp.TestCase{ + Config: hrp.NewConfig("iOS 专家用例"). + WithVariables(map[string]interface{}{ + "device": "${ENV(UDID)}", + "query": "${ENV(query)}", + "bundle_id": "com.ss.iphone.ugc.Aweme", + "app_name": "抖音", + }). + SetIOS( + uixt.WithUDID("$device"), + uixt.WithWDALogOn(true), + uixt.WithWDAPort(8700), + uixt.WithWDAMjpegPort(8800), + ), + TestSteps: []hrp.IStep{ + // 温启动 + // iOS 不支持前台 App 断言操作 + hrp.NewStep("启动应用程序 app_launch"). + IOS(). + AppLaunch("$bundle_id"). + Sleep(2), + hrp.NewStep("home 以及 swipe_to_tap_app 默认配置"). + IOS(). + Home(). + SwipeToTapApp("$app_name"). + Sleep(10), + hrp.NewStep("处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言"). + IOS(). + TapByOCR( + "我知道了", + uixt.WithIgnoreNotFoundError(true), + ). + Validate(). + AssertOCRExists("推荐", "进入抖音失败"), + // 直播赛道 + hrp.NewStep("【直播】feed头像或卡片进房 swipe_to_tap_texts 自定义配置"). + IOS(). + SwipeToTapTexts( + []string{"直播", "直播中", "点击进入直播间"}, + uixt.WithCustomDirection(0.5, 0.7, 0.5, 0.3), + uixt.WithScope(0.2, 0.2, 1, 0.8), + uixt.WithMaxRetryTimes(50), + uixt.WithWaitTime(1.5), + uixt.WithIdentifier("click_live"), + ), + hrp.NewStep("sleep 10s"). + IOS(). + Sleep(10), + hrp.NewStep("【直播】swipe 自定义配置 以及 back"). + IOS(). + Swipe( + 0.5, 0.7, 0.5, 0.3, + uixt.WithIdentifier("slide_in_live"), + ). + Sleep(5). + Back(). + Sleep(5), + // 搜索赛道 + hrp.NewStep("【搜索】点击放大镜 tap_xy 自定义配置"). + IOS(). + TapXY( + 0.9, 0.075, + uixt.WithIdentifier("click_search_in_middle_page"), + ). + Sleep(5), + hrp.NewStep("【搜索】输入query词 input"). + IOS(). + Input( + "$query", + uixt.WithIdentifier("input_query"), + ). + Sleep(5), + hrp.NewStep("【搜索】点击搜索按钮 tap_ocr 自定义配置"). + IOS(). + TapByOCR( + "搜索", + uixt.WithIdentifier("click_search_after_input_query"), + uixt.WithIndex(0), + ). + Sleep(5), + // 生活服务赛道 + hrp.NewStep("选择直播页签 tap_ocr 默认配置"). + IOS(). + TapByOCR("直播"). + Sleep(5), + hrp.NewStep("【生活服务】进入直播间 tap_xy"). + IOS(). + TapXY(0.5, 0.5). + Sleep(5), + hrp.NewStep("【生活服务】点击货架商品 tap_ocr 自定义配置"). + IOS(). + TapByUITypes( + uixt.WithScreenShotUITypes("dyhouse", "shoppingbag"), + uixt.WithIdentifier("click_sales_rack"), + ). + Sleep(5), + // 冷启动 + // iOS 不支持前台 App 断言操作 + hrp.NewStep("终止应用程序 app_terminate"). + IOS(). + AppTerminate("$bundle_id"). + Sleep(2), + hrp.NewStep("home 以及 swipe_to_tap_app 自定义配置"). + IOS(). + Home(). + SwipeToTapApp("$app_name", uixt.WithMaxRetryTimes(5), uixt.WithInterval(1), uixt.WithOffset(0, -50)). + Sleep(10), + hrp.NewStep("处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言"). + IOS(). + TapByOCR( + "我知道了", + uixt.WithIgnoreNotFoundError(true), + ). + Validate(). + AssertOCRExists("推荐", "进入抖音失败"), + // 点播赛道 + hrp.NewStep("【点播】滑动消费"). + IOS(). + VideoCrawler(map[string]interface{}{ + "timeout": 600, + "feed": map[string]interface{}{ + "target_count": 10, + "target_labels": []map[string]interface{}{ + {"text": "^广告$", "scope": []float64{0, 0.5, 1, 1}, "regex": true}, + {"text": "^图文$", "scope": []float64{0, 0.5, 1, 1}, "regex": true}, + {"text": `^特效\|`, "scope": []float64{0, 0.5, 1, 1}, "regex": true}, + {"text": `^模板\|`, "scope": []float64{0, 0.5, 1, 1}, "regex": true}, + {"text": `^购物\|`, "scope": []float64{0, 0.5, 1, 1}, "regex": true}, + }, + "sleep_random": []float64{0, 5, 0.6, 5, 15, 0.2, 15, 50, 0.2}, + }, + "live": map[string]interface{}{ + "target_count": 0, + "sleep_random": []float64{20, 20}, + }, + }), + // localtime 时间戳界面 + hrp.NewStep("返回主界面,并打开本地时间戳"). + IOS(). + Home(). + AppTerminate("$bundle_id"). + Sleep(3). + SwipeToTapApp("local", uixt.WithMaxRetryTimes(5)).Sleep(10), + hrp.NewStep("screeshot 以及 sleep_random"). + Loop(3). + IOS(). + ScreenShot(). + SleepRandom(1, 3), + }, + } + + if err := testCase.Dump2JSON("ios_expert_test.json"); err != nil { + t.Fatal(err) + } +} diff --git a/examples/uitest/ios_expert_test.json b/examples/uitest/ios_expert_test.json new file mode 100644 index 00000000..85fccf35 --- /dev/null +++ b/examples/uitest/ios_expert_test.json @@ -0,0 +1,461 @@ +{ + "config": { + "name": "iOS 专家用例", + "variables": { + "app_name": "抖音", + "bundle_id": "com.ss.iphone.ugc.Aweme", + "device": "${ENV(UDID)}", + "query": "${ENV(query)}" + }, + "ios": [ + { + "udid": "$device", + "port": 8700, + "mjpeg_port": 8800, + "log_on": true + } + ] + }, + "teststeps": [ + { + "name": "启动应用程序 app_launch", + "ios": { + "actions": [ + { + "method": "app_launch", + "params": "$bundle_id" + }, + { + "method": "sleep", + "params": 2 + } + ] + } + }, + { + "name": "home 以及 swipe_to_tap_app 默认配置", + "ios": { + "actions": [ + { + "method": "home" + }, + { + "method": "swipe_to_tap_app", + "params": "$app_name", + "options": {} + }, + { + "method": "sleep", + "params": 10 + } + ] + } + }, + { + "name": "处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言", + "ios": { + "actions": [ + { + "method": "tap_ocr", + "params": "我知道了", + "options": { + "ignore_NotFoundError": true + } + } + ] + }, + "validate": [ + { + "check": "ui_ocr", + "assert": "exists", + "expect": "推荐", + "msg": "进入抖音失败" + } + ] + }, + { + "name": "【直播】feed头像或卡片进房 swipe_to_tap_texts 自定义配置", + "ios": { + "actions": [ + { + "method": "swipe_to_tap_texts", + "params": [ + "直播", + "直播中", + "点击进入直播间" + ], + "options": { + "identifier": "click_live", + "max_retry_times": 50, + "interval": 1.5, + "direction": [ + 0.5, + 0.7, + 0.5, + 0.3 + ], + "scope": [ + 0.2, + 0.2, + 1, + 0.8 + ] + } + } + ] + } + }, + { + "name": "sleep 10s", + "ios": { + "actions": [ + { + "method": "sleep", + "params": 10 + } + ] + } + }, + { + "name": "【直播】swipe 自定义配置 以及 back", + "ios": { + "actions": [ + { + "method": "swipe", + "params": [ + 0.5, + 0.7, + 0.5, + 0.3 + ], + "options": { + "identifier": "slide_in_live" + } + }, + { + "method": "sleep", + "params": 5 + }, + { + "method": "back", + "options": {} + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "【搜索】点击放大镜 tap_xy 自定义配置", + "ios": { + "actions": [ + { + "method": "tap_xy", + "params": [ + 0.9, + 0.075 + ], + "options": { + "identifier": "click_search_in_middle_page" + } + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "【搜索】输入query词 input", + "ios": { + "actions": [ + { + "method": "input", + "params": "$query", + "options": { + "identifier": "input_query" + } + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "【搜索】点击搜索按钮 tap_ocr 自定义配置", + "ios": { + "actions": [ + { + "method": "tap_ocr", + "params": "搜索", + "options": { + "identifier": "click_search_after_input_query" + } + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "选择直播页签 tap_ocr 默认配置", + "ios": { + "actions": [ + { + "method": "tap_ocr", + "params": "直播", + "options": {} + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "【生活服务】进入直播间 tap_xy", + "ios": { + "actions": [ + { + "method": "tap_xy", + "params": [ + 0.5, + 0.5 + ], + "options": {} + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "【生活服务】点击货架商品 tap_ocr 自定义配置", + "ios": { + "actions": [ + { + "method": "tap_cv", + "options": { + "identifier": "click_sales_rack", + "screenshot_with_ui_types": [ + "dyhouse", + "shoppingbag" + ] + } + }, + { + "method": "sleep", + "params": 5 + } + ] + } + }, + { + "name": "终止应用程序 app_terminate", + "ios": { + "actions": [ + { + "method": "app_terminate", + "params": "$bundle_id" + }, + { + "method": "sleep", + "params": 2 + } + ] + } + }, + { + "name": "home 以及 swipe_to_tap_app 自定义配置", + "ios": { + "actions": [ + { + "method": "home" + }, + { + "method": "swipe_to_tap_app", + "params": "$app_name", + "options": { + "max_retry_times": 5, + "interval": 1, + "offset": [ + 0, + -50 + ] + } + }, + { + "method": "sleep", + "params": 10 + } + ] + } + }, + { + "name": "处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言", + "ios": { + "actions": [ + { + "method": "tap_ocr", + "params": "我知道了", + "options": { + "ignore_NotFoundError": true + } + } + ] + }, + "validate": [ + { + "check": "ui_ocr", + "assert": "exists", + "expect": "推荐", + "msg": "进入抖音失败" + } + ] + }, + { + "name": "【点播】滑动消费", + "ios": { + "actions": [ + { + "method": "video_crawler", + "params": { + "feed": { + "sleep_random": [ + 0, + 5, + 0.6, + 5, + 15, + 0.2, + 15, + 50, + 0.2 + ], + "target_count": 10, + "target_labels": [ + { + "regex": true, + "scope": [ + 0, + 0.5, + 1, + 1 + ], + "text": "^广告$" + }, + { + "regex": true, + "scope": [ + 0, + 0.5, + 1, + 1 + ], + "text": "^图文$" + }, + { + "regex": true, + "scope": [ + 0, + 0.5, + 1, + 1 + ], + "text": "^特效\\|" + }, + { + "regex": true, + "scope": [ + 0, + 0.5, + 1, + 1 + ], + "text": "^模板\\|" + }, + { + "regex": true, + "scope": [ + 0, + 0.5, + 1, + 1 + ], + "text": "^购物\\|" + } + ] + }, + "live": { + "sleep_random": [ + 20, + 20 + ], + "target_count": 0 + }, + "timeout": 600 + } + } + ] + } + }, + { + "name": "返回主界面,并打开本地时间戳", + "ios": { + "actions": [ + { + "method": "home" + }, + { + "method": "app_terminate", + "params": "$bundle_id" + }, + { + "method": "sleep", + "params": 3 + }, + { + "method": "swipe_to_tap_app", + "params": "local", + "options": { + "max_retry_times": 5 + } + }, + { + "method": "sleep", + "params": 10 + } + ] + } + }, + { + "name": "screeshot 以及 sleep_random", + "ios": { + "actions": [ + { + "method": "screenshot", + "options": {} + }, + { + "method": "sleep_random", + "params": [ + 1, + 3 + ] + } + ] + }, + "loops": 3 + } + ] +} \ No newline at end of file diff --git a/hrp/pkg/uixt/action.go b/hrp/pkg/uixt/action.go index 2dfa40f0..0b3b14ca 100644 --- a/hrp/pkg/uixt/action.go +++ b/hrp/pkg/uixt/action.go @@ -547,17 +547,8 @@ func (dExt *DriverExt) DoAction(action MobileAction) (err error) { case ACTION_TapByCV: if imagePath, ok := action.Params.(string); ok { return dExt.TapByCV(imagePath, action.GetOptions()...) - } - if uiParams, ok := action.Params.([]interface{}); ok { - var uiTypes []string - for _, uiParam := range uiParams { - uiType, ok := uiParam.(string) - if !ok { - continue - } - uiTypes = append(uiTypes, uiType) - } - return dExt.TapByUIDetection(uiTypes, action.Options.Options()...) + } else if err := dExt.TapByUIDetection(action.GetOptions()...); err == nil { + return nil } return fmt.Errorf("invalid %s params: %v", ACTION_TapByCV, action.Params) case ACTION_DoubleTapXY: diff --git a/hrp/pkg/uixt/service_vedem.go b/hrp/pkg/uixt/service_vedem.go index a57e0d55..cf505d59 100644 --- a/hrp/pkg/uixt/service_vedem.go +++ b/hrp/pkg/uixt/service_vedem.go @@ -478,6 +478,7 @@ func (u UIResults) FilterScope(scope AbsScope) (results UIResults) { type UIResultMap map[string]UIResults +// FilterUIResults filters ui icons, the former the uiTypes, the higher the priority func (u UIResultMap) FilterUIResults(uiTypes []string) (uiResults UIResults, err error) { var ok bool for _, uiType := range uiTypes { @@ -512,20 +513,22 @@ func (u UIResults) GetUIResult(options ...ActionOption) (UIResult, error) { return uiResults[idx], nil } -func (dExt *DriverExt) FindUIResult(uiTypes []string, options ...ActionOption) (point PointF, err error) { - screenResult, err := dExt.GetScreenResult(WithScreenShotUITypes(uiTypes...)) +func (dExt *DriverExt) FindUIResult(options ...ActionOption) (point PointF, err error) { + actionOptions := NewActionOptions(options...) + + screenResult, err := dExt.GetScreenResult(options...) if err != nil { return } - uiResults, err := screenResult.Icons.FilterUIResults(uiTypes) + uiResults, err := screenResult.Icons.FilterUIResults(actionOptions.ScreenShotWithUITypes) if err != nil { return } uiResult, err := uiResults.GetUIResult(dExt.ParseActionOptions(options...)...) point = uiResult.Center() - log.Info().Interface("text", uiTypes). + log.Info().Interface("text", actionOptions.ScreenShotWithUITypes). Interface("point", point).Msg("FindUIResult success") return } diff --git a/hrp/pkg/uixt/tap.go b/hrp/pkg/uixt/tap.go index 83603ccf..b685b7bc 100644 --- a/hrp/pkg/uixt/tap.go +++ b/hrp/pkg/uixt/tap.go @@ -49,10 +49,10 @@ func (dExt *DriverExt) TapByCV(imagePath string, options ...ActionOption) error return dExt.TapAbsXY(point.X, point.Y, options...) } -func (dExt *DriverExt) TapByUIDetection(uiTypes []string, options ...ActionOption) error { +func (dExt *DriverExt) TapByUIDetection(options ...ActionOption) error { actionOptions := NewActionOptions(options...) - point, err := dExt.FindUIResult(uiTypes, options...) + point, err := dExt.FindUIResult(options...) if err != nil { if actionOptions.IgnoreNotFoundError { return nil diff --git a/hrp/step_mobile_ui.go b/hrp/step_mobile_ui.go index 28eec491..47ea7850 100644 --- a/hrp/step_mobile_ui.go +++ b/hrp/step_mobile_ui.go @@ -102,7 +102,7 @@ func (s *StepMobile) Tap(params string, options ...uixt.ActionOption) *StepMobil return &StepMobile{step: s.step} } -// Tap taps on the target element by OCR recognition +// TapByOCR taps on the target element by OCR recognition func (s *StepMobile) TapByOCR(ocrText string, options ...uixt.ActionOption) *StepMobile { action := uixt.MobileAction{ Method: uixt.ACTION_TapByOCR, @@ -114,7 +114,7 @@ func (s *StepMobile) TapByOCR(ocrText string, options ...uixt.ActionOption) *Ste return &StepMobile{step: s.step} } -// Tap taps on the target element by CV recognition +// TapByCV taps on the target element by CV recognition func (s *StepMobile) TapByCV(imagePath string, options ...uixt.ActionOption) *StepMobile { action := uixt.MobileAction{ Method: uixt.ACTION_TapByCV, @@ -126,6 +126,17 @@ func (s *StepMobile) TapByCV(imagePath string, options ...uixt.ActionOption) *St return &StepMobile{step: s.step} } +// TapByUITypes taps on the target element specified by uiTypes, the higher the uiTypes, the higher the priority +func (s *StepMobile) TapByUITypes(options ...uixt.ActionOption) *StepMobile { + action := uixt.MobileAction{ + Method: uixt.ACTION_TapByCV, + Options: uixt.NewActionOptions(options...), + } + + s.mobileStep().Actions = append(s.mobileStep().Actions, action) + return &StepMobile{step: s.step} +} + // DoubleTapXY double taps the point {X,Y}, X & Y is percentage of coordinates func (s *StepMobile) DoubleTapXY(x, y float64, options ...uixt.ActionOption) *StepMobile { s.mobileStep().Actions = append(s.mobileStep().Actions, uixt.MobileAction{