From 7f713c5be9724c4fb79ce96dcd538c3bccdbe069 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Wed, 31 Aug 2022 16:38:15 +0800 Subject: [PATCH] feat: support ignoreNotFoundError, ignore error if target element not found --- hrp/internal/uixt/tap.go | 23 ++++++++++++------ hrp/internal/uixt/tap_test.go | 2 +- hrp/step.go | 17 +++++++++++++ hrp/step_ios_ui.go | 46 +++++++++++++++++++++++------------ hrp/step_ios_ui_test.go | 2 +- 5 files changed, 66 insertions(+), 24 deletions(-) diff --git a/hrp/internal/uixt/tap.go b/hrp/internal/uixt/tap.go index 5b7d1d42..ca8176c1 100644 --- a/hrp/internal/uixt/tap.go +++ b/hrp/internal/uixt/tap.go @@ -17,37 +17,46 @@ func (dExt *DriverExt) TapXY(x, y float64) error { return dExt.WebDriver.TapFloat(x, y) } -func (dExt *DriverExt) TapByOCR(ocrText string) error { +func (dExt *DriverExt) TapByOCR(ocrText string, ignoreNotFoundError bool) error { x, y, width, height, err := dExt.FindTextByOCR(ocrText) if err != nil { + if ignoreNotFoundError { + return nil + } return err } return dExt.WebDriver.TapFloat(x+width*0.5, y+height*0.5) } -func (dExt *DriverExt) TapByCV(imagePath string) error { +func (dExt *DriverExt) TapByCV(imagePath string, ignoreNotFoundError bool) error { x, y, width, height, err := dExt.FindImageRectInUIKit(imagePath) if err != nil { + if ignoreNotFoundError { + return nil + } return err } return dExt.WebDriver.TapFloat(x+width*0.5, y+height*0.5) } -func (dExt *DriverExt) Tap(param string) error { - return dExt.TapOffset(param, 0.5, 0.5) +func (dExt *DriverExt) Tap(param string, ignoreNotFoundError bool) error { + return dExt.TapOffset(param, 0.5, 0.5, ignoreNotFoundError) } -func (dExt *DriverExt) TapOffset(param string, xOffset, yOffset float64) (err error) { +func (dExt *DriverExt) TapOffset(param string, xOffset, yOffset float64, ignoreNotFoundError bool) (err error) { // click on element, find by name attribute ele, err := dExt.FindUIElement(param) if err == nil { return ele.Click() } - var x, y, width, height float64 - if x, y, width, height, err = dExt.FindUIRectInUIKit(param); err != nil { + x, y, width, height, err := dExt.FindUIRectInUIKit(param) + if err != nil { + if ignoreNotFoundError { + return nil + } return err } diff --git a/hrp/internal/uixt/tap_test.go b/hrp/internal/uixt/tap_test.go index f519af3b..174e86d6 100644 --- a/hrp/internal/uixt/tap_test.go +++ b/hrp/internal/uixt/tap_test.go @@ -43,6 +43,6 @@ func TestDriverExt_TapWithOCR(t *testing.T) { checkErr(t, err) // 需要点击文字上方的图标 - err = driverExt.TapOffset("抖音", 0.5, -1) + err = driverExt.TapOffset("抖音", 0.5, -1, false) checkErr(t, err) } diff --git a/hrp/step.go b/hrp/step.go index 709d6647..8e4715b7 100644 --- a/hrp/step.go +++ b/hrp/step.go @@ -54,6 +54,23 @@ const ( type MobileAction struct { Method MobileMethod `json:"method" yaml:"method"` Params interface{} `json:"params,omitempty" yaml:"params,omitempty"` + + timeout int // TODO: wait timeout in seconds for mobile action + ignoreNotFoundError bool // ignore error if target element not found +} + +type ActionOption func(o *MobileAction) + +func WithTimeout(timeout int) ActionOption { + return func(o *MobileAction) { + o.timeout = timeout + } +} + +func WithIgnoreNotFoundError(ignoreError bool) ActionOption { + return func(o *MobileAction) { + o.ignoreNotFoundError = ignoreError + } } type StepResult struct { diff --git a/hrp/step_ios_ui.go b/hrp/step_ios_ui.go index 331ff537..cc6bacb3 100644 --- a/hrp/step_ios_ui.go +++ b/hrp/step_ios_ui.go @@ -87,29 +87,41 @@ func (s *StepIOS) TapXY(x, y float64) *StepIOS { } // Tap taps on the target element -func (s *StepIOS) Tap(params string) *StepIOS { - s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{ +func (s *StepIOS) Tap(params string, options ...ActionOption) *StepIOS { + action := MobileAction{ Method: uiTap, Params: params, - }) + } + for _, option := range options { + option(&action) + } + s.step.IOS.Actions = append(s.step.IOS.Actions, action) return &StepIOS{step: s.step} } // Tap taps on the target element by OCR recognition -func (s *StepIOS) TapByOCR(ocrText string) *StepIOS { - s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{ +func (s *StepIOS) TapByOCR(ocrText string, options ...ActionOption) *StepIOS { + action := MobileAction{ Method: uiTapByOCR, Params: ocrText, - }) + } + for _, option := range options { + option(&action) + } + s.step.IOS.Actions = append(s.step.IOS.Actions, action) return &StepIOS{step: s.step} } // Tap taps on the target element by CV recognition -func (s *StepIOS) TapByCV(imagePath string) *StepIOS { - s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{ +func (s *StepIOS) TapByCV(imagePath string, options ...ActionOption) *StepIOS { + action := MobileAction{ Method: uiTapByCV, Params: imagePath, - }) + } + for _, option := range options { + option(&action) + } + s.step.IOS.Actions = append(s.step.IOS.Actions, action) return &StepIOS{step: s.step} } @@ -122,11 +134,15 @@ func (s *StepIOS) DoubleTapXY(x, y float64) *StepIOS { return &StepIOS{step: s.step} } -func (s *StepIOS) DoubleTap(params string) *StepIOS { - s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{ +func (s *StepIOS) DoubleTap(params string, options ...ActionOption) *StepIOS { + action := MobileAction{ Method: uiDoubleTap, Params: params, - }) + } + for _, option := range options { + option(&action) + } + s.step.IOS.Actions = append(s.step.IOS.Actions, action) return &StepIOS{step: s.step} } @@ -529,17 +545,17 @@ func (ud *uiDriver) doAction(action MobileAction) error { return fmt.Errorf("invalid %s params: %v", uiTapXY, action.Params) case uiTap: if param, ok := action.Params.(string); ok { - return ud.Tap(param) + return ud.Tap(param, action.ignoreNotFoundError) } return fmt.Errorf("invalid %s params: %v", uiTap, action.Params) case uiTapByOCR: if ocrText, ok := action.Params.(string); ok { - return ud.TapByOCR(ocrText) + return ud.TapByOCR(ocrText, action.ignoreNotFoundError) } return fmt.Errorf("invalid %s params: %v", uiTapByOCR, action.Params) case uiTapByCV: if imagePath, ok := action.Params.(string); ok { - return ud.TapByCV(imagePath) + return ud.TapByCV(imagePath, action.ignoreNotFoundError) } return fmt.Errorf("invalid %s params: %v", uiTapByCV, action.Params) case uiDoubleTapXY: diff --git a/hrp/step_ios_ui_test.go b/hrp/step_ios_ui_test.go index c9e8732c..9f867a22 100644 --- a/hrp/step_ios_ui_test.go +++ b/hrp/step_ios_ui_test.go @@ -85,7 +85,7 @@ func TestIOSWeixinLive(t *testing.T) { NewStep("进入直播页"). IOS(). Tap("发现").Sleep(5). // 进入「发现页」;等待 5 秒确保加载完成 - TapXY(0.5, 0.3). // 基于坐标位置点击「直播」;TODO:通过 OCR 识别「直播」 + TapByOCR("直播"). // 通过 OCR 识别「直播」 Validate(). AssertLabelExists("直播"), NewStep("向上滑动 5 次").