mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-10 02:09:51 +08:00
Merge pull request #1506 from httprunner/add-offset-to-tap
feat: support offset for tap point
This commit is contained in:
@@ -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
|
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
|
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
|
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
|
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
|
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
|
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 {
|
func WithText(text string) ActionOption {
|
||||||
return func(o *MobileAction) {
|
return func(o *MobileAction) {
|
||||||
o.Text = text
|
o.Text = text
|
||||||
@@ -396,8 +403,12 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
|
|||||||
if len(action.Scope) != 4 {
|
if len(action.Scope) != 4 {
|
||||||
action.Scope = []float64{0, 0, 1, 1}
|
action.Scope = []float64{0, 0, 1, 1}
|
||||||
}
|
}
|
||||||
|
if len(action.Offset) != 2 {
|
||||||
|
action.Offset = []int{0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
identifierOption := WithDataIdentifier(action.Identifier)
|
identifierOption := WithDataIdentifier(action.Identifier)
|
||||||
|
offsetOption := WithDataOffset(action.Offset[0], action.Offset[1])
|
||||||
indexOption := WithDataIndex(action.Index)
|
indexOption := WithDataIndex(action.Index)
|
||||||
scopeOption := WithDataScope(dExt.getAbsScope(action.Scope[0], action.Scope[1], action.Scope[2], action.Scope[3]))
|
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 {
|
foundTextAction := func(d *DriverExt) error {
|
||||||
// tap text
|
// tap text
|
||||||
return d.TapAbsXY(point.X, point.Y, identifierOption)
|
return d.TapAbsXY(point.X, point.Y, identifierOption, offsetOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
if action.Direction != nil {
|
if action.Direction != nil {
|
||||||
@@ -443,7 +454,12 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
|
|||||||
if len(action.Scope) != 4 {
|
if len(action.Scope) != 4 {
|
||||||
action.Scope = []float64{0, 0, 1, 1}
|
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]))
|
scopeOption := WithDataScope(dExt.getAbsScope(action.Scope[0], action.Scope[1], action.Scope[2], action.Scope[3]))
|
||||||
// default to retry 10 times
|
// default to retry 10 times
|
||||||
if action.MaxRetryTimes == 0 {
|
if action.MaxRetryTimes == 0 {
|
||||||
@@ -468,7 +484,7 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
|
|||||||
}
|
}
|
||||||
foundTextAction := func(d *DriverExt) error {
|
foundTextAction := func(d *DriverExt) error {
|
||||||
// tap text
|
// 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
|
// default to retry 10 times
|
||||||
@@ -517,7 +533,10 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
|
|||||||
}
|
}
|
||||||
x, _ := location[0].(float64)
|
x, _ := location[0].(float64)
|
||||||
y, _ := location[1].(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)
|
return fmt.Errorf("invalid %s params: %v", ACTION_TapAbsXY, action.Params)
|
||||||
case ACTION_Tap:
|
case ACTION_Tap:
|
||||||
@@ -530,12 +549,16 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
|
|||||||
if len(action.Scope) != 4 {
|
if len(action.Scope) != 4 {
|
||||||
action.Scope = []float64{0, 0, 1, 1}
|
action.Scope = []float64{0, 0, 1, 1}
|
||||||
}
|
}
|
||||||
|
if len(action.Offset) != 2 {
|
||||||
|
action.Offset = []int{0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
indexOption := WithDataIndex(action.Index)
|
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]))
|
scopeOption := WithDataScope(dExt.getAbsScope(action.Scope[0], action.Scope[1], action.Scope[2], action.Scope[3]))
|
||||||
identifierOption := WithDataIdentifier(action.Identifier)
|
identifierOption := WithDataIdentifier(action.Identifier)
|
||||||
IgnoreNotFoundErrorOption := WithDataIgnoreNotFoundError(action.IgnoreNotFoundError)
|
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)
|
return fmt.Errorf("invalid %s params: %v", ACTION_TapByOCR, action.Params)
|
||||||
case ACTION_TapByCV:
|
case ACTION_TapByCV:
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -777,6 +779,7 @@ type Rect struct {
|
|||||||
type DataOptions struct {
|
type DataOptions struct {
|
||||||
Data map[string]interface{} // configurations used by ios/android driver
|
Data map[string]interface{} // configurations used by ios/android driver
|
||||||
Scope []int // used by ocr to get text position in the scope
|
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
|
Index int // index of the target element, should start from 1
|
||||||
IgnoreNotFoundError bool // ignore error if target element not found
|
IgnoreNotFoundError bool // ignore error if target element not found
|
||||||
MaxRetryTimes int // max retry times 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 {
|
func WithDataIdentifier(identifier string) DataOption {
|
||||||
if identifier == "" {
|
if identifier == "" {
|
||||||
return func(data *DataOptions) {}
|
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
|
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 {
|
if _, ok := dataOptions.Data["steps"]; !ok {
|
||||||
dataOptions.Data["steps"] = 12 // default steps
|
dataOptions.Data["steps"] = 12 // default steps
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,9 +129,13 @@ func (dExt *DriverExt) swipeToTapApp(appName string, action MobileAction) error
|
|||||||
if len(action.Scope) != 4 {
|
if len(action.Scope) != 4 {
|
||||||
action.Scope = []float64{0, 0, 1, 1}
|
action.Scope = []float64{0, 0, 1, 1}
|
||||||
}
|
}
|
||||||
|
if len(action.Offset) != 2 {
|
||||||
|
action.Offset = []int{0, -25}
|
||||||
|
}
|
||||||
|
|
||||||
identifierOption := WithDataIdentifier(action.Identifier)
|
identifierOption := WithDataIdentifier(action.Identifier)
|
||||||
indexOption := WithDataIndex(action.Index)
|
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]))
|
scopeOption := WithDataScope(dExt.getAbsScope(action.Scope[0], action.Scope[1], action.Scope[2], action.Scope[3]))
|
||||||
|
|
||||||
// default to retry 5 times
|
// default to retry 5 times
|
||||||
@@ -152,7 +156,7 @@ func (dExt *DriverExt) swipeToTapApp(appName string, action MobileAction) error
|
|||||||
}
|
}
|
||||||
foundAppAction := func(d *DriverExt) error {
|
foundAppAction := func(d *DriverExt) error {
|
||||||
// click app to launch
|
// 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
|
// go to home screen
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ var (
|
|||||||
WithDirection = uixt.WithDirection
|
WithDirection = uixt.WithDirection
|
||||||
WithCustomDirection = uixt.WithCustomDirection
|
WithCustomDirection = uixt.WithCustomDirection
|
||||||
WithScope = uixt.WithScope
|
WithScope = uixt.WithScope
|
||||||
|
WithOffset = uixt.WithOffset
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
Reference in New Issue
Block a user