diff --git a/internal/version/VERSION b/internal/version/VERSION index cbeff748..8da30f12 100644 --- a/internal/version/VERSION +++ b/internal/version/VERSION @@ -1 +1 @@ -v5.0.0-beta-2503171509 +v5.0.0-beta-2503171536 diff --git a/uixt/ai/cv.go b/uixt/ai/cv.go index 0a6ff51d..81b6c196 100644 --- a/uixt/ai/cv.go +++ b/uixt/ai/cv.go @@ -5,6 +5,7 @@ import ( "fmt" "image" "math" + "math/rand/v2" "regexp" "github.com/pkg/errors" @@ -96,6 +97,17 @@ func (t OCRText) Center() PointF { return point } +func (t OCRText) RandomPoint() PointF { + rect := t.Rect + x, y := float64(rect.Min.X), float64(rect.Min.Y) + width, height := float64(rect.Dx()), float64(rect.Dy()) + point := PointF{ + X: x + width*rand.Float64(), + Y: y + height*rand.Float64(), + } + return point +} + type OCRTexts []OCRText func (t OCRTexts) texts() (texts []string) { diff --git a/uixt/driver_ext_tap.go b/uixt/driver_ext_tap.go index 8881fc38..1388cd40 100644 --- a/uixt/driver_ext_tap.go +++ b/uixt/driver_ext_tap.go @@ -3,6 +3,7 @@ package uixt import ( "fmt" + "github.com/httprunner/httprunner/v5/uixt/ai" "github.com/httprunner/httprunner/v5/uixt/option" ) @@ -19,7 +20,13 @@ func (dExt *XTDriver) TapByOCR(text string, opts ...option.ActionOption) error { } return err } - point := textRect.Center() + + var point ai.PointF + if actionOptions.TapRandom { + point = textRect.RandomPoint() + } else { + point = textRect.Center() + } return dExt.TapAbsXY(point.X, point.Y, opts...) } diff --git a/uixt/driver_ext_test.go b/uixt/driver_ext_test.go index dec94fb2..1ef1c3b4 100644 --- a/uixt/driver_ext_test.go +++ b/uixt/driver_ext_test.go @@ -182,5 +182,6 @@ func TestDriverExt_Action_Risk(t *testing.T) { option.WithSwipeOffset(-50, 50, -50, 50)) assert.Nil(t, err) - err = driver.TapByOCR("首页", option.WithTapOffset(-10, 10)) + // tap random point in ocr text rect + err = driver.TapByOCR("首页", option.WithTapRandom(true)) } diff --git a/uixt/option/action.go b/uixt/option/action.go index f2c5b0a0..26d84a29 100644 --- a/uixt/option/action.go +++ b/uixt/option/action.go @@ -99,6 +99,10 @@ func (o *ActionOptions) Options() []ActionOption { // for tap [x,y] offset options = append(options, WithTapOffset(o.TapOffset[0], o.TapOffset[1])) } + if o.TapRandom { + // tap random point in OCR/CV rectangle + options = append(options, WithTapRandom(true)) + } if len(o.SwipeOffset) == 4 { // for swipe [fromX, fromY, toX, toY] offset options = append(options, WithSwipeOffset( diff --git a/uixt/option/screen.go b/uixt/option/screen.go index 01659f9c..f2243a17 100644 --- a/uixt/option/screen.go +++ b/uixt/option/screen.go @@ -217,6 +217,7 @@ type ScreenFilterOptions struct { Regex bool `json:"regex,omitempty" yaml:"regex,omitempty"` // use regex to match text TapOffset []int `json:"tap_offset,omitempty" yaml:"tap_offset,omitempty"` // tap with point offset + TapRandom bool `json:"tap_random,omitempty" yaml:"tap_random,omitempty"` // tap random point in text/image rectangle SwipeOffset []int `json:"swipe_offset,omitempty" yaml:"swipe_offset,omitempty"` // swipe with direction offset OffsetRandomRange []int `json:"offset_random_range,omitempty" yaml:"offset_random_range,omitempty"` // set random range [min, max] for tap/swipe points Index int `json:"index,omitempty" yaml:"index,omitempty"` // index of the target element @@ -247,6 +248,14 @@ func WithTapOffset(offsetX, offsetY int) ActionOption { } } +// WithTapRandom is used with TapByOCR and TapByCV +// when set true, tap random point in text/image rectangle +func WithTapRandom(tapRandom bool) ActionOption { + return func(o *ActionOptions) { + o.TapRandom = tapRandom + } +} + func WithRegex(regex bool) ActionOption { return func(o *ActionOptions) { o.Regex = regex