refactor: move action options

This commit is contained in:
lilong.129
2025-05-25 00:15:18 +08:00
parent 97dad38b7b
commit 4ff2692f02
15 changed files with 230 additions and 230 deletions
+3 -4
View File
@@ -8,7 +8,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/uixt"
"github.com/httprunner/httprunner/v5/uixt/option" "github.com/httprunner/httprunner/v5/uixt/option"
) )
@@ -138,17 +137,17 @@ func convertCompatMobileStep(mobileUI *MobileUI) {
ma := mobileUI.Actions[i] ma := mobileUI.Actions[i]
actionOptions := option.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 == option.ACTION_TapByCV {
uiTypes, _ := builtin.ConvertToStringSlice(ma.Params) uiTypes, _ := builtin.ConvertToStringSlice(ma.Params)
ma.ActionOptions.ScreenShotWithUITypes = append(ma.ActionOptions.ScreenShotWithUITypes, uiTypes...) ma.ActionOptions.ScreenShotWithUITypes = append(ma.ActionOptions.ScreenShotWithUITypes, uiTypes...)
ma.ActionOptions.ScreenShotWithUpload = true ma.ActionOptions.ScreenShotWithUpload = true
} }
// set default max_retry_times to 10 for swipe_to_tap_texts // set default max_retry_times to 10 for swipe_to_tap_texts
if ma.Method == uixt.ACTION_SwipeToTapTexts && actionOptions.MaxRetryTimes == 0 { if ma.Method == option.ACTION_SwipeToTapTexts && actionOptions.MaxRetryTimes == 0 {
ma.ActionOptions.MaxRetryTimes = 10 ma.ActionOptions.MaxRetryTimes = 10
} }
// set default max_retry_times to 10 for swipe_to_tap_text // set default max_retry_times to 10 for swipe_to_tap_text
if ma.Method == uixt.ACTION_SwipeToTapText && actionOptions.MaxRetryTimes == 0 { if ma.Method == option.ACTION_SwipeToTapText && actionOptions.MaxRetryTimes == 0 {
ma.ActionOptions.MaxRetryTimes = 10 ma.ActionOptions.MaxRetryTimes = 10
} }
mobileUI.Actions[i] = ma mobileUI.Actions[i] = ma
+1 -1
View File
@@ -1 +1 @@
v5.0.0-beta-2505242351 v5.0.0-beta-2505250015
+63 -63
View File
@@ -67,9 +67,9 @@ func (s *StepMobile) Serial(serial string) *StepMobile {
return s return s
} }
func (s *StepMobile) Log(actionName uixt.ActionMethod) *StepMobile { func (s *StepMobile) Log(actionName option.ActionMethod) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{ s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_LOG, Method: option.ACTION_LOG,
Params: actionName, Params: actionName,
}) })
return s return s
@@ -77,7 +77,7 @@ func (s *StepMobile) Log(actionName uixt.ActionMethod) *StepMobile {
func (s *StepMobile) InstallApp(path string) *StepMobile { func (s *StepMobile) InstallApp(path string) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{ s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_AppInstall, Method: option.ACTION_AppInstall,
Params: path, Params: path,
}) })
return s return s
@@ -85,7 +85,7 @@ func (s *StepMobile) InstallApp(path string) *StepMobile {
func (s *StepMobile) WebLoginNoneUI(packageName, phoneNumber string, captcha, password string) *StepMobile { func (s *StepMobile) WebLoginNoneUI(packageName, phoneNumber string, captcha, password string) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{ s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_WebLoginNoneUI, Method: option.ACTION_WebLoginNoneUI,
Params: []string{packageName, phoneNumber, captcha, password}, Params: []string{packageName, phoneNumber, captcha, password},
}) })
return s return s
@@ -93,7 +93,7 @@ func (s *StepMobile) WebLoginNoneUI(packageName, phoneNumber string, captcha, pa
func (s *StepMobile) AppLaunch(bundleId string) *StepMobile { func (s *StepMobile) AppLaunch(bundleId string) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{ s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_AppLaunch, Method: option.ACTION_AppLaunch,
Params: bundleId, Params: bundleId,
}) })
return s return s
@@ -101,7 +101,7 @@ func (s *StepMobile) AppLaunch(bundleId string) *StepMobile {
func (s *StepMobile) AppTerminate(bundleId string) *StepMobile { func (s *StepMobile) AppTerminate(bundleId string) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{ s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_AppTerminate, Method: option.ACTION_AppTerminate,
Params: bundleId, Params: bundleId,
}) })
return s return s
@@ -109,7 +109,7 @@ func (s *StepMobile) AppTerminate(bundleId string) *StepMobile {
func (s *StepMobile) Home() *StepMobile { func (s *StepMobile) Home() *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{ s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_Home, Method: option.ACTION_Home,
Params: nil, Params: nil,
}) })
return s return s
@@ -120,7 +120,7 @@ func (s *StepMobile) Home() *StepMobile {
// else, X & Y will be considered as absolute coordinates // else, X & Y will be considered as absolute coordinates
func (s *StepMobile) TapXY(x, y float64, opts ...option.ActionOption) *StepMobile { func (s *StepMobile) TapXY(x, y float64, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_TapXY, Method: option.ACTION_TapXY,
Params: []float64{x, y}, Params: []float64{x, y},
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -132,7 +132,7 @@ func (s *StepMobile) TapXY(x, y float64, opts ...option.ActionOption) *StepMobil
// 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 ...option.ActionOption) *StepMobile { func (s *StepMobile) TapAbsXY(x, y float64, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_TapAbsXY, Method: option.ACTION_TapAbsXY,
Params: []float64{x, y}, Params: []float64{x, y},
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -144,7 +144,7 @@ func (s *StepMobile) TapAbsXY(x, y float64, opts ...option.ActionOption) *StepMo
// 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 ...option.ActionOption) *StepMobile { func (s *StepMobile) TapByOCR(ocrText string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_TapByOCR, Method: option.ACTION_TapByOCR,
Params: ocrText, Params: ocrText,
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -156,7 +156,7 @@ func (s *StepMobile) TapByOCR(ocrText string, opts ...option.ActionOption) *Step
// 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 ...option.ActionOption) *StepMobile { func (s *StepMobile) TapByCV(imagePath string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_TapByCV, Method: option.ACTION_TapByCV,
Params: imagePath, Params: imagePath,
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -168,7 +168,7 @@ func (s *StepMobile) TapByCV(imagePath string, opts ...option.ActionOption) *Ste
// 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 ...option.ActionOption) *StepMobile { func (s *StepMobile) TapByUITypes(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_TapByCV, Method: option.ACTION_TapByCV,
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -179,7 +179,7 @@ func (s *StepMobile) TapByUITypes(opts ...option.ActionOption) *StepMobile {
// AIAction do actions with VLM // AIAction do actions with VLM
func (s *StepMobile) AIAction(prompt string, opts ...option.ActionOption) *StepMobile { func (s *StepMobile) AIAction(prompt string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_AIAction, Method: option.ACTION_AIAction,
Params: prompt, Params: prompt,
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -191,7 +191,7 @@ func (s *StepMobile) AIAction(prompt string, opts ...option.ActionOption) *StepM
// 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 ...option.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: option.ACTION_DoubleTapXY,
Params: []float64{x, y}, Params: []float64{x, y},
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
}) })
@@ -200,7 +200,7 @@ func (s *StepMobile) DoubleTapXY(x, y float64, opts ...option.ActionOption) *Ste
func (s *StepMobile) Back() *StepMobile { func (s *StepMobile) Back() *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Back, Method: option.ACTION_Back,
Params: nil, Params: nil,
Options: nil, Options: nil,
} }
@@ -212,7 +212,7 @@ func (s *StepMobile) Back() *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 ...option.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: option.ACTION_Swipe,
Params: []float64{sx, sy, ex, ey}, Params: []float64{sx, sy, ex, ey},
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -223,7 +223,7 @@ func (s *StepMobile) Swipe(sx, sy, ex, ey float64, opts ...option.ActionOption)
func (s *StepMobile) SwipeUp(opts ...option.ActionOption) *StepMobile { func (s *StepMobile) SwipeUp(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Swipe, Method: option.ACTION_Swipe,
Params: "up", Params: "up",
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -234,7 +234,7 @@ func (s *StepMobile) SwipeUp(opts ...option.ActionOption) *StepMobile {
func (s *StepMobile) SwipeDown(opts ...option.ActionOption) *StepMobile { func (s *StepMobile) SwipeDown(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Swipe, Method: option.ACTION_Swipe,
Params: "down", Params: "down",
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -245,7 +245,7 @@ func (s *StepMobile) SwipeDown(opts ...option.ActionOption) *StepMobile {
func (s *StepMobile) SwipeLeft(opts ...option.ActionOption) *StepMobile { func (s *StepMobile) SwipeLeft(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Swipe, Method: option.ACTION_Swipe,
Params: "left", Params: "left",
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -256,7 +256,7 @@ func (s *StepMobile) SwipeLeft(opts ...option.ActionOption) *StepMobile {
func (s *StepMobile) SwipeRight(opts ...option.ActionOption) *StepMobile { func (s *StepMobile) SwipeRight(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Swipe, Method: option.ACTION_Swipe,
Params: "right", Params: "right",
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -267,7 +267,7 @@ func (s *StepMobile) SwipeRight(opts ...option.ActionOption) *StepMobile {
func (s *StepMobile) SwipeToTapApp(appName string, opts ...option.ActionOption) *StepMobile { func (s *StepMobile) SwipeToTapApp(appName string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_SwipeToTapApp, Method: option.ACTION_SwipeToTapApp,
Params: appName, Params: appName,
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -278,7 +278,7 @@ func (s *StepMobile) SwipeToTapApp(appName string, opts ...option.ActionOption)
func (s *StepMobile) SwipeToTapText(text string, opts ...option.ActionOption) *StepMobile { func (s *StepMobile) SwipeToTapText(text string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_SwipeToTapText, Method: option.ACTION_SwipeToTapText,
Params: text, Params: text,
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -289,7 +289,7 @@ func (s *StepMobile) SwipeToTapText(text string, opts ...option.ActionOption) *S
func (s *StepMobile) SwipeToTapTexts(texts interface{}, opts ...option.ActionOption) *StepMobile { func (s *StepMobile) SwipeToTapTexts(texts interface{}, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_SwipeToTapTexts, Method: option.ACTION_SwipeToTapTexts,
Params: texts, Params: texts,
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -300,7 +300,7 @@ func (s *StepMobile) SwipeToTapTexts(texts interface{}, opts ...option.ActionOpt
func (s *StepMobile) SecondaryClick(x, y float64, options ...option.ActionOption) *StepMobile { func (s *StepMobile) SecondaryClick(x, y float64, options ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_SecondaryClick, Method: option.ACTION_SecondaryClick,
Params: []float64{x, y}, Params: []float64{x, y},
Options: option.NewActionOptions(options...), Options: option.NewActionOptions(options...),
} }
@@ -310,7 +310,7 @@ func (s *StepMobile) SecondaryClick(x, y float64, options ...option.ActionOption
func (s *StepMobile) SecondaryClickBySelector(selector string, options ...option.ActionOption) *StepMobile { func (s *StepMobile) SecondaryClickBySelector(selector string, options ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_SecondaryClickBySelector, Method: option.ACTION_SecondaryClickBySelector,
Params: selector, Params: selector,
Options: option.NewActionOptions(options...), Options: option.NewActionOptions(options...),
} }
@@ -320,7 +320,7 @@ func (s *StepMobile) SecondaryClickBySelector(selector string, options ...option
func (s *StepMobile) HoverBySelector(selector string, options ...option.ActionOption) *StepMobile { func (s *StepMobile) HoverBySelector(selector string, options ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_HoverBySelector, Method: option.ACTION_HoverBySelector,
Params: selector, Params: selector,
Options: option.NewActionOptions(options...), Options: option.NewActionOptions(options...),
} }
@@ -330,7 +330,7 @@ func (s *StepMobile) HoverBySelector(selector string, options ...option.ActionOp
func (s *StepMobile) TapBySelector(selector string, options ...option.ActionOption) *StepMobile { func (s *StepMobile) TapBySelector(selector string, options ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_TapBySelector, Method: option.ACTION_TapBySelector,
Params: selector, Params: selector,
Options: option.NewActionOptions(options...), Options: option.NewActionOptions(options...),
} }
@@ -340,7 +340,7 @@ func (s *StepMobile) TapBySelector(selector string, options ...option.ActionOpti
func (s *StepMobile) WebCloseTab(idx int, options ...option.ActionOption) *StepMobile { func (s *StepMobile) WebCloseTab(idx int, options ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_WebCloseTab, Method: option.ACTION_WebCloseTab,
Params: idx, Params: idx,
Options: option.NewActionOptions(options...), Options: option.NewActionOptions(options...),
} }
@@ -350,7 +350,7 @@ func (s *StepMobile) WebCloseTab(idx int, options ...option.ActionOption) *StepM
func (s *StepMobile) GetElementTextBySelector(selector string, options ...option.ActionOption) *StepMobile { func (s *StepMobile) GetElementTextBySelector(selector string, options ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_GetElementTextBySelector, Method: option.ACTION_GetElementTextBySelector,
Params: selector, Params: selector,
Options: option.NewActionOptions(options...), Options: option.NewActionOptions(options...),
} }
@@ -360,7 +360,7 @@ func (s *StepMobile) GetElementTextBySelector(selector string, options ...option
func (s *StepMobile) Input(text string, opts ...option.ActionOption) *StepMobile { func (s *StepMobile) Input(text string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Input, Method: option.ACTION_Input,
Params: text, Params: text,
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
} }
@@ -372,7 +372,7 @@ func (s *StepMobile) Input(text string, opts ...option.ActionOption) *StepMobile
// Sleep specify sleep seconds after last action // Sleep specify sleep seconds after last action
func (s *StepMobile) Sleep(nSeconds float64, startTime ...time.Time) *StepMobile { func (s *StepMobile) Sleep(nSeconds float64, startTime ...time.Time) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_Sleep, Method: option.ACTION_Sleep,
Params: nSeconds, Params: nSeconds,
Options: nil, Options: nil,
} }
@@ -388,7 +388,7 @@ func (s *StepMobile) Sleep(nSeconds float64, startTime ...time.Time) *StepMobile
func (s *StepMobile) SleepMS(nMilliseconds int64, startTime ...time.Time) *StepMobile { func (s *StepMobile) SleepMS(nMilliseconds int64, startTime ...time.Time) *StepMobile {
action := uixt.MobileAction{ action := uixt.MobileAction{
Method: uixt.ACTION_SleepMS, Method: option.ACTION_SleepMS,
Params: nMilliseconds, Params: nMilliseconds,
Options: nil, Options: nil,
} }
@@ -408,7 +408,7 @@ func (s *StepMobile) SleepMS(nMilliseconds int64, startTime ...time.Time) *StepM
// 2. [min1, max1, weight1, min2, max2, weight2, ...] : weight is the probability of the time range // 2. [min1, max1, weight1, min2, max2, weight2, ...] : weight is the probability of the time range
func (s *StepMobile) SleepRandom(params ...float64) *StepMobile { func (s *StepMobile) SleepRandom(params ...float64) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{ s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_SleepRandom, Method: option.ACTION_SleepRandom,
Params: params, Params: params,
Options: nil, Options: nil,
}) })
@@ -417,7 +417,7 @@ func (s *StepMobile) SleepRandom(params ...float64) *StepMobile {
func (s *StepMobile) EndToEndDelay(opts ...option.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: option.ACTION_EndToEndDelay,
Params: nil, Params: nil,
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
}) })
@@ -426,7 +426,7 @@ func (s *StepMobile) EndToEndDelay(opts ...option.ActionOption) *StepMobile {
func (s *StepMobile) ScreenShot(opts ...option.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: option.ACTION_ScreenShot,
Params: nil, Params: nil,
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
}) })
@@ -440,7 +440,7 @@ func (s *StepMobile) DisableAutoPopupHandler() *StepMobile {
func (s *StepMobile) ClosePopups(opts ...option.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: option.ACTION_ClosePopups,
Params: nil, Params: nil,
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
}) })
@@ -449,7 +449,7 @@ func (s *StepMobile) ClosePopups(opts ...option.ActionOption) *StepMobile {
func (s *StepMobile) Call(name string, fn func(), opts ...option.ActionOption) *StepMobile { func (s *StepMobile) Call(name string, fn func(), 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_CallFunction, Method: option.ACTION_CallFunction,
Params: name, // function description Params: name, // function description
Fn: fn, Fn: fn,
Options: option.NewActionOptions(opts...), Options: option.NewActionOptions(opts...),
@@ -493,8 +493,8 @@ type StepMobileUIValidation struct {
func (s *StepMobileUIValidation) AssertNameExists(expectedName string, msg ...string) *StepMobileUIValidation { func (s *StepMobileUIValidation) AssertNameExists(expectedName string, msg ...string) *StepMobileUIValidation {
v := Validator{ v := Validator{
Check: uixt.SelectorName, Check: option.SelectorName,
Assert: uixt.AssertionExists, Assert: option.AssertionExists,
Expect: expectedName, Expect: expectedName,
} }
if len(msg) > 0 { if len(msg) > 0 {
@@ -508,8 +508,8 @@ func (s *StepMobileUIValidation) AssertNameExists(expectedName string, msg ...st
func (s *StepMobileUIValidation) AssertNameNotExists(expectedName string, msg ...string) *StepMobileUIValidation { func (s *StepMobileUIValidation) AssertNameNotExists(expectedName string, msg ...string) *StepMobileUIValidation {
v := Validator{ v := Validator{
Check: uixt.SelectorName, Check: option.SelectorName,
Assert: uixt.AssertionNotExists, Assert: option.AssertionNotExists,
Expect: expectedName, Expect: expectedName,
} }
if len(msg) > 0 { if len(msg) > 0 {
@@ -523,8 +523,8 @@ func (s *StepMobileUIValidation) AssertNameNotExists(expectedName string, msg ..
func (s *StepMobileUIValidation) AssertLabelExists(expectedLabel string, msg ...string) *StepMobileUIValidation { func (s *StepMobileUIValidation) AssertLabelExists(expectedLabel string, msg ...string) *StepMobileUIValidation {
v := Validator{ v := Validator{
Check: uixt.SelectorLabel, Check: option.SelectorLabel,
Assert: uixt.AssertionExists, Assert: option.AssertionExists,
Expect: expectedLabel, Expect: expectedLabel,
} }
if len(msg) > 0 { if len(msg) > 0 {
@@ -538,8 +538,8 @@ func (s *StepMobileUIValidation) AssertLabelExists(expectedLabel string, msg ...
func (s *StepMobileUIValidation) AssertLabelNotExists(expectedLabel string, msg ...string) *StepMobileUIValidation { func (s *StepMobileUIValidation) AssertLabelNotExists(expectedLabel string, msg ...string) *StepMobileUIValidation {
v := Validator{ v := Validator{
Check: uixt.SelectorLabel, Check: option.SelectorLabel,
Assert: uixt.AssertionNotExists, Assert: option.AssertionNotExists,
Expect: expectedLabel, Expect: expectedLabel,
} }
if len(msg) > 0 { if len(msg) > 0 {
@@ -553,8 +553,8 @@ func (s *StepMobileUIValidation) AssertLabelNotExists(expectedLabel string, msg
func (s *StepMobileUIValidation) AssertOCRExists(expectedText string, msg ...string) *StepMobileUIValidation { func (s *StepMobileUIValidation) AssertOCRExists(expectedText string, msg ...string) *StepMobileUIValidation {
v := Validator{ v := Validator{
Check: uixt.SelectorOCR, Check: option.SelectorOCR,
Assert: uixt.AssertionExists, Assert: option.AssertionExists,
Expect: expectedText, Expect: expectedText,
} }
if len(msg) > 0 { if len(msg) > 0 {
@@ -568,8 +568,8 @@ func (s *StepMobileUIValidation) AssertOCRExists(expectedText string, msg ...str
func (s *StepMobileUIValidation) AssertOCRNotExists(expectedText string, msg ...string) *StepMobileUIValidation { func (s *StepMobileUIValidation) AssertOCRNotExists(expectedText string, msg ...string) *StepMobileUIValidation {
v := Validator{ v := Validator{
Check: uixt.SelectorOCR, Check: option.SelectorOCR,
Assert: uixt.AssertionNotExists, Assert: option.AssertionNotExists,
Expect: expectedText, Expect: expectedText,
} }
if len(msg) > 0 { if len(msg) > 0 {
@@ -583,8 +583,8 @@ func (s *StepMobileUIValidation) AssertOCRNotExists(expectedText string, msg ...
func (s *StepMobileUIValidation) AssertImageExists(expectedImagePath string, msg ...string) *StepMobileUIValidation { func (s *StepMobileUIValidation) AssertImageExists(expectedImagePath string, msg ...string) *StepMobileUIValidation {
v := Validator{ v := Validator{
Check: uixt.SelectorImage, Check: option.SelectorImage,
Assert: uixt.AssertionExists, Assert: option.AssertionExists,
Expect: expectedImagePath, Expect: expectedImagePath,
} }
if len(msg) > 0 { if len(msg) > 0 {
@@ -598,8 +598,8 @@ func (s *StepMobileUIValidation) AssertImageExists(expectedImagePath string, msg
func (s *StepMobileUIValidation) AssertImageNotExists(expectedImagePath string, msg ...string) *StepMobileUIValidation { func (s *StepMobileUIValidation) AssertImageNotExists(expectedImagePath string, msg ...string) *StepMobileUIValidation {
v := Validator{ v := Validator{
Check: uixt.SelectorImage, Check: option.SelectorImage,
Assert: uixt.AssertionNotExists, Assert: option.AssertionNotExists,
Expect: expectedImagePath, Expect: expectedImagePath,
} }
if len(msg) > 0 { if len(msg) > 0 {
@@ -613,8 +613,8 @@ func (s *StepMobileUIValidation) AssertImageNotExists(expectedImagePath string,
func (s *StepMobileUIValidation) AssertAI(prompt string, msg ...string) *StepMobileUIValidation { func (s *StepMobileUIValidation) AssertAI(prompt string, msg ...string) *StepMobileUIValidation {
v := Validator{ v := Validator{
Check: uixt.SelectorAI, Check: option.SelectorAI,
Assert: uixt.AssertionAI, Assert: option.AssertionAI,
Expect: prompt, Expect: prompt,
} }
if len(msg) > 0 { if len(msg) > 0 {
@@ -628,8 +628,8 @@ func (s *StepMobileUIValidation) AssertAI(prompt string, msg ...string) *StepMob
func (s *StepMobileUIValidation) AssertAppInForeground(packageName string, msg ...string) *StepMobileUIValidation { func (s *StepMobileUIValidation) AssertAppInForeground(packageName string, msg ...string) *StepMobileUIValidation {
v := Validator{ v := Validator{
Check: uixt.SelectorForegroundApp, Check: option.SelectorForegroundApp,
Assert: uixt.AssertionEqual, Assert: option.AssertionEqual,
Expect: packageName, Expect: packageName,
} }
if len(msg) > 0 { if len(msg) > 0 {
@@ -643,8 +643,8 @@ func (s *StepMobileUIValidation) AssertAppInForeground(packageName string, msg .
func (s *StepMobileUIValidation) AssertAppNotInForeground(packageName string, msg ...string) *StepMobileUIValidation { func (s *StepMobileUIValidation) AssertAppNotInForeground(packageName string, msg ...string) *StepMobileUIValidation {
v := Validator{ v := Validator{
Check: uixt.SelectorForegroundApp, Check: option.SelectorForegroundApp,
Assert: uixt.AssertionNotEqual, Assert: option.AssertionNotEqual,
Expect: packageName, Expect: packageName,
} }
if len(msg) > 0 { if len(msg) > 0 {
@@ -739,7 +739,7 @@ func runStepMobileUI(s *SessionRunner, step IStep) (stepResult *StepResult, err
startTime := time.Now() startTime := time.Now()
actionResult := &ActionResult{ actionResult := &ActionResult{
MobileAction: uixt.MobileAction{ MobileAction: uixt.MobileAction{
Method: uixt.ACTION_GetForegroundApp, Method: option.ACTION_GetForegroundApp,
Params: "[ForDebug] check foreground app", Params: "[ForDebug] check foreground app",
}, },
StartTime: startTime.Unix(), StartTime: startTime.Unix(),
@@ -758,7 +758,7 @@ func runStepMobileUI(s *SessionRunner, step IStep) (stepResult *StepResult, err
startTime := time.Now() startTime := time.Now()
actionResult := &ActionResult{ actionResult := &ActionResult{
MobileAction: uixt.MobileAction{ MobileAction: uixt.MobileAction{
Method: uixt.ACTION_ClosePopups, Method: option.ACTION_ClosePopups,
Params: "[ForDebug] close popups handler", Params: "[ForDebug] close popups handler",
}, },
StartTime: startTime.Unix(), StartTime: startTime.Unix(),
@@ -802,9 +802,9 @@ func runStepMobileUI(s *SessionRunner, step IStep) (stepResult *StepResult, err
} }
// stat uixt action // stat uixt action
if action.Method == uixt.ACTION_LOG { if action.Method == option.ACTION_LOG {
log.Info().Interface("action", action.Params).Msg("stat uixt action") log.Info().Interface("action", action.Params).Msg("stat uixt action")
actionMethod := uixt.ActionMethod(action.Params.(string)) actionMethod := option.ActionMethod(action.Params.(string))
s.summary.Stat.Actions[actionMethod]++ s.summary.Stat.Actions[actionMethod]++
continue continue
} }
+7 -7
View File
@@ -15,7 +15,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/internal/version" "github.com/httprunner/httprunner/v5/internal/version"
"github.com/httprunner/httprunner/v5/uixt" "github.com/httprunner/httprunner/v5/uixt/option"
) )
func NewSummary() *Summary { func NewSummary() *Summary {
@@ -28,7 +28,7 @@ func NewSummary() *Summary {
Success: true, Success: true,
Stat: &Stat{ Stat: &Stat{
TestSteps: TestStepStat{ TestSteps: TestStepStat{
Actions: make(map[uixt.ActionMethod]int), Actions: make(map[option.ActionMethod]int),
}, },
}, },
Time: &TestCaseTime{ Time: &TestCaseTime{
@@ -146,10 +146,10 @@ type TestCaseStat struct {
} }
type TestStepStat struct { type TestStepStat struct {
Total int `json:"total" yaml:"total"` Total int `json:"total" yaml:"total"`
Successes int `json:"successes" yaml:"successes"` Successes int `json:"successes" yaml:"successes"`
Failures int `json:"failures" yaml:"failures"` Failures int `json:"failures" yaml:"failures"`
Actions map[uixt.ActionMethod]int `json:"actions" yaml:"actions"` // record action stats Actions map[option.ActionMethod]int `json:"actions" yaml:"actions"` // record action stats
} }
type TestCaseTime struct { type TestCaseTime struct {
@@ -167,7 +167,7 @@ func NewCaseSummary() *TestCaseSummary {
return &TestCaseSummary{ return &TestCaseSummary{
Success: true, Success: true,
Stat: &TestStepStat{ Stat: &TestStepStat{
Actions: make(map[uixt.ActionMethod]int), Actions: make(map[option.ActionMethod]int),
}, },
Time: &TestCaseTime{ Time: &TestCaseTime{
StartAt: time.Now(), StartAt: time.Now(),
+4 -4
View File
@@ -312,7 +312,7 @@ func (ad *ADBDriver) TapAbsXY(x, y float64, opts ...option.ActionOption) error {
if err != nil { if err != nil {
return err return err
} }
defer postHandler(ad, ACTION_TapAbsXY, actionOptions) defer postHandler(ad, option.ACTION_TapAbsXY, actionOptions)
// adb shell input tap x y // adb shell input tap x y
xStr := fmt.Sprintf("%.1f", x) xStr := fmt.Sprintf("%.1f", x)
@@ -331,7 +331,7 @@ func (ad *ADBDriver) DoubleTap(x, y float64, opts ...option.ActionOption) error
if err != nil { if err != nil {
return err return err
} }
defer postHandler(ad, ACTION_DoubleTapXY, actionOptions) defer postHandler(ad, option.ACTION_DoubleTapXY, actionOptions)
// adb shell input tap x y // adb shell input tap x y
xStr := fmt.Sprintf("%.1f", x) xStr := fmt.Sprintf("%.1f", x)
@@ -380,7 +380,7 @@ func (ad *ADBDriver) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionO
if err != nil { if err != nil {
return err return err
} }
defer postHandler(ad, ACTION_Drag, actionOptions) defer postHandler(ad, option.ACTION_Drag, actionOptions)
duration := 200.0 duration := 200.0
if actionOptions.Duration > 0 { if actionOptions.Duration > 0 {
@@ -412,7 +412,7 @@ func (ad *ADBDriver) Swipe(fromX, fromY, toX, toY float64, opts ...option.Action
if err != nil { if err != nil {
return err return err
} }
defer postHandler(ad, ACTION_Swipe, actionOptions) defer postHandler(ad, option.ACTION_Swipe, actionOptions)
// adb shell input swipe fromX fromY toX toY // adb shell input swipe fromX fromY toX toY
_, err = ad.runShellCommand( _, err = ad.runShellCommand(
+4 -4
View File
@@ -262,7 +262,7 @@ func (ud *UIA2Driver) DoubleTap(x, y float64, opts ...option.ActionOption) error
if err != nil { if err != nil {
return err return err
} }
defer postHandler(ud, ACTION_DoubleTapXY, actionOptions) defer postHandler(ud, option.ACTION_DoubleTapXY, actionOptions)
data := map[string]interface{}{ data := map[string]interface{}{
"actions": []interface{}{ "actions": []interface{}{
@@ -304,7 +304,7 @@ func (ud *UIA2Driver) TapAbsXY(x, y float64, opts ...option.ActionOption) error
if err != nil { if err != nil {
return err return err
} }
defer postHandler(ud, ACTION_TapAbsXY, actionOptions) defer postHandler(ud, option.ACTION_TapAbsXY, actionOptions)
duration := 100.0 duration := 100.0
if actionOptions.PressDuration > 0 { if actionOptions.PressDuration > 0 {
@@ -367,7 +367,7 @@ func (ud *UIA2Driver) Drag(fromX, fromY, toX, toY float64, opts ...option.Action
if err != nil { if err != nil {
return err return err
} }
defer postHandler(ud, ACTION_Drag, actionOptions) defer postHandler(ud, option.ACTION_Drag, actionOptions)
data := map[string]interface{}{ data := map[string]interface{}{
"startX": fromX, "startX": fromX,
@@ -398,7 +398,7 @@ func (ud *UIA2Driver) Swipe(fromX, fromY, toX, toY float64, opts ...option.Actio
if err != nil { if err != nil {
return err return err
} }
defer postHandler(ud, ACTION_Swipe, actionOptions) defer postHandler(ud, option.ACTION_Swipe, actionOptions)
duration := 200.0 duration := 200.0
if actionOptions.PressDuration > 0 { if actionOptions.PressDuration > 0 {
+3 -3
View File
@@ -119,7 +119,7 @@ func (wd *BrowserDriver) Drag(fromX, fromY, toX, toY float64, options ...option.
if err != nil { if err != nil {
return err return err
} }
defer postHandler(wd, ACTION_Drag, actionOptions) defer postHandler(wd, option.ACTION_Drag, actionOptions)
data := map[string]interface{}{ data := map[string]interface{}{
"from_x": fromX, "from_x": fromX,
@@ -518,7 +518,7 @@ func (wd *BrowserDriver) TapFloat(x, y float64, opts ...option.ActionOption) err
if err != nil { if err != nil {
return err return err
} }
defer postHandler(wd, ACTION_TapAbsXY, actionOptions) defer postHandler(wd, option.ACTION_TapAbsXY, actionOptions)
duration := 0.1 duration := 0.1
if actionOptions.Duration > 0 { if actionOptions.Duration > 0 {
@@ -542,7 +542,7 @@ func (wd *BrowserDriver) DoubleTap(x, y float64, options ...option.ActionOption)
if err != nil { if err != nil {
return err return err
} }
defer postHandler(wd, ACTION_DoubleTapXY, actionOptions) defer postHandler(wd, option.ACTION_DoubleTapXY, actionOptions)
data := map[string]interface{}{ data := map[string]interface{}{
"x": x, "x": x,
+49 -118
View File
@@ -14,78 +14,8 @@ import (
"github.com/httprunner/httprunner/v5/uixt/option" "github.com/httprunner/httprunner/v5/uixt/option"
) )
type ActionMethod string
const (
ACTION_LOG ActionMethod = "log"
ACTION_AppInstall ActionMethod = "install"
ACTION_AppUninstall ActionMethod = "uninstall"
ACTION_WebLoginNoneUI ActionMethod = "login_none_ui"
ACTION_AppClear ActionMethod = "app_clear"
ACTION_AppStart ActionMethod = "app_start"
ACTION_AppLaunch ActionMethod = "app_launch" // 启动 app 并堵塞等待 app 首屏加载完成
ACTION_AppTerminate ActionMethod = "app_terminate"
ACTION_AppStop ActionMethod = "app_stop"
ACTION_ScreenShot ActionMethod = "screenshot"
ACTION_Sleep ActionMethod = "sleep"
ACTION_SleepMS ActionMethod = "sleep_ms"
ACTION_SleepRandom ActionMethod = "sleep_random"
ACTION_SetIme ActionMethod = "set_ime"
ACTION_GetSource ActionMethod = "get_source"
ACTION_GetForegroundApp ActionMethod = "get_foreground_app"
ACTION_CallFunction ActionMethod = "call_function"
// UI handling
ACTION_Home ActionMethod = "home"
ACTION_TapXY ActionMethod = "tap_xy"
ACTION_TapAbsXY ActionMethod = "tap_abs_xy"
ACTION_TapByOCR ActionMethod = "tap_ocr"
ACTION_TapByCV ActionMethod = "tap_cv"
ACTION_DoubleTapXY ActionMethod = "double_tap_xy"
ACTION_Swipe ActionMethod = "swipe"
ACTION_Drag ActionMethod = "drag"
ACTION_Input ActionMethod = "input"
ACTION_Back ActionMethod = "back"
ACTION_KeyCode ActionMethod = "keycode"
ACTION_AIAction ActionMethod = "ai_action" // action with ai
ACTION_TapBySelector ActionMethod = "tap_by_selector"
ACTION_HoverBySelector ActionMethod = "hover_by_selector"
ACTION_WebCloseTab ActionMethod = "web_close_tab"
ACTION_SecondaryClick ActionMethod = "secondary_click"
ACTION_SecondaryClickBySelector ActionMethod = "secondary_click_by_selector"
ACTION_GetElementTextBySelector ActionMethod = "get_element_text_by_selector"
// custom actions
ACTION_SwipeToTapApp ActionMethod = "swipe_to_tap_app" // swipe left & right to find app and tap
ACTION_SwipeToTapText ActionMethod = "swipe_to_tap_text" // swipe up & down to find text and tap
ACTION_SwipeToTapTexts ActionMethod = "swipe_to_tap_texts" // swipe up & down to find text and tap
ACTION_ClosePopups ActionMethod = "close_popups"
ACTION_EndToEndDelay ActionMethod = "live_e2e"
ACTION_InstallApp ActionMethod = "install_app"
ACTION_UninstallApp ActionMethod = "uninstall_app"
ACTION_DownloadApp ActionMethod = "download_app"
)
const (
// UI validation
// selectors
SelectorName string = "ui_name"
SelectorLabel string = "ui_label"
SelectorOCR string = "ui_ocr"
SelectorImage string = "ui_image"
SelectorAI string = "ui_ai" // ui query with ai
SelectorForegroundApp string = "ui_foreground_app"
SelectorSelector string = "ui_selector"
// assertions
AssertionEqual string = "equal"
AssertionNotEqual string = "not_equal"
AssertionExists string = "exists"
AssertionNotExists string = "not_exists"
AssertionAI string = "ai_assert" // assert with ai
)
type MobileAction struct { type MobileAction struct {
Method ActionMethod `json:"method,omitempty" yaml:"method,omitempty"` Method option.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:"-"` // used for function action, not serialized Fn func() `json:"-" yaml:"-"` // used for function action, not serialized
Options *option.ActionOptions `json:"options,omitempty" yaml:"options,omitempty"` Options *option.ActionOptions `json:"options,omitempty" yaml:"options,omitempty"`
@@ -102,6 +32,7 @@ func (ma MobileAction) GetOptions() []option.ActionOption {
return actionOptionList return actionOptionList
} }
// TODO: merge to uixt MCP Server
func (dExt *XTDriver) DoAction(action MobileAction) (err error) { func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
actionStartTime := time.Now() actionStartTime := time.Now()
defer func() { defer func() {
@@ -119,7 +50,7 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
}() }()
switch action.Method { switch action.Method {
case ACTION_WebLoginNoneUI: case option.ACTION_WebLoginNoneUI:
if len(action.Params.([]interface{})) == 4 { if len(action.Params.([]interface{})) == 4 {
driver, ok := dExt.IDriver.(*BrowserDriver) driver, ok := dExt.IDriver.(*BrowserDriver)
if !ok { if !ok {
@@ -129,53 +60,53 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
_, err = driver.LoginNoneUI(params[0].(string), params[1].(string), params[2].(string), params[3].(string)) _, err = driver.LoginNoneUI(params[0].(string), params[1].(string), params[2].(string), params[3].(string))
return err return err
} }
return fmt.Errorf("invalid %s params: %v", ACTION_WebLoginNoneUI, action.Params) return fmt.Errorf("invalid %s params: %v", option.ACTION_WebLoginNoneUI, action.Params)
case ACTION_AppInstall: case option.ACTION_AppInstall:
if app, ok := action.Params.(string); ok { if app, ok := action.Params.(string); ok {
if err = dExt.GetDevice().Install(app, if err = dExt.GetDevice().Install(app,
option.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")
} }
} }
case ACTION_AppUninstall: case option.ACTION_AppUninstall:
if packageName, ok := action.Params.(string); ok { if packageName, ok := action.Params.(string); ok {
if err = dExt.GetDevice().Uninstall(packageName); err != nil { if err = dExt.GetDevice().Uninstall(packageName); err != nil {
return errors.Wrap(err, "failed to uninstall app") return errors.Wrap(err, "failed to uninstall app")
} }
} }
case ACTION_AppClear: case option.ACTION_AppClear:
if packageName, ok := action.Params.(string); ok { if packageName, ok := action.Params.(string); ok {
if err = dExt.AppClear(packageName); err != nil { if err = dExt.AppClear(packageName); err != nil {
return errors.Wrap(err, "failed to clear app") return errors.Wrap(err, "failed to clear app")
} }
} }
case ACTION_AppLaunch: case option.ACTION_AppLaunch:
if bundleId, ok := action.Params.(string); ok { if bundleId, ok := action.Params.(string); ok {
return dExt.AppLaunch(bundleId) return dExt.AppLaunch(bundleId)
} }
return fmt.Errorf("invalid %s params, should be bundleId(string), got %v", return fmt.Errorf("invalid %s params, should be bundleId(string), got %v",
ACTION_AppLaunch, action.Params) option.ACTION_AppLaunch, action.Params)
case ACTION_SwipeToTapApp: case option.ACTION_SwipeToTapApp:
if appName, ok := action.Params.(string); ok { if appName, ok := action.Params.(string); ok {
return dExt.SwipeToTapApp(appName, action.GetOptions()...) return dExt.SwipeToTapApp(appName, action.GetOptions()...)
} }
return fmt.Errorf("invalid %s params, should be app name(string), got %v", return fmt.Errorf("invalid %s params, should be app name(string), got %v",
ACTION_SwipeToTapApp, action.Params) option.ACTION_SwipeToTapApp, action.Params)
case ACTION_SwipeToTapText: case option.ACTION_SwipeToTapText:
if text, ok := action.Params.(string); ok { if text, ok := action.Params.(string); ok {
return dExt.SwipeToTapTexts([]string{text}, action.GetOptions()...) return dExt.SwipeToTapTexts([]string{text}, action.GetOptions()...)
} }
return fmt.Errorf("invalid %s params, should be app text(string), got %v", return fmt.Errorf("invalid %s params, should be app text(string), got %v",
ACTION_SwipeToTapText, action.Params) option.ACTION_SwipeToTapText, action.Params)
case ACTION_SwipeToTapTexts: case option.ACTION_SwipeToTapTexts:
if texts, ok := action.Params.([]string); ok { if texts, ok := action.Params.([]string); ok {
return dExt.SwipeToTapTexts(texts, action.GetOptions()...) return dExt.SwipeToTapTexts(texts, action.GetOptions()...)
} }
if texts, err := builtin.ConvertToStringSlice(action.Params); err == nil { if texts, err := builtin.ConvertToStringSlice(action.Params); err == nil {
return dExt.SwipeToTapTexts(texts, action.GetOptions()...) return dExt.SwipeToTapTexts(texts, action.GetOptions()...)
} }
return fmt.Errorf("invalid %s params: %v", ACTION_SwipeToTapTexts, action.Params) return fmt.Errorf("invalid %s params: %v", option.ACTION_SwipeToTapTexts, action.Params)
case ACTION_AppTerminate: case option.ACTION_AppTerminate:
if bundleId, ok := action.Params.(string); ok { if bundleId, ok := action.Params.(string); ok {
success, err := dExt.AppTerminate(bundleId) success, err := dExt.AppTerminate(bundleId)
if err != nil { if err != nil {
@@ -187,9 +118,9 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
return nil return nil
} }
return fmt.Errorf("app_terminate params should be bundleId(string), got %v", action.Params) return fmt.Errorf("app_terminate params should be bundleId(string), got %v", action.Params)
case ACTION_Home: case option.ACTION_Home:
return dExt.Home() return dExt.Home()
case ACTION_SecondaryClick: case option.ACTION_SecondaryClick:
if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil { if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil {
if len(params) != 2 { if len(params) != 2 {
return fmt.Errorf("invalid tap location params: %v", params) return fmt.Errorf("invalid tap location params: %v", params)
@@ -197,23 +128,23 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
x, y := params[0], params[1] x, y := params[0], params[1]
return dExt.SecondaryClick(x, y) return dExt.SecondaryClick(x, y)
} }
return fmt.Errorf("invalid %s params: %v", ACTION_SecondaryClick, action.Params) return fmt.Errorf("invalid %s params: %v", option.ACTION_SecondaryClick, action.Params)
case ACTION_HoverBySelector: case option.ACTION_HoverBySelector:
if selector, ok := action.Params.(string); ok { if selector, ok := action.Params.(string); ok {
return dExt.HoverBySelector(selector, action.GetOptions()...) return dExt.HoverBySelector(selector, action.GetOptions()...)
} }
return fmt.Errorf("invalid %s params: %v", ACTION_HoverBySelector, action.Params) return fmt.Errorf("invalid %s params: %v", option.ACTION_HoverBySelector, action.Params)
case ACTION_TapBySelector: case option.ACTION_TapBySelector:
if selector, ok := action.Params.(string); ok { if selector, ok := action.Params.(string); ok {
return dExt.TapBySelector(selector, action.GetOptions()...) return dExt.TapBySelector(selector, action.GetOptions()...)
} }
return fmt.Errorf("invalid %s params: %v", ACTION_TapBySelector, action.Params) return fmt.Errorf("invalid %s params: %v", option.ACTION_TapBySelector, action.Params)
case ACTION_SecondaryClickBySelector: case option.ACTION_SecondaryClickBySelector:
if selector, ok := action.Params.(string); ok { if selector, ok := action.Params.(string); ok {
return dExt.SecondaryClickBySelector(selector, action.GetOptions()...) return dExt.SecondaryClickBySelector(selector, action.GetOptions()...)
} }
return fmt.Errorf("invalid %s params: %v", ACTION_SecondaryClickBySelector, action.Params) return fmt.Errorf("invalid %s params: %v", option.ACTION_SecondaryClickBySelector, action.Params)
case ACTION_WebCloseTab: case option.ACTION_WebCloseTab:
if param, ok := action.Params.(json.Number); ok { if param, ok := action.Params.(json.Number); ok {
paramInt64, _ := param.Int64() paramInt64, _ := param.Int64()
return dExt.IDriver.(*BrowserDriver).CloseTab(int(paramInt64)) return dExt.IDriver.(*BrowserDriver).CloseTab(int(paramInt64))
@@ -223,7 +154,7 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
return dExt.IDriver.(*BrowserDriver).CloseTab(action.Params.(int)) return dExt.IDriver.(*BrowserDriver).CloseTab(action.Params.(int))
} }
// return fmt.Errorf("invalid %s params: %v", ACTION_WebCloseTab, action.Params) // return fmt.Errorf("invalid %s params: %v", ACTION_WebCloseTab, action.Params)
case ACTION_SetIme: case option.ACTION_SetIme:
if ime, ok := action.Params.(string); ok { if ime, ok := action.Params.(string); ok {
err = dExt.SetIme(ime) err = dExt.SetIme(ime)
if err != nil { if err != nil {
@@ -231,7 +162,7 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
} }
return nil return nil
} }
case ACTION_GetSource: case option.ACTION_GetSource:
if packageName, ok := action.Params.(string); ok { if packageName, ok := action.Params.(string); ok {
_, err = dExt.Source(option.WithProcessName(packageName)) _, err = dExt.Source(option.WithProcessName(packageName))
if err != nil { if err != nil {
@@ -239,7 +170,7 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
} }
return nil return nil
} }
case ACTION_TapXY: case option.ACTION_TapXY:
if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil { if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil {
// relative x,y of window size: [0.5, 0.5] // relative x,y of window size: [0.5, 0.5]
if len(params) != 2 { if len(params) != 2 {
@@ -248,8 +179,8 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
x, y := params[0], params[1] x, y := params[0], params[1]
return dExt.TapXY(x, y, action.GetOptions()...) return dExt.TapXY(x, y, action.GetOptions()...)
} }
return fmt.Errorf("invalid %s params: %v", ACTION_TapXY, action.Params) return fmt.Errorf("invalid %s params: %v", option.ACTION_TapXY, action.Params)
case ACTION_TapAbsXY: case option.ACTION_TapAbsXY:
if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil { if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil {
// absolute coordinates x,y of window size: [100, 300] // absolute coordinates x,y of window size: [100, 300]
if len(params) != 2 { if len(params) != 2 {
@@ -258,19 +189,19 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
x, y := params[0], params[1] x, y := params[0], params[1]
return dExt.TapAbsXY(x, y, action.GetOptions()...) return dExt.TapAbsXY(x, y, action.GetOptions()...)
} }
return fmt.Errorf("invalid %s params: %v", ACTION_TapAbsXY, action.Params) return fmt.Errorf("invalid %s params: %v", option.ACTION_TapAbsXY, action.Params)
case ACTION_TapByOCR: case option.ACTION_TapByOCR:
if ocrText, ok := action.Params.(string); ok { if ocrText, ok := action.Params.(string); ok {
return dExt.TapByOCR(ocrText, action.GetOptions()...) return dExt.TapByOCR(ocrText, action.GetOptions()...)
} }
return fmt.Errorf("invalid %s params: %v", ACTION_TapByOCR, action.Params) return fmt.Errorf("invalid %s params: %v", option.ACTION_TapByOCR, action.Params)
case ACTION_TapByCV: case option.ACTION_TapByCV:
actionOptions := option.NewActionOptions(action.GetOptions()...) actionOptions := option.NewActionOptions(action.GetOptions()...)
if len(actionOptions.ScreenShotWithUITypes) > 0 { if len(actionOptions.ScreenShotWithUITypes) > 0 {
return dExt.TapByCV(action.GetOptions()...) return dExt.TapByCV(action.GetOptions()...)
} }
return fmt.Errorf("invalid %s params: %v", ACTION_TapByCV, action.Params) return fmt.Errorf("invalid %s params: %v", option.ACTION_TapByCV, action.Params)
case ACTION_DoubleTapXY: case option.ACTION_DoubleTapXY:
if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil { if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil {
// relative x,y of window size: [0.5, 0.5] // relative x,y of window size: [0.5, 0.5]
if len(params) != 2 { if len(params) != 2 {
@@ -279,20 +210,20 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
x, y := params[0], params[1] x, y := params[0], params[1]
return dExt.DoubleTap(x, y) return dExt.DoubleTap(x, y)
} }
return fmt.Errorf("invalid %s params: %v", ACTION_DoubleTapXY, action.Params) return fmt.Errorf("invalid %s params: %v", option.ACTION_DoubleTapXY, action.Params)
case ACTION_Swipe: case option.ACTION_Swipe:
params := action.Params params := action.Params
swipeAction := prepareSwipeAction(dExt, params, action.GetOptions()...) swipeAction := prepareSwipeAction(dExt, params, action.GetOptions()...)
return swipeAction(dExt) return swipeAction(dExt)
case ACTION_Input: case option.ACTION_Input:
// input text on current active element // input text on current active element
// append \n to send text with enter // append \n to send text with enter
// send \b\b\b to delete 3 chars // send \b\b\b to delete 3 chars
param := fmt.Sprintf("%v", action.Params) param := fmt.Sprintf("%v", action.Params)
return dExt.Input(param) return dExt.Input(param)
case ACTION_Back: case option.ACTION_Back:
return dExt.Back() return dExt.Back()
case ACTION_Sleep: case option.ACTION_Sleep:
if param, ok := action.Params.(json.Number); ok { if param, ok := action.Params.(json.Number); ok {
seconds, _ := param.Float64() seconds, _ := param.Float64()
time.Sleep(time.Duration(seconds*1000) * time.Millisecond) time.Sleep(time.Duration(seconds*1000) * time.Millisecond)
@@ -315,7 +246,7 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
return nil return nil
} }
return fmt.Errorf("invalid sleep params: %v(%T)", action.Params, action.Params) return fmt.Errorf("invalid sleep params: %v(%T)", action.Params, action.Params)
case ACTION_SleepMS: case option.ACTION_SleepMS:
if param, ok := action.Params.(json.Number); ok { if param, ok := action.Params.(json.Number); ok {
milliseconds, _ := param.Int64() milliseconds, _ := param.Int64()
time.Sleep(time.Duration(milliseconds) * time.Millisecond) time.Sleep(time.Duration(milliseconds) * time.Millisecond)
@@ -328,29 +259,29 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
return nil return nil
} }
return fmt.Errorf("invalid sleep ms params: %v(%T)", action.Params, action.Params) return fmt.Errorf("invalid sleep ms params: %v(%T)", action.Params, action.Params)
case ACTION_SleepRandom: case option.ACTION_SleepRandom:
if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil { if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil {
sleepStrict(time.Now(), getSimulationDuration(params)) sleepStrict(time.Now(), getSimulationDuration(params))
return nil return nil
} }
return fmt.Errorf("invalid sleep random params: %v(%T)", action.Params, action.Params) return fmt.Errorf("invalid sleep random params: %v(%T)", action.Params, action.Params)
case ACTION_ScreenShot: case option.ACTION_ScreenShot:
// take screenshot // take screenshot
log.Info().Msg("take screenshot for current screen") log.Info().Msg("take screenshot for current screen")
_, err := dExt.GetScreenResult(action.GetScreenShotOptions()...) _, err := dExt.GetScreenResult(action.GetScreenShotOptions()...)
return err return err
case ACTION_ClosePopups: case option.ACTION_ClosePopups:
return dExt.ClosePopupsHandler() return dExt.ClosePopupsHandler()
case ACTION_CallFunction: case option.ACTION_CallFunction:
if funcDesc, ok := action.Params.(string); ok { if funcDesc, ok := action.Params.(string); ok {
return dExt.Call(funcDesc, action.Fn, action.GetOptions()...) return dExt.Call(funcDesc, action.Fn, action.GetOptions()...)
} }
return fmt.Errorf("invalid function description: %v", action.Params) return fmt.Errorf("invalid function description: %v", action.Params)
case ACTION_AIAction: case option.ACTION_AIAction:
if prompt, ok := action.Params.(string); ok { if prompt, ok := action.Params.(string); ok {
return dExt.AIAction(prompt, action.GetOptions()...) return dExt.AIAction(prompt, action.GetOptions()...)
} }
return fmt.Errorf("invalid %s params: %v", ACTION_AIAction, action.Params) return fmt.Errorf("invalid %s params: %v", option.ACTION_AIAction, action.Params)
default: default:
log.Warn().Str("action", string(action.Method)).Msg("action not implemented") log.Warn().Str("action", string(action.Method)).Msg("action not implemented")
return errors.Wrapf(code.InvalidCaseError, return errors.Wrapf(code.InvalidCaseError,
+3 -3
View File
@@ -322,7 +322,7 @@ func compressImageBuffer(raw *bytes.Buffer) (compressed *bytes.Buffer, err error
} }
// MarkUIOperation add operation mark for UI operation // MarkUIOperation add operation mark for UI operation
func MarkUIOperation(driver IDriver, actionType ActionMethod, actionCoordinates []float64) error { func MarkUIOperation(driver IDriver, actionType option.ActionMethod, actionCoordinates []float64) error {
if actionType == "" || len(actionCoordinates) == 0 { if actionType == "" || len(actionCoordinates) == 0 {
return nil return nil
} }
@@ -341,14 +341,14 @@ func MarkUIOperation(driver IDriver, actionType ActionMethod, actionCoordinates
fmt.Sprintf("action_%s_pre_%s.png", timestamp, actionType), fmt.Sprintf("action_%s_pre_%s.png", timestamp, actionType),
) )
if actionType == ACTION_TapAbsXY || actionType == ACTION_DoubleTapXY { if actionType == option.ACTION_TapAbsXY || actionType == option.ACTION_DoubleTapXY {
if len(actionCoordinates) != 2 { if len(actionCoordinates) != 2 {
return fmt.Errorf("invalid tap action coordinates: %v", actionCoordinates) return fmt.Errorf("invalid tap action coordinates: %v", actionCoordinates)
} }
x, y := actionCoordinates[0], actionCoordinates[1] x, y := actionCoordinates[0], actionCoordinates[1]
point := image.Point{X: int(x), Y: int(y)} point := image.Point{X: int(x), Y: int(y)}
err = SaveImageWithCircleMarker(compressedBufSource, point, imagePath) err = SaveImageWithCircleMarker(compressedBufSource, point, imagePath)
} else if actionType == ACTION_Swipe || actionType == ACTION_Drag { } else if actionType == option.ACTION_Swipe || actionType == option.ACTION_Drag {
if len(actionCoordinates) != 4 { if len(actionCoordinates) != 4 {
return fmt.Errorf("invalid swipe action coordinates: %v", actionCoordinates) return fmt.Errorf("invalid swipe action coordinates: %v", actionCoordinates)
} }
+5 -5
View File
@@ -51,7 +51,7 @@ func preHandler_TapAbsXY(driver IDriver, options *option.ActionOptions, rawX, ra
// mark UI operation // mark UI operation
if options.PreMarkOperation { if options.PreMarkOperation {
if markErr := MarkUIOperation(driver, ACTION_TapAbsXY, []float64{x, y}); markErr != nil { if markErr := MarkUIOperation(driver, option.ACTION_TapAbsXY, []float64{x, y}); markErr != nil {
log.Warn().Err(markErr).Msg("Failed to mark tap operation") log.Warn().Err(markErr).Msg("Failed to mark tap operation")
} }
} }
@@ -71,7 +71,7 @@ func preHandler_DoubleTap(driver IDriver, options *option.ActionOptions, rawX, r
// mark UI operation // mark UI operation
if options.PreMarkOperation { if options.PreMarkOperation {
if markErr := MarkUIOperation(driver, ACTION_DoubleTapXY, []float64{x, y}); markErr != nil { if markErr := MarkUIOperation(driver, option.ACTION_DoubleTapXY, []float64{x, y}); markErr != nil {
log.Warn().Err(markErr).Msg("Failed to mark double tap operation") log.Warn().Err(markErr).Msg("Failed to mark double tap operation")
} }
} }
@@ -90,7 +90,7 @@ func preHandler_Drag(driver IDriver, options *option.ActionOptions, rawFomX, raw
// mark UI operation // mark UI operation
if options.PreMarkOperation { if options.PreMarkOperation {
if markErr := MarkUIOperation(driver, ACTION_Drag, []float64{fromX, fromY, toX, toY}); markErr != nil { if markErr := MarkUIOperation(driver, option.ACTION_Drag, []float64{fromX, fromY, toX, toY}); markErr != nil {
log.Warn().Err(markErr).Msg("Failed to mark drag operation") log.Warn().Err(markErr).Msg("Failed to mark drag operation")
} }
} }
@@ -109,7 +109,7 @@ func preHandler_Swipe(driver IDriver, options *option.ActionOptions, rawFomX, ra
// save screenshot before action and mark UI operation // save screenshot before action and mark UI operation
if options.PreMarkOperation { if options.PreMarkOperation {
if markErr := MarkUIOperation(driver, ACTION_Swipe, []float64{fromX, fromY, toX, toY}); markErr != nil { if markErr := MarkUIOperation(driver, option.ACTION_Swipe, []float64{fromX, fromY, toX, toY}); markErr != nil {
log.Warn().Err(markErr).Msg("Failed to mark swipe operation") log.Warn().Err(markErr).Msg("Failed to mark swipe operation")
} }
} }
@@ -117,7 +117,7 @@ func preHandler_Swipe(driver IDriver, options *option.ActionOptions, rawFomX, ra
return fromX, fromY, toX, toY, nil return fromX, fromY, toX, toY, nil
} }
func postHandler(driver IDriver, actionType ActionMethod, options *option.ActionOptions) error { func postHandler(driver IDriver, actionType option.ActionMethod, options *option.ActionOptions) error {
// save screenshot after action // save screenshot after action
if options.PostMarkOperation { if options.PostMarkOperation {
// get compressed screenshot buffer // get compressed screenshot buffer
+12 -12
View File
@@ -130,23 +130,23 @@ func (dExt *XTDriver) assertOCR(text, assert string) error {
opts = append(opts, option.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 option.AssertionEqual:
_, err := dExt.FindScreenText(text, opts...) _, err := dExt.FindScreenText(text, opts...)
if err != nil { if err != nil {
return errors.Wrap(err, "assert ocr equal failed") return errors.Wrap(err, "assert ocr equal failed")
} }
case AssertionNotEqual: case option.AssertionNotEqual:
_, err := dExt.FindScreenText(text, opts...) _, err := dExt.FindScreenText(text, opts...)
if err == nil { if err == nil {
return errors.New("assert ocr not equal failed") return errors.New("assert ocr not equal failed")
} }
case AssertionExists: case option.AssertionExists:
opts = append(opts, option.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 option.AssertionNotExists:
opts = append(opts, option.WithRegex(true)) opts = append(opts, option.WithRegex(true))
_, err := dExt.FindScreenText(text, opts...) _, err := dExt.FindScreenText(text, opts...)
if err == nil { if err == nil {
@@ -166,11 +166,11 @@ func (dExt *XTDriver) assertForegroundApp(appName, assert string) error {
} }
switch assert { switch assert {
case AssertionEqual: case option.AssertionEqual:
if app.PackageName != appName { if app.PackageName != appName {
return errors.Wrap(err, "assert foreground app equal failed") return errors.Wrap(err, "assert foreground app equal failed")
} }
case AssertionNotEqual: case option.AssertionNotEqual:
if app.PackageName == appName { if app.PackageName == appName {
return errors.New("assert foreground app not equal failed") return errors.New("assert foreground app not equal failed")
} }
@@ -186,12 +186,12 @@ func (dExt *XTDriver) assertSelector(selector, assert string) error {
return errors.New("assert selector only supports browser driver") return errors.New("assert selector only supports browser driver")
} }
switch assert { switch assert {
case AssertionExists: case option.AssertionExists:
_, err := driver.IsElementExistBySelector(selector) _, err := driver.IsElementExistBySelector(selector)
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 option.AssertionNotExists:
_, err := driver.IsElementExistBySelector(selector) _, err := driver.IsElementExistBySelector(selector)
if err == nil { if err == nil {
return errors.New("assert ocr not exists failed") return errors.New("assert ocr not exists failed")
@@ -204,13 +204,13 @@ func (dExt *XTDriver) assertSelector(selector, assert string) error {
func (dExt *XTDriver) 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 option.SelectorOCR:
err = dExt.assertOCR(expected, assert) err = dExt.assertOCR(expected, assert)
case SelectorAI: case option.SelectorAI:
err = dExt.AIAssert(assert) err = dExt.AIAssert(assert)
case SelectorForegroundApp: case option.SelectorForegroundApp:
err = dExt.assertForegroundApp(expected, assert) err = dExt.assertForegroundApp(expected, assert)
case SelectorSelector: case option.SelectorSelector:
err = dExt.assertSelector(expected, assert) err = dExt.assertSelector(expected, assert)
default: default:
return fmt.Errorf("validator %s not implemented", check) return fmt.Errorf("validator %s not implemented", check)
+2 -2
View File
@@ -159,7 +159,7 @@ func (hd *HDCDriver) TapAbsXY(x, y float64, opts ...option.ActionOption) error {
if err != nil { if err != nil {
return err return err
} }
defer postHandler(hd, ACTION_TapAbsXY, actionOptions) defer postHandler(hd, option.ACTION_TapAbsXY, actionOptions)
if actionOptions.Identifier != "" { if actionOptions.Identifier != "" {
startTime := int(time.Now().UnixMilli()) startTime := int(time.Now().UnixMilli())
@@ -191,7 +191,7 @@ func (hd *HDCDriver) Swipe(fromX, fromY, toX, toY float64, opts ...option.Action
if err != nil { if err != nil {
return err return err
} }
defer postHandler(hd, ACTION_Swipe, actionOptions) defer postHandler(hd, option.ACTION_Swipe, actionOptions)
duration := 200 duration := 200
if actionOptions.PressDuration > 0 { if actionOptions.PressDuration > 0 {
+3 -3
View File
@@ -602,7 +602,7 @@ func (wd *WDADriver) TapAbsXY(x, y float64, opts ...option.ActionOption) error {
if err != nil { if err != nil {
return err return err
} }
defer postHandler(wd, ACTION_TapAbsXY, actionOptions) defer postHandler(wd, option.ACTION_TapAbsXY, actionOptions)
data := map[string]interface{}{ data := map[string]interface{}{
"x": x, "x": x,
@@ -627,7 +627,7 @@ func (wd *WDADriver) DoubleTap(x, y float64, opts ...option.ActionOption) error
if err != nil { if err != nil {
return err return err
} }
defer postHandler(wd, ACTION_DoubleTapXY, actionOptions) defer postHandler(wd, option.ACTION_DoubleTapXY, actionOptions)
data := map[string]interface{}{ data := map[string]interface{}{
"x": x, "x": x,
@@ -664,7 +664,7 @@ func (wd *WDADriver) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionO
if err != nil { if err != nil {
return err return err
} }
defer postHandler(wd, ACTION_Drag, actionOptions) defer postHandler(wd, option.ACTION_Drag, actionOptions)
data := map[string]interface{}{ data := map[string]interface{}{
"fromX": math.Round(fromX*10) / 10, "fromX": math.Round(fromX*10) / 10,
+70
View File
@@ -8,6 +8,76 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
type ActionMethod string
const (
ACTION_LOG ActionMethod = "log"
ACTION_AppInstall ActionMethod = "install"
ACTION_AppUninstall ActionMethod = "uninstall"
ACTION_WebLoginNoneUI ActionMethod = "login_none_ui"
ACTION_AppClear ActionMethod = "app_clear"
ACTION_AppStart ActionMethod = "app_start"
ACTION_AppLaunch ActionMethod = "app_launch" // 启动 app 并堵塞等待 app 首屏加载完成
ACTION_AppTerminate ActionMethod = "app_terminate"
ACTION_AppStop ActionMethod = "app_stop"
ACTION_ScreenShot ActionMethod = "screenshot"
ACTION_Sleep ActionMethod = "sleep"
ACTION_SleepMS ActionMethod = "sleep_ms"
ACTION_SleepRandom ActionMethod = "sleep_random"
ACTION_SetIme ActionMethod = "set_ime"
ACTION_GetSource ActionMethod = "get_source"
ACTION_GetForegroundApp ActionMethod = "get_foreground_app"
ACTION_CallFunction ActionMethod = "call_function"
// UI handling
ACTION_Home ActionMethod = "home"
ACTION_TapXY ActionMethod = "tap_xy"
ACTION_TapAbsXY ActionMethod = "tap_abs_xy"
ACTION_TapByOCR ActionMethod = "tap_ocr"
ACTION_TapByCV ActionMethod = "tap_cv"
ACTION_DoubleTapXY ActionMethod = "double_tap_xy"
ACTION_Swipe ActionMethod = "swipe"
ACTION_Drag ActionMethod = "drag"
ACTION_Input ActionMethod = "input"
ACTION_Back ActionMethod = "back"
ACTION_KeyCode ActionMethod = "keycode"
ACTION_AIAction ActionMethod = "ai_action" // action with ai
ACTION_TapBySelector ActionMethod = "tap_by_selector"
ACTION_HoverBySelector ActionMethod = "hover_by_selector"
ACTION_WebCloseTab ActionMethod = "web_close_tab"
ACTION_SecondaryClick ActionMethod = "secondary_click"
ACTION_SecondaryClickBySelector ActionMethod = "secondary_click_by_selector"
ACTION_GetElementTextBySelector ActionMethod = "get_element_text_by_selector"
// custom actions
ACTION_SwipeToTapApp ActionMethod = "swipe_to_tap_app" // swipe left & right to find app and tap
ACTION_SwipeToTapText ActionMethod = "swipe_to_tap_text" // swipe up & down to find text and tap
ACTION_SwipeToTapTexts ActionMethod = "swipe_to_tap_texts" // swipe up & down to find text and tap
ACTION_ClosePopups ActionMethod = "close_popups"
ACTION_EndToEndDelay ActionMethod = "live_e2e"
ACTION_InstallApp ActionMethod = "install_app"
ACTION_UninstallApp ActionMethod = "uninstall_app"
ACTION_DownloadApp ActionMethod = "download_app"
)
const (
// UI validation
// selectors
SelectorName string = "ui_name"
SelectorLabel string = "ui_label"
SelectorOCR string = "ui_ocr"
SelectorImage string = "ui_image"
SelectorAI string = "ui_ai" // ui query with ai
SelectorForegroundApp string = "ui_foreground_app"
SelectorSelector string = "ui_selector"
// assertions
AssertionEqual string = "equal"
AssertionNotEqual string = "not_equal"
AssertionExists string = "exists"
AssertionNotExists string = "not_exists"
AssertionAI string = "ai_assert" // assert with ai
)
type ActionOptions struct { type ActionOptions struct {
Context context.Context `json:"-" yaml:"-"` Context context.Context `json:"-" yaml:"-"`
// log // log
+1 -1
View File
@@ -94,7 +94,7 @@ func convertActionToCallToolRequest(action MobileAction) (mcp.CallToolRequest, e
return mcp.CallToolRequest{}, nil return mcp.CallToolRequest{}, nil
} }
func (dExt *XTDriver) DoAction2(action MobileAction) (err error) { func (dExt *XTDriver) ExecuteAction(action MobileAction) (err error) {
// convert action to call tool request // convert action to call tool request
req, err := convertActionToCallToolRequest(action) req, err := convertActionToCallToolRequest(action)
if err != nil { if err != nil {