From 00acae20af0e9441a87e1a84cec4519f3b9d7a94 Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Tue, 29 Aug 2023 17:29:08 +0800 Subject: [PATCH 1/3] add popup close_status=found --- hrp/pkg/uixt/ext.go | 6 +++--- hrp/pkg/uixt/interface.go | 8 ++++++++ hrp/pkg/uixt/popups.go | 10 ++++++++++ hrp/pkg/uixt/service_vedem.go | 7 +++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/hrp/pkg/uixt/ext.go b/hrp/pkg/uixt/ext.go index 5b26f157..2f96b560 100644 --- a/hrp/pkg/uixt/ext.go +++ b/hrp/pkg/uixt/ext.go @@ -113,12 +113,12 @@ func (screenResults ScreenResultMap) updatePopupCloseStatus() { continue } // popup existed, but identical popups occurs during next retry - if curPopup.Text == nextPopup.Text && curPopup.Type == nextPopup.Type { - popupScreenResultList[i].Popup.CloseStatus = "fail" + if nextPopup.CloseArea.IsIdentical(curPopup.CloseArea) { + popupScreenResultList[i].Popup.CloseStatus = CloseStatusFail continue } // popup existed, but no popup or different popup occurs during next retry (IsClosed=true) - popupScreenResultList[i].Popup.CloseStatus = "success" + popupScreenResultList[i].Popup.CloseStatus = CloseStatusSuccess } } diff --git a/hrp/pkg/uixt/interface.go b/hrp/pkg/uixt/interface.go index e816573d..e292d93c 100644 --- a/hrp/pkg/uixt/interface.go +++ b/hrp/pkg/uixt/interface.go @@ -2,10 +2,13 @@ package uixt import ( "bytes" + "math" "strings" "time" "github.com/httprunner/funplugin" + + "github.com/httprunner/httprunner/v4/hrp/internal/builtin" ) var ( @@ -434,6 +437,11 @@ type PointF struct { Y float64 `json:"y"` } +func (p PointF) IsIdentical(p2 PointF) bool { + return builtin.IsZeroFloat64(math.Abs(p.X-p2.X)) && + builtin.IsZeroFloat64(math.Abs(p.Y-p2.Y)) +} + type Rect struct { Point Size diff --git a/hrp/pkg/uixt/popups.go b/hrp/pkg/uixt/popups.go index 87d078d3..efe9ad05 100644 --- a/hrp/pkg/uixt/popups.go +++ b/hrp/pkg/uixt/popups.go @@ -27,6 +27,12 @@ var popups = [][]string{ {"管理使用时间", ".*忽略.*"}, } +const ( + CloseStatusFound = "found" + CloseStatusSuccess = "success" + CloseStatusFail = "fail" +) + func findTextPopup(screenTexts OCRTexts) (closePoint *OCRText) { for _, popup := range popups { if len(popup) != 2 { @@ -126,9 +132,13 @@ func (dExt *DriverExt) ClosePopupsHandler(options ...ActionOption) error { break } screenResult.Popup.RetryCount = retryCount + if !screenResult.Popup.PopupArea.IsEmpty() { + screenResult.Popup.CloseStatus = CloseStatusFound + } if screenResult.Popup.CloseArea.IsEmpty() { break } + screenResult.Popup.CloseStatus = CloseStatusFound if err = dExt.tapPopupHandler(screenResult.Popup); err != nil { return err diff --git a/hrp/pkg/uixt/service_vedem.go b/hrp/pkg/uixt/service_vedem.go index 8b6f6ce1..716f33e9 100644 --- a/hrp/pkg/uixt/service_vedem.go +++ b/hrp/pkg/uixt/service_vedem.go @@ -5,6 +5,7 @@ import ( "fmt" "image" "io/ioutil" + "math" "mime/multipart" "net/http" "regexp" @@ -463,6 +464,12 @@ func (box Box) IsEmpty() bool { return builtin.IsZeroFloat64(box.Width) && builtin.IsZeroFloat64(box.Height) } +func (box Box) IsIdentical(box2 Box) bool { + return box.Point.IsIdentical(box2.Point) && + builtin.IsZeroFloat64(math.Abs(box.Width-box2.Width)) && + builtin.IsZeroFloat64(math.Abs(box.Height-box2.Height)) +} + func (box Box) Center() PointF { return PointF{ X: box.Point.X + box.Width*0.5, From b8bed927fa16e9c3afe8a6719bb50694c507942e Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Tue, 29 Aug 2023 22:17:38 +0800 Subject: [PATCH 2/3] compatible with old tap_cv params --- hrp/internal/builtin/utils.go | 28 ++++++++++++++++++++++++++ hrp/pkg/uixt/action.go | 38 +++++------------------------------ hrp/testcase.go | 28 ++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 33 deletions(-) diff --git a/hrp/internal/builtin/utils.go b/hrp/internal/builtin/utils.go index dd50d61c..2937018e 100644 --- a/hrp/internal/builtin/utils.go +++ b/hrp/internal/builtin/utils.go @@ -455,3 +455,31 @@ func IsZeroFloat64(f float64) bool { threshold := 1e-3 return math.Abs(f) < threshold } + +func ConvertToFloat64(val interface{}) (float64, error) { + switch v := val.(type) { + case float64: + return v, nil + case int: + return float64(v), nil + case int64: + return float64(v), nil + default: + return 0, fmt.Errorf("invalid type for conversion to float64: %T, value: %+v", val, val) + } +} + +func ConvertToStringSlice(val interface{}) ([]string, error) { + if valSlice, ok := val.([]interface{}); ok { + var res []string + for _, iVal := range valSlice { + valString, ok := iVal.(string) + if !ok { + return nil, fmt.Errorf("invalid type for converting one of the elements to string: %T, value: %v", iVal, iVal) + } + res = append(res, valString) + } + return res, nil + } + return nil, fmt.Errorf("invalid type for conversion to []string") +} diff --git a/hrp/pkg/uixt/action.go b/hrp/pkg/uixt/action.go index 40ebc6cf..1a813f3b 100644 --- a/hrp/pkg/uixt/action.go +++ b/hrp/pkg/uixt/action.go @@ -520,7 +520,7 @@ func (dExt *DriverExt) DoAction(action MobileAction) (err error) { if texts, ok := action.Params.([]string); ok { return dExt.swipeToTapTexts(texts, action.GetOptions()...) } - if texts, err := convertToStringSlice(action.Params); err == nil { + if texts, err := builtin.ConvertToStringSlice(action.Params); err == nil { return dExt.swipeToTapTexts(texts, action.GetOptions()...) } return fmt.Errorf("invalid %s params: %v", ACTION_SwipeToTapTexts, action.Params) @@ -652,39 +652,11 @@ func (dExt *DriverExt) DoAction(action MobileAction) (err error) { var errActionNotImplemented = errors.New("UI action not implemented") -func convertToFloat64(val interface{}) (float64, error) { - switch v := val.(type) { - case float64: - return v, nil - case int: - return float64(v), nil - case int64: - return float64(v), nil - default: - return 0, fmt.Errorf("invalid type for conversion to float64: %T, value: %+v", val, val) - } -} - -func convertToStringSlice(val interface{}) ([]string, error) { - if valSlice, ok := val.([]interface{}); ok { - var res []string - for _, iVal := range valSlice { - valString, ok := iVal.(string) - if !ok { - return nil, fmt.Errorf("invalid type for converting one of the elements to string: %T, value: %v", iVal, iVal) - } - res = append(res, valString) - } - return res, nil - } - return nil, fmt.Errorf("invalid type for conversion to []string") -} - // getSimulationDuration returns simulation duration by given params (in seconds) func getSimulationDuration(params []interface{}) (milliseconds int64) { if len(params) == 1 { // given constant duration time - seconds, err := convertToFloat64(params[0]) + seconds, err := builtin.ConvertToFloat64(params[0]) if err != nil { log.Error().Err(err).Interface("params", params).Msg("invalid params") return 0 @@ -703,17 +675,17 @@ func getSimulationDuration(params []interface{}) (milliseconds int64) { } totalProb := 0.0 for i := 0; i+3 <= len(params); i += 3 { - min, err := convertToFloat64(params[i]) + min, err := builtin.ConvertToFloat64(params[i]) if err != nil { log.Error().Err(err).Interface("min", params[i]).Msg("invalid minimum time") return 0 } - max, err := convertToFloat64(params[i+1]) + max, err := builtin.ConvertToFloat64(params[i+1]) if err != nil { log.Error().Err(err).Interface("max", params[i+1]).Msg("invalid maximum time") return 0 } - weight, err := convertToFloat64(params[i+2]) + weight, err := builtin.ConvertToFloat64(params[i+2]) if err != nil { log.Error().Err(err).Interface("weight", params[i+2]).Msg("invalid weight value") return 0 diff --git a/hrp/testcase.go b/hrp/testcase.go index 67d0d715..28dd5150 100644 --- a/hrp/testcase.go +++ b/hrp/testcase.go @@ -11,6 +11,7 @@ import ( "github.com/httprunner/httprunner/v4/hrp/internal/builtin" "github.com/httprunner/httprunner/v4/hrp/internal/code" + "github.com/httprunner/httprunner/v4/hrp/pkg/uixt" ) // ITestCase represents interface for testcases, @@ -112,6 +113,13 @@ func (tc *TCase) MakeCompat() (err error) { // 3. deal with extract expr including hyphen convertExtract(step.Extract) + + // 4. deal with mobile step compatibility + if step.Android != nil { + convertCompatMobileStep(step.Android) + } else if step.IOS != nil { + convertCompatMobileStep(step.IOS) + } } return nil } @@ -352,6 +360,26 @@ func convertExtract(extract map[string]string) { } } +func convertCompatMobileStep(mobileStep *MobileStep) { + if mobileStep == nil { + return + } + if mobileStep.MobileAction.Method == uixt.ACTION_TapByCV { + uiTypes, _ := builtin.ConvertToStringSlice(mobileStep.MobileAction.Params) + options := mobileStep.MobileAction.ActionOptions + options.ScreenShotWithUITypes = append(options.ScreenShotWithUITypes, uiTypes...) + } + for i := 0; i < len(mobileStep.Actions); i++ { + ma := mobileStep.Actions[i] + if ma.Method != uixt.ACTION_TapByCV { + continue + } + uiTypes, _ := builtin.ConvertToStringSlice(ma.Params) + ma.ActionOptions.ScreenShotWithUITypes = append(ma.ActionOptions.ScreenShotWithUITypes, uiTypes...) + mobileStep.Actions[i] = ma + } +} + // convertJmespathExpr deals with limited jmespath expression conversion func convertJmespathExpr(checkExpr string) string { if strings.Contains(checkExpr, textExtractorSubRegexp) { From 2c20cc5f39301edce2b6995f6884fabfae4feb6b Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Wed, 30 Aug 2023 14:31:44 +0800 Subject: [PATCH 3/3] compatible with old swipe_to_tap_texts --- hrp/testcase.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/hrp/testcase.go b/hrp/testcase.go index 28dd5150..ee7f19b1 100644 --- a/hrp/testcase.go +++ b/hrp/testcase.go @@ -364,18 +364,18 @@ func convertCompatMobileStep(mobileStep *MobileStep) { if mobileStep == nil { return } - if mobileStep.MobileAction.Method == uixt.ACTION_TapByCV { - uiTypes, _ := builtin.ConvertToStringSlice(mobileStep.MobileAction.Params) - options := mobileStep.MobileAction.ActionOptions - options.ScreenShotWithUITypes = append(options.ScreenShotWithUITypes, uiTypes...) - } for i := 0; i < len(mobileStep.Actions); i++ { ma := mobileStep.Actions[i] - if ma.Method != uixt.ACTION_TapByCV { - continue + actionOptions := uixt.NewActionOptions(ma.GetOptions()...) + // append tap_cv params to screenshot_with_ui_types option + if ma.Method == uixt.ACTION_TapByCV { + uiTypes, _ := builtin.ConvertToStringSlice(ma.Params) + ma.ActionOptions.ScreenShotWithUITypes = append(ma.ActionOptions.ScreenShotWithUITypes, uiTypes...) + } + // set default max_retry_times to 10 for swipe_to_tap_texts + if ma.Method == uixt.ACTION_SwipeToTapTexts && actionOptions.MaxRetryTimes == 0 { + ma.ActionOptions.MaxRetryTimes = 10 } - uiTypes, _ := builtin.ConvertToStringSlice(ma.Params) - ma.ActionOptions.ScreenShotWithUITypes = append(ma.ActionOptions.ScreenShotWithUITypes, uiTypes...) mobileStep.Actions[i] = ma } }