From ed926fe2028893d99024a3d41e89b6863c5c2d81 Mon Sep 17 00:00:00 2001 From: "xucong.053" Date: Mon, 24 Oct 2022 22:39:36 +0800 Subject: [PATCH] feat: add tap offset of point --- hrp/pkg/uixt/ext.go | 31 +++++++++++++++++++++++++++---- hrp/pkg/uixt/interface.go | 20 ++++++++++++++++++++ hrp/pkg/uixt/swipe.go | 6 +++++- hrp/step.go | 1 + 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/hrp/pkg/uixt/ext.go b/hrp/pkg/uixt/ext.go index f7b353bf..7d3d1cee 100644 --- a/hrp/pkg/uixt/ext.go +++ b/hrp/pkg/uixt/ext.go @@ -69,6 +69,7 @@ type MobileAction struct { WaitTime float64 `json:"wait_time,omitempty" yaml:"wait_time,omitempty"` // wait time between swipe and ocr, unit: second Direction interface{} `json:"direction,omitempty" yaml:"direction,omitempty"` // used by swipe to tap text or app Scope []float64 `json:"scope,omitempty" yaml:"scope,omitempty"` // used by ocr to get text position in the scope + Offset []int `json:"offset,omitempty" yaml:"offset,omitempty"` // used to tap offset of point Index int `json:"index,omitempty" yaml:"index,omitempty"` // index of the target element, should start from 1 Timeout int `json:"timeout,omitempty" yaml:"timeout,omitempty"` // TODO: wait timeout in seconds for mobile action IgnoreNotFoundError bool `json:"ignore_NotFoundError,omitempty" yaml:"ignore_NotFoundError,omitempty"` // ignore error if target element not found @@ -118,6 +119,12 @@ func WithScope(x1, y1, x2, y2 float64) ActionOption { } } +func WithOffset(offsetX, offsetY int) ActionOption { + return func(o *MobileAction) { + o.Offset = []int{offsetX, offsetY} + } +} + func WithText(text string) ActionOption { return func(o *MobileAction) { o.Text = text @@ -396,8 +403,12 @@ func (dExt *DriverExt) DoAction(action MobileAction) error { if len(action.Scope) != 4 { action.Scope = []float64{0, 0, 1, 1} } + if len(action.Offset) != 2 { + action.Offset = []int{0, 0} + } identifierOption := WithDataIdentifier(action.Identifier) + OffsetOption := WithDataOffset(action.Offset[0], action.Offset[1]) indexOption := WithDataIndex(action.Index) scopeOption := WithDataScope(dExt.getAbsScope(action.Scope[0], action.Scope[1], action.Scope[2], action.Scope[3])) @@ -419,7 +430,7 @@ func (dExt *DriverExt) DoAction(action MobileAction) error { } foundTextAction := func(d *DriverExt) error { // tap text - return d.TapAbsXY(point.X, point.Y, identifierOption) + return d.TapAbsXY(point.X, point.Y, identifierOption, OffsetOption) } if action.Direction != nil { @@ -443,7 +454,12 @@ func (dExt *DriverExt) DoAction(action MobileAction) error { if len(action.Scope) != 4 { action.Scope = []float64{0, 0, 1, 1} } + if len(action.Offset) != 2 { + action.Offset = []int{0, 0} + } + identifierOption := WithDataIdentifier(action.Identifier) + OffsetOption := WithDataOffset(action.Offset[0], action.Offset[1]) scopeOption := WithDataScope(dExt.getAbsScope(action.Scope[0], action.Scope[1], action.Scope[2], action.Scope[3])) // default to retry 10 times if action.MaxRetryTimes == 0 { @@ -468,7 +484,7 @@ func (dExt *DriverExt) DoAction(action MobileAction) error { } foundTextAction := func(d *DriverExt) error { // tap text - return d.TapAbsXY(point.X, point.Y, WithDataIdentifier(action.Identifier)) + return d.TapAbsXY(point.X, point.Y, identifierOption, OffsetOption) } // default to retry 10 times @@ -517,7 +533,10 @@ func (dExt *DriverExt) DoAction(action MobileAction) error { } x, _ := location[0].(float64) y, _ := location[1].(float64) - return dExt.TapAbsXY(x, y, WithDataIdentifier(action.Identifier)) + if len(action.Offset) != 2 { + action.Offset = []int{0, 0} + } + return dExt.TapAbsXY(x, y, WithDataIdentifier(action.Identifier), WithDataOffset(action.Offset[0], action.Offset[1])) } return fmt.Errorf("invalid %s params: %v", ACTION_TapAbsXY, action.Params) case ACTION_Tap: @@ -530,12 +549,16 @@ func (dExt *DriverExt) DoAction(action MobileAction) error { if len(action.Scope) != 4 { action.Scope = []float64{0, 0, 1, 1} } + if len(action.Offset) != 2 { + action.Offset = []int{0, 0} + } indexOption := WithDataIndex(action.Index) + OffsetOption := WithDataOffset(action.Offset[0], action.Offset[1]) scopeOption := WithDataScope(dExt.getAbsScope(action.Scope[0], action.Scope[1], action.Scope[2], action.Scope[3])) identifierOption := WithDataIdentifier(action.Identifier) IgnoreNotFoundErrorOption := WithDataIgnoreNotFoundError(action.IgnoreNotFoundError) - return dExt.TapByOCR(ocrText, identifierOption, IgnoreNotFoundErrorOption, indexOption, scopeOption) + return dExt.TapByOCR(ocrText, identifierOption, IgnoreNotFoundErrorOption, indexOption, scopeOption, OffsetOption) } return fmt.Errorf("invalid %s params: %v", ACTION_TapByOCR, action.Params) case ACTION_TapByCV: diff --git a/hrp/pkg/uixt/interface.go b/hrp/pkg/uixt/interface.go index 547197a4..f805a2bd 100644 --- a/hrp/pkg/uixt/interface.go +++ b/hrp/pkg/uixt/interface.go @@ -8,6 +8,8 @@ import ( "strconv" "strings" "time" + + "github.com/httprunner/httprunner/v4/hrp/internal/builtin" ) var ( @@ -777,6 +779,7 @@ type Rect struct { type DataOptions struct { Data map[string]interface{} // configurations used by ios/android driver Scope []int // used by ocr to get text position in the scope + Offset []int // used to tap offset of point Index int // index of the target element, should start from 1 IgnoreNotFoundError bool // ignore error if target element not found MaxRetryTimes int // max retry times if target element not found @@ -821,6 +824,12 @@ func WithDataScope(x1, x2, y1, y2 int) DataOption { } } +func WithDataOffset(offsetX, offsetY int) DataOption { + return func(data *DataOptions) { + data.Offset = []int{offsetX, offsetY} + } +} + func WithDataIdentifier(identifier string) DataOption { if identifier == "" { return func(data *DataOptions) {} @@ -866,6 +875,17 @@ func NewData(data map[string]interface{}, options ...DataOption) *DataOptions { dataOptions.Scope = []int{0, 0, math.MaxInt64, math.MaxInt64} // default scope } + if len(dataOptions.Offset) == 2 { + if x, ok := data["x"]; ok { + xf, _ := builtin.Interface2Float64(x) + data["x"] = xf + float64(dataOptions.Offset[0]) + } + if y, ok := data["y"]; ok { + yf, _ := builtin.Interface2Float64(y) + data["y"] = yf + float64(dataOptions.Offset[1]) + } + } + if _, ok := dataOptions.Data["steps"]; !ok { dataOptions.Data["steps"] = 12 // default steps } diff --git a/hrp/pkg/uixt/swipe.go b/hrp/pkg/uixt/swipe.go index 9d0089ff..2a499eb4 100644 --- a/hrp/pkg/uixt/swipe.go +++ b/hrp/pkg/uixt/swipe.go @@ -129,9 +129,13 @@ func (dExt *DriverExt) swipeToTapApp(appName string, action MobileAction) error if len(action.Scope) != 4 { action.Scope = []float64{0, 0, 1, 1} } + if len(action.Offset) != 2 { + action.Offset = []int{0, -25} + } identifierOption := WithDataIdentifier(action.Identifier) indexOption := WithDataIndex(action.Index) + OffsetOption := WithDataOffset(action.Offset[0], action.Offset[1]) scopeOption := WithDataScope(dExt.getAbsScope(action.Scope[0], action.Scope[1], action.Scope[2], action.Scope[3])) // default to retry 5 times @@ -152,7 +156,7 @@ func (dExt *DriverExt) swipeToTapApp(appName string, action MobileAction) error } foundAppAction := func(d *DriverExt) error { // click app to launch - return d.TapAbsXY(point.X, point.Y-25, identifierOption) + return d.TapAbsXY(point.X, point.Y, identifierOption, OffsetOption) } // go to home screen diff --git a/hrp/step.go b/hrp/step.go index 8adb9e7d..6c41f9d5 100644 --- a/hrp/step.go +++ b/hrp/step.go @@ -32,6 +32,7 @@ var ( WithDirection = uixt.WithDirection WithCustomDirection = uixt.WithCustomDirection WithScope = uixt.WithScope + WithOffset = uixt.WithOffset ) var (