refactor: XTDriver

This commit is contained in:
lilong.129
2025-02-11 11:48:36 +08:00
parent 3cb2eac442
commit c097461987
29 changed files with 194 additions and 174 deletions
+2 -2
View File
@@ -41,13 +41,13 @@ var installCmd = &cobra.Command{
fmt.Println(err) fmt.Println(err)
return err return err
} }
driverExt, err := device.NewDriver() driver, err := device.NewDriver()
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return err return err
} }
err = driverExt.GetDriver().GetDevice().Install(args[0], err = driver.GetDevice().Install(args[0],
option.WithReinstall(replace), option.WithReinstall(replace),
option.WithDowngrade(downgrade), option.WithDowngrade(downgrade),
option.WithGrantPermission(grant), option.WithGrantPermission(grant),
+11 -9
View File
@@ -28,46 +28,48 @@ func init() {
fmt.Printf("=== start running cases, serial=%s, runTimes=%d ===\n", serial, runTimes) fmt.Printf("=== start running cases, serial=%s, runTimes=%d ===\n", serial, runTimes)
} }
func launchAppDriver(pkgName string) (driver uixt.IDriverExt, err error) { func launchAppDriver(pkgName string) (driverExt *uixt.XTDriver, err error) {
device, _ := uixt.NewAndroidDevice(option.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
} }
_, err = driver.GetDriver().AppTerminate(pkgName) _, err = driver.AppTerminate(pkgName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = driver.GetDriver().Homescreen() err = driver.Homescreen()
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = driver.GetDriver().AppLaunch(pkgName) err = driver.AppLaunch(pkgName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
time.Sleep(15 * time.Second) time.Sleep(15 * time.Second)
driverExt = uixt.NewXTDriver(driver)
// 处理弹窗 // 处理弹窗
err = driver.ClosePopupsHandler() err = driverExt.ClosePopupsHandler()
if err != nil { if err != nil {
return nil, err return nil, err
} }
// 进入推荐页 // 进入推荐页
err = driver.TapByOCR("推荐", option.WithScope(0, 0, 1, 0.3)) err = driverExt.TapByOCR("推荐", option.WithScope(0, 0, 1, 0.3))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return driver, nil return driverExt, nil
} }
func watchVideo(driver uixt.IDriverExt) (err error) { func watchVideo(driver *uixt.XTDriver) (err error) {
time.Sleep(3 * time.Second) time.Sleep(3 * time.Second)
err = driver.SwipeRelative(0.7, 0.7, 0.7, 0.2) err = driver.SwipeRelative(0.7, 0.7, 0.7, 0.2)
if err != nil { if err != nil {
+10 -6
View File
@@ -7,6 +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/ai"
"github.com/httprunner/httprunner/v5/pkg/uixt/option" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
@@ -28,9 +29,9 @@ func init() {
fmt.Printf("=== start running cases, serial=%s, runTimes=%d ===\n", serial, runTimes) fmt.Printf("=== start running cases, serial=%s, runTimes=%d ===\n", serial, runTimes)
} }
func launchAppDriver(pkgName string) (driver uixt.IDriverExt, err error) { func launchAppDriver(pkgName string) (driverExt *uixt.XTDriver, err error) {
device, _ := uixt.NewIOSDevice(option.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
} }
@@ -52,22 +53,25 @@ func launchAppDriver(pkgName string) (driver uixt.IDriverExt, err error) {
time.Sleep(15 * time.Second) time.Sleep(15 * time.Second)
driverExt = uixt.NewXTDriver(driver,
ai.WithCVService(ai.CVServiceTypeVEDEM))
// 处理弹窗 // 处理弹窗
err = driver.ClosePopupsHandler() err = driverExt.ClosePopupsHandler()
if err != nil { if err != nil {
return nil, err return nil, err
} }
// 进入推荐页 // 进入推荐页
err = driver.TapByOCR("推荐", option.WithScope(0, 0, 1, 0.3)) err = driverExt.TapByOCR("推荐", option.WithScope(0, 0, 1, 0.3))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return driver, nil return driverExt, nil
} }
func watchVideo(driver uixt.IDriverExt) (err error) { func watchVideo(driver *uixt.XTDriver) (err error) {
time.Sleep(3 * time.Second) time.Sleep(3 * time.Second)
err = driver.SwipeRelative(0.7, 0.7, 0.7, 0.2) err = driver.SwipeRelative(0.7, 0.7, 0.7, 0.2)
if err != nil { if err != nil {
+1 -4
View File
@@ -39,12 +39,9 @@ var rootCmd = &cobra.Command{
return errors.New("android or ios app bundldID is required") return errors.New("android or ios app bundldID is required")
} }
driverExt, err := uixt.NewDriverExt(driver, driverExt := uixt.NewXTDriver(driver,
ai.WithCVService(ai.CVServiceTypeVEDEM), ai.WithCVService(ai.CVServiceTypeVEDEM),
) )
if err != nil {
return err
}
wc := NewWorldCupLive(driverExt, matchName, bundleID, duration, interval) wc := NewWorldCupLive(driverExt, matchName, bundleID, duration, interval)
+8 -6
View File
@@ -37,7 +37,7 @@ func convertTimeToSeconds(timeStr string) (int, error) {
return seconds, nil return seconds, nil
} }
func initIOSDriver(uuid string) uixt.IDriverExt { func initIOSDriver(uuid string) *uixt.XTDriver {
device, err := uixt.NewIOSDevice( device, err := uixt.NewIOSDevice(
option.WithUDID(uuid), option.WithUDID(uuid),
option.WithWDAPort(8700), option.WithWDAMjpegPort(8800), option.WithWDAPort(8700), option.WithWDAMjpegPort(8800),
@@ -48,16 +48,18 @@ func initIOSDriver(uuid string) uixt.IDriverExt {
log.Fatal().Err(err).Msg("failed to init ios device") log.Fatal().Err(err).Msg("failed to init ios device")
} }
driver, _ := device.NewDriver() driver, _ := device.NewDriver()
return driver driverExt := uixt.NewXTDriver(driver)
return driverExt
} }
func initAndroidDriver(uuid string) uixt.IDriverExt { func initAndroidDriver(uuid string) *uixt.XTDriver {
device, err := uixt.NewAndroidDevice(option.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")
} }
driver, _ := device.NewDriver() driver, _ := device.NewDriver()
return driver driverExt := uixt.NewXTDriver(driver)
return driverExt
} }
type timeLog struct { type timeLog struct {
@@ -68,7 +70,7 @@ type timeLog struct {
} }
type WorldCupLive struct { type WorldCupLive struct {
driver uixt.IDriverExt driver *uixt.XTDriver
file *os.File file *os.File
resultDir string resultDir string
MatchName string `json:"matchName"` MatchName string `json:"matchName"`
@@ -81,7 +83,7 @@ type WorldCupLive struct {
PerfFile string `json:"perf"` PerfFile string `json:"perf"`
} }
func NewWorldCupLive(driver uixt.IDriverExt, matchName, bundleID string, duration, interval int) *WorldCupLive { func NewWorldCupLive(driver *uixt.XTDriver, matchName, bundleID string, duration, interval int) *WorldCupLive {
if matchName == "" { if matchName == "" {
matchName = "unknown-match" matchName = "unknown-match"
} }
+1 -1
View File
@@ -1 +1 @@
v5.0.0+2502102239 v5.0.0+2502111148
+3 -10
View File
@@ -24,7 +24,6 @@ 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/ai"
"github.com/httprunner/httprunner/v5/pkg/uixt/option" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
"github.com/httprunner/httprunner/v5/pkg/uixt/types" "github.com/httprunner/httprunner/v5/pkg/uixt/types"
) )
@@ -149,8 +148,7 @@ func (dev *AndroidDevice) LogEnabled() bool {
return dev.Options.LogOn return dev.Options.LogOn
} }
func (dev *AndroidDevice) NewDriver() (driverExt IDriverExt, err error) { func (dev *AndroidDevice) NewDriver() (driver IDriver, err error) {
var driver IDriver
if dev.Options.UIA2 || dev.Options.LogOn { if dev.Options.UIA2 || dev.Options.LogOn {
driver, err = NewUIA2Driver(dev) driver, err = NewUIA2Driver(dev)
} else { } else {
@@ -166,16 +164,11 @@ func (dev *AndroidDevice) NewDriver() (driverExt IDriverExt, err error) {
return nil, err return nil, err
} }
} }
driverExt, err = NewDriverExt(driver, ai.WithCVService(ai.CVServiceTypeVEDEM))
if err != nil {
return nil, errors.Wrap(err, "init android driver ext failed")
}
// setup driver // setup driver
if err := driverExt.GetDriver().Setup(); err != nil { if err := driver.Setup(); err != nil {
return nil, err return nil, err
} }
return driverExt, nil return driver, nil
} }
func (dev *AndroidDevice) StartPerf() error { func (dev *AndroidDevice) StartPerf() error {
+14 -9
View File
@@ -9,19 +9,22 @@ import (
"time" "time"
"github.com/httprunner/httprunner/v5/internal/builtin" "github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/pkg/uixt/ai"
"github.com/httprunner/httprunner/v5/pkg/uixt/option" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
"github.com/httprunner/httprunner/v5/pkg/uixt/types" "github.com/httprunner/httprunner/v5/pkg/uixt/types"
) )
var driverExt IDriverExt var driverExt *XTDriver
func setupAndroidAdbDriver(t *testing.T) { func setupAndroidAdbDriver(t *testing.T) {
device, err := NewAndroidDevice() device, err := NewAndroidDevice()
checkErr(t, err) checkErr(t, err)
device.Options.UIA2 = false device.Options.UIA2 = false
device.Options.LogOn = false device.Options.LogOn = false
driverExt, err = device.NewDriver() driver, err = device.NewDriver()
checkErr(t, err) checkErr(t, err)
driverExt = NewXTDriver(driver,
ai.WithCVService(ai.CVServiceTypeVEDEM))
} }
func setupAndroidUIA2Driver(t *testing.T) { func setupAndroidUIA2Driver(t *testing.T) {
@@ -29,8 +32,10 @@ func setupAndroidUIA2Driver(t *testing.T) {
checkErr(t, err) checkErr(t, err)
device.Options.UIA2 = true device.Options.UIA2 = true
device.Options.LogOn = false device.Options.LogOn = false
driverExt, err = device.NewDriver() driver, err = device.NewDriver()
checkErr(t, err) checkErr(t, err)
driverExt = NewXTDriver(driver,
ai.WithCVService(ai.CVServiceTypeVEDEM))
} }
func TestAndroidDevice_GetPackageInfo(t *testing.T) { func TestAndroidDevice_GetPackageInfo(t *testing.T) {
@@ -252,12 +257,12 @@ func TestDriver_AppLaunch(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
err = driver.GetDriver().AppLaunch("com.android.settings") err = driver.AppLaunch("com.android.settings")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
raw, err := driver.GetDriver().Screenshot() raw, err := driver.Screenshot()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -305,19 +310,19 @@ func TestDriver_KeepAlive(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
err = driver.GetDriver().AppLaunch("com.android.settings") err = driver.AppLaunch("com.android.settings")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
_, err = driver.GetDriver().Screenshot() _, err = driver.Screenshot()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
time.Sleep(60 * time.Second) time.Sleep(60 * time.Second)
_, err = driver.GetDriver().Screenshot() _, err = driver.Screenshot()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -330,7 +335,7 @@ func TestDriver_AppTerminate(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
_, err = driver.GetDriver().AppTerminate("tv.danmaku.bili") _, err = driver.AppTerminate("tv.danmaku.bili")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
+5 -1
View File
@@ -9,6 +9,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/ai"
"github.com/httprunner/httprunner/v5/pkg/uixt/option" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
@@ -22,10 +23,13 @@ func TestIOSDemo(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
driverExt, err := device.NewDriver() driver, err := device.NewDriver()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
driverExt := uixt.NewXTDriver(driver,
ai.WithCVService(ai.CVServiceTypeVEDEM),
)
// release session // release session
defer func() { defer func() {
+37 -24
View File
@@ -147,6 +147,37 @@ type IDriver interface {
TearDown() error TearDown() error
} }
func NewXTDriver(driver IDriver, opts ...ai.AIServiceOption) *XTDriver {
services := ai.NewAIService(opts...)
driverExt := &XTDriver{
Driver: driver,
CVService: services.ICVService,
LLMService: services.ILLMService,
}
return driverExt
}
func NewDriverExt(driver IDriver, opts ...ai.AIServiceOption) (*XTDriver, error) {
services := ai.NewAIService(opts...)
driverExt := &XTDriver{
Driver: driver,
CVService: services.ICVService,
LLMService: services.ILLMService,
}
// create results directory
// TODO: move to setup
if err := builtin.EnsureFolderExists(config.ResultsPath); err != nil {
return nil, errors.Wrap(err, "create results directory failed")
}
if err := builtin.EnsureFolderExists(config.ScreenShotsPath); err != nil {
return nil, errors.Wrap(err, "create screenshots directory failed")
}
return driverExt, nil
}
var _ IDriverExt = (*XTDriver)(nil)
// XTDriver = IDriver + AI
type IDriverExt interface { type IDriverExt interface {
GetDriver() IDriver // get original driver GetDriver() IDriver // get original driver
@@ -176,35 +207,17 @@ type IDriverExt interface {
DoValidation(check, assert, expected string, message ...string) (err error) DoValidation(check, assert, expected string, message ...string) (err error)
} }
func NewDriverExt(driver IDriver, opts ...ai.AIServiceOption) (IDriverExt, error) { type XTDriver struct {
services := ai.NewAIService(opts...)
driverExt := &DriverExt{
Driver: driver,
CVService: services.ICVService,
LLMService: services.ILLMService,
}
// create results directory
// TODO: move to setup
if err := builtin.EnsureFolderExists(config.ResultsPath); err != nil {
return nil, errors.Wrap(err, "create results directory failed")
}
if err := builtin.EnsureFolderExists(config.ScreenShotsPath); err != nil {
return nil, errors.Wrap(err, "create screenshots directory failed")
}
return driverExt, nil
}
type DriverExt struct {
Driver IDriver Driver IDriver
CVService ai.ICVService // OCR/CV CVService ai.ICVService // OCR/CV
LLMService ai.ILLMService // LLM LLMService ai.ILLMService // LLM
} }
func (dExt *DriverExt) GetDriver() IDriver { func (dExt *XTDriver) GetDriver() IDriver {
return dExt.Driver return dExt.Driver
} }
func (dExt *DriverExt) Setup() error { func (dExt *XTDriver) Setup() error {
// unlock device screen // unlock device screen
err := dExt.Driver.Unlock() err := dExt.Driver.Unlock()
if err != nil { if err != nil {
@@ -215,7 +228,7 @@ func (dExt *DriverExt) Setup() error {
return nil return nil
} }
func (dExt *DriverExt) assertOCR(text, assert string) error { func (dExt *XTDriver) assertOCR(text, assert string) error {
var opts []option.ActionOption var opts []option.ActionOption
opts = append(opts, option.WithScreenShotFileName(fmt.Sprintf("assert_ocr_%s", text))) opts = append(opts, option.WithScreenShotFileName(fmt.Sprintf("assert_ocr_%s", text)))
@@ -248,7 +261,7 @@ func (dExt *DriverExt) assertOCR(text, assert string) error {
return nil return nil
} }
func (dExt *DriverExt) assertForegroundApp(appName, assert string) (err error) { func (dExt *XTDriver) assertForegroundApp(appName, assert string) (err error) {
err = dExt.Driver.AssertForegroundApp(appName) err = dExt.Driver.AssertForegroundApp(appName)
switch assert { switch assert {
case AssertionEqual: case AssertionEqual:
@@ -265,7 +278,7 @@ func (dExt *DriverExt) assertForegroundApp(appName, assert string) (err error) {
return nil return nil
} }
func (dExt *DriverExt) DoValidation(check, assert, expected string, message ...string) (err error) { func (dExt *XTDriver) DoValidation(check, assert, expected string, message ...string) (err error) {
switch check { switch check {
case SelectorOCR: case SelectorOCR:
err = dExt.assertOCR(expected, assert) err = dExt.assertOCR(expected, assert)
+3 -3
View File
@@ -103,7 +103,7 @@ type TapTextAction struct {
Options []option.ActionOption Options []option.ActionOption
} }
func (dExt *DriverExt) ParseActionOptions(opts ...option.ActionOption) []option.ActionOption { func (dExt *XTDriver) ParseActionOptions(opts ...option.ActionOption) []option.ActionOption {
actionOptions := option.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
// convert relative scope to absolute scope // convert relative scope to absolute scope
@@ -116,7 +116,7 @@ func (dExt *DriverExt) ParseActionOptions(opts ...option.ActionOption) []option.
return actionOptions.Options() return actionOptions.Options()
} }
func (dExt *DriverExt) GenAbsScope(x1, y1, x2, y2 float64) option.AbsScope { func (dExt *XTDriver) 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))
@@ -126,7 +126,7 @@ func (dExt *DriverExt) GenAbsScope(x1, y1, x2, y2 float64) option.AbsScope {
return option.AbsScope{absX1, absY1, absX2, absY2} return option.AbsScope{absX1, absY1, absX2, absY2}
} }
func (dExt *DriverExt) DoAction(action MobileAction) (err error) { func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
actionStartTime := time.Now() actionStartTime := time.Now()
defer func() { defer func() {
var logger *zerolog.Event var logger *zerolog.Event
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func (dExt *DriverExt) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionOption) (err error) { func (dExt *XTDriver) 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())
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/code"
) )
func (dExt *DriverExt) Input(text string) (err error) { func (dExt *XTDriver) Input(text string) (err error) {
err = dExt.Driver.Input(text) err = dExt.Driver.Input(text)
if err != nil { if err != nil {
return errors.Wrap(code.MobileUIInputError, err.Error()) return errors.Wrap(code.MobileUIInputError, err.Error())
+3 -3
View File
@@ -18,7 +18,7 @@ type InstallResult struct {
ErrorMsg string `json:"errorMsg"` ErrorMsg string `json:"errorMsg"`
} }
func (dExt *DriverExt) InstallByUrl(url string, opts ...option.InstallOption) error { func (dExt *XTDriver) 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 ...option.InstallOption) er
return nil return nil
} }
func (dExt *DriverExt) Install(filePath string, opts ...option.InstallOption) error { func (dExt *XTDriver) Install(filePath string, opts ...option.InstallOption) error {
if _, ok := dExt.Driver.GetDevice().(*AndroidDevice); ok { if _, ok := dExt.Driver.GetDevice().(*AndroidDevice); ok {
stopChan := make(chan struct{}) stopChan := make(chan struct{})
go func() { go func() {
@@ -90,7 +90,7 @@ func (dExt *DriverExt) Install(filePath string, opts ...option.InstallOption) er
return dExt.Driver.GetDevice().Install(filePath, opts...) return dExt.Driver.GetDevice().Install(filePath, opts...)
} }
func (dExt *DriverExt) Uninstall(packageName string, opts ...option.ActionOption) error { func (dExt *XTDriver) Uninstall(packageName string, opts ...option.ActionOption) error {
actionOptions := option.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
err := dExt.Driver.GetDevice().Uninstall(packageName) err := dExt.Driver.GetDevice().Uninstall(packageName)
if err != nil { if err != nil {
+4 -4
View File
@@ -43,7 +43,7 @@ func findTextPopup(screenTexts ai.OCRTexts) (closePoint *ai.OCRText) {
return return
} }
func (dExt *DriverExt) handleTextPopup(screenTexts ai.OCRTexts) error { func (dExt *XTDriver) handleTextPopup(screenTexts ai.OCRTexts) error {
closePoint := findTextPopup(screenTexts) closePoint := findTextPopup(screenTexts)
if closePoint == nil { if closePoint == nil {
// no popup found // no popup found
@@ -60,7 +60,7 @@ func (dExt *DriverExt) handleTextPopup(screenTexts ai.OCRTexts) error {
return nil return nil
} }
func (dExt *DriverExt) AutoPopupHandler() error { func (dExt *XTDriver) AutoPopupHandler() error {
// TODO: check popup by activity type // TODO: check popup by activity type
// check popup by screenshot // check popup by screenshot
@@ -98,7 +98,7 @@ func (p *PopupInfo) ClosePoint() *ai.PointF {
return &closePoint return &closePoint
} }
func (dExt *DriverExt) CheckPopup() (popup *PopupInfo, err error) { func (dExt *XTDriver) CheckPopup() (popup *PopupInfo, err error) {
screenResult, err := dExt.GetScreenResult( screenResult, err := dExt.GetScreenResult(
option.WithScreenShotUpload(true), option.WithScreenShotUpload(true),
option.WithScreenShotClosePopups(true), // get popup area and close area option.WithScreenShotClosePopups(true), // get popup area and close area
@@ -122,7 +122,7 @@ func (dExt *DriverExt) CheckPopup() (popup *PopupInfo, err error) {
return popup, nil return popup, nil
} }
func (dExt *DriverExt) ClosePopupsHandler() (err error) { func (dExt *XTDriver) ClosePopupsHandler() (err error) {
log.Info().Msg("try to find and close popups") log.Info().Msg("try to find and close popups")
popup, err := dExt.CheckPopup() popup, err := dExt.CheckPopup()
+6 -6
View File
@@ -46,7 +46,7 @@ func (s *ScreenResult) FilterTextsByScope(x1, y1, x2, y2 float64) ai.OCRTexts {
} }
// GetScreenResult takes a screenshot, returns the image recognition result // GetScreenResult takes a screenshot, returns the image recognition result
func (dExt *DriverExt) GetScreenResult(opts ...option.ActionOption) (screenResult *ScreenResult, err error) { func (dExt *XTDriver) GetScreenResult(opts ...option.ActionOption) (screenResult *ScreenResult, err error) {
screenshotOptions := option.NewActionOptions(opts...) screenshotOptions := option.NewActionOptions(opts...)
var fileName string var fileName string
@@ -129,7 +129,7 @@ func (dExt *DriverExt) GetScreenResult(opts ...option.ActionOption) (screenResul
return screenResult, nil return screenResult, nil
} }
func (dExt *DriverExt) GetScreenTexts(opts ...option.ActionOption) (ocrTexts ai.OCRTexts, err error) { func (dExt *XTDriver) GetScreenTexts(opts ...option.ActionOption) (ocrTexts ai.OCRTexts, err error) {
options := option.NewActionOptions(opts...) options := option.NewActionOptions(opts...)
if options.ScreenShotFileName == "" { if options.ScreenShotFileName == "" {
opts = append(opts, option.WithScreenShotFileName("get_screen_texts")) opts = append(opts, option.WithScreenShotFileName("get_screen_texts"))
@@ -142,7 +142,7 @@ func (dExt *DriverExt) GetScreenTexts(opts ...option.ActionOption) (ocrTexts ai.
return screenResult.Texts, nil return screenResult.Texts, nil
} }
func (dExt *DriverExt) FindUIRectInUIKit(search string, opts ...option.ActionOption) (point ai.PointF, err error) { func (dExt *XTDriver) FindUIRectInUIKit(search string, opts ...option.ActionOption) (point ai.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...)
@@ -152,7 +152,7 @@ func (dExt *DriverExt) FindUIRectInUIKit(search string, opts ...option.ActionOpt
return return
} }
func (dExt *DriverExt) FindScreenText(text string, opts ...option.ActionOption) (point ai.PointF, err error) { func (dExt *XTDriver) FindScreenText(text string, opts ...option.ActionOption) (point ai.PointF, err error) {
options := option.NewActionOptions(opts...) options := option.NewActionOptions(opts...)
if options.ScreenShotFileName == "" { if options.ScreenShotFileName == "" {
opts = append(opts, option.WithScreenShotFileName(fmt.Sprintf("find_screen_text_%s", text))) opts = append(opts, option.WithScreenShotFileName(fmt.Sprintf("find_screen_text_%s", text)))
@@ -174,7 +174,7 @@ func (dExt *DriverExt) FindScreenText(text string, opts ...option.ActionOption)
return return
} }
func (dExt *DriverExt) FindUIResult(opts ...option.ActionOption) (point ai.PointF, err error) { func (dExt *XTDriver) FindUIResult(opts ...option.ActionOption) (point ai.PointF, err error) {
options := option.NewActionOptions(opts...) options := option.NewActionOptions(opts...)
if options.ScreenShotFileName == "" { if options.ScreenShotFileName == "" {
opts = append(opts, option.WithScreenShotFileName( opts = append(opts, option.WithScreenShotFileName(
@@ -199,7 +199,7 @@ func (dExt *DriverExt) FindUIResult(opts ...option.ActionOption) (point ai.Point
} }
// GetScreenShot takes screenshot and saves image file to $CWD/screenshots/ folder // GetScreenShot takes screenshot and saves image file to $CWD/screenshots/ folder
func (dExt *DriverExt) GetScreenShot(fileName string) (raw *bytes.Buffer, path string, err error) { func (dExt *XTDriver) GetScreenShot(fileName string) (raw *bytes.Buffer, path string, err error) {
if raw, err = dExt.Driver.Screenshot(); err != nil { if raw, err = dExt.Driver.Screenshot(); err != nil {
log.Error().Err(err).Msg("capture screenshot data failed") log.Error().Err(err).Msg("capture screenshot data failed")
return nil, "", errors.Wrap(code.DeviceScreenShotError, err.Error()) return nil, "", errors.Wrap(code.DeviceScreenShotError, err.Error())
+13 -13
View File
@@ -19,7 +19,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 ...option.ActionOption) error { func (dExt *XTDriver) 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,
@@ -45,25 +45,25 @@ func (dExt *DriverExt) SwipeRelative(fromX, fromY, toX, toY float64, opts ...opt
return nil return nil
} }
func (dExt *DriverExt) SwipeUp(opts ...option.ActionOption) (err error) { func (dExt *XTDriver) 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 ...option.ActionOption) (err error) { func (dExt *XTDriver) 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 ...option.ActionOption) (err error) { func (dExt *XTDriver) 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 ...option.ActionOption) (err error) { func (dExt *XTDriver) 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 *XTDriver) error
func (dExt *DriverExt) LoopUntil(findAction, findCondition, foundAction Action, opts ...option.ActionOption) error { func (dExt *XTDriver) LoopUntil(findAction, findCondition, foundAction Action, opts ...option.ActionOption) error {
actionOptions := option.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
maxRetryTimes := actionOptions.MaxRetryTimes maxRetryTimes := actionOptions.MaxRetryTimes
interval := actionOptions.Interval interval := actionOptions.Interval
@@ -86,7 +86,7 @@ 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 prepareSwipeAction(dExt *DriverExt, params interface{}, opts ...option.ActionOption) func(d *DriverExt) error { func prepareSwipeAction(dExt *XTDriver, params interface{}, opts ...option.ActionOption) func(d *XTDriver) error {
actionOptions := option.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
var swipeDirection interface{} var swipeDirection interface{}
@@ -103,7 +103,7 @@ func prepareSwipeAction(dExt *DriverExt, params interface{}, opts ...option.Acti
actionOptions.Steps = 10 actionOptions.Steps = 10
} }
return func(d *DriverExt) error { return func(d *XTDriver) error {
defer func() { defer func() {
// wait for swipe action to completed and content to load completely // wait for swipe action to completed and content to load completely
time.Sleep(time.Duration(1000*actionOptions.Interval) * time.Millisecond) time.Sleep(time.Duration(1000*actionOptions.Interval) * time.Millisecond)
@@ -138,7 +138,7 @@ func prepareSwipeAction(dExt *DriverExt, params interface{}, opts ...option.Acti
} }
} }
func (dExt *DriverExt) swipeToTapTexts(texts []string, opts ...option.ActionOption) error { func (dExt *XTDriver) 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")
} }
@@ -148,7 +148,7 @@ func (dExt *DriverExt) swipeToTapTexts(texts []string, opts ...option.ActionOpti
actionOptions.Identifier = "" actionOptions.Identifier = ""
optionsWithoutIdentifier := actionOptions.Options() optionsWithoutIdentifier := actionOptions.Options()
var point ai.PointF var point ai.PointF
findTexts := func(d *DriverExt) error { findTexts := func(d *XTDriver) error {
var err error var err error
screenResult, err := d.GetScreenResult( screenResult, err := d.GetScreenResult(
option.WithScreenShotOCR(true), option.WithScreenShotOCR(true),
@@ -172,7 +172,7 @@ func (dExt *DriverExt) swipeToTapTexts(texts []string, opts ...option.ActionOpti
point = points[0].Center() // FIXME point = points[0].Center() // FIXME
return nil return nil
} }
foundTextAction := func(d *DriverExt) error { foundTextAction := func(d *XTDriver) error {
// tap text // tap text
return d.TapAbsXY(point.X, point.Y, opts...) return d.TapAbsXY(point.X, point.Y, opts...)
} }
@@ -181,7 +181,7 @@ func (dExt *DriverExt) swipeToTapTexts(texts []string, opts ...option.ActionOpti
return dExt.LoopUntil(findAction, findTexts, foundTextAction, optionsWithoutIdentifier...) return dExt.LoopUntil(findAction, findTexts, foundTextAction, optionsWithoutIdentifier...)
} }
func (dExt *DriverExt) SwipeToTapApp(appName string, opts ...option.ActionOption) error { func (dExt *XTDriver) 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")
+5 -7
View File
@@ -11,13 +11,12 @@ import (
func TestAndroidSwipeAction(t *testing.T) { func TestAndroidSwipeAction(t *testing.T) {
setupAndroidAdbDriver(t) setupAndroidAdbDriver(t)
dExt := driverExt.(*DriverExt) swipeAction := prepareSwipeAction(driverExt, "up", option.WithDirection("down"))
swipeAction := prepareSwipeAction(dExt, "up", option.WithDirection("down")) err := swipeAction(driverExt)
err := swipeAction(dExt)
checkErr(t, err) checkErr(t, err)
swipeAction = prepareSwipeAction(dExt, "up", option.WithCustomDirection(0.5, 0.5, 0.5, 0.9)) swipeAction = prepareSwipeAction(driverExt, "up", option.WithCustomDirection(0.5, 0.5, 0.5, 0.9))
err = swipeAction(dExt) err = swipeAction(driverExt)
checkErr(t, err) checkErr(t, err)
} }
@@ -34,7 +33,6 @@ func TestAndroidSwipeToTapTexts(t *testing.T) {
err := driverExt.GetDriver().AppLaunch("com.ss.android.ugc.aweme") err := driverExt.GetDriver().AppLaunch("com.ss.android.ugc.aweme")
checkErr(t, err) checkErr(t, err)
dExt := driverExt.(*DriverExt) err = driverExt.swipeToTapTexts([]string{"点击进入直播间", "直播中"}, option.WithDirection("up"))
err = dExt.swipeToTapTexts([]string{"点击进入直播间", "直播中"}, option.WithDirection("up"))
checkErr(t, err) checkErr(t, err)
} }
+9 -9
View File
@@ -9,7 +9,7 @@ import (
"github.com/httprunner/httprunner/v5/pkg/uixt/option" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
func (dExt *DriverExt) TapAbsXY(x, y float64, opts ...option.ActionOption) error { func (dExt *XTDriver) 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 ...option.ActionOption) error
return nil return nil
} }
func (dExt *DriverExt) TapXY(x, y float64, opts ...option.ActionOption) error { func (dExt *XTDriver) 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,7 +33,7 @@ func (dExt *DriverExt) TapXY(x, y float64, opts ...option.ActionOption) error {
return dExt.TapAbsXY(x, y, opts...) return dExt.TapAbsXY(x, y, opts...)
} }
func (dExt *DriverExt) TapByOCR(ocrText string, opts ...option.ActionOption) error { func (dExt *XTDriver) TapByOCR(ocrText string, opts ...option.ActionOption) error {
actionOptions := option.NewActionOptions(opts...) actionOptions := option.NewActionOptions(opts...)
if actionOptions.ScreenShotFileName == "" { if actionOptions.ScreenShotFileName == "" {
opts = append(opts, option.WithScreenShotFileName(fmt.Sprintf("tap_by_ocr_%s", ocrText))) opts = append(opts, option.WithScreenShotFileName(fmt.Sprintf("tap_by_ocr_%s", ocrText)))
@@ -50,7 +50,7 @@ func (dExt *DriverExt) TapByOCR(ocrText string, opts ...option.ActionOption) err
return dExt.TapAbsXY(point.X, point.Y, opts...) return dExt.TapAbsXY(point.X, point.Y, opts...)
} }
func (dExt *DriverExt) TapByUIDetection(opts ...option.ActionOption) error { func (dExt *XTDriver) TapByUIDetection(opts ...option.ActionOption) error {
options := option.NewActionOptions(opts...) options := option.NewActionOptions(opts...)
point, err := dExt.FindUIResult(opts...) point, err := dExt.FindUIResult(opts...)
@@ -64,11 +64,11 @@ func (dExt *DriverExt) TapByUIDetection(opts ...option.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 ...option.ActionOption) error { func (dExt *XTDriver) 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 ...option.ActionOption) (err error) { func (dExt *XTDriver) TapOffset(param string, xOffset, yOffset float64, opts ...option.ActionOption) (err error) {
options := option.NewActionOptions(opts...) options := option.NewActionOptions(opts...)
point, err := dExt.FindUIRectInUIKit(param, opts...) point, err := dExt.FindUIRectInUIKit(param, opts...)
@@ -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 ...option.ActionOption) error { func (dExt *XTDriver) 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 ...option.ActionOption) er
return nil return nil
} }
func (dExt *DriverExt) DoubleTap(param string, opts ...option.ActionOption) (err error) { func (dExt *XTDriver) 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 ...option.ActionOption) (err error) { func (dExt *XTDriver) 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
+12 -13
View File
@@ -4,35 +4,34 @@ package uixt
import ( import (
"testing" "testing"
"github.com/httprunner/httprunner/v5/pkg/uixt/ai"
) )
var iosDevice *IOSDevice var (
iosDevice *IOSDevice
iosDriverExt *XTDriver
)
func init() { func init() {
iosDevice, _ = NewIOSDevice() iosDevice, _ = NewIOSDevice()
driver, _ := iosDevice.NewDriver()
iosDriverExt = NewXTDriver(driver,
ai.WithCVService(ai.CVServiceTypeVEDEM))
} }
func TestDriverExt_TapXY(t *testing.T) { func TestDriverExt_TapXY(t *testing.T) {
driverExt, err := iosDevice.NewDriver() err := iosDriverExt.TapXY(0.4, 0.5)
checkErr(t, err)
err = driverExt.TapXY(0.4, 0.5)
checkErr(t, err) checkErr(t, err)
} }
func TestDriverExt_TapAbsXY(t *testing.T) { func TestDriverExt_TapAbsXY(t *testing.T) {
driverExt, err := iosDevice.NewDriver() err := iosDriverExt.TapAbsXY(100, 300)
checkErr(t, err)
err = driverExt.TapAbsXY(100, 300)
checkErr(t, err) checkErr(t, err)
} }
func TestDriverExt_TapWithOCR(t *testing.T) { func TestDriverExt_TapWithOCR(t *testing.T) {
driverExt, err := iosDevice.NewDriver()
checkErr(t, err)
// 需要点击文字上方的图标 // 需要点击文字上方的图标
err = driverExt.TapOffset("抖音", 0, -20) err := iosDriverExt.TapOffset("抖音", 0, -20)
checkErr(t, err) checkErr(t, err)
} }
+1 -1
View File
@@ -15,7 +15,7 @@ func TestNewDriverExt(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
driverExt, _ := NewDriverExt(driver, driverExt := NewXTDriver(driver,
ai.WithCVService(ai.CVServiceTypeVEDEM)) ai.WithCVService(ai.CVServiceTypeVEDEM))
texts, _ := driverExt.GetScreenTexts() texts, _ := driverExt.GetScreenTexts()
+3 -10
View File
@@ -6,7 +6,6 @@ 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/ai"
"github.com/httprunner/httprunner/v5/pkg/uixt/option" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
"github.com/httprunner/httprunner/v5/pkg/uixt/types" "github.com/httprunner/httprunner/v5/pkg/uixt/types"
) )
@@ -94,21 +93,15 @@ func (dev *HarmonyDevice) GetPackageInfo(packageName string) (types.AppInfo, err
return types.AppInfo{}, nil return types.AppInfo{}, nil
} }
func (dev *HarmonyDevice) NewDriver() (IDriverExt, error) { func (dev *HarmonyDevice) NewDriver() (IDriver, error) {
// init harmony driver // init harmony driver
driver, err := NewHDCDriver(dev) driver, err := NewHDCDriver(dev)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "init harmony driver failed") return nil, errors.Wrap(err, "init harmony driver failed")
} }
driverExt, err := NewDriverExt(driver, ai.WithCVService(ai.CVServiceTypeVEDEM))
if err != nil {
return nil, errors.Wrap(err, "init harmony driver ext failed")
}
// setup driver // setup driver
if err := driverExt.GetDriver().Setup(); err != nil { if err := driver.Setup(); err != nil {
return nil, err return nil, err
} }
return driver, nil
return driverExt, nil
} }
+10 -3
View File
@@ -5,9 +5,14 @@ package uixt
import ( import (
"fmt" "fmt"
"testing" "testing"
"github.com/httprunner/httprunner/v5/pkg/uixt/ai"
) )
var hdcDriver *HDCDriver var (
hdcDriver *HDCDriver
hdcDriverExt *XTDriver
)
func setupHarmonyDevice(t *testing.T) { func setupHarmonyDevice(t *testing.T) {
device, err := NewHarmonyDevice() device, err := NewHarmonyDevice()
@@ -18,6 +23,8 @@ func setupHarmonyDevice(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
hdcDriverExt = NewXTDriver(hdcDriver,
ai.WithCVService(ai.CVServiceTypeVEDEM))
} }
func TestWindowSize(t *testing.T) { func TestWindowSize(t *testing.T) {
@@ -31,7 +38,7 @@ func TestWindowSize(t *testing.T) {
func TestHarmonyTap(t *testing.T) { func TestHarmonyTap(t *testing.T) {
setupHarmonyDevice(t) setupHarmonyDevice(t)
err := hdcDriver.TapAbsXY(200, 2000) err := hdcDriverExt.TapAbsXY(200, 2000)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -39,7 +46,7 @@ func TestHarmonyTap(t *testing.T) {
func TestHarmonySwipe(t *testing.T) { func TestHarmonySwipe(t *testing.T) {
setupHarmonyDevice(t) setupHarmonyDevice(t)
err := hdcDriver.SwipeLeft() err := hdcDriverExt.SwipeLeft()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
+4 -12
View File
@@ -28,7 +28,6 @@ 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/ai"
"github.com/httprunner/httprunner/v5/pkg/uixt/option" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
"github.com/httprunner/httprunner/v5/pkg/uixt/types" "github.com/httprunner/httprunner/v5/pkg/uixt/types"
) )
@@ -203,8 +202,8 @@ func (dev *IOSDevice) getAppInfo(packageName string) (appInfo types.AppInfo, err
return types.AppInfo{}, fmt.Errorf("not found App by bundle id: %s", packageName) return types.AppInfo{}, fmt.Errorf("not found App by bundle id: %s", packageName)
} }
func (dev *IOSDevice) NewDriver() (driverExt IDriverExt, err error) { func (dev *IOSDevice) NewDriver() (driver IDriver, err error) {
driver, err := NewWDADriver(dev) driver, err = NewWDADriver(dev)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to init WDA driver") return nil, errors.Wrap(err, "failed to init WDA driver")
} }
@@ -230,18 +229,11 @@ func (dev *IOSDevice) NewDriver() (driverExt IDriverExt, err error) {
return nil, err return nil, err
} }
} }
driverExt, err = NewDriverExt(driver, ai.WithCVService(ai.CVServiceTypeVEDEM))
if err != nil {
return nil, errors.Wrap(err, "init ios driver ext failed")
}
// setup driver // setup driver
if err := driverExt.GetDriver().Setup(); err != nil { if err := driver.Setup(); err != nil {
return nil, err return nil, err
} }
return driver, nil
return driverExt, nil
} }
func (dev *IOSDevice) Install(appPath string, opts ...option.InstallOption) (err error) { func (dev *IOSDevice) Install(appPath string, opts ...option.InstallOption) (err error) {
+4 -2
View File
@@ -10,6 +10,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/httprunner/httprunner/v5/pkg/uixt/ai"
"github.com/httprunner/httprunner/v5/pkg/uixt/option" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
"github.com/httprunner/httprunner/v5/pkg/uixt/types" "github.com/httprunner/httprunner/v5/pkg/uixt/types"
) )
@@ -17,7 +18,7 @@ import (
var ( var (
bundleId = "com.apple.Preferences" bundleId = "com.apple.Preferences"
driver IDriver driver IDriver
iOSDriverExt IDriverExt iOSDriverExt *XTDriver
) )
func setup(t *testing.T) { func setup(t *testing.T) {
@@ -30,10 +31,11 @@ func setup(t *testing.T) {
} }
capabilities := option.NewCapabilities() capabilities := option.NewCapabilities()
capabilities.WithDefaultAlertAction(option.AlertActionAccept) capabilities.WithDefaultAlertAction(option.AlertActionAccept)
iOSDriverExt, err = device.NewDriver() driver, err = device.NewDriver()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
iOSDriverExt = NewXTDriver(driver, ai.WithCVService(ai.CVServiceTypeVEDEM))
} }
func TestViaUSB(t *testing.T) { func TestViaUSB(t *testing.T) {
+2 -2
View File
@@ -22,7 +22,7 @@ type timeLog struct {
} }
type EndToEndDelay struct { type EndToEndDelay struct {
driver *DriverExt driver *XTDriver
StartTime string `json:"startTime"` StartTime string `json:"startTime"`
EndTime string `json:"endTime"` EndTime string `json:"endTime"`
Interval int `json:"interval"` // seconds Interval int `json:"interval"` // seconds
@@ -30,7 +30,7 @@ type EndToEndDelay struct {
Timelines []timeLog `json:"timelines"` Timelines []timeLog `json:"timelines"`
} }
func CollectEndToEndDelay(dExt *DriverExt, opts ...option.ActionOption) { func CollectEndToEndDelay(dExt *XTDriver, opts ...option.ActionOption) {
dataOptions := option.NewActionOptions(opts...) dataOptions := option.NewActionOptions(opts...)
startTime := time.Now() startTime := time.Now()
+10 -6
View File
@@ -27,6 +27,7 @@ import (
"github.com/httprunner/httprunner/v5/internal/sdk" "github.com/httprunner/httprunner/v5/internal/sdk"
"github.com/httprunner/httprunner/v5/internal/version" "github.com/httprunner/httprunner/v5/internal/version"
"github.com/httprunner/httprunner/v5/pkg/uixt" "github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/ai"
) )
// Run starts to run testcase with default configs. // Run starts to run testcase with default configs.
@@ -281,7 +282,7 @@ func (r *HRPRunner) NewCaseRunner(testcase TestCase) (*CaseRunner, error) {
TestCase: testcase, TestCase: testcase,
hrpRunner: r, hrpRunner: r,
parser: newParser(), parser: newParser(),
uixtDrivers: make(map[string]uixt.IDriverExt), uixtDrivers: make(map[string]*uixt.XTDriver),
} }
config := testcase.Config.Get() config := testcase.Config.Get()
@@ -336,7 +337,7 @@ type CaseRunner struct {
parametersIterator *ParametersIterator parametersIterator *ParametersIterator
// UI automation clients for iOS and Android, key is udid/serial // UI automation clients for iOS and Android, key is udid/serial
uixtDrivers map[string]uixt.IDriverExt uixtDrivers map[string]*uixt.XTDriver
} }
func (r *CaseRunner) GetParametersIterator() *ParametersIterator { func (r *CaseRunner) GetParametersIterator() *ParametersIterator {
@@ -430,11 +431,12 @@ func (r *CaseRunner) parseConfig() (parsedConfig *TConfig, err error) {
if err := device.Setup(); err != nil { if err := device.Setup(); err != nil {
return nil, errors.Wrap(err, "setup android device failed") return nil, errors.Wrap(err, "setup android device failed")
} }
driverExt, err := device.NewDriver() driver, err := device.NewDriver()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "init android driver failed") return nil, errors.Wrap(err, "init android driver failed")
} }
driverExt := uixt.NewXTDriver(driver, ai.WithCVService(ai.CVServiceTypeVEDEM))
r.uixtDrivers[androidDevice.Options.SerialNumber] = driverExt r.uixtDrivers[androidDevice.Options.SerialNumber] = driverExt
} }
// parse iOS devices config // parse iOS devices config
@@ -452,11 +454,12 @@ func (r *CaseRunner) parseConfig() (parsedConfig *TConfig, err error) {
if err := device.Setup(); err != nil { if err := device.Setup(); err != nil {
return nil, errors.Wrap(err, "setup ios device failed") return nil, errors.Wrap(err, "setup ios device failed")
} }
driverExt, err := device.NewDriver() driver, err := device.NewDriver()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "init ios driver failed") return nil, errors.Wrap(err, "init ios driver failed")
} }
driverExt := uixt.NewXTDriver(driver, ai.WithCVService(ai.CVServiceTypeVEDEM))
r.uixtDrivers[iosDevice.Options.UDID] = driverExt r.uixtDrivers[iosDevice.Options.UDID] = driverExt
} }
// parse harmony devices config // parse harmony devices config
@@ -474,11 +477,12 @@ func (r *CaseRunner) parseConfig() (parsedConfig *TConfig, err error) {
if err := device.Setup(); err != nil { if err := device.Setup(); err != nil {
return nil, errors.Wrap(err, "setup harmony device failed") return nil, errors.Wrap(err, "setup harmony device failed")
} }
driverExt, err := device.NewDriver() driver, err := device.NewDriver()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "init harmony driver failed") return nil, errors.Wrap(err, "init harmony driver failed")
} }
driverExt := uixt.NewXTDriver(driver, ai.WithCVService(ai.CVServiceTypeVEDEM))
r.uixtDrivers[harmonyDevice.Options.ConnectKey] = driverExt r.uixtDrivers[harmonyDevice.Options.ConnectKey] = driverExt
} }
@@ -521,7 +525,7 @@ func (r *CaseRunner) parseDeviceConfig(device interface{}, configVariables map[s
return nil return nil
} }
func (r *CaseRunner) GetUIXTDriver(serial string) (driver uixt.IDriverExt, err error) { func (r *CaseRunner) GetUIXTDriver(serial string) (driver *uixt.XTDriver, err error) {
for key, driver := range r.uixtDrivers { for key, driver := range r.uixtDrivers {
// return the driver with the same serial // return the driver with the same serial
if key == serial { if key == serial {
+10 -5
View File
@@ -10,10 +10,11 @@ import (
"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/ai"
"github.com/httprunner/httprunner/v5/pkg/uixt/option" "github.com/httprunner/httprunner/v5/pkg/uixt/option"
) )
var uiClients = make(map[string]uixt.IDriverExt) // UI automation clients for iOS and Android, key is udid/serial var uiClients = make(map[string]*uixt.XTDriver) // UI automation clients for iOS and Android, key is udid/serial
func (r *Router) HandleDeviceContext() gin.HandlerFunc { func (r *Router) HandleDeviceContext() gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
@@ -66,9 +67,13 @@ func (r *Router) HandleDeviceContext() gin.HandlerFunc {
c.Abort() c.Abort()
return return
} }
c.Set("driver", driver)
driverExt := uixt.NewXTDriver(driver,
ai.WithCVService(ai.CVServiceTypeVEDEM))
c.Set("driver", driverExt)
// cache driver // cache driver
uiClients[serial] = driver uiClients[serial] = driverExt
default: default:
c.JSON(http.StatusBadRequest, HttpResponse{ c.JSON(http.StatusBadRequest, HttpResponse{
Code: code.GetErrorCode(code.InvalidParamError), Code: code.GetErrorCode(code.InvalidParamError),
@@ -81,13 +86,13 @@ func (r *Router) HandleDeviceContext() gin.HandlerFunc {
} }
} }
func GetContextDriver(c *gin.Context) (uixt.IDriverExt, error) { func GetContextDriver(c *gin.Context) (*uixt.XTDriver, error) {
driverObj, exists := c.Get("driver") driverObj, exists := c.Get("driver")
if !exists { if !exists {
handlerInitDeviceDriverFailedContext(c) handlerInitDeviceDriverFailedContext(c)
return nil, fmt.Errorf("driver not found") return nil, fmt.Errorf("driver not found")
} }
dExt := driverObj.(*uixt.DriverExt) dExt := driverObj.(*uixt.XTDriver)
return dExt, nil return dExt, nil
} }
+1 -1
View File
@@ -780,7 +780,7 @@ func runStepMobileUI(s *SessionRunner, step IStep) (stepResult *StepResult, err
return stepResult, nil return stepResult, nil
} }
func validateUI(ud uixt.IDriverExt, iValidators []interface{}) (validateResults []*ValidationResult, err error) { func validateUI(ud *uixt.XTDriver, iValidators []interface{}) (validateResults []*ValidationResult, err error) {
for _, iValidator := range iValidators { for _, iValidator := range iValidators {
validator, ok := iValidator.(Validator) validator, ok := iValidator.(Validator)
if !ok { if !ok {