refactor: rename options pkg to option

This commit is contained in:
lilong.129
2025-02-06 17:50:09 +08:00
parent b22f24cb6b
commit 194b61718f
61 changed files with 554 additions and 548 deletions
+5 -5
View File
@@ -9,7 +9,7 @@ import (
"github.com/httprunner/httprunner/v5/internal/sdk" "github.com/httprunner/httprunner/v5/internal/sdk"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var ( var (
@@ -36,7 +36,7 @@ var installCmd = &cobra.Command{
return err return err
} }
device, err := uixt.NewAndroidDevice(options.WithSerialNumber(serial)) device, err := uixt.NewAndroidDevice(option.WithSerialNumber(serial))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return err return err
@@ -48,9 +48,9 @@ var installCmd = &cobra.Command{
} }
err = driverExt.Install(args[0], err = driverExt.Install(args[0],
options.WithReinstall(replace), option.WithReinstall(replace),
options.WithDowngrade(downgrade), option.WithDowngrade(downgrade),
options.WithGrantPermission(grant), option.WithGrantPermission(grant),
) )
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
+2 -2
View File
@@ -4,7 +4,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var iosRootCmd = &cobra.Command{ var iosRootCmd = &cobra.Command{
@@ -13,7 +13,7 @@ var iosRootCmd = &cobra.Command{
} }
func getDevice(udid string) (*uixt.IOSDevice, error) { func getDevice(udid string) (*uixt.IOSDevice, error) {
device, err := uixt.NewIOSDevice(options.WithUDID(udid)) device, err := uixt.NewIOSDevice(option.WithUDID(udid))
if err != nil { if err != nil {
return nil, err return nil, err
} }
+2 -2
View File
@@ -9,7 +9,7 @@ import (
"github.com/httprunner/httprunner/v5/internal/sdk" "github.com/httprunner/httprunner/v5/internal/sdk"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var installCmd = &cobra.Command{ var installCmd = &cobra.Command{
@@ -30,7 +30,7 @@ var installCmd = &cobra.Command{
return err return err
} }
device, err := uixt.NewIOSDevice(options.WithUDID(udid)) device, err := uixt.NewIOSDevice(option.WithUDID(udid))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return err return err
+2 -2
View File
@@ -9,7 +9,7 @@ import (
"github.com/httprunner/httprunner/v5/internal/sdk" "github.com/httprunner/httprunner/v5/internal/sdk"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var uninstallCmd = &cobra.Command{ var uninstallCmd = &cobra.Command{
@@ -34,7 +34,7 @@ var uninstallCmd = &cobra.Command{
return err return err
} }
device, err := uixt.NewIOSDevice(options.WithUDID(udid)) device, err := uixt.NewIOSDevice(option.WithUDID(udid))
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return err return err
+4 -3
View File
@@ -4,11 +4,12 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/pkg/errors"
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
"github.com/pkg/errors"
) )
// ConvertCaseCompatibility converts TestCase compatible with Golang engine style // ConvertCaseCompatibility converts TestCase compatible with Golang engine style
@@ -135,7 +136,7 @@ func convertCompatMobileStep(mobileUI *MobileUI) {
} }
for i := 0; i < len(mobileUI.Actions); i++ { for i := 0; i < len(mobileUI.Actions); i++ {
ma := mobileUI.Actions[i] ma := mobileUI.Actions[i]
actionOptions := options.NewActionOptions(ma.GetOptions()...) actionOptions := option.NewActionOptions(ma.GetOptions()...)
// append tap_cv params to screenshot_with_ui_types option // append tap_cv params to screenshot_with_ui_types option
if ma.Method == uixt.ACTION_TapByCV { if ma.Method == uixt.ACTION_TapByCV {
uiTypes, _ := builtin.ConvertToStringSlice(ma.Params) uiTypes, _ := builtin.ConvertToStringSlice(ma.Params)
+7 -7
View File
@@ -5,7 +5,7 @@ import (
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
type IConfig interface { type IConfig interface {
@@ -118,8 +118,8 @@ func (c *TConfig) SetWebSocket(times, interval, timeout, size int64) *TConfig {
return c return c
} }
func (c *TConfig) SetIOS(opts ...options.IOSDeviceOption) *TConfig { func (c *TConfig) SetIOS(opts ...option.IOSDeviceOption) *TConfig {
iosOptions := options.NewIOSDeviceConfig(opts...) iosOptions := option.NewIOSDeviceConfig(opts...)
device := &uixt.IOSDevice{ device := &uixt.IOSDevice{
IOSDeviceConfig: iosOptions, IOSDeviceConfig: iosOptions,
} }
@@ -139,8 +139,8 @@ func (c *TConfig) SetIOS(opts ...options.IOSDeviceOption) *TConfig {
return c return c
} }
func (c *TConfig) SetHarmony(opts ...options.HarmonyDeviceOption) *TConfig { func (c *TConfig) SetHarmony(opts ...option.HarmonyDeviceOption) *TConfig {
harmonyOptions := options.NewHarmonyDeviceConfig(opts...) harmonyOptions := option.NewHarmonyDeviceConfig(opts...)
device := &uixt.HarmonyDevice{ device := &uixt.HarmonyDevice{
HarmonyDeviceConfig: harmonyOptions, HarmonyDeviceConfig: harmonyOptions,
} }
@@ -160,8 +160,8 @@ func (c *TConfig) SetHarmony(opts ...options.HarmonyDeviceOption) *TConfig {
return c return c
} }
func (c *TConfig) SetAndroid(opts ...options.AndroidDeviceOption) *TConfig { func (c *TConfig) SetAndroid(opts ...option.AndroidDeviceOption) *TConfig {
uiaOptions := options.NewAndroidDeviceConfig(opts...) uiaOptions := option.NewAndroidDeviceConfig(opts...)
device := &uixt.AndroidDevice{ device := &uixt.AndroidDevice{
AndroidDeviceConfig: uiaOptions, AndroidDeviceConfig: uiaOptions,
} }
+9 -9
View File
@@ -4,7 +4,7 @@ import (
"testing" "testing"
hrp "github.com/httprunner/httprunner/v5" hrp "github.com/httprunner/httprunner/v5"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func TestAndroidDouyinE2E(t *testing.T) { func TestAndroidDouyinE2E(t *testing.T) {
@@ -15,8 +15,8 @@ func TestAndroidDouyinE2E(t *testing.T) {
"ups": "${ENV(LIVEUPLIST)}", "ups": "${ENV(LIVEUPLIST)}",
}). }).
SetAndroid( SetAndroid(
options.WithSerialNumber("$device"), option.WithSerialNumber("$device"),
options.WithAdbLogOn(true)), option.WithAdbLogOn(true)),
TestSteps: []hrp.IStep{ TestSteps: []hrp.IStep{
hrp.NewStep("启动抖音"). hrp.NewStep("启动抖音").
Android(). Android().
@@ -25,8 +25,8 @@ func TestAndroidDouyinE2E(t *testing.T) {
Home(). Home().
SwipeToTapApp( SwipeToTapApp(
"抖音", "抖音",
options.WithMaxRetryTimes(5), option.WithMaxRetryTimes(5),
options.WithTapOffset(0, -50), option.WithTapOffset(0, -50),
). ).
Sleep(20). Sleep(20).
Validate(). Validate().
@@ -47,11 +47,11 @@ func TestAndroidDouyinE2E(t *testing.T) {
Android(). Android().
TapByOCR( TapByOCR(
"直播中", "直播中",
options.WithIgnoreNotFoundError(true), option.WithIgnoreNotFoundError(true),
options.WithIndex(-1), option.WithIndex(-1),
). ).
EndToEndDelay(options.WithInterval(5), options.WithTimeout(120)). EndToEndDelay(option.WithInterval(5), option.WithTimeout(120)).
TapByUITypes(options.WithScreenShotUITypes("close")), TapByUITypes(option.WithScreenShotUITypes("close")),
}, },
} }
+4 -4
View File
@@ -7,7 +7,7 @@ import (
"time" "time"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var ( var (
@@ -29,7 +29,7 @@ func init() {
} }
func launchAppDriver(pkgName string) (driver *uixt.DriverExt, err error) { func launchAppDriver(pkgName string) (driver *uixt.DriverExt, err error) {
device, _ := uixt.NewAndroidDevice(options.WithSerialNumber(serial)) device, _ := uixt.NewAndroidDevice(option.WithSerialNumber(serial))
driver, err = device.NewDriver() driver, err = device.NewDriver()
if err != nil { if err != nil {
return nil, err return nil, err
@@ -59,7 +59,7 @@ func launchAppDriver(pkgName string) (driver *uixt.DriverExt, err error) {
} }
// 进入推荐页 // 进入推荐页
err = driver.TapByOCR("推荐", options.WithScope(0, 0, 1, 0.3)) err = driver.TapByOCR("推荐", option.WithScope(0, 0, 1, 0.3))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -92,7 +92,7 @@ func watchVideo(driver *uixt.DriverExt) (err error) {
// 切换横屏 // 切换横屏
err = driver.TapByUIDetection( err = driver.TapByUIDetection(
options.WithScreenShotUITypes("fullScreen")) option.WithScreenShotUITypes("fullScreen"))
if err != nil { if err != nil {
// 未找到横屏图标,该页面可能不是横版视频(直播|广告|Feed) // 未找到横屏图标,该页面可能不是横版视频(直播|广告|Feed)
// 退出回到推荐页 // 退出回到推荐页
+4 -4
View File
@@ -7,7 +7,7 @@ import (
"time" "time"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var ( var (
@@ -29,7 +29,7 @@ func init() {
} }
func launchAppDriver(pkgName string) (driver *uixt.DriverExt, err error) { func launchAppDriver(pkgName string) (driver *uixt.DriverExt, err error) {
device, _ := uixt.NewIOSDevice(options.WithUDID(serial)) device, _ := uixt.NewIOSDevice(option.WithUDID(serial))
driver, err = device.NewDriver() driver, err = device.NewDriver()
if err != nil { if err != nil {
return nil, err return nil, err
@@ -59,7 +59,7 @@ func launchAppDriver(pkgName string) (driver *uixt.DriverExt, err error) {
} }
// 进入推荐页 // 进入推荐页
err = driver.TapByOCR("推荐", options.WithScope(0, 0, 1, 0.3)) err = driver.TapByOCR("推荐", option.WithScope(0, 0, 1, 0.3))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -92,7 +92,7 @@ func watchVideo(driver *uixt.DriverExt) (err error) {
// 切换横屏 // 切换横屏
err = driver.TapByUIDetection( err = driver.TapByUIDetection(
options.WithScreenShotUITypes("fullScreen")) option.WithScreenShotUITypes("fullScreen"))
if err != nil { if err != nil {
// 未找到横屏图标,该页面可能不是横版视频(直播|广告|Feed) // 未找到横屏图标,该页面可能不是横版视频(直播|广告|Feed)
// 退出回到推荐页 // 退出回到推荐页
@@ -6,7 +6,7 @@ import (
"testing" "testing"
hrp "github.com/httprunner/httprunner/v5" hrp "github.com/httprunner/httprunner/v5"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func TestAndroidDouyinFeedTest(t *testing.T) { func TestAndroidDouyinFeedTest(t *testing.T) {
@@ -15,7 +15,7 @@ func TestAndroidDouyinFeedTest(t *testing.T) {
WithVariables(map[string]interface{}{ WithVariables(map[string]interface{}{
"device": "${ENV(SerialNumber)}", "device": "${ENV(SerialNumber)}",
}). }).
SetAndroid(options.WithSerialNumber("$device")), SetAndroid(option.WithSerialNumber("$device")),
TestSteps: []hrp.IStep{ TestSteps: []hrp.IStep{
hrp.NewStep("启动抖音"). hrp.NewStep("启动抖音").
Android(). Android().
@@ -26,7 +26,7 @@ func TestAndroidDouyinFeedTest(t *testing.T) {
AssertAppInForeground("com.ss.android.ugc.aweme"), AssertAppInForeground("com.ss.android.ugc.aweme"),
hrp.NewStep("处理青少年弹窗"). hrp.NewStep("处理青少年弹窗").
Android(). Android().
TapByOCR("我知道了", options.WithIgnoreNotFoundError(true)), TapByOCR("我知道了", option.WithIgnoreNotFoundError(true)),
hrp.NewStep("滑动 Feed 3 次,随机间隔 0-5s"). hrp.NewStep("滑动 Feed 3 次,随机间隔 0-5s").
Loop(3). Loop(3).
Android(). Android().
@@ -6,7 +6,7 @@ import (
"testing" "testing"
hrp "github.com/httprunner/httprunner/v5" hrp "github.com/httprunner/httprunner/v5"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func TestAndroidLiveSwipeTest(t *testing.T) { func TestAndroidLiveSwipeTest(t *testing.T) {
@@ -15,7 +15,7 @@ func TestAndroidLiveSwipeTest(t *testing.T) {
WithVariables(map[string]interface{}{ WithVariables(map[string]interface{}{
"device": "${ENV(SerialNumber)}", "device": "${ENV(SerialNumber)}",
}). }).
SetAndroid(options.WithSerialNumber("$device")), SetAndroid(option.WithSerialNumber("$device")),
TestSteps: []hrp.IStep{ TestSteps: []hrp.IStep{
hrp.NewStep("启动抖音"). hrp.NewStep("启动抖音").
Android(). Android().
@@ -26,10 +26,10 @@ func TestAndroidLiveSwipeTest(t *testing.T) {
AssertAppInForeground("com.ss.android.ugc.aweme"), AssertAppInForeground("com.ss.android.ugc.aweme"),
hrp.NewStep("处理青少年弹窗"). hrp.NewStep("处理青少年弹窗").
Android(). Android().
TapByOCR("我知道了", options.WithIgnoreNotFoundError(true)), TapByOCR("我知道了", option.WithIgnoreNotFoundError(true)),
hrp.NewStep("在推荐页上划,直到出现「点击进入直播间」"). hrp.NewStep("在推荐页上划,直到出现「点击进入直播间」").
Android(). Android().
SwipeToTapText("点击进入直播间", options.WithMaxRetryTimes(10), options.WithIdentifier("进入直播间")), SwipeToTapText("点击进入直播间", option.WithMaxRetryTimes(10), option.WithIdentifier("进入直播间")),
hrp.NewStep("滑动 Feed 5 次,60% 随机间隔 0-5s40% 随机间隔 5-10s"). hrp.NewStep("滑动 Feed 5 次,60% 随机间隔 0-5s40% 随机间隔 5-10s").
Loop(5). Loop(5).
Android(). Android().
@@ -37,8 +37,8 @@ func TestAndroidLiveSwipeTest(t *testing.T) {
SleepRandom(0, 5, 0.6, 5, 10, 0.4), SleepRandom(0, 5, 0.6, 5, 10, 0.4),
hrp.NewStep("向上滑动,等待 10s"). hrp.NewStep("向上滑动,等待 10s").
Android(). Android().
SwipeUp(options.WithIdentifier("第一次上划")).Sleep(5).ScreenShot(). // 上划 1 次,等待 5s,截图保存 SwipeUp(option.WithIdentifier("第一次上划")).Sleep(5).ScreenShot(). // 上划 1 次,等待 5s,截图保存
SwipeUp(options.WithIdentifier("第二次上划")).Sleep(5).ScreenShot(), // 再上划 1 次,等待 5s,截图保存 SwipeUp(option.WithIdentifier("第二次上划")).Sleep(5).ScreenShot(), // 再上划 1 次,等待 5s,截图保存
hrp.NewStep("exit"). hrp.NewStep("exit").
Android(). Android().
AppTerminate("com.ss.android.ugc.aweme"). AppTerminate("com.ss.android.ugc.aweme").
+15 -15
View File
@@ -6,7 +6,7 @@ import (
"testing" "testing"
hrp "github.com/httprunner/httprunner/v5" hrp "github.com/httprunner/httprunner/v5"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func TestIOSDouyinFollowLive(t *testing.T) { func TestIOSDouyinFollowLive(t *testing.T) {
@@ -16,9 +16,9 @@ func TestIOSDouyinFollowLive(t *testing.T) {
"app_name": "抖音", "app_name": "抖音",
}). }).
SetIOS( SetIOS(
options.WithWDALogOn(true), option.WithWDALogOn(true),
options.WithWDAPort(8700), option.WithWDAPort(8700),
options.WithWDAMjpegPort(8800), option.WithWDAMjpegPort(8800),
), ),
TestSteps: []hrp.IStep{ TestSteps: []hrp.IStep{
hrp.NewStep("启动抖音"). hrp.NewStep("启动抖音").
@@ -26,32 +26,32 @@ func TestIOSDouyinFollowLive(t *testing.T) {
Home(). Home().
AppTerminate("com.ss.iphone.ugc.Aweme"). // 关闭已运行的抖音 AppTerminate("com.ss.iphone.ugc.Aweme"). // 关闭已运行的抖音
SwipeToTapApp("$app_name", SwipeToTapApp("$app_name",
options.WithMaxRetryTimes(5), option.WithMaxRetryTimes(5),
options.WithIdentifier("启动抖音")). option.WithIdentifier("启动抖音")).
Sleep(5). Sleep(5).
Validate(). Validate().
AssertOCRExists("推荐", "抖音启动失败,「推荐」不存在"), AssertOCRExists("推荐", "抖音启动失败,「推荐」不存在"),
hrp.NewStep("处理青少年弹窗"). hrp.NewStep("处理青少年弹窗").
IOS(). IOS().
TapByOCR("我知道了", options.WithIgnoreNotFoundError(true)), TapByOCR("我知道了", option.WithIgnoreNotFoundError(true)),
hrp.NewStep("点击首页"). hrp.NewStep("点击首页").
IOS(). IOS().
TapByOCR("首页", options.WithIndex(-1)).Sleep(10), TapByOCR("首页", option.WithIndex(-1)).Sleep(10),
hrp.NewStep("点击关注页"). hrp.NewStep("点击关注页").
IOS(). IOS().
TapByOCR("关注", options.WithIndex(1)).Sleep(10), TapByOCR("关注", option.WithIndex(1)).Sleep(10),
hrp.NewStep("向上滑动 2 次"). hrp.NewStep("向上滑动 2 次").
IOS(). IOS().
SwipeToTapTexts([]string{"理肤泉", "婉宝"}, SwipeToTapTexts([]string{"理肤泉", "婉宝"},
options.WithCustomDirection(0.6, 0.2, 0.2, 0.2), option.WithCustomDirection(0.6, 0.2, 0.2, 0.2),
options.WithIdentifier("click_live")).Sleep(10). option.WithIdentifier("click_live")).Sleep(10).
Swipe(0.9, 0.7, 0.9, 0.3, Swipe(0.9, 0.7, 0.9, 0.3,
options.WithIdentifier("slide_in_live"), option.WithIdentifier("slide_in_live"),
options.WithOffsetRandomRange(-10, 10)). option.WithOffsetRandomRange(-10, 10)).
Sleep(10).ScreenShot(). // 上划 1 次,等待 10s,截图保存 Sleep(10).ScreenShot(). // 上划 1 次,等待 10s,截图保存
Swipe(0.9, 0.7, 0.9, 0.3, Swipe(0.9, 0.7, 0.9, 0.3,
options.WithIdentifier("slide_in_live"), option.WithIdentifier("slide_in_live"),
options.WithOffsetRandomRange(-10, 10)). option.WithOffsetRandomRange(-10, 10)).
Sleep(10).ScreenShot(), // 再上划 1 次,等待 10s,截图保存 Sleep(10).ScreenShot(), // 再上划 1 次,等待 10s,截图保存
}, },
} }
+2 -2
View File
@@ -6,7 +6,7 @@ import (
"testing" "testing"
hrp "github.com/httprunner/httprunner/v5" hrp "github.com/httprunner/httprunner/v5"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func TestHamonyDouyinFeedTest(t *testing.T) { func TestHamonyDouyinFeedTest(t *testing.T) {
@@ -16,7 +16,7 @@ func TestHamonyDouyinFeedTest(t *testing.T) {
"device": "a38c2c5c", "device": "a38c2c5c",
"query": "${ENV(query)}", "query": "${ENV(query)}",
}). }).
SetAndroid(options.WithSerialNumber("$device")), SetAndroid(option.WithSerialNumber("$device")),
TestSteps: []hrp.IStep{ TestSteps: []hrp.IStep{
hrp.NewStep("启动抖音"). hrp.NewStep("启动抖音").
Android(). Android().
+11 -11
View File
@@ -6,7 +6,7 @@ import (
"testing" "testing"
hrp "github.com/httprunner/httprunner/v5" hrp "github.com/httprunner/httprunner/v5"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func TestIOSDouyinLive(t *testing.T) { func TestIOSDouyinLive(t *testing.T) {
@@ -16,9 +16,9 @@ func TestIOSDouyinLive(t *testing.T) {
"app_name": "抖音", "app_name": "抖音",
}). }).
SetIOS( SetIOS(
options.WithWDALogOn(true), option.WithWDALogOn(true),
options.WithWDAPort(8700), option.WithWDAPort(8700),
options.WithWDAMjpegPort(8800), option.WithWDAMjpegPort(8800),
), ),
TestSteps: []hrp.IStep{ TestSteps: []hrp.IStep{
hrp.NewStep("启动抖音"). hrp.NewStep("启动抖音").
@@ -26,22 +26,22 @@ func TestIOSDouyinLive(t *testing.T) {
Home(). Home().
AppTerminate("com.ss.iphone.ugc.Aweme"). // 关闭已运行的抖音 AppTerminate("com.ss.iphone.ugc.Aweme"). // 关闭已运行的抖音
SwipeToTapApp("$app_name", SwipeToTapApp("$app_name",
options.WithMaxRetryTimes(5), option.WithMaxRetryTimes(5),
options.WithIdentifier("启动抖音")).Sleep(5). option.WithIdentifier("启动抖音")).Sleep(5).
Validate(). Validate().
AssertOCRExists("推荐", "抖音启动失败,「推荐」不存在"), AssertOCRExists("推荐", "抖音启动失败,「推荐」不存在"),
hrp.NewStep("处理青少年弹窗"). hrp.NewStep("处理青少年弹窗").
IOS(). IOS().
TapByOCR("我知道了", options.WithIgnoreNotFoundError(true)), TapByOCR("我知道了", option.WithIgnoreNotFoundError(true)),
hrp.NewStep("向上滑动 2 次"). hrp.NewStep("向上滑动 2 次").
IOS(). IOS().
SwipeUp(options.WithIdentifier("第一次上划")).Sleep(2).ScreenShot(). // 上划 1 次,等待 2s,截图保存 SwipeUp(option.WithIdentifier("第一次上划")).Sleep(2).ScreenShot(). // 上划 1 次,等待 2s,截图保存
SwipeUp(options.WithIdentifier("第二次上划")).Sleep(2).ScreenShot(), // 再上划 1 次,等待 2s,截图保存 SwipeUp(option.WithIdentifier("第二次上划")).Sleep(2).ScreenShot(), // 再上划 1 次,等待 2s,截图保存
hrp.NewStep("在推荐页上划,直到出现「点击进入直播间」"). hrp.NewStep("在推荐页上划,直到出现「点击进入直播间」").
IOS(). IOS().
SwipeToTapText("点击进入直播间", SwipeToTapText("点击进入直播间",
options.WithMaxRetryTimes(10), option.WithMaxRetryTimes(10),
options.WithIdentifier("进入直播间")), option.WithIdentifier("进入直播间")),
}, },
} }
+14 -14
View File
@@ -6,7 +6,7 @@ import (
"testing" "testing"
hrp "github.com/httprunner/httprunner/v5" hrp "github.com/httprunner/httprunner/v5"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func TestWDALog(t *testing.T) { func TestWDALog(t *testing.T) {
@@ -16,9 +16,9 @@ func TestWDALog(t *testing.T) {
"app_name": "抖音", "app_name": "抖音",
}). }).
SetIOS( SetIOS(
options.WithWDALogOn(true), option.WithWDALogOn(true),
options.WithWDAPort(8700), option.WithWDAPort(8700),
options.WithWDAMjpegPort(8800), option.WithWDAMjpegPort(8800),
), ),
TestSteps: []hrp.IStep{ TestSteps: []hrp.IStep{
hrp.NewStep("启动抖音"). hrp.NewStep("启动抖音").
@@ -26,24 +26,24 @@ func TestWDALog(t *testing.T) {
Home(). Home().
AppTerminate("com.ss.iphone.ugc.Aweme"). // 关闭已运行的抖音 AppTerminate("com.ss.iphone.ugc.Aweme"). // 关闭已运行的抖音
SwipeToTapApp("$app_name", SwipeToTapApp("$app_name",
options.WithMaxRetryTimes(5), option.WithMaxRetryTimes(5),
options.WithIdentifier("启动抖音")).Sleep(5). option.WithIdentifier("启动抖音")).Sleep(5).
Validate(). Validate().
AssertOCRExists("推荐", "抖音启动失败,「推荐」不存在"), AssertOCRExists("推荐", "抖音启动失败,「推荐」不存在"),
hrp.NewStep("处理青少年弹窗"). hrp.NewStep("处理青少年弹窗").
IOS(). IOS().
TapByOCR("我知道了", options.WithIgnoreNotFoundError(true)), TapByOCR("我知道了", option.WithIgnoreNotFoundError(true)),
hrp.NewStep("进入购物页"). hrp.NewStep("进入购物页").
IOS().TapByOCR("商城", options.WithIdentifier("点击商城")).Sleep(5), IOS().TapByOCR("商城", option.WithIdentifier("点击商城")).Sleep(5),
hrp.NewStep("进入推荐页"). hrp.NewStep("进入推荐页").
IOS().TapByOCR("推荐", options.WithIdentifier("点击推荐")).Sleep(5), IOS().TapByOCR("推荐", option.WithIdentifier("点击推荐")).Sleep(5),
hrp.NewStep("向上滑动 2 次"). hrp.NewStep("向上滑动 2 次").
IOS(). IOS().
SwipeUp(options.WithIdentifier("第 1 次上划")).Sleep(2). SwipeUp(option.WithIdentifier("第 1 次上划")).Sleep(2).
SwipeUp(options.WithIdentifier("第 2 次上划")).Sleep(2). SwipeUp(option.WithIdentifier("第 2 次上划")).Sleep(2).
SwipeUp(options.WithIdentifier("第 3 次上划")).Sleep(2). SwipeUp(option.WithIdentifier("第 3 次上划")).Sleep(2).
TapXY(0.9, 0.1, options.WithIdentifier("点击进入搜索框")).Sleep(2). TapXY(0.9, 0.1, option.WithIdentifier("点击进入搜索框")).Sleep(2).
Input("httprunner", options.WithIdentifier("输入搜索关键词")), Input("httprunner", option.WithIdentifier("输入搜索关键词")),
}, },
} }
+40 -40
View File
@@ -4,7 +4,7 @@ import (
"testing" "testing"
hrp "github.com/httprunner/httprunner/v5" hrp "github.com/httprunner/httprunner/v5"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func TestAndroidExpertTest(t *testing.T) { func TestAndroidExpertTest(t *testing.T) {
@@ -17,9 +17,9 @@ func TestAndroidExpertTest(t *testing.T) {
"app_name": "抖音", "app_name": "抖音",
}). }).
SetAndroid( SetAndroid(
options.WithSerialNumber("$device"), option.WithSerialNumber("$device"),
options.WithAdbLogOn(true), option.WithAdbLogOn(true),
options.WithUIA2(true), option.WithUIA2(true),
), ),
TestSteps: []hrp.IStep{ TestSteps: []hrp.IStep{
// 温启动 // 温启动
@@ -44,11 +44,11 @@ func TestAndroidExpertTest(t *testing.T) {
Android(). Android().
SwipeToTapTexts( SwipeToTapTexts(
[]string{"直播", "直播中", "点击进入直播间"}, []string{"直播", "直播中", "点击进入直播间"},
options.WithCustomDirection(0.5, 0.7, 0.5, 0.3), option.WithCustomDirection(0.5, 0.7, 0.5, 0.3),
options.WithScope(0.2, 0.2, 1, 0.8), option.WithScope(0.2, 0.2, 1, 0.8),
options.WithMaxRetryTimes(50), option.WithMaxRetryTimes(50),
options.WithWaitTime(1.5), option.WithWaitTime(1.5),
options.WithIdentifier("click_live"), option.WithIdentifier("click_live"),
), ),
hrp.NewStep("sleep 10s"). hrp.NewStep("sleep 10s").
Android(). Android().
@@ -57,7 +57,7 @@ func TestAndroidExpertTest(t *testing.T) {
Android(). Android().
Swipe( Swipe(
0.5, 0.7, 0.5, 0.3, 0.5, 0.7, 0.5, 0.3,
options.WithIdentifier("slide_in_live"), option.WithIdentifier("slide_in_live"),
). ).
Sleep(5). Sleep(5).
Back(). Back().
@@ -67,22 +67,22 @@ func TestAndroidExpertTest(t *testing.T) {
Android(). Android().
TapXY( TapXY(
0.9, 0.08, 0.9, 0.08,
options.WithIdentifier("click_search_in_middle_page"), option.WithIdentifier("click_search_in_middle_page"),
). ).
Sleep(5), Sleep(5),
hrp.NewStep("【搜索】输入query词 input"). hrp.NewStep("【搜索】输入query词 input").
Android(). Android().
Input( Input(
"$query", "$query",
options.WithIdentifier("input_query"), option.WithIdentifier("input_query"),
). ).
Sleep(5), Sleep(5),
hrp.NewStep("【搜索】点击搜索按钮 tap_ocr 自定义配置"). hrp.NewStep("【搜索】点击搜索按钮 tap_ocr 自定义配置").
Android(). Android().
TapByOCR( TapByOCR(
"搜索", "搜索",
options.WithIdentifier("click_search_after_input_query"), option.WithIdentifier("click_search_after_input_query"),
options.WithIndex(0), option.WithIndex(0),
). ).
Sleep(5), Sleep(5),
hrp.NewStep("选择直播页签 tap_ocr 默认配置"). hrp.NewStep("选择直播页签 tap_ocr 默认配置").
@@ -97,8 +97,8 @@ func TestAndroidExpertTest(t *testing.T) {
hrp.NewStep("【生活服务】点击货架商品 tap_ocr 自定义配置"). hrp.NewStep("【生活服务】点击货架商品 tap_ocr 自定义配置").
Android(). Android().
TapByUITypes( TapByUITypes(
options.WithScreenShotUITypes("dyhouse", "shoppingbag"), option.WithScreenShotUITypes("dyhouse", "shoppingbag"),
options.WithIdentifier("click_sales_rack"), option.WithIdentifier("click_sales_rack"),
). ).
Sleep(5), Sleep(5),
// 冷启动 // 冷启动
@@ -111,13 +111,13 @@ func TestAndroidExpertTest(t *testing.T) {
hrp.NewStep("home 以及 swipe_to_tap_app 自定义配置"). hrp.NewStep("home 以及 swipe_to_tap_app 自定义配置").
Android(). Android().
Home(). Home().
SwipeToTapApp("$app_name", options.WithMaxRetryTimes(5), options.WithInterval(1), options.WithTapOffset(0, -50)). SwipeToTapApp("$app_name", option.WithMaxRetryTimes(5), option.WithInterval(1), option.WithTapOffset(0, -50)).
Sleep(10), Sleep(10),
hrp.NewStep("处理弹窗 close_popups 自定义配置 以及 ui_ocr exists 断言"). hrp.NewStep("处理弹窗 close_popups 自定义配置 以及 ui_ocr exists 断言").
Android(). Android().
ClosePopups( ClosePopups(
options.WithMaxRetryTimes(3), option.WithMaxRetryTimes(3),
options.WithInterval(2), option.WithInterval(2),
). ).
Validate(). Validate().
AssertOCRExists("推荐", "进入抖音失败"), AssertOCRExists("推荐", "进入抖音失败"),
@@ -127,7 +127,7 @@ func TestAndroidExpertTest(t *testing.T) {
Home(). Home().
AppTerminate("$bundle_id"). AppTerminate("$bundle_id").
Sleep(3). Sleep(3).
SwipeToTapApp("local", options.WithMaxRetryTimes(5)).Sleep(10), SwipeToTapApp("local", option.WithMaxRetryTimes(5)).Sleep(10),
hrp.NewStep("screeshot 以及 sleep_random"). hrp.NewStep("screeshot 以及 sleep_random").
Loop(3). Loop(3).
Android(). Android().
@@ -151,10 +151,10 @@ func TestIOSExpertTest(t *testing.T) {
"app_name": "抖音", "app_name": "抖音",
}). }).
SetIOS( SetIOS(
options.WithUDID("$device"), option.WithUDID("$device"),
options.WithWDALogOn(true), option.WithWDALogOn(true),
options.WithWDAPort(8700), option.WithWDAPort(8700),
options.WithWDAMjpegPort(8800), option.WithWDAMjpegPort(8800),
), ),
TestSteps: []hrp.IStep{ TestSteps: []hrp.IStep{
// 温启动 // 温启动
@@ -178,11 +178,11 @@ func TestIOSExpertTest(t *testing.T) {
IOS(). IOS().
SwipeToTapTexts( SwipeToTapTexts(
[]string{"直播", "直播中", "点击进入直播间"}, []string{"直播", "直播中", "点击进入直播间"},
options.WithCustomDirection(0.5, 0.7, 0.5, 0.3), option.WithCustomDirection(0.5, 0.7, 0.5, 0.3),
options.WithScope(0.2, 0.2, 1, 0.8), option.WithScope(0.2, 0.2, 1, 0.8),
options.WithMaxRetryTimes(50), option.WithMaxRetryTimes(50),
options.WithWaitTime(1.5), option.WithWaitTime(1.5),
options.WithIdentifier("click_live"), option.WithIdentifier("click_live"),
), ),
hrp.NewStep("sleep 10s"). hrp.NewStep("sleep 10s").
IOS(). IOS().
@@ -191,7 +191,7 @@ func TestIOSExpertTest(t *testing.T) {
IOS(). IOS().
Swipe( Swipe(
0.5, 0.7, 0.5, 0.3, 0.5, 0.7, 0.5, 0.3,
options.WithIdentifier("slide_in_live"), option.WithIdentifier("slide_in_live"),
). ).
Sleep(5). Sleep(5).
Back(). Back().
@@ -201,22 +201,22 @@ func TestIOSExpertTest(t *testing.T) {
IOS(). IOS().
TapXY( TapXY(
0.9, 0.075, 0.9, 0.075,
options.WithIdentifier("click_search_in_middle_page"), option.WithIdentifier("click_search_in_middle_page"),
). ).
Sleep(5), Sleep(5),
hrp.NewStep("【搜索】输入query词 input"). hrp.NewStep("【搜索】输入query词 input").
IOS(). IOS().
Input( Input(
"$query", "$query",
options.WithIdentifier("input_query"), option.WithIdentifier("input_query"),
). ).
Sleep(5), Sleep(5),
hrp.NewStep("【搜索】点击搜索按钮 tap_ocr 自定义配置"). hrp.NewStep("【搜索】点击搜索按钮 tap_ocr 自定义配置").
IOS(). IOS().
TapByOCR( TapByOCR(
"搜索", "搜索",
options.WithIdentifier("click_search_after_input_query"), option.WithIdentifier("click_search_after_input_query"),
options.WithIndex(0), option.WithIndex(0),
). ).
Sleep(5), Sleep(5),
// 生活服务赛道 // 生活服务赛道
@@ -231,8 +231,8 @@ func TestIOSExpertTest(t *testing.T) {
hrp.NewStep("【生活服务】点击货架商品 tap_ocr 自定义配置"). hrp.NewStep("【生活服务】点击货架商品 tap_ocr 自定义配置").
IOS(). IOS().
TapByUITypes( TapByUITypes(
options.WithScreenShotUITypes("dyhouse", "shoppingbag"), option.WithScreenShotUITypes("dyhouse", "shoppingbag"),
options.WithIdentifier("click_sales_rack"), option.WithIdentifier("click_sales_rack"),
). ).
Sleep(5), Sleep(5),
// 冷启动 // 冷启动
@@ -244,13 +244,13 @@ func TestIOSExpertTest(t *testing.T) {
hrp.NewStep("home 以及 swipe_to_tap_app 自定义配置"). hrp.NewStep("home 以及 swipe_to_tap_app 自定义配置").
IOS(). IOS().
Home(). Home().
SwipeToTapApp("$app_name", options.WithMaxRetryTimes(5), options.WithInterval(1), options.WithTapOffset(0, -50)). SwipeToTapApp("$app_name", option.WithMaxRetryTimes(5), option.WithInterval(1), option.WithTapOffset(0, -50)).
Sleep(10), Sleep(10),
hrp.NewStep("处理弹窗 close_popups 自定义配置 以及 ui_ocr exists 断言"). hrp.NewStep("处理弹窗 close_popups 自定义配置 以及 ui_ocr exists 断言").
IOS(). IOS().
ClosePopups( ClosePopups(
options.WithMaxRetryTimes(3), option.WithMaxRetryTimes(3),
options.WithInterval(2), option.WithInterval(2),
). ).
Validate(). Validate().
AssertOCRExists("推荐", "进入抖音失败"), AssertOCRExists("推荐", "进入抖音失败"),
@@ -260,7 +260,7 @@ func TestIOSExpertTest(t *testing.T) {
Home(). Home().
AppTerminate("$bundle_id"). AppTerminate("$bundle_id").
Sleep(3). Sleep(3).
SwipeToTapApp("local", options.WithMaxRetryTimes(5)).Sleep(10), SwipeToTapApp("local", option.WithMaxRetryTimes(5)).Sleep(10),
hrp.NewStep("screeshot 以及 sleep_random"). hrp.NewStep("screeshot 以及 sleep_random").
Loop(3). Loop(3).
IOS(). IOS().
+9 -9
View File
@@ -4,7 +4,7 @@ import (
"testing" "testing"
hrp "github.com/httprunner/httprunner/v5" hrp "github.com/httprunner/httprunner/v5"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func TestHarmonyDouyinE2E(t *testing.T) { func TestHarmonyDouyinE2E(t *testing.T) {
@@ -15,8 +15,8 @@ func TestHarmonyDouyinE2E(t *testing.T) {
"ups": "${ENV(LIVEUPLIST)}", "ups": "${ENV(LIVEUPLIST)}",
}). }).
SetHarmony( SetHarmony(
options.WithConnectKey("$device"), option.WithConnectKey("$device"),
options.WithLogOn(true)), option.WithLogOn(true)),
TestSteps: []hrp.IStep{ TestSteps: []hrp.IStep{
hrp.NewStep("启动抖音"). hrp.NewStep("启动抖音").
Harmony(). Harmony().
@@ -25,8 +25,8 @@ func TestHarmonyDouyinE2E(t *testing.T) {
Home(). Home().
SwipeToTapApp( SwipeToTapApp(
"抖音", "抖音",
options.WithMaxRetryTimes(5), option.WithMaxRetryTimes(5),
options.WithTapOffset(0, -50), option.WithTapOffset(0, -50),
). ).
Sleep(20). Sleep(20).
Validate(). Validate().
@@ -47,11 +47,11 @@ func TestHarmonyDouyinE2E(t *testing.T) {
Harmony(). Harmony().
TapByOCR( TapByOCR(
"直播中", "直播中",
options.WithIgnoreNotFoundError(true), option.WithIgnoreNotFoundError(true),
options.WithIndex(-1), option.WithIndex(-1),
). ).
EndToEndDelay(options.WithInterval(5), options.WithTimeout(120)). EndToEndDelay(option.WithInterval(5), option.WithTimeout(120)).
TapByUITypes(options.WithScreenShotUITypes("close")), TapByUITypes(option.WithScreenShotUITypes("close")),
}, },
} }
+5 -5
View File
@@ -16,7 +16,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func convertTimeToSeconds(timeStr string) (int, error) { func convertTimeToSeconds(timeStr string) (int, error) {
@@ -39,9 +39,9 @@ func convertTimeToSeconds(timeStr string) (int, error) {
func initIOSDevice(uuid string) uixt.IDevice { func initIOSDevice(uuid string) uixt.IDevice {
device, err := uixt.NewIOSDevice( device, err := uixt.NewIOSDevice(
options.WithUDID(uuid), option.WithUDID(uuid),
options.WithWDAPort(8700), options.WithWDAMjpegPort(8800), option.WithWDAPort(8700), option.WithWDAMjpegPort(8800),
options.WithResetHomeOnStartup(false), // not reset home on startup option.WithResetHomeOnStartup(false), // not reset home on startup
) )
if err != nil { if err != nil {
@@ -51,7 +51,7 @@ func initIOSDevice(uuid string) uixt.IDevice {
} }
func initAndroidDevice(uuid string) uixt.IDevice { func initAndroidDevice(uuid string) uixt.IDevice {
device, err := uixt.NewAndroidDevice(options.WithSerialNumber(uuid)) device, err := uixt.NewAndroidDevice(option.WithSerialNumber(uuid))
if err != nil { if err != nil {
log.Fatal().Err(err).Msg("failed to init android device") log.Fatal().Err(err).Msg("failed to init android device")
} }
+13 -13
View File
@@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
hrp "github.com/httprunner/httprunner/v5" hrp "github.com/httprunner/httprunner/v5"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func TestConvertTimeToSeconds(t *testing.T) { func TestConvertTimeToSeconds(t *testing.T) {
@@ -55,10 +55,10 @@ func TestIOSDouyinWorldCupLive(t *testing.T) {
"appBundleID": "com.ss.iphone.ugc.Aweme", "appBundleID": "com.ss.iphone.ugc.Aweme",
}). }).
SetIOS( SetIOS(
options.WithUDID(uuid), option.WithUDID(uuid),
options.WithWDALogOn(true), option.WithWDALogOn(true),
options.WithWDAPort(8700), option.WithWDAPort(8700),
options.WithWDAMjpegPort(8800), option.WithWDAMjpegPort(8800),
), ),
TestSteps: []hrp.IStep{ TestSteps: []hrp.IStep{
hrp.NewStep("启动抖音"). hrp.NewStep("启动抖音").
@@ -66,26 +66,26 @@ func TestIOSDouyinWorldCupLive(t *testing.T) {
Home(). Home().
AppTerminate("$appBundleID"). // 关闭已运行的抖音 AppTerminate("$appBundleID"). // 关闭已运行的抖音
AppLaunch("$appBundleID"). AppLaunch("$appBundleID").
TapByOCR("我知道了", options.WithIgnoreNotFoundError(true)). // 处理青少年弹窗 TapByOCR("我知道了", option.WithIgnoreNotFoundError(true)). // 处理青少年弹窗
Validate(). Validate().
AssertOCRExists("首页", "抖音启动失败,「首页」不存在"), AssertOCRExists("首页", "抖音启动失败,「首页」不存在"),
hrp.NewStep("点击首页"). hrp.NewStep("点击首页").
IOS(). IOS().
TapByOCR("首页", options.WithIndex(-1)).Sleep(2), TapByOCR("首页", option.WithIndex(-1)).Sleep(2),
hrp.NewStep("点击世界杯页"). hrp.NewStep("点击世界杯页").
IOS(). IOS().
SwipeToTapText("世界杯", SwipeToTapText("世界杯",
options.WithMaxRetryTimes(5), option.WithMaxRetryTimes(5),
options.WithCustomDirection(0.4, 0.07, 0.6, 0.07), // 滑动 tab,从左到右,解决「世界杯」被遮挡的问题 option.WithCustomDirection(0.4, 0.07, 0.6, 0.07), // 滑动 tab,从左到右,解决「世界杯」被遮挡的问题
options.WithScope(0, 0, 1, 0.15), // 限定 tab 区域 option.WithScope(0, 0, 1, 0.15), // 限定 tab 区域
options.WithInterval(1), option.WithInterval(1),
), ),
hrp.NewStep("点击进入赛程晋级"). hrp.NewStep("点击进入赛程晋级").
Loop(5). // 重复执行 5 次 Loop(5). // 重复执行 5 次
IOS(). IOS().
TapByOCR("赛程晋级", TapByOCR("赛程晋级",
options.WithIdentifier("click_live"), option.WithIdentifier("click_live"),
options.WithIndex(-1)). option.WithIndex(-1)).
Sleep(3).Back().Sleep(3), Sleep(3).Back().Sleep(3),
hrp.NewStep("关闭抖音"). hrp.NewStep("关闭抖音").
IOS(). IOS().
+15 -15
View File
@@ -12,7 +12,7 @@ import (
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
type ActionMethod string type ActionMethod string
@@ -80,15 +80,15 @@ const (
) )
type MobileAction struct { type MobileAction struct {
Method ActionMethod `json:"method,omitempty" yaml:"method,omitempty"` Method ActionMethod `json:"method,omitempty" yaml:"method,omitempty"`
Params interface{} `json:"params,omitempty" yaml:"params,omitempty"` Params interface{} `json:"params,omitempty" yaml:"params,omitempty"`
Fn func() `json:"-" yaml:"-"` // only used for function action, not serialized Fn func() `json:"-" yaml:"-"` // only used for function action, not serialized
Options *options.ActionOptions `json:"options,omitempty" yaml:"options,omitempty"` Options *option.ActionOptions `json:"options,omitempty" yaml:"options,omitempty"`
options.ActionOptions option.ActionOptions
} }
func (ma MobileAction) GetOptions() []options.ActionOption { func (ma MobileAction) GetOptions() []option.ActionOption {
var actionOptionList []options.ActionOption var actionOptionList []option.ActionOption
// Notice: merge options from ma.Options and ma.ActionOptions // Notice: merge options from ma.Options and ma.ActionOptions
if ma.Options != nil { if ma.Options != nil {
actionOptionList = append(actionOptionList, ma.Options.Options()...) actionOptionList = append(actionOptionList, ma.Options.Options()...)
@@ -99,11 +99,11 @@ func (ma MobileAction) GetOptions() []options.ActionOption {
type TapTextAction struct { type TapTextAction struct {
Text string Text string
Options []options.ActionOption Options []option.ActionOption
} }
func (dExt *DriverExt) ParseActionOptions(opts ...options.ActionOption) []options.ActionOption { func (dExt *DriverExt) ParseActionOptions(opts ...option.ActionOption) []option.ActionOption {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
// convert relative scope to absolute scope // convert relative scope to absolute scope
if len(actionOptions.AbsScope) != 4 && len(actionOptions.Scope) == 4 { if len(actionOptions.AbsScope) != 4 && len(actionOptions.Scope) == 4 {
@@ -115,14 +115,14 @@ func (dExt *DriverExt) ParseActionOptions(opts ...options.ActionOption) []option
return actionOptions.Options() return actionOptions.Options()
} }
func (dExt *DriverExt) GenAbsScope(x1, y1, x2, y2 float64) options.AbsScope { func (dExt *DriverExt) GenAbsScope(x1, y1, x2, y2 float64) option.AbsScope {
// convert relative scope to absolute scope // convert relative scope to absolute scope
windowSize, _ := dExt.Driver.WindowSize() windowSize, _ := dExt.Driver.WindowSize()
absX1 := int(x1 * float64(windowSize.Width)) absX1 := int(x1 * float64(windowSize.Width))
absY1 := int(y1 * float64(windowSize.Height)) absY1 := int(y1 * float64(windowSize.Height))
absX2 := int(x2 * float64(windowSize.Width)) absX2 := int(x2 * float64(windowSize.Width))
absY2 := int(y2 * float64(windowSize.Height)) absY2 := int(y2 * float64(windowSize.Height))
return options.AbsScope{absX1, absY1, absX2, absY2} return option.AbsScope{absX1, absY1, absX2, absY2}
} }
func (dExt *DriverExt) DoAction(action MobileAction) (err error) { func (dExt *DriverExt) DoAction(action MobileAction) (err error) {
@@ -145,7 +145,7 @@ func (dExt *DriverExt) DoAction(action MobileAction) (err error) {
case ACTION_AppInstall: case ACTION_AppInstall:
if appUrl, ok := action.Params.(string); ok { if appUrl, ok := action.Params.(string); ok {
if err = dExt.InstallByUrl(appUrl, if err = dExt.InstallByUrl(appUrl,
options.WithRetryTimes(action.MaxRetryTimes)); err != nil { option.WithRetryTimes(action.MaxRetryTimes)); err != nil {
return errors.Wrap(err, "failed to install app") return errors.Wrap(err, "failed to install app")
} }
} }
@@ -258,7 +258,7 @@ func (dExt *DriverExt) DoAction(action MobileAction) (err error) {
} }
return fmt.Errorf("invalid %s params: %v", ACTION_TapByOCR, action.Params) return fmt.Errorf("invalid %s params: %v", ACTION_TapByOCR, action.Params)
case ACTION_TapByCV: case ACTION_TapByCV:
actionOptions := options.NewActionOptions(action.GetOptions()...) actionOptions := option.NewActionOptions(action.GetOptions()...)
if len(actionOptions.ScreenShotWithUITypes) > 0 { if len(actionOptions.ScreenShotWithUITypes) > 0 {
return dExt.TapByUIDetection(action.GetOptions()...) return dExt.TapByUIDetection(action.GetOptions()...)
} }
+10 -10
View File
@@ -11,12 +11,12 @@ import (
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
type IImageService interface { type IImageService interface {
// GetImage returns image result including ocr texts, uploaded image url, etc // GetImage returns image result including ocr texts, uploaded image url, etc
GetImage(imageBuf *bytes.Buffer, opts ...options.ActionOption) (imageResult *ImageResult, err error) GetImage(imageBuf *bytes.Buffer, opts ...option.ActionOption) (imageResult *ImageResult, err error)
} }
type ImageResult struct { type ImageResult struct {
@@ -106,7 +106,7 @@ func (t OCRTexts) texts() (texts []string) {
return texts return texts
} }
func (t OCRTexts) FilterScope(scope options.AbsScope) (results OCRTexts) { func (t OCRTexts) FilterScope(scope option.AbsScope) (results OCRTexts) {
for _, ocrText := range t { for _, ocrText := range t {
rect := ocrText.Rect rect := ocrText.Rect
@@ -128,8 +128,8 @@ func (t OCRTexts) FilterScope(scope options.AbsScope) (results OCRTexts) {
// FindText returns matched text with options // FindText returns matched text with options
// Notice: filter scope should be specified with WithAbsScope // Notice: filter scope should be specified with WithAbsScope
func (t OCRTexts) FindText(text string, opts ...options.ActionOption) (result OCRText, err error) { func (t OCRTexts) FindText(text string, opts ...option.ActionOption) (result OCRText, err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
var results []OCRText var results []OCRText
for _, ocrText := range t.FilterScope(actionOptions.AbsScope) { for _, ocrText := range t.FilterScope(actionOptions.AbsScope) {
@@ -173,8 +173,8 @@ func (t OCRTexts) FindText(text string, opts ...options.ActionOption) (result OC
return results[idx], nil return results[idx], nil
} }
func (t OCRTexts) FindTexts(texts []string, opts ...options.ActionOption) (results OCRTexts, err error) { func (t OCRTexts) FindTexts(texts []string, opts ...option.ActionOption) (results OCRTexts, err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
for _, text := range texts { for _, text := range texts {
ocrText, err := t.FindText(text, opts...) ocrText, err := t.FindText(text, opts...)
if err != nil { if err != nil {
@@ -240,7 +240,7 @@ func (box Box) Center() PointF {
type UIResults []UIResult type UIResults []UIResult
func (u UIResults) FilterScope(scope options.AbsScope) (results UIResults) { func (u UIResults) FilterScope(scope option.AbsScope) (results UIResults) {
for _, uiResult := range u { for _, uiResult := range u {
rect := image.Rectangle{ rect := image.Rectangle{
Min: image.Point{ Min: image.Point{
@@ -268,8 +268,8 @@ func (u UIResults) FilterScope(scope options.AbsScope) (results UIResults) {
return return
} }
func (u UIResults) GetUIResult(opts ...options.ActionOption) (UIResult, error) { func (u UIResults) GetUIResult(opts ...option.ActionOption) (UIResult, error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
uiResults := u.FilterScope(actionOptions.AbsScope) uiResults := u.FilterScope(actionOptions.AbsScope)
if len(uiResults) == 0 { if len(uiResults) == 0 {
+3 -3
View File
@@ -16,7 +16,7 @@ import (
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/internal/json" "github.com/httprunner/httprunner/v5/internal/json"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var client = &http.Client{ var client = &http.Client{
@@ -47,8 +47,8 @@ func newVEDEMImageService() (*veDEMImageService, error) {
// ui - get ui position by type(s) // ui - get ui position by type(s)
type veDEMImageService struct{} type veDEMImageService struct{}
func (s *veDEMImageService) GetImage(imageBuf *bytes.Buffer, opts ...options.ActionOption) (imageResult *ImageResult, err error) { func (s *veDEMImageService) GetImage(imageBuf *bytes.Buffer, opts ...option.ActionOption) (imageResult *ImageResult, err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
screenshotActions := actionOptions.ScreenshotActions() screenshotActions := actionOptions.ScreenshotActions()
if len(screenshotActions) == 0 { if len(screenshotActions) == 0 {
// skip // skip
+3 -3
View File
@@ -8,7 +8,7 @@ import (
"os" "os"
"testing" "testing"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func checkOCR(buff *bytes.Buffer) error { func checkOCR(buff *bytes.Buffer) error {
@@ -55,14 +55,14 @@ func TestOCRWithLocalFile(t *testing.T) {
func TestTapUIWithScreenshot(t *testing.T) { func TestTapUIWithScreenshot(t *testing.T) {
serialNumber := os.Getenv("SERIAL_NUMBER") serialNumber := os.Getenv("SERIAL_NUMBER")
device, _ := NewAndroidDevice(options.WithSerialNumber(serialNumber)) device, _ := NewAndroidDevice(option.WithSerialNumber(serialNumber))
driver, err := device.NewDriver() driver, err := device.NewDriver()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = driver.TapByUIDetection( err = driver.TapByUIDetection(
options.WithScreenShotUITypes("dyhouse", "shoppingbag")) option.WithScreenShotUITypes("dyhouse", "shoppingbag"))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
+15 -15
View File
@@ -24,7 +24,7 @@ import (
"github.com/httprunner/httprunner/v5/internal/config" "github.com/httprunner/httprunner/v5/internal/config"
"github.com/httprunner/httprunner/v5/internal/json" "github.com/httprunner/httprunner/v5/internal/json"
"github.com/httprunner/httprunner/v5/pkg/gadb" "github.com/httprunner/httprunner/v5/pkg/gadb"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var ( var (
@@ -49,8 +49,8 @@ var evalite embed.FS
const forwardToPrefix = "forward-to-" const forwardToPrefix = "forward-to-"
func NewAndroidDevice(opts ...options.AndroidDeviceOption) (device *AndroidDevice, err error) { func NewAndroidDevice(opts ...option.AndroidDeviceOption) (device *AndroidDevice, err error) {
androidOptions := &options.AndroidDeviceConfig{ androidOptions := &option.AndroidDeviceConfig{
UIA2IP: UIA2ServerHost, UIA2IP: UIA2ServerHost,
UIA2Port: UIA2ServerPort, UIA2Port: UIA2ServerPort,
} }
@@ -68,18 +68,18 @@ func NewAndroidDevice(opts ...options.AndroidDeviceOption) (device *AndroidDevic
dev := deviceList[0] dev := deviceList[0]
if device.SerialNumber == "" { if androidOptions.SerialNumber == "" {
selectSerial := dev.Serial() selectSerial := dev.Serial()
device.SerialNumber = selectSerial androidOptions.SerialNumber = selectSerial
log.Warn(). log.Warn().
Str("serial", device.SerialNumber). Str("serial", androidOptions.SerialNumber).
Msg("android SerialNumber is not specified, select the first one") Msg("android SerialNumber is not specified, select the first one")
} }
device = &AndroidDevice{ device = &AndroidDevice{
AndroidDeviceConfig: androidOptions, AndroidDeviceConfig: androidOptions,
d: dev, d: dev,
logcat: NewAdbLogcat(device.SerialNumber), logcat: NewAdbLogcat(androidOptions.SerialNumber),
} }
evalToolRaw, err := evalite.ReadFile("evalite") evalToolRaw, err := evalite.ReadFile("evalite")
@@ -128,7 +128,7 @@ func GetAndroidDevices(serial ...string) (devices []*gadb.Device, err error) {
} }
type AndroidDevice struct { type AndroidDevice struct {
*options.AndroidDeviceConfig *option.AndroidDeviceConfig
d *gadb.Device d *gadb.Device
logcat *AdbLogcat logcat *AdbLogcat
} }
@@ -174,8 +174,8 @@ func (dev *AndroidDevice) LogEnabled() bool {
return dev.LogOn return dev.LogOn
} }
func (dev *AndroidDevice) NewDriver(opts ...options.DriverOption) (driverExt *DriverExt, err error) { func (dev *AndroidDevice) NewDriver(opts ...option.DriverOption) (driverExt *DriverExt, err error) {
driverOptions := options.NewDriverOptions(opts...) driverOptions := option.NewDriverOptions(opts...)
var driver IWebDriver var driver IWebDriver
if dev.UIA2 || dev.LogOn { if dev.UIA2 || dev.LogOn {
@@ -205,7 +205,7 @@ func (dev *AndroidDevice) NewDriver(opts ...options.DriverOption) (driverExt *Dr
} }
// NewUSBDriver creates new client via USB connected device, this will also start a new session. // NewUSBDriver creates new client via USB connected device, this will also start a new session.
func (dev *AndroidDevice) NewUSBDriver(capabilities options.Capabilities) (driver IWebDriver, err error) { func (dev *AndroidDevice) NewUSBDriver(capabilities option.Capabilities) (driver IWebDriver, err error) {
localPort, err := dev.d.Forward(dev.UIA2Port) localPort, err := dev.d.Forward(dev.UIA2Port)
if err != nil { if err != nil {
return nil, errors.Wrap(code.DeviceConnectionError, return nil, errors.Wrap(code.DeviceConnectionError,
@@ -226,7 +226,7 @@ func (dev *AndroidDevice) NewUSBDriver(capabilities options.Capabilities) (drive
return uiaDriver, nil return uiaDriver, nil
} }
func (dev *AndroidDevice) NewStubDriver(capabilities options.Capabilities) (driver *stubAndroidDriver, err error) { func (dev *AndroidDevice) NewStubDriver(capabilities option.Capabilities) (driver *stubAndroidDriver, err error) {
socketLocalPort, err := dev.d.Forward(StubSocketName) socketLocalPort, err := dev.d.Forward(StubSocketName)
if err != nil { if err != nil {
return nil, errors.Wrap(code.DeviceConnectionError, return nil, errors.Wrap(code.DeviceConnectionError,
@@ -257,7 +257,7 @@ func (dev *AndroidDevice) NewStubDriver(capabilities options.Capabilities) (driv
} }
// NewHTTPDriver creates new remote HTTP client, this will also start a new session. // NewHTTPDriver creates new remote HTTP client, this will also start a new session.
func (dev *AndroidDevice) NewHTTPDriver(capabilities options.Capabilities) (driver IWebDriver, err error) { func (dev *AndroidDevice) NewHTTPDriver(capabilities option.Capabilities) (driver IWebDriver, err error) {
rawURL := fmt.Sprintf("http://%s:%d/wd/hub", dev.UIA2IP, dev.UIA2Port) rawURL := fmt.Sprintf("http://%s:%d/wd/hub", dev.UIA2IP, dev.UIA2Port)
uiaDriver, err := NewUIADriver(capabilities, rawURL) uiaDriver, err := NewUIADriver(capabilities, rawURL)
if err != nil { if err != nil {
@@ -301,8 +301,8 @@ func (dev *AndroidDevice) Uninstall(packageName string) error {
return err return err
} }
func (dev *AndroidDevice) Install(apkPath string, opts ...options.InstallOption) error { func (dev *AndroidDevice) Install(apkPath string, opts ...option.InstallOption) error {
installOpts := options.NewInstallOptions(opts...) installOpts := option.NewInstallOptions(opts...)
brand, err := dev.d.Brand() brand, err := dev.d.Brand()
if err != nil { if err != nil {
return err return err
+22 -22
View File
@@ -24,7 +24,7 @@ import (
"github.com/httprunner/httprunner/v5/internal/config" "github.com/httprunner/httprunner/v5/internal/config"
"github.com/httprunner/httprunner/v5/internal/utf7" "github.com/httprunner/httprunner/v5/internal/utf7"
"github.com/httprunner/httprunner/v5/pkg/gadb" "github.com/httprunner/httprunner/v5/pkg/gadb"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
const ( const (
@@ -79,7 +79,7 @@ func (ad *adbDriver) runShellCommand(cmd string, args ...string) (output string,
return output, err return output, err
} }
func (ad *adbDriver) NewSession(capabilities options.Capabilities) (sessionInfo SessionInfo, err error) { func (ad *adbDriver) NewSession(capabilities option.Capabilities) (sessionInfo SessionInfo, err error) {
ad.Driver.session.Reset() ad.Driver.session.Reset()
err = errDriverNotImplemented err = errDriverNotImplemented
return return
@@ -193,7 +193,7 @@ func (ad *adbDriver) GetTimestamp() (timestamp int64, err error) {
} }
// PressBack simulates a short press on the BACK button. // PressBack simulates a short press on the BACK button.
func (ad *adbDriver) PressBack(opts ...options.ActionOption) (err error) { func (ad *adbDriver) PressBack(opts ...option.ActionOption) (err error) {
// adb shell input keyevent 4 // adb shell input keyevent 4
_, err = ad.runShellCommand("input", "keyevent", fmt.Sprintf("%d", KCBack)) _, err = ad.runShellCommand("input", "keyevent", fmt.Sprintf("%d", KCBack))
if err != nil { if err != nil {
@@ -294,7 +294,7 @@ func (ad *adbDriver) Unlock() (err error) {
return ad.Swipe(500, 1500, 500, 500) return ad.Swipe(500, 1500, 500, 500)
} }
func (ad *adbDriver) Backspace(count int, opts ...options.ActionOption) (err error) { func (ad *adbDriver) Backspace(count int, opts ...option.ActionOption) (err error) {
if count == 0 { if count == 0 {
return nil return nil
} }
@@ -370,8 +370,8 @@ func (ad *adbDriver) AppTerminate(packageName string) (successful bool, err erro
return true, nil return true, nil
} }
func (ad *adbDriver) Tap(x, y float64, opts ...options.ActionOption) error { func (ad *adbDriver) Tap(x, y float64, opts ...option.ActionOption) error {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if len(actionOptions.Offset) == 2 { if len(actionOptions.Offset) == 2 {
x += float64(actionOptions.Offset[0]) x += float64(actionOptions.Offset[0])
@@ -391,7 +391,7 @@ func (ad *adbDriver) Tap(x, y float64, opts ...options.ActionOption) error {
return nil return nil
} }
func (ad *adbDriver) DoubleTap(x, y float64, opts ...options.ActionOption) error { func (ad *adbDriver) DoubleTap(x, y float64, opts ...option.ActionOption) error {
// adb shell input tap x y // adb shell input tap x y
xStr := fmt.Sprintf("%.1f", x) xStr := fmt.Sprintf("%.1f", x)
yStr := fmt.Sprintf("%.1f", y) yStr := fmt.Sprintf("%.1f", y)
@@ -409,8 +409,8 @@ func (ad *adbDriver) DoubleTap(x, y float64, opts ...options.ActionOption) error
return nil return nil
} }
func (ad *adbDriver) TouchAndHold(x, y float64, opts ...options.ActionOption) (err error) { func (ad *adbDriver) TouchAndHold(x, y float64, opts ...option.ActionOption) (err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if len(actionOptions.Offset) == 2 { if len(actionOptions.Offset) == 2 {
x += float64(actionOptions.Offset[0]) x += float64(actionOptions.Offset[0])
@@ -435,8 +435,8 @@ func (ad *adbDriver) TouchAndHold(x, y float64, opts ...options.ActionOption) (e
return nil return nil
} }
func (ad *adbDriver) Drag(fromX, fromY, toX, toY float64, opts ...options.ActionOption) (err error) { func (ad *adbDriver) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionOption) (err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if len(actionOptions.Offset) == 4 { if len(actionOptions.Offset) == 4 {
fromX += float64(actionOptions.Offset[0]) fromX += float64(actionOptions.Offset[0])
@@ -469,8 +469,8 @@ func (ad *adbDriver) Drag(fromX, fromY, toX, toY float64, opts ...options.Action
return nil return nil
} }
func (ad *adbDriver) Swipe(fromX, fromY, toX, toY float64, opts ...options.ActionOption) error { func (ad *adbDriver) Swipe(fromX, fromY, toX, toY float64, opts ...option.ActionOption) error {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if len(actionOptions.Offset) == 4 { if len(actionOptions.Offset) == 4 {
fromX += float64(actionOptions.Offset[0]) fromX += float64(actionOptions.Offset[0])
@@ -514,7 +514,7 @@ func (ad *adbDriver) GetPasteboard(contentType PasteboardType) (raw *bytes.Buffe
return return
} }
func (ad *adbDriver) SendKeys(text string, opts ...options.ActionOption) (err error) { func (ad *adbDriver) SendKeys(text string, opts ...option.ActionOption) (err error) {
err = ad.SendUnicodeKeys(text, opts...) err = ad.SendUnicodeKeys(text, opts...)
if err == nil { if err == nil {
return return
@@ -523,7 +523,7 @@ func (ad *adbDriver) SendKeys(text string, opts ...options.ActionOption) (err er
return return
} }
func (ad *adbDriver) InputText(text string, opts ...options.ActionOption) error { func (ad *adbDriver) InputText(text string, opts ...option.ActionOption) error {
// adb shell input text <text> // adb shell input text <text>
_, err := ad.runShellCommand("input", "text", text) _, err := ad.runShellCommand("input", "text", text)
if err != nil { if err != nil {
@@ -532,7 +532,7 @@ func (ad *adbDriver) InputText(text string, opts ...options.ActionOption) error
return nil return nil
} }
func (ad *adbDriver) SendUnicodeKeys(text string, opts ...options.ActionOption) (err error) { func (ad *adbDriver) SendUnicodeKeys(text string, opts ...option.ActionOption) (err error) {
// If the Unicode IME is not installed, fall back to the old interface. // If the Unicode IME is not installed, fall back to the old interface.
// There might be differences in the tracking schemes across different phones, and it is pending further verification. // There might be differences in the tracking schemes across different phones, and it is pending further verification.
// In release version: without the Unicode IME installed, the test cannot execute. // In release version: without the Unicode IME installed, the test cannot execute.
@@ -619,7 +619,7 @@ func (ad *adbDriver) SendKeysByAdbKeyBoard(text string) (err error) {
return return
} }
func (ad *adbDriver) Input(text string, opts ...options.ActionOption) (err error) { func (ad *adbDriver) Input(text string, opts ...option.ActionOption) (err error) {
return ad.SendKeys(text, opts...) return ad.SendKeys(text, opts...)
} }
@@ -694,7 +694,7 @@ func (ad *adbDriver) sourceTree(srcOpt ...SourceOption) (sourceTree *Hierarchy,
return return
} }
func (ad *adbDriver) TapByText(text string, opts ...options.ActionOption) error { func (ad *adbDriver) TapByText(text string, opts ...option.ActionOption) error {
sourceTree, err := ad.sourceTree() sourceTree, err := ad.sourceTree()
if err != nil { if err != nil {
return err return err
@@ -702,9 +702,9 @@ func (ad *adbDriver) TapByText(text string, opts ...options.ActionOption) error
return ad.tapByTextUsingHierarchy(sourceTree, text, opts...) return ad.tapByTextUsingHierarchy(sourceTree, text, opts...)
} }
func (ad *adbDriver) tapByTextUsingHierarchy(hierarchy *Hierarchy, text string, opts ...options.ActionOption) error { func (ad *adbDriver) tapByTextUsingHierarchy(hierarchy *Hierarchy, text string, opts ...option.ActionOption) error {
bounds := ad.searchNodes(hierarchy.Layout, text, opts...) bounds := ad.searchNodes(hierarchy.Layout, text, opts...)
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if len(bounds) == 0 { if len(bounds) == 0 {
if actionOptions.IgnoreNotFoundError { if actionOptions.IgnoreNotFoundError {
log.Info().Msg("not found element by text " + text) log.Info().Msg("not found element by text " + text)
@@ -737,8 +737,8 @@ func (ad *adbDriver) TapByTexts(actions ...TapTextAction) error {
return nil return nil
} }
func (ad *adbDriver) searchNodes(nodes []Layout, text string, opts ...options.ActionOption) []Bounds { func (ad *adbDriver) searchNodes(nodes []Layout, text string, opts ...option.ActionOption) []Bounds {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
var results []Bounds var results []Bounds
for _, node := range nodes { for _, node := range nodes {
result := ad.searchNodes(node.Layout, text, opts...) result := ad.searchNodes(node.Layout, text, opts...)
+2 -2
View File
@@ -13,7 +13,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/internal/json" "github.com/httprunner/httprunner/v5/internal/json"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
type stubAndroidDriver struct { type stubAndroidDriver struct {
@@ -101,7 +101,7 @@ func (sad *stubAndroidDriver) httpPOST(data interface{}, pathElem ...string) (ra
return sad.Request(http.MethodPost, sad.concatURL(nil, pathElem...), bsJSON) return sad.Request(http.MethodPost, sad.concatURL(nil, pathElem...), bsJSON)
} }
func (sad *stubAndroidDriver) NewSession(capabilities options.Capabilities) (SessionInfo, error) { func (sad *stubAndroidDriver) NewSession(capabilities option.Capabilities) (SessionInfo, error) {
sad.Driver.session.Reset() sad.Driver.session.Reset()
return SessionInfo{}, errDriverNotImplemented return SessionInfo{}, errDriverNotImplemented
} }
+3 -3
View File
@@ -5,7 +5,7 @@ import (
"os" "os"
"testing" "testing"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var androidStubDriver *stubAndroidDriver var androidStubDriver *stubAndroidDriver
@@ -14,7 +14,7 @@ func setupStubDriver(t *testing.T) {
device, err := NewAndroidDevice() device, err := NewAndroidDevice()
checkErr(t, err) checkErr(t, err)
device.STUB = true device.STUB = true
androidStubDriver, err = device.NewStubDriver(options.Capabilities{}) androidStubDriver, err = device.NewStubDriver(option.Capabilities{})
checkErr(t, err) checkErr(t, err)
} }
@@ -80,7 +80,7 @@ func TestDoubleTap(t *testing.T) {
func TestLongPress(t *testing.T) { func TestLongPress(t *testing.T) {
setupStubDriver(t) setupStubDriver(t)
err := androidStubDriver.Swipe(1036, 1076, 1036, 1076, err := androidStubDriver.Swipe(1036, 1076, 1036, 1076,
options.WithDuration(3)) option.WithDuration(3))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
+22 -22
View File
@@ -17,7 +17,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/internal/utf7" "github.com/httprunner/httprunner/v5/internal/utf7"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var errDriverNotImplemented = errors.New("driver method not implemented") var errDriverNotImplemented = errors.New("driver method not implemented")
@@ -26,10 +26,10 @@ type uiaDriver struct {
adbDriver adbDriver
} }
func NewUIADriver(capabilities options.Capabilities, urlPrefix string) (driver *uiaDriver, err error) { func NewUIADriver(capabilities option.Capabilities, urlPrefix string) (driver *uiaDriver, err error) {
log.Info().Msg("init uiautomator2 driver") log.Info().Msg("init uiautomator2 driver")
if capabilities == nil { if capabilities == nil {
capabilities = options.NewCapabilities() capabilities = option.NewCapabilities()
capabilities.WithWaitForIdleTimeout(0) capabilities.WithWaitForIdleTimeout(0)
} }
driver = new(uiaDriver) driver = new(uiaDriver)
@@ -86,7 +86,7 @@ func (bs BatteryStatus) String() string {
} }
func (ud *uiaDriver) resetDriver() error { func (ud *uiaDriver) resetDriver() error {
newUIADriver, err := NewUIADriver(options.NewCapabilities(), ud.urlPrefix.String()) newUIADriver, err := NewUIADriver(option.NewCapabilities(), ud.urlPrefix.String())
if err != nil { if err != nil {
return err return err
} }
@@ -134,7 +134,7 @@ func (ud *uiaDriver) httpDELETE(pathElem ...string) (rawResp rawResponse, err er
return ud.httpRequest(http.MethodDelete, ud.concatURL(nil, pathElem...), nil) return ud.httpRequest(http.MethodDelete, ud.concatURL(nil, pathElem...), nil)
} }
func (ud *uiaDriver) NewSession(capabilities options.Capabilities) (sessionInfo SessionInfo, err error) { func (ud *uiaDriver) NewSession(capabilities option.Capabilities) (sessionInfo SessionInfo, err error) {
// register(postHandler, new NewSession("/wd/hub/session")) // register(postHandler, new NewSession("/wd/hub/session"))
var rawResp rawResponse var rawResp rawResponse
data := make(map[string]interface{}) data := make(map[string]interface{})
@@ -250,7 +250,7 @@ func (ud *uiaDriver) WindowSize() (size Size, err error) {
} }
// PressBack simulates a short press on the BACK button. // PressBack simulates a short press on the BACK button.
func (ud *uiaDriver) PressBack(opts ...options.ActionOption) (err error) { func (ud *uiaDriver) PressBack(opts ...option.ActionOption) (err error) {
// register(postHandler, new PressBack("/wd/hub/session/:sessionId/back")) // register(postHandler, new PressBack("/wd/hub/session/:sessionId/back"))
_, err = ud.httpPOST(nil, "/session", ud.session.ID, "back") _, err = ud.httpPOST(nil, "/session", ud.session.ID, "back")
return return
@@ -293,7 +293,7 @@ func (ud *uiaDriver) Orientation() (orientation Orientation, err error) {
return return
} }
func (ud *uiaDriver) DoubleTap(x, y float64, opts ...options.ActionOption) error { func (ud *uiaDriver) DoubleTap(x, y float64, opts ...option.ActionOption) error {
return ud.DoubleFloatTap(x, y) return ud.DoubleFloatTap(x, y)
} }
@@ -319,9 +319,9 @@ func (ud *uiaDriver) DoubleFloatTap(x, y float64) error {
return err return err
} }
func (ud *uiaDriver) Tap(x, y float64, opts ...options.ActionOption) (err error) { func (ud *uiaDriver) Tap(x, y float64, opts ...option.ActionOption) (err error) {
// register(postHandler, new Tap("/wd/hub/session/:sessionId/appium/tap")) // register(postHandler, new Tap("/wd/hub/session/:sessionId/appium/tap"))
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if len(actionOptions.Offset) == 2 { if len(actionOptions.Offset) == 2 {
x += float64(actionOptions.Offset[0]) x += float64(actionOptions.Offset[0])
@@ -357,8 +357,8 @@ func (ud *uiaDriver) Tap(x, y float64, opts ...options.ActionOption) (err error)
return err return err
} }
func (ud *uiaDriver) TouchAndHold(x, y float64, opts ...options.ActionOption) (err error) { func (ud *uiaDriver) TouchAndHold(x, y float64, opts ...option.ActionOption) (err error) {
actionOpts := options.NewActionOptions(opts...) actionOpts := option.NewActionOptions(opts...)
duration := actionOpts.Duration duration := actionOpts.Duration
if duration == 0 { if duration == 0 {
duration = 1.0 duration = 1.0
@@ -379,8 +379,8 @@ func (ud *uiaDriver) TouchAndHold(x, y float64, opts ...options.ActionOption) (e
// the smoothness and speed of the swipe by specifying the number of steps. // the smoothness and speed of the swipe by specifying the number of steps.
// Each step execution is throttled to 5 milliseconds per step, so for a 100 // Each step execution is throttled to 5 milliseconds per step, so for a 100
// steps, the swipe will take around 0.5 seconds to complete. // steps, the swipe will take around 0.5 seconds to complete.
func (ud *uiaDriver) Drag(fromX, fromY, toX, toY float64, opts ...options.ActionOption) (err error) { func (ud *uiaDriver) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionOption) (err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if len(actionOptions.Offset) == 4 { if len(actionOptions.Offset) == 4 {
fromX += float64(actionOptions.Offset[0]) fromX += float64(actionOptions.Offset[0])
fromY += float64(actionOptions.Offset[1]) fromY += float64(actionOptions.Offset[1])
@@ -412,9 +412,9 @@ func (ud *uiaDriver) Drag(fromX, fromY, toX, toY float64, opts ...options.Action
// per step. So for a 100 steps, the swipe will take about 1/2 second to complete. // per step. So for a 100 steps, the swipe will take about 1/2 second to complete.
// //
// `steps` is the number of move steps sent to the system // `steps` is the number of move steps sent to the system
func (ud *uiaDriver) Swipe(fromX, fromY, toX, toY float64, opts ...options.ActionOption) error { func (ud *uiaDriver) Swipe(fromX, fromY, toX, toY float64, opts ...option.ActionOption) error {
// register(postHandler, new Swipe("/wd/hub/session/:sessionId/touch/perform")) // register(postHandler, new Swipe("/wd/hub/session/:sessionId/touch/perform"))
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if len(actionOptions.Offset) == 4 { if len(actionOptions.Offset) == 4 {
fromX += float64(actionOptions.Offset[0]) fromX += float64(actionOptions.Offset[0])
fromY += float64(actionOptions.Offset[1]) fromY += float64(actionOptions.Offset[1])
@@ -497,10 +497,10 @@ func (ud *uiaDriver) GetPasteboard(contentType PasteboardType) (raw *bytes.Buffe
} }
// SendKeys Android input does not support setting frequency. // SendKeys Android input does not support setting frequency.
func (ud *uiaDriver) SendKeys(text string, opts ...options.ActionOption) (err error) { func (ud *uiaDriver) SendKeys(text string, opts ...option.ActionOption) (err error) {
// register(postHandler, new SendKeysToElement("/wd/hub/session/:sessionId/keys")) // register(postHandler, new SendKeysToElement("/wd/hub/session/:sessionId/keys"))
// https://github.com/appium/appium-uiautomator2-server/blob/master/app/src/main/java/io/appium/uiautomator2/handler/SendKeysToElement.java#L76-L85 // https://github.com/appium/appium-uiautomator2-server/blob/master/app/src/main/java/io/appium/uiautomator2/handler/SendKeysToElement.java#L76-L85
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
err = ud.SendUnicodeKeys(text, opts...) err = ud.SendUnicodeKeys(text, opts...)
if err != nil { if err != nil {
data := map[string]interface{}{ data := map[string]interface{}{
@@ -515,7 +515,7 @@ func (ud *uiaDriver) SendKeys(text string, opts ...options.ActionOption) (err er
return return
} }
func (ud *uiaDriver) SendUnicodeKeys(text string, opts ...options.ActionOption) (err error) { func (ud *uiaDriver) SendUnicodeKeys(text string, opts ...option.ActionOption) (err error) {
// If the Unicode IME is not installed, fall back to the old interface. // If the Unicode IME is not installed, fall back to the old interface.
// There might be differences in the tracking schemes across different phones, and it is pending further verification. // There might be differences in the tracking schemes across different phones, and it is pending further verification.
// In release version: without the Unicode IME installed, the test cannot execute. // In release version: without the Unicode IME installed, the test cannot execute.
@@ -545,8 +545,8 @@ func (ud *uiaDriver) SendUnicodeKeys(text string, opts ...options.ActionOption)
return return
} }
func (ud *uiaDriver) SendActionKey(text string, opts ...options.ActionOption) (err error) { func (ud *uiaDriver) SendActionKey(text string, opts ...option.ActionOption) (err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
var actions []interface{} var actions []interface{}
for i, c := range text { for i, c := range text {
actions = append(actions, map[string]interface{}{"type": "keyDown", "value": string(c)}, actions = append(actions, map[string]interface{}{"type": "keyDown", "value": string(c)},
@@ -572,7 +572,7 @@ func (ud *uiaDriver) SendActionKey(text string, opts ...options.ActionOption) (e
return return
} }
func (ud *uiaDriver) Input(text string, opts ...options.ActionOption) (err error) { func (ud *uiaDriver) Input(text string, opts ...option.ActionOption) (err error) {
return ud.SendKeys(text, opts...) return ud.SendKeys(text, opts...)
} }
@@ -625,7 +625,7 @@ func (ud *uiaDriver) sourceTree(srcOpt ...SourceOption) (sourceTree *Hierarchy,
return return
} }
func (ud *uiaDriver) TapByText(text string, opts ...options.ActionOption) error { func (ud *uiaDriver) TapByText(text string, opts ...option.ActionOption) error {
sourceTree, err := ud.sourceTree() sourceTree, err := ud.sourceTree()
if err != nil { if err != nil {
return err return err
+17 -17
View File
@@ -9,7 +9,7 @@ import (
"time" "time"
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var ( var (
@@ -60,7 +60,7 @@ func TestDriver_NewSession(t *testing.T) {
firstMatchEntry := make(map[string]interface{}) firstMatchEntry := make(map[string]interface{})
firstMatchEntry["package"] = "com.android.settings" firstMatchEntry["package"] = "com.android.settings"
firstMatchEntry["activity"] = "com.android.settings/.Settings" firstMatchEntry["activity"] = "com.android.settings/.Settings"
caps := options.Capabilities{ caps := option.Capabilities{
"firstMatch": []interface{}{firstMatchEntry}, "firstMatch": []interface{}{firstMatchEntry},
"alwaysMatch": struct{}{}, "alwaysMatch": struct{}{},
} }
@@ -221,8 +221,8 @@ func TestDriver_Tap(t *testing.T) {
setupAndroidUIA2Driver(t) setupAndroidUIA2Driver(t)
driverExt.Driver.StartCaptureLog("") driverExt.Driver.StartCaptureLog("")
err := driverExt.TapXY(0.5, 0.5, err := driverExt.TapXY(0.5, 0.5,
options.WithIdentifier("test"), option.WithIdentifier("test"),
options.WithPressDuration(4)) option.WithPressDuration(4))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -240,7 +240,7 @@ func TestDriver_Tap(t *testing.T) {
func TestDriver_Swipe(t *testing.T) { func TestDriver_Swipe(t *testing.T) {
setupAndroidUIA2Driver(t) setupAndroidUIA2Driver(t)
err := driverExt.Driver.Swipe(400, 1000, 400, 500, err := driverExt.Driver.Swipe(400, 1000, 400, 500,
options.WithPressDuration(0.5)) option.WithPressDuration(0.5))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -277,7 +277,7 @@ func TestDriver_SendKeys(t *testing.T) {
setupAndroidUIA2Driver(t) setupAndroidUIA2Driver(t)
err := driverExt.Driver.SendKeys("辽宁省沈阳市新民市民族街36-4", err := driverExt.Driver.SendKeys("辽宁省沈阳市新民市民族街36-4",
options.WithIdentifier("test")) option.WithIdentifier("test"))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -500,25 +500,25 @@ func TestTapTexts(t *testing.T) {
actions := []TapTextAction{ actions := []TapTextAction{
{ {
Text: "^.*无视风险安装$", Text: "^.*无视风险安装$",
Options: []options.ActionOption{ Options: []option.ActionOption{
options.WithTapOffset(100, 0), option.WithTapOffset(100, 0),
options.WithRegex(true), option.WithRegex(true),
options.WithIgnoreNotFoundError(true), option.WithIgnoreNotFoundError(true),
}, },
}, },
{ {
Text: "已了解此应用未经检测.*", Text: "已了解此应用未经检测.*",
Options: []options.ActionOption{ Options: []option.ActionOption{
options.WithTapOffset(-450, 0), option.WithTapOffset(-450, 0),
options.WithRegex(true), option.WithRegex(true),
options.WithIgnoreNotFoundError(true), option.WithIgnoreNotFoundError(true),
}, },
}, },
{ {
Text: "^(.*无视风险安装|确定|继续|完成|点击继续安装|继续安装旧版本|替换|安装|授权本次安装|继续安装|重新安装)$", Text: "^(.*无视风险安装|确定|继续|完成|点击继续安装|继续安装旧版本|替换|安装|授权本次安装|继续安装|重新安装)$",
Options: []options.ActionOption{ Options: []option.ActionOption{
options.WithRegex(true), option.WithRegex(true),
options.WithIgnoreNotFoundError(true), option.WithIgnoreNotFoundError(true),
}, },
}, },
} }
+7 -7
View File
@@ -9,22 +9,22 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func TestIOSDemo(t *testing.T) { func TestIOSDemo(t *testing.T) {
device, err := uixt.NewIOSDevice( device, err := uixt.NewIOSDevice(
options.WithWDAPort(8700), option.WithWDAPort(8700),
options.WithWDAMjpegPort(8800), option.WithWDAMjpegPort(8800),
options.WithResetHomeOnStartup(false), // not reset home on startup option.WithResetHomeOnStartup(false), // not reset home on startup
) )
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
capabilities := options.NewCapabilities() capabilities := option.NewCapabilities()
capabilities.WithDefaultAlertAction(options.AlertActionAccept) // or uixt.AlertActionDismiss capabilities.WithDefaultAlertAction(option.AlertActionAccept) // or uixt.AlertActionDismiss
driverExt, err := device.NewDriver(options.WithDriverCapabilities(capabilities)) driverExt, err := device.NewDriver(option.WithDriverCapabilities(capabilities))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
+7 -7
View File
@@ -12,7 +12,7 @@ import (
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/internal/config" "github.com/httprunner/httprunner/v5/internal/config"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
type DriverExt struct { type DriverExt struct {
@@ -25,8 +25,8 @@ type DriverExt struct {
plugin funplugin.IPlugin plugin funplugin.IPlugin
} }
func newDriverExt(device IDevice, driver IWebDriver, opts ...options.DriverOption) (dExt *DriverExt, err error) { func newDriverExt(device IDevice, driver IWebDriver, opts ...option.DriverOption) (dExt *DriverExt, err error) {
driverOptions := options.NewDriverOptions(opts...) driverOptions := option.NewDriverOptions(opts...)
dExt = &DriverExt{ dExt = &DriverExt{
Device: device, Device: device,
@@ -63,8 +63,8 @@ func (dExt *DriverExt) Init() error {
} }
func (dExt *DriverExt) assertOCR(text, assert string) error { func (dExt *DriverExt) assertOCR(text, assert string) error {
var opts []options.ActionOption var opts []option.ActionOption
opts = append(opts, options.WithScreenShotFileName(fmt.Sprintf("assert_ocr_%s", text))) opts = append(opts, option.WithScreenShotFileName(fmt.Sprintf("assert_ocr_%s", text)))
switch assert { switch assert {
case AssertionEqual: case AssertionEqual:
@@ -78,13 +78,13 @@ func (dExt *DriverExt) assertOCR(text, assert string) error {
return errors.New("assert ocr not equal failed") return errors.New("assert ocr not equal failed")
} }
case AssertionExists: case AssertionExists:
opts = append(opts, options.WithRegex(true)) opts = append(opts, option.WithRegex(true))
_, err := dExt.FindScreenText(text, opts...) _, err := dExt.FindScreenText(text, opts...)
if err != nil { if err != nil {
return errors.Wrap(err, "assert ocr exists failed") return errors.Wrap(err, "assert ocr exists failed")
} }
case AssertionNotExists: case AssertionNotExists:
opts = append(opts, options.WithRegex(true)) opts = append(opts, option.WithRegex(true))
_, err := dExt.FindScreenText(text, opts...) _, err := dExt.FindScreenText(text, opts...)
if err == nil { if err == nil {
return errors.New("assert ocr not exists failed") return errors.New("assert ocr not exists failed")
+7 -7
View File
@@ -8,7 +8,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var ( var (
@@ -17,12 +17,12 @@ var (
) )
type HarmonyDevice struct { type HarmonyDevice struct {
*options.HarmonyDeviceConfig *option.HarmonyDeviceConfig
d *ghdc.Device d *ghdc.Device
} }
func NewHarmonyDevice(opts ...options.HarmonyDeviceOption) (device *HarmonyDevice, err error) { func NewHarmonyDevice(opts ...option.HarmonyDeviceOption) (device *HarmonyDevice, err error) {
deviceConfig := options.NewHarmonyDeviceConfig(opts...) deviceConfig := option.NewHarmonyDeviceConfig(opts...)
deviceList, err := GetHarmonyDevices(deviceConfig.ConnectKey) deviceList, err := GetHarmonyDevices(deviceConfig.ConnectKey)
if err != nil { if err != nil {
@@ -95,7 +95,7 @@ func (dev *HarmonyDevice) LogEnabled() bool {
return dev.LogOn return dev.LogOn
} }
func (dev *HarmonyDevice) NewDriver(opts ...options.DriverOption) (driverExt *DriverExt, err error) { func (dev *HarmonyDevice) NewDriver(opts ...option.DriverOption) (driverExt *DriverExt, err error) {
driver, err := newHarmonyDriver(dev.d) driver, err := newHarmonyDriver(dev.d)
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to new harmony driver") log.Error().Err(err).Msg("failed to new harmony driver")
@@ -110,7 +110,7 @@ func (dev *HarmonyDevice) NewDriver(opts ...options.DriverOption) (driverExt *Dr
return driverExt, nil return driverExt, nil
} }
func (dev *HarmonyDevice) NewUSBDriver(opts ...options.DriverOption) (driver IWebDriver, err error) { func (dev *HarmonyDevice) NewUSBDriver(opts ...option.DriverOption) (driver IWebDriver, err error) {
harmonyDriver, err := newHarmonyDriver(dev.d) harmonyDriver, err := newHarmonyDriver(dev.d)
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed to new harmony driver") log.Error().Err(err).Msg("failed to new harmony driver")
@@ -120,7 +120,7 @@ func (dev *HarmonyDevice) NewUSBDriver(opts ...options.DriverOption) (driver IWe
return harmonyDriver, nil return harmonyDriver, nil
} }
func (dev *HarmonyDevice) Install(appPath string, opts ...options.InstallOption) error { func (dev *HarmonyDevice) Install(appPath string, opts ...option.InstallOption) error {
return nil return nil
} }
+15 -14
View File
@@ -8,8 +8,9 @@ import (
"time" "time"
"code.byted.org/iesqa/ghdc" "code.byted.org/iesqa/ghdc"
"github.com/httprunner/httprunner/v5/pkg/uixt/options"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
type hdcDriver struct { type hdcDriver struct {
@@ -40,7 +41,7 @@ func newHarmonyDriver(device *ghdc.Device) (driver *hdcDriver, err error) {
return return
} }
func (hd *hdcDriver) NewSession(capabilities options.Capabilities) (SessionInfo, error) { func (hd *hdcDriver) NewSession(capabilities option.Capabilities) (SessionInfo, error) {
hd.Driver.session.Reset() hd.Driver.session.Reset()
hd.Unlock() hd.Unlock()
return SessionInfo{}, errDriverNotImplemented return SessionInfo{}, errDriverNotImplemented
@@ -155,8 +156,8 @@ func (hd *hdcDriver) Orientation() (orientation Orientation, err error) {
return OrientationPortrait, nil return OrientationPortrait, nil
} }
func (hd *hdcDriver) Tap(x, y float64, opts ...options.ActionOption) error { func (hd *hdcDriver) Tap(x, y float64, opts ...option.ActionOption) error {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if len(actionOptions.Offset) == 2 { if len(actionOptions.Offset) == 2 {
x += float64(actionOptions.Offset[0]) x += float64(actionOptions.Offset[0])
@@ -172,21 +173,21 @@ func (hd *hdcDriver) Tap(x, y float64, opts ...options.ActionOption) error {
return hd.uiDriver.InjectGesture(ghdc.NewGesture().Start(ghdc.Point{X: int(x), Y: int(y)}).Pause(100)) return hd.uiDriver.InjectGesture(ghdc.NewGesture().Start(ghdc.Point{X: int(x), Y: int(y)}).Pause(100))
} }
func (hd *hdcDriver) DoubleTap(x, y float64, opts ...options.ActionOption) error { func (hd *hdcDriver) DoubleTap(x, y float64, opts ...option.ActionOption) error {
return errDriverNotImplemented return errDriverNotImplemented
} }
func (hd *hdcDriver) TouchAndHold(x, y float64, opts ...options.ActionOption) (err error) { func (hd *hdcDriver) TouchAndHold(x, y float64, opts ...option.ActionOption) (err error) {
return errDriverNotImplemented return errDriverNotImplemented
} }
func (hd *hdcDriver) Drag(fromX, fromY, toX, toY float64, opts ...options.ActionOption) error { func (hd *hdcDriver) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionOption) error {
return errDriverNotImplemented return errDriverNotImplemented
} }
// Swipe works like Drag, but `pressForDuration` value is 0 // Swipe works like Drag, but `pressForDuration` value is 0
func (hd *hdcDriver) Swipe(fromX, fromY, toX, toY float64, opts ...options.ActionOption) error { func (hd *hdcDriver) Swipe(fromX, fromY, toX, toY float64, opts ...option.ActionOption) error {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if len(actionOptions.Offset) == 4 { if len(actionOptions.Offset) == 4 {
fromX += float64(actionOptions.Offset[0]) fromX += float64(actionOptions.Offset[0])
fromY += float64(actionOptions.Offset[1]) fromY += float64(actionOptions.Offset[1])
@@ -221,11 +222,11 @@ func (hd *hdcDriver) SetIme(ime string) error {
return errDriverNotImplemented return errDriverNotImplemented
} }
func (hd *hdcDriver) SendKeys(text string, opts ...options.ActionOption) error { func (hd *hdcDriver) SendKeys(text string, opts ...option.ActionOption) error {
return hd.uiDriver.InputText(text) return hd.uiDriver.InputText(text)
} }
func (hd *hdcDriver) Input(text string, opts ...options.ActionOption) error { func (hd *hdcDriver) Input(text string, opts ...option.ActionOption) error {
return hd.uiDriver.InputText(text) return hd.uiDriver.InputText(text)
} }
@@ -237,11 +238,11 @@ func (hd *hdcDriver) PressButton(devBtn DeviceButton) error {
return errDriverNotImplemented return errDriverNotImplemented
} }
func (hd *hdcDriver) PressBack(opts ...options.ActionOption) error { func (hd *hdcDriver) PressBack(opts ...option.ActionOption) error {
return hd.uiDriver.PressBack() return hd.uiDriver.PressBack()
} }
func (hd *hdcDriver) Backspace(count int, opts ...options.ActionOption) (err error) { func (hd *hdcDriver) Backspace(count int, opts ...option.ActionOption) (err error) {
return nil return nil
} }
@@ -286,7 +287,7 @@ func (hd *hdcDriver) LogoutNoneUI(packageName string) error {
return errDriverNotImplemented return errDriverNotImplemented
} }
func (hd *hdcDriver) TapByText(text string, opts ...options.ActionOption) error { func (hd *hdcDriver) TapByText(text string, opts ...option.ActionOption) error {
return errDriverNotImplemented return errDriverNotImplemented
} }
+15 -15
View File
@@ -9,7 +9,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
type InstallResult struct { type InstallResult struct {
@@ -18,7 +18,7 @@ type InstallResult struct {
ErrorMsg string `json:"errorMsg"` ErrorMsg string `json:"errorMsg"`
} }
func (dExt *DriverExt) InstallByUrl(url string, opts ...options.InstallOption) error { func (dExt *DriverExt) InstallByUrl(url string, opts ...option.InstallOption) error {
// 获取当前目录 // 获取当前目录
cwd, err := os.Getwd() cwd, err := os.Getwd()
if err != nil { if err != nil {
@@ -41,7 +41,7 @@ func (dExt *DriverExt) InstallByUrl(url string, opts ...options.InstallOption) e
return nil return nil
} }
func (dExt *DriverExt) Install(filePath string, opts ...options.InstallOption) error { func (dExt *DriverExt) Install(filePath string, opts ...option.InstallOption) error {
if _, ok := dExt.Device.(*AndroidDevice); ok { if _, ok := dExt.Device.(*AndroidDevice); ok {
stopChan := make(chan struct{}) stopChan := make(chan struct{})
go func() { go func() {
@@ -54,18 +54,18 @@ func (dExt *DriverExt) Install(filePath string, opts ...options.InstallOption) e
actions := []TapTextAction{ actions := []TapTextAction{
{ {
Text: "^.*无视风险安装$", Text: "^.*无视风险安装$",
Options: []options.ActionOption{ Options: []option.ActionOption{
options.WithTapOffset(100, 0), option.WithTapOffset(100, 0),
options.WithRegex(true), option.WithRegex(true),
options.WithIgnoreNotFoundError(true), option.WithIgnoreNotFoundError(true),
}, },
}, },
{ {
Text: "^已了解此应用未经检测.*", Text: "^已了解此应用未经检测.*",
Options: []options.ActionOption{ Options: []option.ActionOption{
options.WithTapOffset(-450, 0), option.WithTapOffset(-450, 0),
options.WithRegex(true), option.WithRegex(true),
options.WithIgnoreNotFoundError(true), option.WithIgnoreNotFoundError(true),
}, },
}, },
} }
@@ -73,8 +73,8 @@ func (dExt *DriverExt) Install(filePath string, opts ...options.InstallOption) e
_ = dExt.TapByOCR( _ = dExt.TapByOCR(
"^(.*无视风险安装|确定|继续|完成|点击继续安装|继续安装旧版本|替换|授权本次安装|稍后提醒|继续安装|重新安装|安装)$", "^(.*无视风险安装|确定|继续|完成|点击继续安装|继续安装旧版本|替换|授权本次安装|稍后提醒|继续安装|重新安装|安装)$",
options.WithRegex(true), option.WithRegex(true),
options.WithIgnoreNotFoundError(true), option.WithIgnoreNotFoundError(true),
) )
case <-stopChan: case <-stopChan:
log.Info().Msg("Ticker stopped") log.Info().Msg("Ticker stopped")
@@ -90,8 +90,8 @@ func (dExt *DriverExt) Install(filePath string, opts ...options.InstallOption) e
return dExt.Device.Install(filePath, opts...) return dExt.Device.Install(filePath, opts...)
} }
func (dExt *DriverExt) Uninstall(packageName string, opts ...options.ActionOption) error { func (dExt *DriverExt) Uninstall(packageName string, opts ...option.ActionOption) error {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
err := dExt.Device.Uninstall(packageName) err := dExt.Device.Uninstall(packageName)
if err != nil { if err != nil {
log.Warn().Err(err).Msg("failed to uninstall") log.Warn().Err(err).Msg("failed to uninstall")
+14 -14
View File
@@ -6,7 +6,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var ( var (
@@ -357,9 +357,9 @@ type IDevice interface {
LogEnabled() bool LogEnabled() bool
// TODO: add ctx to NewDriver // TODO: add ctx to NewDriver
NewDriver(...options.DriverOption) (driverExt *DriverExt, err error) NewDriver(...option.DriverOption) (driverExt *DriverExt, err error)
Install(appPath string, opts ...options.InstallOption) error Install(appPath string, opts ...option.InstallOption) error
Uninstall(packageName string) error Uninstall(packageName string) error
GetPackageInfo(packageName string) (AppInfo, error) GetPackageInfo(packageName string) (AppInfo, error)
@@ -376,7 +376,7 @@ type ForegroundApp struct {
// IWebDriver defines methods supported by IWebDriver drivers. // IWebDriver defines methods supported by IWebDriver drivers.
type IWebDriver interface { type IWebDriver interface {
// NewSession starts a new session and returns the SessionInfo. // NewSession starts a new session and returns the SessionInfo.
NewSession(capabilities options.Capabilities) (SessionInfo, error) NewSession(capabilities option.Capabilities) (SessionInfo, error)
// DeleteSession Kills application associated with that session and removes session // DeleteSession Kills application associated with that session and removes session
// 1) alertsMonitor disable // 1) alertsMonitor disable
@@ -438,21 +438,21 @@ type IWebDriver interface {
Orientation() (orientation Orientation, err error) Orientation() (orientation Orientation, err error)
// Tap Sends a tap event at the coordinate. // Tap Sends a tap event at the coordinate.
Tap(x, y float64, opts ...options.ActionOption) error Tap(x, y float64, opts ...option.ActionOption) error
// DoubleTap Sends a double tap event at the coordinate. // DoubleTap Sends a double tap event at the coordinate.
DoubleTap(x, y float64, opts ...options.ActionOption) error DoubleTap(x, y float64, opts ...option.ActionOption) error
// TouchAndHold Initiates a long-press gesture at the coordinate, holding for the specified duration. // TouchAndHold Initiates a long-press gesture at the coordinate, holding for the specified duration.
// second: The default value is 1 // second: The default value is 1
TouchAndHold(x, y float64, opts ...options.ActionOption) error TouchAndHold(x, y float64, opts ...option.ActionOption) error
// Drag Initiates a press-and-hold gesture at the coordinate, then drags to another coordinate. // Drag Initiates a press-and-hold gesture at the coordinate, then drags to another coordinate.
// WithPressDurationOption option can be used to set pressForDuration (default to 1 second). // WithPressDurationOption option can be used to set pressForDuration (default to 1 second).
Drag(fromX, fromY, toX, toY float64, opts ...options.ActionOption) error Drag(fromX, fromY, toX, toY float64, opts ...option.ActionOption) error
// Swipe works like Drag, but `pressForDuration` value is 0 // Swipe works like Drag, but `pressForDuration` value is 0
Swipe(fromX, fromY, toX, toY float64, opts ...options.ActionOption) error Swipe(fromX, fromY, toX, toY float64, opts ...option.ActionOption) error
// SetPasteboard Sets data to the general pasteboard // SetPasteboard Sets data to the general pasteboard
SetPasteboard(contentType PasteboardType, content string) error SetPasteboard(contentType PasteboardType, content string) error
@@ -465,10 +465,10 @@ type IWebDriver interface {
// SendKeys Types a string into active element. There must be element with keyboard focus, // SendKeys Types a string into active element. There must be element with keyboard focus,
// otherwise an error is raised. // otherwise an error is raised.
// WithFrequency option can be used to set frequency of typing (letters per sec). The default value is 60 // WithFrequency option can be used to set frequency of typing (letters per sec). The default value is 60
SendKeys(text string, opts ...options.ActionOption) error SendKeys(text string, opts ...option.ActionOption) error
// Input works like SendKeys // Input works like SendKeys
Input(text string, opts ...options.ActionOption) error Input(text string, opts ...option.ActionOption) error
Clear(packageName string) error Clear(packageName string) error
@@ -476,11 +476,11 @@ type IWebDriver interface {
PressButton(devBtn DeviceButton) error PressButton(devBtn DeviceButton) error
// PressBack Presses the back button // PressBack Presses the back button
PressBack(opts ...options.ActionOption) error PressBack(opts ...option.ActionOption) error
PressKeyCode(keyCode KeyCode) (err error) PressKeyCode(keyCode KeyCode) (err error)
Backspace(count int, opts ...options.ActionOption) (err error) Backspace(count int, opts ...option.ActionOption) (err error)
Screenshot() (*bytes.Buffer, error) Screenshot() (*bytes.Buffer, error)
@@ -490,7 +490,7 @@ type IWebDriver interface {
LoginNoneUI(packageName, phoneNumber string, captcha, password string) (info AppLoginInfo, err error) LoginNoneUI(packageName, phoneNumber string, captcha, password string) (info AppLoginInfo, err error)
LogoutNoneUI(packageName string) error LogoutNoneUI(packageName string) error
TapByText(text string, opts ...options.ActionOption) error TapByText(text string, opts ...option.ActionOption) error
TapByTexts(actions ...TapTextAction) error TapByTexts(actions ...TapTextAction) error
// AccessibleSource Return application elements accessibility tree // AccessibleSource Return application elements accessibility tree
+12 -12
View File
@@ -28,7 +28,7 @@ import (
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
const ( const (
@@ -125,8 +125,8 @@ func RebootTunnel() (err error) {
return StartTunnel(os.TempDir(), ios.HttpApiPort(), true) return StartTunnel(os.TempDir(), ios.HttpApiPort(), true)
} }
func NewIOSDevice(opts ...options.IOSDeviceOption) (device *IOSDevice, err error) { func NewIOSDevice(opts ...option.IOSDeviceOption) (device *IOSDevice, err error) {
deviceOptions := &options.IOSDeviceConfig{ deviceOptions := &option.IOSDeviceConfig{
Port: defaultWDAPort, Port: defaultWDAPort,
MjpegPort: defaultMjpegPort, MjpegPort: defaultMjpegPort,
SnapshotMaxDepth: snapshotMaxDepth, SnapshotMaxDepth: snapshotMaxDepth,
@@ -174,7 +174,7 @@ func NewIOSDevice(opts ...options.IOSDeviceOption) (device *IOSDevice, err error
} }
type IOSDevice struct { type IOSDevice struct {
*options.IOSDeviceConfig *option.IOSDeviceConfig
d ios.DeviceEntry d ios.DeviceEntry
listeners map[int]*forward.ConnListener listeners map[int]*forward.ConnListener
} }
@@ -260,14 +260,14 @@ func (dev *IOSDevice) getAppInfo(packageName string) (appInfo AppInfo, err error
return AppInfo{}, fmt.Errorf("not found App by bundle id: %s", packageName) return AppInfo{}, fmt.Errorf("not found App by bundle id: %s", packageName)
} }
func (dev *IOSDevice) NewDriver(opts ...options.DriverOption) (driverExt *DriverExt, err error) { func (dev *IOSDevice) NewDriver(opts ...option.DriverOption) (driverExt *DriverExt, err error) {
driverOptions := options.NewDriverOptions() driverOptions := option.NewDriverOptions()
// init WDA driver // init WDA driver
capabilities := driverOptions.Capabilities capabilities := driverOptions.Capabilities
if capabilities == nil { if capabilities == nil {
capabilities = options.NewCapabilities() capabilities = option.NewCapabilities()
capabilities.WithDefaultAlertAction(options.AlertActionAccept) capabilities.WithDefaultAlertAction(option.AlertActionAccept)
} }
var driver IWebDriver var driver IWebDriver
@@ -323,8 +323,8 @@ func (dev *IOSDevice) NewDriver(opts ...options.DriverOption) (driverExt *Driver
return driverExt, nil return driverExt, nil
} }
func (dev *IOSDevice) Install(appPath string, opts ...options.InstallOption) (err error) { func (dev *IOSDevice) Install(appPath string, opts ...option.InstallOption) (err error) {
installOpts := options.NewInstallOptions(opts...) installOpts := option.NewInstallOptions(opts...)
for i := 0; i <= installOpts.RetryTimes; i++ { for i := 0; i <= installOpts.RetryTimes; i++ {
var conn *zipconduit.Connection var conn *zipconduit.Connection
conn, err = zipconduit.New(dev.d) conn, err = zipconduit.New(dev.d)
@@ -343,7 +343,7 @@ func (dev *IOSDevice) Install(appPath string, opts ...options.InstallOption) (er
return err return err
} }
func (dev *IOSDevice) InstallByUrl(url string, opts ...options.InstallOption) (err error) { func (dev *IOSDevice) InstallByUrl(url string, opts ...option.InstallOption) (err error) {
appPath, err := builtin.DownloadFileByUrl(url) appPath, err := builtin.DownloadFileByUrl(url)
if err != nil { if err != nil {
return err return err
@@ -561,7 +561,7 @@ func (dev *IOSDevice) Reboot() error {
} }
// NewHTTPDriver creates new remote HTTP client, this will also start a new session. // NewHTTPDriver creates new remote HTTP client, this will also start a new session.
func (dev *IOSDevice) NewHTTPDriver(capabilities options.Capabilities) (driver IWebDriver, err error) { func (dev *IOSDevice) NewHTTPDriver(capabilities option.Capabilities) (driver IWebDriver, err error) {
var localPort int var localPort int
localPort, err = strconv.Atoi(os.Getenv("WDA_LOCAL_PORT")) localPort, err = strconv.Atoi(os.Getenv("WDA_LOCAL_PORT"))
if err != nil { if err != nil {
+13 -12
View File
@@ -7,8 +7,9 @@ import (
"net/http" "net/http"
"time" "time"
"github.com/httprunner/httprunner/v5/pkg/uixt/options"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
type stubIOSDriver struct { type stubIOSDriver struct {
@@ -38,8 +39,8 @@ func newStubIOSDriver(bightInsightAddr, serverAddr string, dev *IOSDevice, readT
func (s *stubIOSDriver) setUpWda() (err error) { func (s *stubIOSDriver) setUpWda() (err error) {
if s.wdaDriver == nil { if s.wdaDriver == nil {
capabilities := options.NewCapabilities() capabilities := option.NewCapabilities()
capabilities.WithDefaultAlertAction(options.AlertActionAccept) capabilities.WithDefaultAlertAction(option.AlertActionAccept)
driver, err := s.device.NewHTTPDriver(capabilities) driver, err := s.device.NewHTTPDriver(capabilities)
if err != nil { if err != nil {
log.Error().Err(err).Msg("stub driver failed to init wda driver") log.Error().Err(err).Msg("stub driver failed to init wda driver")
@@ -51,7 +52,7 @@ func (s *stubIOSDriver) setUpWda() (err error) {
} }
// NewSession starts a new session and returns the SessionInfo. // NewSession starts a new session and returns the SessionInfo.
func (s *stubIOSDriver) NewSession(capabilities options.Capabilities) (SessionInfo, error) { func (s *stubIOSDriver) NewSession(capabilities option.Capabilities) (SessionInfo, error) {
err := s.setUpWda() err := s.setUpWda()
if err != nil { if err != nil {
return SessionInfo{}, err return SessionInfo{}, err
@@ -220,7 +221,7 @@ func (s *stubIOSDriver) Orientation() (orientation Orientation, err error) {
} }
// Tap Sends a tap event at the coordinate. // Tap Sends a tap event at the coordinate.
func (s *stubIOSDriver) Tap(x, y float64, opts ...options.ActionOption) error { func (s *stubIOSDriver) Tap(x, y float64, opts ...option.ActionOption) error {
err := s.setUpWda() err := s.setUpWda()
if err != nil { if err != nil {
return err return err
@@ -229,7 +230,7 @@ func (s *stubIOSDriver) Tap(x, y float64, opts ...options.ActionOption) error {
} }
// DoubleTap Sends a double tap event at the coordinate. // DoubleTap Sends a double tap event at the coordinate.
func (s *stubIOSDriver) DoubleTap(x, y float64, opts ...options.ActionOption) error { func (s *stubIOSDriver) DoubleTap(x, y float64, opts ...option.ActionOption) error {
err := s.setUpWda() err := s.setUpWda()
if err != nil { if err != nil {
return err return err
@@ -240,7 +241,7 @@ func (s *stubIOSDriver) DoubleTap(x, y float64, opts ...options.ActionOption) er
// TouchAndHold Initiates a long-press gesture at the coordinate, holding for the specified duration. // TouchAndHold Initiates a long-press gesture at the coordinate, holding for the specified duration.
// //
// second: The default value is 1 // second: The default value is 1
func (s *stubIOSDriver) TouchAndHold(x, y float64, opts ...options.ActionOption) error { func (s *stubIOSDriver) TouchAndHold(x, y float64, opts ...option.ActionOption) error {
err := s.setUpWda() err := s.setUpWda()
if err != nil { if err != nil {
return err return err
@@ -250,7 +251,7 @@ func (s *stubIOSDriver) TouchAndHold(x, y float64, opts ...options.ActionOption)
// Drag Initiates a press-and-hold gesture at the coordinate, then drags to another coordinate. // Drag Initiates a press-and-hold gesture at the coordinate, then drags to another coordinate.
// WithPressDurationOption option can be used to set pressForDuration (default to 1 second). // WithPressDurationOption option can be used to set pressForDuration (default to 1 second).
func (s *stubIOSDriver) Drag(fromX, fromY, toX, toY float64, opts ...options.ActionOption) error { func (s *stubIOSDriver) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionOption) error {
err := s.setUpWda() err := s.setUpWda()
if err != nil { if err != nil {
return err return err
@@ -289,7 +290,7 @@ func (s *stubIOSDriver) SetIme(ime string) error {
// SendKeys Types a string into active element. There must be element with keyboard focus, // SendKeys Types a string into active element. There must be element with keyboard focus,
// otherwise an error is raised. // otherwise an error is raised.
// WithFrequency option can be used to set frequency of typing (letters per sec). The default value is 60 // WithFrequency option can be used to set frequency of typing (letters per sec). The default value is 60
func (s *stubIOSDriver) SendKeys(text string, opts ...options.ActionOption) error { func (s *stubIOSDriver) SendKeys(text string, opts ...option.ActionOption) error {
err := s.setUpWda() err := s.setUpWda()
if err != nil { if err != nil {
return err return err
@@ -298,7 +299,7 @@ func (s *stubIOSDriver) SendKeys(text string, opts ...options.ActionOption) erro
} }
// Input works like SendKeys // Input works like SendKeys
func (s *stubIOSDriver) Input(text string, opts ...options.ActionOption) error { func (s *stubIOSDriver) Input(text string, opts ...option.ActionOption) error {
err := s.setUpWda() err := s.setUpWda()
if err != nil { if err != nil {
return err return err
@@ -324,7 +325,7 @@ func (s *stubIOSDriver) PressButton(devBtn DeviceButton) error {
} }
// PressBack Presses the back button // PressBack Presses the back button
func (s *stubIOSDriver) PressBack(opts ...options.ActionOption) error { func (s *stubIOSDriver) PressBack(opts ...option.ActionOption) error {
err := s.setUpWda() err := s.setUpWda()
if err != nil { if err != nil {
return err return err
@@ -361,7 +362,7 @@ func (s *stubIOSDriver) Screenshot() (*bytes.Buffer, error) {
//return bytes.NewBuffer(imageBytes), nil //return bytes.NewBuffer(imageBytes), nil
} }
func (s *stubIOSDriver) TapByText(text string, opts ...options.ActionOption) error { func (s *stubIOSDriver) TapByText(text string, opts ...option.ActionOption) error {
err := s.setUpWda() err := s.setUpWda()
if err != nil { if err != nil {
return err return err
+4 -4
View File
@@ -7,7 +7,7 @@ import (
"testing" "testing"
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var ( var (
@@ -18,9 +18,9 @@ var (
func setupiOSStubDriver(t *testing.T) { func setupiOSStubDriver(t *testing.T) {
var err error var err error
iOSDevice, err = NewIOSDevice( iOSDevice, err = NewIOSDevice(
options.WithWDAPort(8700), option.WithWDAPort(8700),
options.WithWDAMjpegPort(8800), option.WithWDAMjpegPort(8800),
options.WithIOSStub(false)) option.WithIOSStub(false))
checkErr(t, err) checkErr(t, err)
iOSStubDriver, err = iOSDevice.NewStubDriver() iOSStubDriver, err = iOSDevice.NewStubDriver()
checkErr(t, err) checkErr(t, err)
+22 -22
View File
@@ -24,7 +24,7 @@ import (
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/internal/json" "github.com/httprunner/httprunner/v5/internal/json"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
type wdaDriver struct { type wdaDriver struct {
@@ -37,8 +37,8 @@ type wdaDriver struct {
} }
func (wd *wdaDriver) resetSession() error { func (wd *wdaDriver) resetSession() error {
capabilities := options.NewCapabilities() capabilities := option.NewCapabilities()
capabilities.WithDefaultAlertAction(options.AlertActionAccept) capabilities.WithDefaultAlertAction(option.AlertActionAccept)
data := map[string]interface{}{ data := map[string]interface{}{
"capabilities": map[string]interface{}{ "capabilities": map[string]interface{}{
@@ -116,7 +116,7 @@ func (wd *wdaDriver) GetMjpegClient() *http.Client {
return wd.mjpegClient return wd.mjpegClient
} }
func (wd *wdaDriver) NewSession(capabilities options.Capabilities) (sessionInfo SessionInfo, err error) { func (wd *wdaDriver) NewSession(capabilities option.Capabilities) (sessionInfo SessionInfo, err error) {
// [[FBRoute POST:@"/session"].withoutSession respondWithTarget:self action:@selector(handleCreateSession:)] // [[FBRoute POST:@"/session"].withoutSession respondWithTarget:self action:@selector(handleCreateSession:)]
data := make(map[string]interface{}) data := make(map[string]interface{})
if len(capabilities) == 0 { if len(capabilities) == 0 {
@@ -508,9 +508,9 @@ func (wd *wdaDriver) AssertForegroundApp(bundleId string, viewControllerType ...
return nil return nil
} }
func (wd *wdaDriver) Tap(x, y float64, opts ...options.ActionOption) (err error) { func (wd *wdaDriver) Tap(x, y float64, opts ...option.ActionOption) (err error) {
// [[FBRoute POST:@"/wda/tap/:uuid"] respondWithTarget:self action:@selector(handleTap:)] // [[FBRoute POST:@"/wda/tap/:uuid"] respondWithTarget:self action:@selector(handleTap:)]
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
x = wd.toScale(x) x = wd.toScale(x)
y = wd.toScale(y) y = wd.toScale(y)
@@ -532,9 +532,9 @@ func (wd *wdaDriver) Tap(x, y float64, opts ...options.ActionOption) (err error)
return return
} }
func (wd *wdaDriver) DoubleTap(x, y float64, opts ...options.ActionOption) (err error) { func (wd *wdaDriver) DoubleTap(x, y float64, opts ...option.ActionOption) (err error) {
// [[FBRoute POST:@"/wda/doubleTap"] respondWithTarget:self action:@selector(handleDoubleTapCoordinate:)] // [[FBRoute POST:@"/wda/doubleTap"] respondWithTarget:self action:@selector(handleDoubleTapCoordinate:)]
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
x = wd.toScale(x) x = wd.toScale(x)
y = wd.toScale(y) y = wd.toScale(y)
if len(actionOptions.Offset) == 2 { if len(actionOptions.Offset) == 2 {
@@ -552,17 +552,17 @@ func (wd *wdaDriver) DoubleTap(x, y float64, opts ...options.ActionOption) (err
return return
} }
func (wd *wdaDriver) TouchAndHold(x, y float64, opts ...options.ActionOption) (err error) { func (wd *wdaDriver) TouchAndHold(x, y float64, opts ...option.ActionOption) (err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if actionOptions.Duration == 0 { if actionOptions.Duration == 0 {
opts = append(opts, options.WithDuration(1)) opts = append(opts, option.WithDuration(1))
} }
return wd.Tap(x, y, opts...) return wd.Tap(x, y, opts...)
} }
func (wd *wdaDriver) Drag(fromX, fromY, toX, toY float64, opts ...options.ActionOption) (err error) { func (wd *wdaDriver) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionOption) (err error) {
// [[FBRoute POST:@"/wda/dragfromtoforduration"] respondWithTarget:self action:@selector(handleDragCoordinate:)] // [[FBRoute POST:@"/wda/dragfromtoforduration"] respondWithTarget:self action:@selector(handleDragCoordinate:)]
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
fromX = wd.toScale(fromX) fromX = wd.toScale(fromX)
fromY = wd.toScale(fromY) fromY = wd.toScale(fromY)
@@ -597,7 +597,7 @@ func (wd *wdaDriver) Drag(fromX, fromY, toX, toY float64, opts ...options.Action
return return
} }
func (wd *wdaDriver) Swipe(fromX, fromY, toX, toY float64, opts ...options.ActionOption) error { func (wd *wdaDriver) Swipe(fromX, fromY, toX, toY float64, opts ...option.ActionOption) error {
return wd.Drag(fromX, fromY, toX, toY, opts...) return wd.Drag(fromX, fromY, toX, toY, opts...)
} }
@@ -632,9 +632,9 @@ func (wd *wdaDriver) PressKeyCode(keyCode KeyCode) (err error) {
return errDriverNotImplemented return errDriverNotImplemented
} }
func (wd *wdaDriver) SendKeys(text string, opts ...options.ActionOption) (err error) { func (wd *wdaDriver) SendKeys(text string, opts ...option.ActionOption) (err error) {
// [[FBRoute POST:@"/wda/keys"] respondWithTarget:self action:@selector(handleKeys:)] // [[FBRoute POST:@"/wda/keys"] respondWithTarget:self action:@selector(handleKeys:)]
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
data := map[string]interface{}{"value": strings.Split(text, "")} data := map[string]interface{}{"value": strings.Split(text, "")}
// new data options in post data for extra WDA configurations // new data options in post data for extra WDA configurations
@@ -644,11 +644,11 @@ func (wd *wdaDriver) SendKeys(text string, opts ...options.ActionOption) (err er
return return
} }
func (wd *wdaDriver) Backspace(count int, opts ...options.ActionOption) (err error) { func (wd *wdaDriver) Backspace(count int, opts ...option.ActionOption) (err error) {
if count == 0 { if count == 0 {
return nil return nil
} }
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
data := map[string]interface{}{"count": count} data := map[string]interface{}{"count": count}
// new data options in post data for extra WDA configurations // new data options in post data for extra WDA configurations
@@ -658,7 +658,7 @@ func (wd *wdaDriver) Backspace(count int, opts ...options.ActionOption) (err err
return return
} }
func (wd *wdaDriver) Input(text string, opts ...options.ActionOption) (err error) { func (wd *wdaDriver) Input(text string, opts ...option.ActionOption) (err error) {
return wd.SendKeys(text, opts...) return wd.SendKeys(text, opts...)
} }
@@ -667,8 +667,8 @@ func (wd *wdaDriver) Clear(packageName string) error {
} }
// PressBack simulates a short press on the BACK button. // PressBack simulates a short press on the BACK button.
func (wd *wdaDriver) PressBack(opts ...options.ActionOption) (err error) { func (wd *wdaDriver) PressBack(opts ...option.ActionOption) (err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
windowSize, err := wd.WindowSize() windowSize, err := wd.WindowSize()
if err != nil { if err != nil {
@@ -826,7 +826,7 @@ func (wd *wdaDriver) Source(srcOpt ...SourceOption) (source string, err error) {
return return
} }
func (wd *wdaDriver) TapByText(text string, opts ...options.ActionOption) error { func (wd *wdaDriver) TapByText(text string, opts ...option.ActionOption) error {
return errDriverNotImplemented return errDriverNotImplemented
} }
+19 -18
View File
@@ -8,8 +8,9 @@ import (
"testing" "testing"
"time" "time"
"github.com/httprunner/httprunner/v5/pkg/uixt/options"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var ( var (
@@ -20,14 +21,14 @@ var (
func setup(t *testing.T) { func setup(t *testing.T) {
device, err := NewIOSDevice( device, err := NewIOSDevice(
options.WithWDAPort(8700), option.WithWDAPort(8700),
options.WithWDAMjpegPort(8800), option.WithWDAMjpegPort(8800),
options.WithWDALogOn(true)) option.WithWDALogOn(true))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
capabilities := options.NewCapabilities() capabilities := option.NewCapabilities()
capabilities.WithDefaultAlertAction(options.AlertActionAccept) capabilities.WithDefaultAlertAction(option.AlertActionAccept)
driver, err = device.NewHTTPDriver(capabilities) driver, err = device.NewHTTPDriver(capabilities)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -46,7 +47,7 @@ func TestViaUSB(t *testing.T) {
func TestInstall(t *testing.T) { func TestInstall(t *testing.T) {
setup(t) setup(t)
err := iOSDriverExt.Install("xxx.ipa", err := iOSDriverExt.Install("xxx.ipa",
options.WithRetryTimes(5)) option.WithRetryTimes(5))
log.Error().Err(err) log.Error().Err(err)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -55,35 +56,35 @@ func TestInstall(t *testing.T) {
func TestNewIOSDevice(t *testing.T) { func TestNewIOSDevice(t *testing.T) {
device, _ := NewIOSDevice( device, _ := NewIOSDevice(
options.WithWDAPort(8700), option.WithWDAPort(8700),
options.WithWDAMjpegPort(8800)) option.WithWDAMjpegPort(8800))
if device != nil { if device != nil {
t.Log(device) t.Log(device)
} }
device, _ = NewIOSDevice(options.WithUDID("xxxx")) device, _ = NewIOSDevice(option.WithUDID("xxxx"))
if device != nil { if device != nil {
t.Log(device) t.Log(device)
} }
device, _ = NewIOSDevice( device, _ = NewIOSDevice(
options.WithWDAPort(8700), option.WithWDAPort(8700),
options.WithWDAMjpegPort(8800)) option.WithWDAMjpegPort(8800))
if device != nil { if device != nil {
t.Log(device) t.Log(device)
} }
device, _ = NewIOSDevice( device, _ = NewIOSDevice(
options.WithUDID("xxxx"), option.WithUDID("xxxx"),
options.WithWDAPort(8700), option.WithWDAPort(8700),
options.WithWDAMjpegPort(8800)) option.WithWDAMjpegPort(8800))
if device != nil { if device != nil {
t.Log(device) t.Log(device)
} }
} }
func TestIOSDevice_GetPackageInfo(t *testing.T) { func TestIOSDevice_GetPackageInfo(t *testing.T) {
device, err := NewIOSDevice(options.WithWDAPort(8700)) device, err := NewIOSDevice(option.WithWDAPort(8700))
checkErr(t, err) checkErr(t, err)
appInfo, err := device.GetPackageInfo("com.ss.iphone.ugc.Aweme") appInfo, err := device.GetPackageInfo("com.ss.iphone.ugc.Aweme")
checkErr(t, err) checkErr(t, err)
@@ -299,7 +300,7 @@ func Test_remoteWD_Drag(t *testing.T) {
// err := driver.Drag(200, 300, 200, 500, WithDataPressDuration(0.5)) // err := driver.Drag(200, 300, 200, 500, WithDataPressDuration(0.5))
err := driver.Drag(200, 300, 200, 500, err := driver.Drag(200, 300, 200, 500,
options.WithPressDuration(2), options.WithDuration(3)) option.WithPressDuration(2), option.WithDuration(3))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -354,7 +355,7 @@ func Test_remoteWD_GetPasteboard(t *testing.T) {
func Test_remoteWD_SendKeys(t *testing.T) { func Test_remoteWD_SendKeys(t *testing.T) {
setup(t) setup(t)
// driver.StartCaptureLog("hrp_wda_log") // driver.StartCaptureLog("hrp_wda_log")
err := driver.SendKeys("test", options.WithIdentifier("test")) err := driver.SendKeys("test", option.WithIdentifier("test"))
// result, _ := driver.StopCaptureLog() // result, _ := driver.StopCaptureLog()
// err := driver.SendKeys("App Store", WithFrequency(3)) // err := driver.SendKeys("App Store", WithFrequency(3))
if err != nil { if err != nil {
+4 -3
View File
@@ -8,8 +8,9 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/httprunner/httprunner/v5/pkg/uixt/options"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
type timeLog struct { type timeLog struct {
@@ -29,8 +30,8 @@ type EndToEndDelay struct {
Timelines []timeLog `json:"timelines"` Timelines []timeLog `json:"timelines"`
} }
func CollectEndToEndDelay(dExt *DriverExt, opts ...options.ActionOption) { func CollectEndToEndDelay(dExt *DriverExt, opts ...option.ActionOption) {
dataOptions := options.NewActionOptions(opts...) dataOptions := option.NewActionOptions(opts...)
startTime := time.Now() startTime := time.Now()
if dataOptions.Interval == 0 { if dataOptions.Interval == 0 {
@@ -1,4 +1,4 @@
package options package option
import ( import (
"math/rand/v2" "math/rand/v2"
@@ -1,4 +1,4 @@
package options package option
type AndroidDeviceConfig struct { type AndroidDeviceConfig struct {
SerialNumber string `json:"serial,omitempty" yaml:"serial,omitempty"` SerialNumber string `json:"serial,omitempty" yaml:"serial,omitempty"`
@@ -1,4 +1,4 @@
package options package option
type AlertAction string type AlertAction string
@@ -1,4 +1,4 @@
package options package option
import "github.com/httprunner/funplugin" import "github.com/httprunner/funplugin"
@@ -1,4 +1,4 @@
package options package option
type HarmonyDeviceConfig struct { type HarmonyDeviceConfig struct {
ConnectKey string `json:"connect_key,omitempty" yaml:"connect_key,omitempty"` ConnectKey string `json:"connect_key,omitempty" yaml:"connect_key,omitempty"`
@@ -1,4 +1,4 @@
package options package option
type InstallOptions struct { type InstallOptions struct {
Reinstall bool Reinstall bool
@@ -1,4 +1,4 @@
package options package option
type IOSDeviceConfig struct { type IOSDeviceConfig struct {
UDID string `json:"udid,omitempty" yaml:"udid,omitempty"` UDID string `json:"udid,omitempty" yaml:"udid,omitempty"`
+8 -8
View File
@@ -5,7 +5,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
// TODO: add more popup texts // TODO: add more popup texts
@@ -31,7 +31,7 @@ func findTextPopup(screenTexts OCRTexts) (closePoint *OCRText) {
continue continue
} }
points, err := screenTexts.FindTexts([]string{popup[0], popup[1]}, options.WithRegex(true)) points, err := screenTexts.FindTexts([]string{popup[0], popup[1]}, option.WithRegex(true))
if err == nil { if err == nil {
log.Warn().Interface("popup", popup). log.Warn().Interface("popup", popup).
Interface("texts", screenTexts).Msg("text popup found") Interface("texts", screenTexts).Msg("text popup found")
@@ -64,9 +64,9 @@ func (dExt *DriverExt) AutoPopupHandler() error {
// check popup by screenshot // check popup by screenshot
screenResult, err := dExt.GetScreenResult( screenResult, err := dExt.GetScreenResult(
options.WithScreenShotOCR(true), option.WithScreenShotOCR(true),
options.WithScreenShotUpload(true), option.WithScreenShotUpload(true),
options.WithScreenShotFileName("check_popup"), option.WithScreenShotFileName("check_popup"),
) )
if err != nil { if err != nil {
return errors.Wrap(err, "get screen result failed for popup handler") return errors.Wrap(err, "get screen result failed for popup handler")
@@ -99,9 +99,9 @@ func (p *PopupInfo) ClosePoint() *PointF {
func (dExt *DriverExt) CheckPopup() (popup *PopupInfo, err error) { func (dExt *DriverExt) CheckPopup() (popup *PopupInfo, err error) {
screenResult, err := dExt.GetScreenResult( screenResult, err := dExt.GetScreenResult(
options.WithScreenShotUpload(true), option.WithScreenShotUpload(true),
options.WithScreenShotClosePopups(true), // get popup area and close area option.WithScreenShotClosePopups(true), // get popup area and close area
options.WithScreenShotFileName("check_popup"), option.WithScreenShotFileName("check_popup"),
) )
if err != nil { if err != nil {
return nil, errors.Wrap(err, "get screen result failed for popup handler") return nil, errors.Wrap(err, "get screen result failed for popup handler")
+15 -15
View File
@@ -18,7 +18,7 @@ import (
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/internal/config" "github.com/httprunner/httprunner/v5/internal/config"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
type ScreenResult struct { type ScreenResult struct {
@@ -37,15 +37,15 @@ func (s *ScreenResult) FilterTextsByScope(x1, y1, x2, y2 float64) OCRTexts {
log.Warn().Msg("x1, y1, x2, y2 should be in percentage, skip filter scope") log.Warn().Msg("x1, y1, x2, y2 should be in percentage, skip filter scope")
return s.Texts return s.Texts
} }
return s.Texts.FilterScope(options.AbsScope{ return s.Texts.FilterScope(option.AbsScope{
int(float64(s.Resolution.Width) * x1), int(float64(s.Resolution.Height) * y1), int(float64(s.Resolution.Width) * x1), int(float64(s.Resolution.Height) * y1),
int(float64(s.Resolution.Width) * x2), int(float64(s.Resolution.Height) * y2), int(float64(s.Resolution.Width) * x2), int(float64(s.Resolution.Height) * y2),
}) })
} }
// GetScreenResult takes a screenshot, returns the image recognition result // GetScreenResult takes a screenshot, returns the image recognition result
func (dExt *DriverExt) GetScreenResult(opts ...options.ActionOption) (screenResult *ScreenResult, err error) { func (dExt *DriverExt) GetScreenResult(opts ...option.ActionOption) (screenResult *ScreenResult, err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if actionOptions.MaxRetryTimes == 0 { if actionOptions.MaxRetryTimes == 0 {
actionOptions.MaxRetryTimes = 1 actionOptions.MaxRetryTimes = 1
} }
@@ -130,12 +130,12 @@ func (dExt *DriverExt) GetScreenResult(opts ...options.ActionOption) (screenResu
return screenResult, nil return screenResult, nil
} }
func (dExt *DriverExt) GetScreenTexts(opts ...options.ActionOption) (ocrTexts OCRTexts, err error) { func (dExt *DriverExt) GetScreenTexts(opts ...option.ActionOption) (ocrTexts OCRTexts, err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if actionOptions.ScreenShotFileName == "" { if actionOptions.ScreenShotFileName == "" {
opts = append(opts, options.WithScreenShotFileName("get_screen_texts")) opts = append(opts, option.WithScreenShotFileName("get_screen_texts"))
} }
opts = append(opts, options.WithScreenShotOCR(true), options.WithScreenShotUpload(true)) opts = append(opts, option.WithScreenShotOCR(true), option.WithScreenShotUpload(true))
screenResult, err := dExt.GetScreenResult(opts...) screenResult, err := dExt.GetScreenResult(opts...)
if err != nil { if err != nil {
return return
@@ -143,7 +143,7 @@ func (dExt *DriverExt) GetScreenTexts(opts ...options.ActionOption) (ocrTexts OC
return screenResult.Texts, nil return screenResult.Texts, nil
} }
func (dExt *DriverExt) FindUIRectInUIKit(search string, opts ...options.ActionOption) (point PointF, err error) { func (dExt *DriverExt) FindUIRectInUIKit(search string, opts ...option.ActionOption) (point PointF, err error) {
// find text using OCR // find text using OCR
if !builtin.IsPathExists(search) { if !builtin.IsPathExists(search) {
return dExt.FindScreenText(search, opts...) return dExt.FindScreenText(search, opts...)
@@ -153,10 +153,10 @@ func (dExt *DriverExt) FindUIRectInUIKit(search string, opts ...options.ActionOp
return return
} }
func (dExt *DriverExt) FindScreenText(text string, opts ...options.ActionOption) (point PointF, err error) { func (dExt *DriverExt) FindScreenText(text string, opts ...option.ActionOption) (point PointF, err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if actionOptions.ScreenShotFileName == "" { if actionOptions.ScreenShotFileName == "" {
opts = append(opts, options.WithScreenShotFileName(fmt.Sprintf("find_screen_text_%s", text))) opts = append(opts, option.WithScreenShotFileName(fmt.Sprintf("find_screen_text_%s", text)))
} }
ocrTexts, err := dExt.GetScreenTexts(opts...) ocrTexts, err := dExt.GetScreenTexts(opts...)
if err != nil { if err != nil {
@@ -175,10 +175,10 @@ func (dExt *DriverExt) FindScreenText(text string, opts ...options.ActionOption)
return return
} }
func (dExt *DriverExt) FindUIResult(opts ...options.ActionOption) (point PointF, err error) { func (dExt *DriverExt) FindUIResult(opts ...option.ActionOption) (point PointF, err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if actionOptions.ScreenShotFileName == "" { if actionOptions.ScreenShotFileName == "" {
opts = append(opts, options.WithScreenShotFileName( opts = append(opts, option.WithScreenShotFileName(
fmt.Sprintf("find_ui_result_%s", strings.Join(actionOptions.ScreenShotWithUITypes, "_")))) fmt.Sprintf("find_ui_result_%s", strings.Join(actionOptions.ScreenShotWithUITypes, "_"))))
} }
+2 -2
View File
@@ -4,11 +4,11 @@ import (
"fmt" "fmt"
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func (dExt *DriverExt) Drag(fromX, fromY, toX, toY float64, opts ...options.ActionOption) (err error) { func (dExt *DriverExt) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionOption) (err error) {
windowSize, err := dExt.Driver.WindowSize() windowSize, err := dExt.Driver.WindowSize()
if err != nil { if err != nil {
return errors.Wrap(code.DeviceGetInfoError, err.Error()) return errors.Wrap(code.DeviceGetInfoError, err.Error())
+22 -22
View File
@@ -10,7 +10,7 @@ import (
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func assertRelative(p float64) bool { func assertRelative(p float64) bool {
@@ -18,7 +18,7 @@ func assertRelative(p float64) bool {
} }
// SwipeRelative swipe from relative position [fromX, fromY] to relative position [toX, toY] // SwipeRelative swipe from relative position [fromX, fromY] to relative position [toX, toY]
func (dExt *DriverExt) SwipeRelative(fromX, fromY, toX, toY float64, opts ...options.ActionOption) error { func (dExt *DriverExt) SwipeRelative(fromX, fromY, toX, toY float64, opts ...option.ActionOption) error {
if !assertRelative(fromX) || !assertRelative(fromY) || if !assertRelative(fromX) || !assertRelative(fromY) ||
!assertRelative(toX) || !assertRelative(toY) { !assertRelative(toX) || !assertRelative(toY) {
return errors.Wrap(code.InvalidCaseError, return errors.Wrap(code.InvalidCaseError,
@@ -44,26 +44,26 @@ func (dExt *DriverExt) SwipeRelative(fromX, fromY, toX, toY float64, opts ...opt
return nil return nil
} }
func (dExt *DriverExt) SwipeUp(opts ...options.ActionOption) (err error) { func (dExt *DriverExt) SwipeUp(opts ...option.ActionOption) (err error) {
return dExt.SwipeRelative(0.5, 0.5, 0.5, 0.1, opts...) return dExt.SwipeRelative(0.5, 0.5, 0.5, 0.1, opts...)
} }
func (dExt *DriverExt) SwipeDown(opts ...options.ActionOption) (err error) { func (dExt *DriverExt) SwipeDown(opts ...option.ActionOption) (err error) {
return dExt.SwipeRelative(0.5, 0.5, 0.5, 0.9, opts...) return dExt.SwipeRelative(0.5, 0.5, 0.5, 0.9, opts...)
} }
func (dExt *DriverExt) SwipeLeft(opts ...options.ActionOption) (err error) { func (dExt *DriverExt) SwipeLeft(opts ...option.ActionOption) (err error) {
return dExt.SwipeRelative(0.5, 0.5, 0.1, 0.5, opts...) return dExt.SwipeRelative(0.5, 0.5, 0.1, 0.5, opts...)
} }
func (dExt *DriverExt) SwipeRight(opts ...options.ActionOption) (err error) { func (dExt *DriverExt) SwipeRight(opts ...option.ActionOption) (err error) {
return dExt.SwipeRelative(0.5, 0.5, 0.9, 0.5, opts...) return dExt.SwipeRelative(0.5, 0.5, 0.9, 0.5, opts...)
} }
type Action func(driver *DriverExt) error type Action func(driver *DriverExt) error
func (dExt *DriverExt) LoopUntil(findAction, findCondition, foundAction Action, opts ...options.ActionOption) error { func (dExt *DriverExt) LoopUntil(findAction, findCondition, foundAction Action, opts ...option.ActionOption) error {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
maxRetryTimes := actionOptions.MaxRetryTimes maxRetryTimes := actionOptions.MaxRetryTimes
interval := actionOptions.Interval interval := actionOptions.Interval
@@ -85,8 +85,8 @@ func (dExt *DriverExt) LoopUntil(findAction, findCondition, foundAction Action,
fmt.Sprintf("loop %d times, match find condition failed", maxRetryTimes)) fmt.Sprintf("loop %d times, match find condition failed", maxRetryTimes))
} }
func (dExt *DriverExt) prepareSwipeAction(params interface{}, opts ...options.ActionOption) func(d *DriverExt) error { func (dExt *DriverExt) prepareSwipeAction(params interface{}, opts ...option.ActionOption) func(d *DriverExt) error {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
var swipeDirection interface{} var swipeDirection interface{}
// priority: params > actionOptions.Direction, default swipe up // priority: params > actionOptions.Direction, default swipe up
@@ -137,22 +137,22 @@ func (dExt *DriverExt) prepareSwipeAction(params interface{}, opts ...options.Ac
} }
} }
func (dExt *DriverExt) swipeToTapTexts(texts []string, opts ...options.ActionOption) error { func (dExt *DriverExt) swipeToTapTexts(texts []string, opts ...option.ActionOption) error {
if len(texts) == 0 { if len(texts) == 0 {
return errors.New("no text to tap") return errors.New("no text to tap")
} }
opts = append(opts, options.WithMatchOne(true), options.WithRegex(true)) opts = append(opts, option.WithMatchOne(true), option.WithRegex(true))
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
actionOptions.Identifier = "" actionOptions.Identifier = ""
optionsWithoutIdentifier := actionOptions.Options() optionsWithoutIdentifier := actionOptions.Options()
var point PointF var point PointF
findTexts := func(d *DriverExt) error { findTexts := func(d *DriverExt) error {
var err error var err error
screenResult, err := d.GetScreenResult( screenResult, err := d.GetScreenResult(
options.WithScreenShotOCR(true), option.WithScreenShotOCR(true),
options.WithScreenShotUpload(true), option.WithScreenShotUpload(true),
options.WithScreenShotFileName( option.WithScreenShotFileName(
fmt.Sprintf("swipe_to_tap_texts_%s", strings.Join(texts, "_")), fmt.Sprintf("swipe_to_tap_texts_%s", strings.Join(texts, "_")),
), ),
) )
@@ -180,7 +180,7 @@ func (dExt *DriverExt) swipeToTapTexts(texts []string, opts ...options.ActionOpt
return dExt.LoopUntil(findAction, findTexts, foundTextAction, optionsWithoutIdentifier...) return dExt.LoopUntil(findAction, findTexts, foundTextAction, optionsWithoutIdentifier...)
} }
func (dExt *DriverExt) swipeToTapApp(appName string, opts ...options.ActionOption) error { func (dExt *DriverExt) swipeToTapApp(appName string, opts ...option.ActionOption) error {
// go to home screen // go to home screen
if err := dExt.Driver.Homescreen(); err != nil { if err := dExt.Driver.Homescreen(); err != nil {
return errors.Wrap(err, "go to home screen failed") return errors.Wrap(err, "go to home screen failed")
@@ -196,20 +196,20 @@ func (dExt *DriverExt) swipeToTapApp(appName string, opts ...options.ActionOptio
dExt.SwipeRight() dExt.SwipeRight()
} }
opts = append(opts, options.WithDirection("left")) opts = append(opts, option.WithDirection("left"))
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
// default to retry 5 times // default to retry 5 times
if actionOptions.MaxRetryTimes == 0 { if actionOptions.MaxRetryTimes == 0 {
opts = append(opts, options.WithMaxRetryTimes(5)) opts = append(opts, option.WithMaxRetryTimes(5))
} }
// tap app icon above the text // tap app icon above the text
if len(actionOptions.Offset) == 0 { if len(actionOptions.Offset) == 0 {
opts = append(opts, options.WithTapOffset(0, -25)) opts = append(opts, option.WithTapOffset(0, -25))
} }
// set default swipe interval to 1 second // set default swipe interval to 1 second
if builtin.IsZeroFloat64(actionOptions.Interval) { if builtin.IsZeroFloat64(actionOptions.Interval) {
opts = append(opts, options.WithInterval(1)) opts = append(opts, option.WithInterval(1))
} }
return dExt.swipeToTapTexts([]string{appName}, opts...) return dExt.swipeToTapTexts([]string{appName}, opts...)
+4 -4
View File
@@ -5,17 +5,17 @@ package uixt
import ( import (
"testing" "testing"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func TestAndroidSwipeAction(t *testing.T) { func TestAndroidSwipeAction(t *testing.T) {
setupAndroidAdbDriver(t) setupAndroidAdbDriver(t)
swipeAction := driverExt.prepareSwipeAction("up", options.WithDirection("down")) swipeAction := driverExt.prepareSwipeAction("up", option.WithDirection("down"))
err := swipeAction(driverExt) err := swipeAction(driverExt)
checkErr(t, err) checkErr(t, err)
swipeAction = driverExt.prepareSwipeAction("up", options.WithCustomDirection(0.5, 0.5, 0.5, 0.9)) swipeAction = driverExt.prepareSwipeAction("up", option.WithCustomDirection(0.5, 0.5, 0.5, 0.9))
err = swipeAction(driverExt) err = swipeAction(driverExt)
checkErr(t, err) checkErr(t, err)
} }
@@ -33,6 +33,6 @@ func TestAndroidSwipeToTapTexts(t *testing.T) {
err := driverExt.Driver.AppLaunch("com.ss.android.ugc.aweme") err := driverExt.Driver.AppLaunch("com.ss.android.ugc.aweme")
checkErr(t, err) checkErr(t, err)
err = driverExt.swipeToTapTexts([]string{"点击进入直播间", "直播中"}, options.WithDirection("up")) err = driverExt.swipeToTapTexts([]string{"点击进入直播间", "直播中"}, option.WithDirection("up"))
checkErr(t, err) checkErr(t, err)
} }
+14 -14
View File
@@ -6,10 +6,10 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func (dExt *DriverExt) TapAbsXY(x, y float64, opts ...options.ActionOption) error { func (dExt *DriverExt) TapAbsXY(x, y float64, opts ...option.ActionOption) error {
// tap on absolute coordinate [x, y] // tap on absolute coordinate [x, y]
err := dExt.Driver.Tap(x, y, opts...) err := dExt.Driver.Tap(x, y, opts...)
if err != nil { if err != nil {
@@ -18,7 +18,7 @@ func (dExt *DriverExt) TapAbsXY(x, y float64, opts ...options.ActionOption) erro
return nil return nil
} }
func (dExt *DriverExt) TapXY(x, y float64, opts ...options.ActionOption) error { func (dExt *DriverExt) TapXY(x, y float64, opts ...option.ActionOption) error {
// tap on [x, y] percent of window size // tap on [x, y] percent of window size
if x > 1 || y > 1 { if x > 1 || y > 1 {
return fmt.Errorf("x, y percentage should be <= 1, got x=%v, y=%v", x, y) return fmt.Errorf("x, y percentage should be <= 1, got x=%v, y=%v", x, y)
@@ -33,10 +33,10 @@ func (dExt *DriverExt) TapXY(x, y float64, opts ...options.ActionOption) error {
return dExt.TapAbsXY(x, y, opts...) return dExt.TapAbsXY(x, y, opts...)
} }
func (dExt *DriverExt) TapByOCR(ocrText string, opts ...options.ActionOption) error { func (dExt *DriverExt) TapByOCR(ocrText string, opts ...option.ActionOption) error {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if actionOptions.ScreenShotFileName == "" { if actionOptions.ScreenShotFileName == "" {
opts = append(opts, options.WithScreenShotFileName(fmt.Sprintf("tap_by_ocr_%s", ocrText))) opts = append(opts, option.WithScreenShotFileName(fmt.Sprintf("tap_by_ocr_%s", ocrText)))
} }
point, err := dExt.FindScreenText(ocrText, opts...) point, err := dExt.FindScreenText(ocrText, opts...)
@@ -50,8 +50,8 @@ func (dExt *DriverExt) TapByOCR(ocrText string, opts ...options.ActionOption) er
return dExt.TapAbsXY(point.X, point.Y, opts...) return dExt.TapAbsXY(point.X, point.Y, opts...)
} }
func (dExt *DriverExt) TapByUIDetection(opts ...options.ActionOption) error { func (dExt *DriverExt) TapByUIDetection(opts ...option.ActionOption) error {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
point, err := dExt.FindUIResult(opts...) point, err := dExt.FindUIResult(opts...)
if err != nil { if err != nil {
@@ -64,12 +64,12 @@ func (dExt *DriverExt) TapByUIDetection(opts ...options.ActionOption) error {
return dExt.TapAbsXY(point.X, point.Y, opts...) return dExt.TapAbsXY(point.X, point.Y, opts...)
} }
func (dExt *DriverExt) Tap(param string, opts ...options.ActionOption) error { func (dExt *DriverExt) Tap(param string, opts ...option.ActionOption) error {
return dExt.TapOffset(param, 0, 0, opts...) return dExt.TapOffset(param, 0, 0, opts...)
} }
func (dExt *DriverExt) TapOffset(param string, xOffset, yOffset float64, opts ...options.ActionOption) (err error) { func (dExt *DriverExt) TapOffset(param string, xOffset, yOffset float64, opts ...option.ActionOption) (err error) {
actionOptions := options.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
point, err := dExt.FindUIRectInUIKit(param, opts...) point, err := dExt.FindUIRectInUIKit(param, opts...)
if err != nil { if err != nil {
@@ -82,7 +82,7 @@ func (dExt *DriverExt) TapOffset(param string, xOffset, yOffset float64, opts ..
return dExt.TapAbsXY(point.X+xOffset, point.Y+yOffset, opts...) return dExt.TapAbsXY(point.X+xOffset, point.Y+yOffset, opts...)
} }
func (dExt *DriverExt) DoubleTapXY(x, y float64, opts ...options.ActionOption) error { func (dExt *DriverExt) DoubleTapXY(x, y float64, opts ...option.ActionOption) error {
// double tap on coordinate: [x, y] should be relative // double tap on coordinate: [x, y] should be relative
if x > 1 || y > 1 { if x > 1 || y > 1 {
return fmt.Errorf("x, y percentage should be < 1, got x=%v, y=%v", x, y) return fmt.Errorf("x, y percentage should be < 1, got x=%v, y=%v", x, y)
@@ -101,11 +101,11 @@ func (dExt *DriverExt) DoubleTapXY(x, y float64, opts ...options.ActionOption) e
return nil return nil
} }
func (dExt *DriverExt) DoubleTap(param string, opts ...options.ActionOption) (err error) { func (dExt *DriverExt) DoubleTap(param string, opts ...option.ActionOption) (err error) {
return dExt.DoubleTapOffset(param, 0, 0, opts...) return dExt.DoubleTapOffset(param, 0, 0, opts...)
} }
func (dExt *DriverExt) DoubleTapOffset(param string, xOffset, yOffset float64, opts ...options.ActionOption) (err error) { func (dExt *DriverExt) DoubleTapOffset(param string, xOffset, yOffset float64, opts ...option.ActionOption) (err error) {
point, err := dExt.FindUIRectInUIKit(param) point, err := dExt.FindUIRectInUIKit(param)
if err != nil { if err != nil {
return err return err
+7 -6
View File
@@ -6,10 +6,11 @@ import (
"strings" "strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
"github.com/rs/zerolog/log"
) )
var uiClients = make(map[string]*uixt.DriverExt) // UI automation clients for iOS and Android, key is udid/serial var uiClients = make(map[string]*uixt.DriverExt) // UI automation clients for iOS and Android, key is udid/serial
@@ -37,8 +38,8 @@ func handleDeviceContext() gin.HandlerFunc {
switch strings.ToLower(platform) { switch strings.ToLower(platform) {
case "android": case "android":
device, err := uixt.NewAndroidDevice( device, err := uixt.NewAndroidDevice(
options.WithSerialNumber(serial), option.WithSerialNumber(serial),
options.WithStub(true)) option.WithStub(true))
if err != nil { if err != nil {
log.Error().Err(err).Str("platform", platform).Str("serial", serial). log.Error().Err(err).Str("platform", platform).Str("serial", serial).
Msg("device not found") Msg("device not found")
@@ -54,8 +55,8 @@ func handleDeviceContext() gin.HandlerFunc {
device.Init() device.Init()
driver, err := device.NewDriver( driver, err := device.NewDriver(
options.WithDriverImageService(true), option.WithDriverImageService(true),
options.WithDriverResultFolder(true)) option.WithDriverResultFolder(true))
if err != nil { if err != nil {
log.Error().Err(err).Str("platform", platform).Str("serial", serial). log.Error().Err(err).Str("platform", platform).Str("serial", serial).
Msg("failed to init driver") Msg("failed to init driver")
+4 -6
View File
@@ -1,8 +1,6 @@
package server package server
import ( import "github.com/httprunner/httprunner/v5/pkg/uixt/option"
"github.com/httprunner/httprunner/v5/pkg/uixt/options"
)
type HttpResponse struct { type HttpResponse struct {
Code int `json:"code"` Code int `json:"code"`
@@ -15,7 +13,7 @@ type TapRequest struct {
Y float64 `json:"y"` Y float64 `json:"y"`
Text string `json:"text"` Text string `json:"text"`
Options *options.ActionOptions `json:"options,omitempty"` Options *option.ActionOptions `json:"options,omitempty"`
} }
type DragRequest struct { type DragRequest struct {
@@ -24,7 +22,7 @@ type DragRequest struct {
ToX float64 `json:"to_x"` ToX float64 `json:"to_x"`
ToY float64 `json:"to_y"` ToY float64 `json:"to_y"`
Options *options.ActionOptions `json:"options,omitempty"` Options *option.ActionOptions `json:"options,omitempty"`
} }
type InputRequest struct { type InputRequest struct {
@@ -33,7 +31,7 @@ type InputRequest struct {
} }
type ScreenRequest struct { type ScreenRequest struct {
Options *options.ActionOptions `json:"options,omitempty"` Options *option.ActionOptions `json:"options,omitempty"`
} }
type KeycodeRequest struct { type KeycodeRequest struct {
+4 -3
View File
@@ -6,10 +6,11 @@ import (
"net/http" "net/http"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
"github.com/rs/zerolog/log"
) )
func screenshotHandler(c *gin.Context) { func screenshotHandler(c *gin.Context) {
@@ -52,7 +53,7 @@ func screenResultHandler(c *gin.Context) {
return return
} }
var actionOptions []options.ActionOption var actionOptions []option.ActionOption
if screenReq.Options != nil { if screenReq.Options != nil {
actionOptions = screenReq.Options.Options() actionOptions = screenReq.Options.Options()
} }
+6 -5
View File
@@ -5,9 +5,10 @@ import (
"net/http" "net/http"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/pkg/uixt/options"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func tapHandler(c *gin.Context) { func tapHandler(c *gin.Context) {
@@ -22,7 +23,7 @@ func tapHandler(c *gin.Context) {
return return
} }
var actionOptions []options.ActionOption var actionOptions []option.ActionOption
if tapReq.Options != nil { if tapReq.Options != nil {
actionOptions = tapReq.Options.Options() actionOptions = tapReq.Options.Options()
} }
@@ -82,7 +83,7 @@ func dragHandler(c *gin.Context) {
return return
} }
var actionOptions []options.ActionOption var actionOptions []option.ActionOption
if dragReq.Options != nil { if dragReq.Options != nil {
actionOptions = dragReq.Options.Options() actionOptions = dragReq.Options.Options()
} }
@@ -140,7 +141,7 @@ func inputHandler(c *gin.Context) {
} }
err = dExt.Driver.SendKeys(inputReq.Text, err = dExt.Driver.SendKeys(inputReq.Text,
options.WithFrequency(inputReq.Frequency)) option.WithFrequency(inputReq.Frequency))
if err != nil { if err != nil {
log.Err(err).Msg(fmt.Sprintf("[%s]: failed to input text %s", c.HandlerName(), inputReq.Text)) log.Err(err).Msg(fmt.Sprintf("[%s]: failed to input text %s", c.HandlerName(), inputReq.Text))
c.JSON(http.StatusInternalServerError, c.JSON(http.StatusInternalServerError,
+43 -43
View File
@@ -11,7 +11,7 @@ import (
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/internal/sdk" "github.com/httprunner/httprunner/v5/internal/sdk"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
type MobileUI struct { type MobileUI struct {
@@ -104,11 +104,11 @@ func (s *StepMobile) Home() *StepMobile {
} }
// TapXY taps the point {X,Y}, X & Y is percentage of coordinates // TapXY taps the point {X,Y}, X & Y is percentage of coordinates
func (s *StepMobile) TapXY(x, y float64, opts ...options.ActionOption) *StepMobile { func (s *StepMobile) TapXY(x, y float64, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_TapXY, Method: uixt.ACTION_TapXY,
Params: []float64{x, y}, Params: []float64{x, y},
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
@@ -116,11 +116,11 @@ func (s *StepMobile) TapXY(x, y float64, opts ...options.ActionOption) *StepMobi
} }
// TapAbsXY taps the point {X,Y}, X & Y is absolute coordinates // TapAbsXY taps the point {X,Y}, X & Y is absolute coordinates
func (s *StepMobile) TapAbsXY(x, y float64, opts ...options.ActionOption) *StepMobile { func (s *StepMobile) TapAbsXY(x, y float64, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_TapAbsXY, Method: uixt.ACTION_TapAbsXY,
Params: []float64{x, y}, Params: []float64{x, y},
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
@@ -128,11 +128,11 @@ func (s *StepMobile) TapAbsXY(x, y float64, opts ...options.ActionOption) *StepM
} }
// Tap taps on the target element // Tap taps on the target element
func (s *StepMobile) Tap(params string, opts ...options.ActionOption) *StepMobile { func (s *StepMobile) Tap(params string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Tap, Method: uixt.ACTION_Tap,
Params: params, Params: params,
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
@@ -140,11 +140,11 @@ func (s *StepMobile) Tap(params string, opts ...options.ActionOption) *StepMobil
} }
// TapByOCR taps on the target element by OCR recognition // TapByOCR taps on the target element by OCR recognition
func (s *StepMobile) TapByOCR(ocrText string, opts ...options.ActionOption) *StepMobile { func (s *StepMobile) TapByOCR(ocrText string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_TapByOCR, Method: uixt.ACTION_TapByOCR,
Params: ocrText, Params: ocrText,
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
@@ -152,11 +152,11 @@ func (s *StepMobile) TapByOCR(ocrText string, opts ...options.ActionOption) *Ste
} }
// TapByCV taps on the target element by CV recognition // TapByCV taps on the target element by CV recognition
func (s *StepMobile) TapByCV(imagePath string, opts ...options.ActionOption) *StepMobile { func (s *StepMobile) TapByCV(imagePath string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_TapByCV, Method: uixt.ACTION_TapByCV,
Params: imagePath, Params: imagePath,
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
@@ -164,10 +164,10 @@ func (s *StepMobile) TapByCV(imagePath string, opts ...options.ActionOption) *St
} }
// TapByUITypes taps on the target element specified by uiTypes, the higher the uiTypes, the higher the priority // TapByUITypes taps on the target element specified by uiTypes, the higher the uiTypes, the higher the priority
func (s *StepMobile) TapByUITypes(opts ...options.ActionOption) *StepMobile { func (s *StepMobile) TapByUITypes(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_TapByCV, Method: uixt.ACTION_TapByCV,
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
@@ -175,31 +175,31 @@ func (s *StepMobile) TapByUITypes(opts ...options.ActionOption) *StepMobile {
} }
// DoubleTapXY double taps the point {X,Y}, X & Y is percentage of coordinates // DoubleTapXY double taps the point {X,Y}, X & Y is percentage of coordinates
func (s *StepMobile) DoubleTapXY(x, y float64, opts ...options.ActionOption) *StepMobile { func (s *StepMobile) DoubleTapXY(x, y float64, opts ...option.ActionOption) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{ s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_DoubleTapXY, Method: uixt.ACTION_DoubleTapXY,
Params: []float64{x, y}, Params: []float64{x, y},
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
}) })
return s return s
} }
func (s *StepMobile) DoubleTap(params string, opts ...options.ActionOption) *StepMobile { func (s *StepMobile) DoubleTap(params string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_DoubleTap, Method: uixt.ACTION_DoubleTap,
Params: params, Params: params,
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
return s return s
} }
func (s *StepMobile) Back(opts ...options.ActionOption) *StepMobile { func (s *StepMobile) Back(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Back, Method: uixt.ACTION_Back,
Params: nil, Params: nil,
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
@@ -207,99 +207,99 @@ func (s *StepMobile) Back(opts ...options.ActionOption) *StepMobile {
} }
// Swipe drags from [sx, sy] to [ex, ey] // Swipe drags from [sx, sy] to [ex, ey]
func (s *StepMobile) Swipe(sx, sy, ex, ey float64, opts ...options.ActionOption) *StepMobile { func (s *StepMobile) Swipe(sx, sy, ex, ey float64, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Swipe, Method: uixt.ACTION_Swipe,
Params: []float64{sx, sy, ex, ey}, Params: []float64{sx, sy, ex, ey},
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
return s return s
} }
func (s *StepMobile) SwipeUp(opts ...options.ActionOption) *StepMobile { func (s *StepMobile) SwipeUp(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Swipe, Method: uixt.ACTION_Swipe,
Params: "up", Params: "up",
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
return s return s
} }
func (s *StepMobile) SwipeDown(opts ...options.ActionOption) *StepMobile { func (s *StepMobile) SwipeDown(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Swipe, Method: uixt.ACTION_Swipe,
Params: "down", Params: "down",
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
return s return s
} }
func (s *StepMobile) SwipeLeft(opts ...options.ActionOption) *StepMobile { func (s *StepMobile) SwipeLeft(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Swipe, Method: uixt.ACTION_Swipe,
Params: "left", Params: "left",
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
return s return s
} }
func (s *StepMobile) SwipeRight(opts ...options.ActionOption) *StepMobile { func (s *StepMobile) SwipeRight(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Swipe, Method: uixt.ACTION_Swipe,
Params: "right", Params: "right",
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
return s return s
} }
func (s *StepMobile) SwipeToTapApp(appName string, opts ...options.ActionOption) *StepMobile { func (s *StepMobile) SwipeToTapApp(appName string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_SwipeToTapApp, Method: uixt.ACTION_SwipeToTapApp,
Params: appName, Params: appName,
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
return s return s
} }
func (s *StepMobile) SwipeToTapText(text string, opts ...options.ActionOption) *StepMobile { func (s *StepMobile) SwipeToTapText(text string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_SwipeToTapText, Method: uixt.ACTION_SwipeToTapText,
Params: text, Params: text,
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
return s return s
} }
func (s *StepMobile) SwipeToTapTexts(texts interface{}, opts ...options.ActionOption) *StepMobile { func (s *StepMobile) SwipeToTapTexts(texts interface{}, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_SwipeToTapTexts, Method: uixt.ACTION_SwipeToTapTexts,
Params: texts, Params: texts,
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
return s return s
} }
func (s *StepMobile) Input(text string, opts ...options.ActionOption) *StepMobile { func (s *StepMobile) Input(text string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Input, Method: uixt.ACTION_Input,
Params: text, Params: text,
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
s.obj().Actions = append(s.obj().Actions, action) s.obj().Actions = append(s.obj().Actions, action)
@@ -352,20 +352,20 @@ func (s *StepMobile) SleepRandom(params ...float64) *StepMobile {
return s return s
} }
func (s *StepMobile) EndToEndDelay(opts ...options.ActionOption) *StepMobile { func (s *StepMobile) EndToEndDelay(opts ...option.ActionOption) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{ s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_EndToEndDelay, Method: uixt.ACTION_EndToEndDelay,
Params: nil, Params: nil,
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
}) })
return s return s
} }
func (s *StepMobile) ScreenShot(opts ...options.ActionOption) *StepMobile { func (s *StepMobile) ScreenShot(opts ...option.ActionOption) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{ s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_ScreenShot, Method: uixt.ACTION_ScreenShot,
Params: nil, Params: nil,
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
}) })
return s return s
} }
@@ -393,11 +393,11 @@ func (s *StepMobile) DisableAutoPopupHandler() *StepMobile {
return s return s
} }
func (s *StepMobile) ClosePopups(opts ...options.ActionOption) *StepMobile { func (s *StepMobile) ClosePopups(opts ...option.ActionOption) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{ s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_ClosePopups, Method: uixt.ACTION_ClosePopups,
Params: nil, Params: nil,
Options: options.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
}) })
return s return s
} }
+3 -3
View File
@@ -5,13 +5,13 @@ package hrp
import ( import (
"testing" "testing"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func TestIOSSettingsAction(t *testing.T) { func TestIOSSettingsAction(t *testing.T) {
testCase := &TestCase{ testCase := &TestCase{
Config: NewConfig("ios ui action on Settings"). Config: NewConfig("ios ui action on Settings").
SetIOS(options.WithWDAPort(8700), options.WithWDAMjpegPort(8800)), SetIOS(option.WithWDAPort(8700), option.WithWDAMjpegPort(8800)),
TestSteps: []IStep{ TestSteps: []IStep{
NewStep("launch Settings"). NewStep("launch Settings").
IOS().Home().Tap("设置"). IOS().Home().Tap("设置").
@@ -50,7 +50,7 @@ func TestIOSSearchApp(t *testing.T) {
func TestIOSAppLaunch(t *testing.T) { func TestIOSAppLaunch(t *testing.T) {
testCase := &TestCase{ testCase := &TestCase{
Config: NewConfig("启动 & 关闭 App"). Config: NewConfig("启动 & 关闭 App").
SetIOS(options.WithWDAPort(8700), options.WithWDAMjpegPort(8800)), SetIOS(option.WithWDAPort(8700), option.WithWDAMjpegPort(8800)),
TestSteps: []IStep{ TestSteps: []IStep{
NewStep("终止今日头条"). NewStep("终止今日头条").
IOS().AppTerminate("com.ss.iphone.article.News"), IOS().AppTerminate("com.ss.iphone.article.News"),
+7 -7
View File
@@ -24,7 +24,7 @@ import (
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/internal/json" "github.com/httprunner/httprunner/v5/internal/json"
"github.com/httprunner/httprunner/v5/pkg/httpstat" "github.com/httprunner/httprunner/v5/pkg/httpstat"
"github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
type HTTPMethod string type HTTPMethod string
@@ -759,8 +759,8 @@ func (s *StepRequest) MobileUI() *StepMobile {
} }
// Android creates a new android step session // Android creates a new android step session
func (s *StepRequest) Android(opts ...options.AndroidDeviceOption) *StepMobile { func (s *StepRequest) Android(opts ...option.AndroidDeviceOption) *StepMobile {
androidOptions := options.NewAndroidDeviceConfig(opts...) androidOptions := option.NewAndroidDeviceConfig(opts...)
return &StepMobile{ return &StepMobile{
StepConfig: s.StepConfig, StepConfig: s.StepConfig,
Android: &MobileUI{ Android: &MobileUI{
@@ -770,8 +770,8 @@ func (s *StepRequest) Android(opts ...options.AndroidDeviceOption) *StepMobile {
} }
// IOS creates a new ios step session // IOS creates a new ios step session
func (s *StepRequest) IOS(opts ...options.IOSDeviceOption) *StepMobile { func (s *StepRequest) IOS(opts ...option.IOSDeviceOption) *StepMobile {
iosOptions := options.NewIOSDeviceConfig(opts...) iosOptions := option.NewIOSDeviceConfig(opts...)
return &StepMobile{ return &StepMobile{
StepConfig: s.StepConfig, StepConfig: s.StepConfig,
IOS: &MobileUI{ IOS: &MobileUI{
@@ -781,8 +781,8 @@ func (s *StepRequest) IOS(opts ...options.IOSDeviceOption) *StepMobile {
} }
// Harmony creates a new harmony step session // Harmony creates a new harmony step session
func (s *StepRequest) Harmony(opts ...options.HarmonyDeviceOption) *StepMobile { func (s *StepRequest) Harmony(opts ...option.HarmonyDeviceOption) *StepMobile {
harmonyOptions := options.NewHarmonyDeviceConfig(opts...) harmonyOptions := option.NewHarmonyDeviceConfig(opts...)
return &StepMobile{ return &StepMobile{
StepConfig: s.StepConfig, StepConfig: s.StepConfig,
Harmony: &MobileUI{ Harmony: &MobileUI{