refactor: move action options

This commit is contained in:
lilong.129
2025-05-25 00:09:25 +08:00
parent 97dad38b7b
commit 4ff2692f02
15 changed files with 230 additions and 230 deletions

View File

@@ -8,7 +8,6 @@ import (
"github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/uixt"
"github.com/httprunner/httprunner/v5/uixt/option"
)
@@ -138,17 +137,17 @@ func convertCompatMobileStep(mobileUI *MobileUI) {
ma := mobileUI.Actions[i]
actionOptions := option.NewActionOptions(ma.GetOptions()...)
// 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)
ma.ActionOptions.ScreenShotWithUITypes = append(ma.ActionOptions.ScreenShotWithUITypes, uiTypes...)
ma.ActionOptions.ScreenShotWithUpload = true
}
// 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
}
// 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
}
mobileUI.Actions[i] = ma

View File

@@ -1 +1 @@
v5.0.0-beta-2505242351
v5.0.0-beta-2505250015

View File

@@ -67,9 +67,9 @@ func (s *StepMobile) Serial(serial string) *StepMobile {
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{
Method: uixt.ACTION_LOG,
Method: option.ACTION_LOG,
Params: actionName,
})
return s
@@ -77,7 +77,7 @@ func (s *StepMobile) Log(actionName uixt.ActionMethod) *StepMobile {
func (s *StepMobile) InstallApp(path string) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_AppInstall,
Method: option.ACTION_AppInstall,
Params: path,
})
return s
@@ -85,7 +85,7 @@ func (s *StepMobile) InstallApp(path string) *StepMobile {
func (s *StepMobile) WebLoginNoneUI(packageName, phoneNumber string, captcha, password string) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_WebLoginNoneUI,
Method: option.ACTION_WebLoginNoneUI,
Params: []string{packageName, phoneNumber, captcha, password},
})
return s
@@ -93,7 +93,7 @@ func (s *StepMobile) WebLoginNoneUI(packageName, phoneNumber string, captcha, pa
func (s *StepMobile) AppLaunch(bundleId string) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_AppLaunch,
Method: option.ACTION_AppLaunch,
Params: bundleId,
})
return s
@@ -101,7 +101,7 @@ func (s *StepMobile) AppLaunch(bundleId string) *StepMobile {
func (s *StepMobile) AppTerminate(bundleId string) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_AppTerminate,
Method: option.ACTION_AppTerminate,
Params: bundleId,
})
return s
@@ -109,7 +109,7 @@ func (s *StepMobile) AppTerminate(bundleId string) *StepMobile {
func (s *StepMobile) Home() *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_Home,
Method: option.ACTION_Home,
Params: nil,
})
return s
@@ -120,7 +120,7 @@ func (s *StepMobile) Home() *StepMobile {
// else, X & Y will be considered as absolute coordinates
func (s *StepMobile) TapXY(x, y float64, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_TapXY,
Method: option.ACTION_TapXY,
Params: []float64{x, y},
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
func (s *StepMobile) TapAbsXY(x, y float64, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_TapAbsXY,
Method: option.ACTION_TapAbsXY,
Params: []float64{x, y},
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
func (s *StepMobile) TapByOCR(ocrText string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_TapByOCR,
Method: option.ACTION_TapByOCR,
Params: ocrText,
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
func (s *StepMobile) TapByCV(imagePath string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_TapByCV,
Method: option.ACTION_TapByCV,
Params: imagePath,
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
func (s *StepMobile) TapByUITypes(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_TapByCV,
Method: option.ACTION_TapByCV,
Options: option.NewActionOptions(opts...),
}
@@ -179,7 +179,7 @@ func (s *StepMobile) TapByUITypes(opts ...option.ActionOption) *StepMobile {
// AIAction do actions with VLM
func (s *StepMobile) AIAction(prompt string, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_AIAction,
Method: option.ACTION_AIAction,
Params: prompt,
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
func (s *StepMobile) DoubleTapXY(x, y float64, opts ...option.ActionOption) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_DoubleTapXY,
Method: option.ACTION_DoubleTapXY,
Params: []float64{x, y},
Options: option.NewActionOptions(opts...),
})
@@ -200,7 +200,7 @@ func (s *StepMobile) DoubleTapXY(x, y float64, opts ...option.ActionOption) *Ste
func (s *StepMobile) Back() *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_Back,
Method: option.ACTION_Back,
Params: nil,
Options: nil,
}
@@ -212,7 +212,7 @@ func (s *StepMobile) Back() *StepMobile {
// Swipe drags from [sx, sy] to [ex, ey]
func (s *StepMobile) Swipe(sx, sy, ex, ey float64, opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_Swipe,
Method: option.ACTION_Swipe,
Params: []float64{sx, sy, ex, ey},
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 {
action := uixt.MobileAction{
Method: uixt.ACTION_Swipe,
Method: option.ACTION_Swipe,
Params: "up",
Options: option.NewActionOptions(opts...),
}
@@ -234,7 +234,7 @@ func (s *StepMobile) SwipeUp(opts ...option.ActionOption) *StepMobile {
func (s *StepMobile) SwipeDown(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_Swipe,
Method: option.ACTION_Swipe,
Params: "down",
Options: option.NewActionOptions(opts...),
}
@@ -245,7 +245,7 @@ func (s *StepMobile) SwipeDown(opts ...option.ActionOption) *StepMobile {
func (s *StepMobile) SwipeLeft(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_Swipe,
Method: option.ACTION_Swipe,
Params: "left",
Options: option.NewActionOptions(opts...),
}
@@ -256,7 +256,7 @@ func (s *StepMobile) SwipeLeft(opts ...option.ActionOption) *StepMobile {
func (s *StepMobile) SwipeRight(opts ...option.ActionOption) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_Swipe,
Method: option.ACTION_Swipe,
Params: "right",
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 {
action := uixt.MobileAction{
Method: uixt.ACTION_SwipeToTapApp,
Method: option.ACTION_SwipeToTapApp,
Params: appName,
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 {
action := uixt.MobileAction{
Method: uixt.ACTION_SwipeToTapText,
Method: option.ACTION_SwipeToTapText,
Params: text,
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 {
action := uixt.MobileAction{
Method: uixt.ACTION_SwipeToTapTexts,
Method: option.ACTION_SwipeToTapTexts,
Params: texts,
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 {
action := uixt.MobileAction{
Method: uixt.ACTION_SecondaryClick,
Method: option.ACTION_SecondaryClick,
Params: []float64{x, y},
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 {
action := uixt.MobileAction{
Method: uixt.ACTION_SecondaryClickBySelector,
Method: option.ACTION_SecondaryClickBySelector,
Params: selector,
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 {
action := uixt.MobileAction{
Method: uixt.ACTION_HoverBySelector,
Method: option.ACTION_HoverBySelector,
Params: selector,
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 {
action := uixt.MobileAction{
Method: uixt.ACTION_TapBySelector,
Method: option.ACTION_TapBySelector,
Params: selector,
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 {
action := uixt.MobileAction{
Method: uixt.ACTION_WebCloseTab,
Method: option.ACTION_WebCloseTab,
Params: idx,
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 {
action := uixt.MobileAction{
Method: uixt.ACTION_GetElementTextBySelector,
Method: option.ACTION_GetElementTextBySelector,
Params: selector,
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 {
action := uixt.MobileAction{
Method: uixt.ACTION_Input,
Method: option.ACTION_Input,
Params: text,
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
func (s *StepMobile) Sleep(nSeconds float64, startTime ...time.Time) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_Sleep,
Method: option.ACTION_Sleep,
Params: nSeconds,
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 {
action := uixt.MobileAction{
Method: uixt.ACTION_SleepMS,
Method: option.ACTION_SleepMS,
Params: nMilliseconds,
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
func (s *StepMobile) SleepRandom(params ...float64) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_SleepRandom,
Method: option.ACTION_SleepRandom,
Params: params,
Options: nil,
})
@@ -417,7 +417,7 @@ func (s *StepMobile) SleepRandom(params ...float64) *StepMobile {
func (s *StepMobile) EndToEndDelay(opts ...option.ActionOption) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_EndToEndDelay,
Method: option.ACTION_EndToEndDelay,
Params: nil,
Options: option.NewActionOptions(opts...),
})
@@ -426,7 +426,7 @@ func (s *StepMobile) EndToEndDelay(opts ...option.ActionOption) *StepMobile {
func (s *StepMobile) ScreenShot(opts ...option.ActionOption) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_ScreenShot,
Method: option.ACTION_ScreenShot,
Params: nil,
Options: option.NewActionOptions(opts...),
})
@@ -440,7 +440,7 @@ func (s *StepMobile) DisableAutoPopupHandler() *StepMobile {
func (s *StepMobile) ClosePopups(opts ...option.ActionOption) *StepMobile {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_ClosePopups,
Method: option.ACTION_ClosePopups,
Params: nil,
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 {
s.obj().Actions = append(s.obj().Actions, uixt.MobileAction{
Method: uixt.ACTION_CallFunction,
Method: option.ACTION_CallFunction,
Params: name, // function description
Fn: fn,
Options: option.NewActionOptions(opts...),
@@ -493,8 +493,8 @@ type StepMobileUIValidation struct {
func (s *StepMobileUIValidation) AssertNameExists(expectedName string, msg ...string) *StepMobileUIValidation {
v := Validator{
Check: uixt.SelectorName,
Assert: uixt.AssertionExists,
Check: option.SelectorName,
Assert: option.AssertionExists,
Expect: expectedName,
}
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 {
v := Validator{
Check: uixt.SelectorName,
Assert: uixt.AssertionNotExists,
Check: option.SelectorName,
Assert: option.AssertionNotExists,
Expect: expectedName,
}
if len(msg) > 0 {
@@ -523,8 +523,8 @@ func (s *StepMobileUIValidation) AssertNameNotExists(expectedName string, msg ..
func (s *StepMobileUIValidation) AssertLabelExists(expectedLabel string, msg ...string) *StepMobileUIValidation {
v := Validator{
Check: uixt.SelectorLabel,
Assert: uixt.AssertionExists,
Check: option.SelectorLabel,
Assert: option.AssertionExists,
Expect: expectedLabel,
}
if len(msg) > 0 {
@@ -538,8 +538,8 @@ func (s *StepMobileUIValidation) AssertLabelExists(expectedLabel string, msg ...
func (s *StepMobileUIValidation) AssertLabelNotExists(expectedLabel string, msg ...string) *StepMobileUIValidation {
v := Validator{
Check: uixt.SelectorLabel,
Assert: uixt.AssertionNotExists,
Check: option.SelectorLabel,
Assert: option.AssertionNotExists,
Expect: expectedLabel,
}
if len(msg) > 0 {
@@ -553,8 +553,8 @@ func (s *StepMobileUIValidation) AssertLabelNotExists(expectedLabel string, msg
func (s *StepMobileUIValidation) AssertOCRExists(expectedText string, msg ...string) *StepMobileUIValidation {
v := Validator{
Check: uixt.SelectorOCR,
Assert: uixt.AssertionExists,
Check: option.SelectorOCR,
Assert: option.AssertionExists,
Expect: expectedText,
}
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 {
v := Validator{
Check: uixt.SelectorOCR,
Assert: uixt.AssertionNotExists,
Check: option.SelectorOCR,
Assert: option.AssertionNotExists,
Expect: expectedText,
}
if len(msg) > 0 {
@@ -583,8 +583,8 @@ func (s *StepMobileUIValidation) AssertOCRNotExists(expectedText string, msg ...
func (s *StepMobileUIValidation) AssertImageExists(expectedImagePath string, msg ...string) *StepMobileUIValidation {
v := Validator{
Check: uixt.SelectorImage,
Assert: uixt.AssertionExists,
Check: option.SelectorImage,
Assert: option.AssertionExists,
Expect: expectedImagePath,
}
if len(msg) > 0 {
@@ -598,8 +598,8 @@ func (s *StepMobileUIValidation) AssertImageExists(expectedImagePath string, msg
func (s *StepMobileUIValidation) AssertImageNotExists(expectedImagePath string, msg ...string) *StepMobileUIValidation {
v := Validator{
Check: uixt.SelectorImage,
Assert: uixt.AssertionNotExists,
Check: option.SelectorImage,
Assert: option.AssertionNotExists,
Expect: expectedImagePath,
}
if len(msg) > 0 {
@@ -613,8 +613,8 @@ func (s *StepMobileUIValidation) AssertImageNotExists(expectedImagePath string,
func (s *StepMobileUIValidation) AssertAI(prompt string, msg ...string) *StepMobileUIValidation {
v := Validator{
Check: uixt.SelectorAI,
Assert: uixt.AssertionAI,
Check: option.SelectorAI,
Assert: option.AssertionAI,
Expect: prompt,
}
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 {
v := Validator{
Check: uixt.SelectorForegroundApp,
Assert: uixt.AssertionEqual,
Check: option.SelectorForegroundApp,
Assert: option.AssertionEqual,
Expect: packageName,
}
if len(msg) > 0 {
@@ -643,8 +643,8 @@ func (s *StepMobileUIValidation) AssertAppInForeground(packageName string, msg .
func (s *StepMobileUIValidation) AssertAppNotInForeground(packageName string, msg ...string) *StepMobileUIValidation {
v := Validator{
Check: uixt.SelectorForegroundApp,
Assert: uixt.AssertionNotEqual,
Check: option.SelectorForegroundApp,
Assert: option.AssertionNotEqual,
Expect: packageName,
}
if len(msg) > 0 {
@@ -739,7 +739,7 @@ func runStepMobileUI(s *SessionRunner, step IStep) (stepResult *StepResult, err
startTime := time.Now()
actionResult := &ActionResult{
MobileAction: uixt.MobileAction{
Method: uixt.ACTION_GetForegroundApp,
Method: option.ACTION_GetForegroundApp,
Params: "[ForDebug] check foreground app",
},
StartTime: startTime.Unix(),
@@ -758,7 +758,7 @@ func runStepMobileUI(s *SessionRunner, step IStep) (stepResult *StepResult, err
startTime := time.Now()
actionResult := &ActionResult{
MobileAction: uixt.MobileAction{
Method: uixt.ACTION_ClosePopups,
Method: option.ACTION_ClosePopups,
Params: "[ForDebug] close popups handler",
},
StartTime: startTime.Unix(),
@@ -802,9 +802,9 @@ func runStepMobileUI(s *SessionRunner, step IStep) (stepResult *StepResult, err
}
// 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")
actionMethod := uixt.ActionMethod(action.Params.(string))
actionMethod := option.ActionMethod(action.Params.(string))
s.summary.Stat.Actions[actionMethod]++
continue
}

View File

@@ -15,7 +15,7 @@ import (
"github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/internal/config"
"github.com/httprunner/httprunner/v5/internal/version"
"github.com/httprunner/httprunner/v5/uixt"
"github.com/httprunner/httprunner/v5/uixt/option"
)
func NewSummary() *Summary {
@@ -28,7 +28,7 @@ func NewSummary() *Summary {
Success: true,
Stat: &Stat{
TestSteps: TestStepStat{
Actions: make(map[uixt.ActionMethod]int),
Actions: make(map[option.ActionMethod]int),
},
},
Time: &TestCaseTime{
@@ -146,10 +146,10 @@ type TestCaseStat struct {
}
type TestStepStat struct {
Total int `json:"total" yaml:"total"`
Successes int `json:"successes" yaml:"successes"`
Failures int `json:"failures" yaml:"failures"`
Actions map[uixt.ActionMethod]int `json:"actions" yaml:"actions"` // record action stats
Total int `json:"total" yaml:"total"`
Successes int `json:"successes" yaml:"successes"`
Failures int `json:"failures" yaml:"failures"`
Actions map[option.ActionMethod]int `json:"actions" yaml:"actions"` // record action stats
}
type TestCaseTime struct {
@@ -167,7 +167,7 @@ func NewCaseSummary() *TestCaseSummary {
return &TestCaseSummary{
Success: true,
Stat: &TestStepStat{
Actions: make(map[uixt.ActionMethod]int),
Actions: make(map[option.ActionMethod]int),
},
Time: &TestCaseTime{
StartAt: time.Now(),

View File

@@ -312,7 +312,7 @@ func (ad *ADBDriver) TapAbsXY(x, y float64, opts ...option.ActionOption) error {
if err != nil {
return err
}
defer postHandler(ad, ACTION_TapAbsXY, actionOptions)
defer postHandler(ad, option.ACTION_TapAbsXY, actionOptions)
// adb shell input tap x y
xStr := fmt.Sprintf("%.1f", x)
@@ -331,7 +331,7 @@ func (ad *ADBDriver) DoubleTap(x, y float64, opts ...option.ActionOption) error
if err != nil {
return err
}
defer postHandler(ad, ACTION_DoubleTapXY, actionOptions)
defer postHandler(ad, option.ACTION_DoubleTapXY, actionOptions)
// adb shell input tap x y
xStr := fmt.Sprintf("%.1f", x)
@@ -380,7 +380,7 @@ func (ad *ADBDriver) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionO
if err != nil {
return err
}
defer postHandler(ad, ACTION_Drag, actionOptions)
defer postHandler(ad, option.ACTION_Drag, actionOptions)
duration := 200.0
if actionOptions.Duration > 0 {
@@ -412,7 +412,7 @@ func (ad *ADBDriver) Swipe(fromX, fromY, toX, toY float64, opts ...option.Action
if err != nil {
return err
}
defer postHandler(ad, ACTION_Swipe, actionOptions)
defer postHandler(ad, option.ACTION_Swipe, actionOptions)
// adb shell input swipe fromX fromY toX toY
_, err = ad.runShellCommand(

View File

@@ -262,7 +262,7 @@ func (ud *UIA2Driver) DoubleTap(x, y float64, opts ...option.ActionOption) error
if err != nil {
return err
}
defer postHandler(ud, ACTION_DoubleTapXY, actionOptions)
defer postHandler(ud, option.ACTION_DoubleTapXY, actionOptions)
data := map[string]interface{}{
"actions": []interface{}{
@@ -304,7 +304,7 @@ func (ud *UIA2Driver) TapAbsXY(x, y float64, opts ...option.ActionOption) error
if err != nil {
return err
}
defer postHandler(ud, ACTION_TapAbsXY, actionOptions)
defer postHandler(ud, option.ACTION_TapAbsXY, actionOptions)
duration := 100.0
if actionOptions.PressDuration > 0 {
@@ -367,7 +367,7 @@ func (ud *UIA2Driver) Drag(fromX, fromY, toX, toY float64, opts ...option.Action
if err != nil {
return err
}
defer postHandler(ud, ACTION_Drag, actionOptions)
defer postHandler(ud, option.ACTION_Drag, actionOptions)
data := map[string]interface{}{
"startX": fromX,
@@ -398,7 +398,7 @@ func (ud *UIA2Driver) Swipe(fromX, fromY, toX, toY float64, opts ...option.Actio
if err != nil {
return err
}
defer postHandler(ud, ACTION_Swipe, actionOptions)
defer postHandler(ud, option.ACTION_Swipe, actionOptions)
duration := 200.0
if actionOptions.PressDuration > 0 {

View File

@@ -119,7 +119,7 @@ func (wd *BrowserDriver) Drag(fromX, fromY, toX, toY float64, options ...option.
if err != nil {
return err
}
defer postHandler(wd, ACTION_Drag, actionOptions)
defer postHandler(wd, option.ACTION_Drag, actionOptions)
data := map[string]interface{}{
"from_x": fromX,
@@ -518,7 +518,7 @@ func (wd *BrowserDriver) TapFloat(x, y float64, opts ...option.ActionOption) err
if err != nil {
return err
}
defer postHandler(wd, ACTION_TapAbsXY, actionOptions)
defer postHandler(wd, option.ACTION_TapAbsXY, actionOptions)
duration := 0.1
if actionOptions.Duration > 0 {
@@ -542,7 +542,7 @@ func (wd *BrowserDriver) DoubleTap(x, y float64, options ...option.ActionOption)
if err != nil {
return err
}
defer postHandler(wd, ACTION_DoubleTapXY, actionOptions)
defer postHandler(wd, option.ACTION_DoubleTapXY, actionOptions)
data := map[string]interface{}{
"x": x,

View File

@@ -14,78 +14,8 @@ import (
"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 {
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"`
Fn func() `json:"-" yaml:"-"` // used for function action, not serialized
Options *option.ActionOptions `json:"options,omitempty" yaml:"options,omitempty"`
@@ -102,6 +32,7 @@ func (ma MobileAction) GetOptions() []option.ActionOption {
return actionOptionList
}
// TODO: merge to uixt MCP Server
func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
actionStartTime := time.Now()
defer func() {
@@ -119,7 +50,7 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
}()
switch action.Method {
case ACTION_WebLoginNoneUI:
case option.ACTION_WebLoginNoneUI:
if len(action.Params.([]interface{})) == 4 {
driver, ok := dExt.IDriver.(*BrowserDriver)
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))
return err
}
return fmt.Errorf("invalid %s params: %v", ACTION_WebLoginNoneUI, action.Params)
case ACTION_AppInstall:
return fmt.Errorf("invalid %s params: %v", option.ACTION_WebLoginNoneUI, action.Params)
case option.ACTION_AppInstall:
if app, ok := action.Params.(string); ok {
if err = dExt.GetDevice().Install(app,
option.WithRetryTimes(action.MaxRetryTimes)); err != nil {
return errors.Wrap(err, "failed to install app")
}
}
case ACTION_AppUninstall:
case option.ACTION_AppUninstall:
if packageName, ok := action.Params.(string); ok {
if err = dExt.GetDevice().Uninstall(packageName); err != nil {
return errors.Wrap(err, "failed to uninstall app")
}
}
case ACTION_AppClear:
case option.ACTION_AppClear:
if packageName, ok := action.Params.(string); ok {
if err = dExt.AppClear(packageName); err != nil {
return errors.Wrap(err, "failed to clear app")
}
}
case ACTION_AppLaunch:
case option.ACTION_AppLaunch:
if bundleId, ok := action.Params.(string); ok {
return dExt.AppLaunch(bundleId)
}
return fmt.Errorf("invalid %s params, should be bundleId(string), got %v",
ACTION_AppLaunch, action.Params)
case ACTION_SwipeToTapApp:
option.ACTION_AppLaunch, action.Params)
case option.ACTION_SwipeToTapApp:
if appName, ok := action.Params.(string); ok {
return dExt.SwipeToTapApp(appName, action.GetOptions()...)
}
return fmt.Errorf("invalid %s params, should be app name(string), got %v",
ACTION_SwipeToTapApp, action.Params)
case ACTION_SwipeToTapText:
option.ACTION_SwipeToTapApp, action.Params)
case option.ACTION_SwipeToTapText:
if text, ok := action.Params.(string); ok {
return dExt.SwipeToTapTexts([]string{text}, action.GetOptions()...)
}
return fmt.Errorf("invalid %s params, should be app text(string), got %v",
ACTION_SwipeToTapText, action.Params)
case ACTION_SwipeToTapTexts:
option.ACTION_SwipeToTapText, action.Params)
case option.ACTION_SwipeToTapTexts:
if texts, ok := action.Params.([]string); ok {
return dExt.SwipeToTapTexts(texts, action.GetOptions()...)
}
if texts, err := builtin.ConvertToStringSlice(action.Params); err == nil {
return dExt.SwipeToTapTexts(texts, action.GetOptions()...)
}
return fmt.Errorf("invalid %s params: %v", ACTION_SwipeToTapTexts, action.Params)
case ACTION_AppTerminate:
return fmt.Errorf("invalid %s params: %v", option.ACTION_SwipeToTapTexts, action.Params)
case option.ACTION_AppTerminate:
if bundleId, ok := action.Params.(string); ok {
success, err := dExt.AppTerminate(bundleId)
if err != nil {
@@ -187,9 +118,9 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
return nil
}
return fmt.Errorf("app_terminate params should be bundleId(string), got %v", action.Params)
case ACTION_Home:
case option.ACTION_Home:
return dExt.Home()
case ACTION_SecondaryClick:
case option.ACTION_SecondaryClick:
if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil {
if len(params) != 2 {
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]
return dExt.SecondaryClick(x, y)
}
return fmt.Errorf("invalid %s params: %v", ACTION_SecondaryClick, action.Params)
case ACTION_HoverBySelector:
return fmt.Errorf("invalid %s params: %v", option.ACTION_SecondaryClick, action.Params)
case option.ACTION_HoverBySelector:
if selector, ok := action.Params.(string); ok {
return dExt.HoverBySelector(selector, action.GetOptions()...)
}
return fmt.Errorf("invalid %s params: %v", ACTION_HoverBySelector, action.Params)
case ACTION_TapBySelector:
return fmt.Errorf("invalid %s params: %v", option.ACTION_HoverBySelector, action.Params)
case option.ACTION_TapBySelector:
if selector, ok := action.Params.(string); ok {
return dExt.TapBySelector(selector, action.GetOptions()...)
}
return fmt.Errorf("invalid %s params: %v", ACTION_TapBySelector, action.Params)
case ACTION_SecondaryClickBySelector:
return fmt.Errorf("invalid %s params: %v", option.ACTION_TapBySelector, action.Params)
case option.ACTION_SecondaryClickBySelector:
if selector, ok := action.Params.(string); ok {
return dExt.SecondaryClickBySelector(selector, action.GetOptions()...)
}
return fmt.Errorf("invalid %s params: %v", ACTION_SecondaryClickBySelector, action.Params)
case ACTION_WebCloseTab:
return fmt.Errorf("invalid %s params: %v", option.ACTION_SecondaryClickBySelector, action.Params)
case option.ACTION_WebCloseTab:
if param, ok := action.Params.(json.Number); ok {
paramInt64, _ := param.Int64()
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 fmt.Errorf("invalid %s params: %v", ACTION_WebCloseTab, action.Params)
case ACTION_SetIme:
case option.ACTION_SetIme:
if ime, ok := action.Params.(string); ok {
err = dExt.SetIme(ime)
if err != nil {
@@ -231,7 +162,7 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
}
return nil
}
case ACTION_GetSource:
case option.ACTION_GetSource:
if packageName, ok := action.Params.(string); ok {
_, err = dExt.Source(option.WithProcessName(packageName))
if err != nil {
@@ -239,7 +170,7 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
}
return nil
}
case ACTION_TapXY:
case option.ACTION_TapXY:
if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil {
// relative x,y of window size: [0.5, 0.5]
if len(params) != 2 {
@@ -248,8 +179,8 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
x, y := params[0], params[1]
return dExt.TapXY(x, y, action.GetOptions()...)
}
return fmt.Errorf("invalid %s params: %v", ACTION_TapXY, action.Params)
case ACTION_TapAbsXY:
return fmt.Errorf("invalid %s params: %v", option.ACTION_TapXY, action.Params)
case option.ACTION_TapAbsXY:
if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil {
// absolute coordinates x,y of window size: [100, 300]
if len(params) != 2 {
@@ -258,19 +189,19 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
x, y := params[0], params[1]
return dExt.TapAbsXY(x, y, action.GetOptions()...)
}
return fmt.Errorf("invalid %s params: %v", ACTION_TapAbsXY, action.Params)
case ACTION_TapByOCR:
return fmt.Errorf("invalid %s params: %v", option.ACTION_TapAbsXY, action.Params)
case option.ACTION_TapByOCR:
if ocrText, ok := action.Params.(string); ok {
return dExt.TapByOCR(ocrText, action.GetOptions()...)
}
return fmt.Errorf("invalid %s params: %v", ACTION_TapByOCR, action.Params)
case ACTION_TapByCV:
return fmt.Errorf("invalid %s params: %v", option.ACTION_TapByOCR, action.Params)
case option.ACTION_TapByCV:
actionOptions := option.NewActionOptions(action.GetOptions()...)
if len(actionOptions.ScreenShotWithUITypes) > 0 {
return dExt.TapByCV(action.GetOptions()...)
}
return fmt.Errorf("invalid %s params: %v", ACTION_TapByCV, action.Params)
case ACTION_DoubleTapXY:
return fmt.Errorf("invalid %s params: %v", option.ACTION_TapByCV, action.Params)
case option.ACTION_DoubleTapXY:
if params, err := builtin.ConvertToFloat64Slice(action.Params); err == nil {
// relative x,y of window size: [0.5, 0.5]
if len(params) != 2 {
@@ -279,20 +210,20 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
x, y := params[0], params[1]
return dExt.DoubleTap(x, y)
}
return fmt.Errorf("invalid %s params: %v", ACTION_DoubleTapXY, action.Params)
case ACTION_Swipe:
return fmt.Errorf("invalid %s params: %v", option.ACTION_DoubleTapXY, action.Params)
case option.ACTION_Swipe:
params := action.Params
swipeAction := prepareSwipeAction(dExt, params, action.GetOptions()...)
return swipeAction(dExt)
case ACTION_Input:
case option.ACTION_Input:
// input text on current active element
// append \n to send text with enter
// send \b\b\b to delete 3 chars
param := fmt.Sprintf("%v", action.Params)
return dExt.Input(param)
case ACTION_Back:
case option.ACTION_Back:
return dExt.Back()
case ACTION_Sleep:
case option.ACTION_Sleep:
if param, ok := action.Params.(json.Number); ok {
seconds, _ := param.Float64()
time.Sleep(time.Duration(seconds*1000) * time.Millisecond)
@@ -315,7 +246,7 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
return nil
}
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 {
milliseconds, _ := param.Int64()
time.Sleep(time.Duration(milliseconds) * time.Millisecond)
@@ -328,29 +259,29 @@ func (dExt *XTDriver) DoAction(action MobileAction) (err error) {
return nil
}
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 {
sleepStrict(time.Now(), getSimulationDuration(params))
return nil
}
return fmt.Errorf("invalid sleep random params: %v(%T)", action.Params, action.Params)
case ACTION_ScreenShot:
case option.ACTION_ScreenShot:
// take screenshot
log.Info().Msg("take screenshot for current screen")
_, err := dExt.GetScreenResult(action.GetScreenShotOptions()...)
return err
case ACTION_ClosePopups:
case option.ACTION_ClosePopups:
return dExt.ClosePopupsHandler()
case ACTION_CallFunction:
case option.ACTION_CallFunction:
if funcDesc, ok := action.Params.(string); ok {
return dExt.Call(funcDesc, action.Fn, action.GetOptions()...)
}
return fmt.Errorf("invalid function description: %v", action.Params)
case ACTION_AIAction:
case option.ACTION_AIAction:
if prompt, ok := action.Params.(string); ok {
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:
log.Warn().Str("action", string(action.Method)).Msg("action not implemented")
return errors.Wrapf(code.InvalidCaseError,

View File

@@ -322,7 +322,7 @@ func compressImageBuffer(raw *bytes.Buffer) (compressed *bytes.Buffer, err error
}
// 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 {
return nil
}
@@ -341,14 +341,14 @@ func MarkUIOperation(driver IDriver, actionType ActionMethod, actionCoordinates
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 {
return fmt.Errorf("invalid tap action coordinates: %v", actionCoordinates)
}
x, y := actionCoordinates[0], actionCoordinates[1]
point := image.Point{X: int(x), Y: int(y)}
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 {
return fmt.Errorf("invalid swipe action coordinates: %v", actionCoordinates)
}

View File

@@ -51,7 +51,7 @@ func preHandler_TapAbsXY(driver IDriver, options *option.ActionOptions, rawX, ra
// mark UI operation
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")
}
}
@@ -71,7 +71,7 @@ func preHandler_DoubleTap(driver IDriver, options *option.ActionOptions, rawX, r
// mark UI operation
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")
}
}
@@ -90,7 +90,7 @@ func preHandler_Drag(driver IDriver, options *option.ActionOptions, rawFomX, raw
// mark UI operation
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")
}
}
@@ -109,7 +109,7 @@ func preHandler_Swipe(driver IDriver, options *option.ActionOptions, rawFomX, ra
// save screenshot before action and mark UI operation
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")
}
}
@@ -117,7 +117,7 @@ func preHandler_Swipe(driver IDriver, options *option.ActionOptions, rawFomX, ra
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
if options.PostMarkOperation {
// get compressed screenshot buffer

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)))
switch assert {
case AssertionEqual:
case option.AssertionEqual:
_, err := dExt.FindScreenText(text, opts...)
if err != nil {
return errors.Wrap(err, "assert ocr equal failed")
}
case AssertionNotEqual:
case option.AssertionNotEqual:
_, err := dExt.FindScreenText(text, opts...)
if err == nil {
return errors.New("assert ocr not equal failed")
}
case AssertionExists:
case option.AssertionExists:
opts = append(opts, option.WithRegex(true))
_, err := dExt.FindScreenText(text, opts...)
if err != nil {
return errors.Wrap(err, "assert ocr exists failed")
}
case AssertionNotExists:
case option.AssertionNotExists:
opts = append(opts, option.WithRegex(true))
_, err := dExt.FindScreenText(text, opts...)
if err == nil {
@@ -166,11 +166,11 @@ func (dExt *XTDriver) assertForegroundApp(appName, assert string) error {
}
switch assert {
case AssertionEqual:
case option.AssertionEqual:
if app.PackageName != appName {
return errors.Wrap(err, "assert foreground app equal failed")
}
case AssertionNotEqual:
case option.AssertionNotEqual:
if app.PackageName == appName {
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")
}
switch assert {
case AssertionExists:
case option.AssertionExists:
_, err := driver.IsElementExistBySelector(selector)
if err != nil {
return errors.Wrap(err, "assert ocr exists failed")
}
case AssertionNotExists:
case option.AssertionNotExists:
_, err := driver.IsElementExistBySelector(selector)
if err == nil {
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) {
switch check {
case SelectorOCR:
case option.SelectorOCR:
err = dExt.assertOCR(expected, assert)
case SelectorAI:
case option.SelectorAI:
err = dExt.AIAssert(assert)
case SelectorForegroundApp:
case option.SelectorForegroundApp:
err = dExt.assertForegroundApp(expected, assert)
case SelectorSelector:
case option.SelectorSelector:
err = dExt.assertSelector(expected, assert)
default:
return fmt.Errorf("validator %s not implemented", check)

View File

@@ -159,7 +159,7 @@ func (hd *HDCDriver) TapAbsXY(x, y float64, opts ...option.ActionOption) error {
if err != nil {
return err
}
defer postHandler(hd, ACTION_TapAbsXY, actionOptions)
defer postHandler(hd, option.ACTION_TapAbsXY, actionOptions)
if actionOptions.Identifier != "" {
startTime := int(time.Now().UnixMilli())
@@ -191,7 +191,7 @@ func (hd *HDCDriver) Swipe(fromX, fromY, toX, toY float64, opts ...option.Action
if err != nil {
return err
}
defer postHandler(hd, ACTION_Swipe, actionOptions)
defer postHandler(hd, option.ACTION_Swipe, actionOptions)
duration := 200
if actionOptions.PressDuration > 0 {

View File

@@ -602,7 +602,7 @@ func (wd *WDADriver) TapAbsXY(x, y float64, opts ...option.ActionOption) error {
if err != nil {
return err
}
defer postHandler(wd, ACTION_TapAbsXY, actionOptions)
defer postHandler(wd, option.ACTION_TapAbsXY, actionOptions)
data := map[string]interface{}{
"x": x,
@@ -627,7 +627,7 @@ func (wd *WDADriver) DoubleTap(x, y float64, opts ...option.ActionOption) error
if err != nil {
return err
}
defer postHandler(wd, ACTION_DoubleTapXY, actionOptions)
defer postHandler(wd, option.ACTION_DoubleTapXY, actionOptions)
data := map[string]interface{}{
"x": x,
@@ -664,7 +664,7 @@ func (wd *WDADriver) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionO
if err != nil {
return err
}
defer postHandler(wd, ACTION_Drag, actionOptions)
defer postHandler(wd, option.ACTION_Drag, actionOptions)
data := map[string]interface{}{
"fromX": math.Round(fromX*10) / 10,

View File

@@ -8,6 +8,76 @@ import (
"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 {
Context context.Context `json:"-" yaml:"-"`
// log

View File

@@ -94,7 +94,7 @@ func convertActionToCallToolRequest(action MobileAction) (mcp.CallToolRequest, e
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
req, err := convertActionToCallToolRequest(action)
if err != nil {