Merge pull request #1506 from httprunner/add-offset-to-tap

feat: support offset for tap point
This commit is contained in:
debugtalk
2022-10-25 15:04:40 +08:00
committed by GitHub
4 changed files with 53 additions and 5 deletions

View File

@@ -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:

View File

@@ -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
}

View File

@@ -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

View File

@@ -32,6 +32,7 @@ var (
WithDirection = uixt.WithDirection
WithCustomDirection = uixt.WithCustomDirection
WithScope = uixt.WithScope
WithOffset = uixt.WithOffset
)
var (