mirror of
https://github.com/httprunner/httprunner.git
synced 2026-08-27 11:10:31 +08:00
Merge branch 'byx-bugfix' into 'video-release'
Byx bugfix See merge request iesqa/httprunner!15
This commit is contained in:
@@ -1 +1 @@
|
|||||||
v4.3.6
|
v4.3.6.2310111458
|
||||||
@@ -121,6 +121,7 @@ type ActionOptions struct {
|
|||||||
ScreenShotWithLiveType bool `json:"screenshot_with_live_type,omitempty" yaml:"screenshot_with_live_type,omitempty"`
|
ScreenShotWithLiveType bool `json:"screenshot_with_live_type,omitempty" yaml:"screenshot_with_live_type,omitempty"`
|
||||||
ScreenShotWithUITypes []string `json:"screenshot_with_ui_types,omitempty" yaml:"screenshot_with_ui_types,omitempty"`
|
ScreenShotWithUITypes []string `json:"screenshot_with_ui_types,omitempty" yaml:"screenshot_with_ui_types,omitempty"`
|
||||||
ScreenShotWithClosePopups bool `json:"screenshot_with_close_popups,omitempty" yaml:"screenshot_with_close_popups,omitempty"`
|
ScreenShotWithClosePopups bool `json:"screenshot_with_close_popups,omitempty" yaml:"screenshot_with_close_popups,omitempty"`
|
||||||
|
ScreenShotWithOCRCluster string `json:"screenshot_with_ocr_cluster,omitempty" yaml:"screenshot_with_ocr_cluster,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *ActionOptions) Options() []ActionOption {
|
func (o *ActionOptions) Options() []ActionOption {
|
||||||
@@ -180,6 +181,9 @@ func (o *ActionOptions) Options() []ActionOption {
|
|||||||
if len(o.AbsScope) == 4 {
|
if len(o.AbsScope) == 4 {
|
||||||
options = append(options, WithAbsScope(
|
options = append(options, WithAbsScope(
|
||||||
o.AbsScope[0], o.AbsScope[1], o.AbsScope[2], o.AbsScope[3]))
|
o.AbsScope[0], o.AbsScope[1], o.AbsScope[2], o.AbsScope[3]))
|
||||||
|
} else if len(o.Scope) == 4 {
|
||||||
|
options = append(options, WithScope(
|
||||||
|
o.Scope[0], o.Scope[1], o.Scope[2], o.Scope[3]))
|
||||||
}
|
}
|
||||||
if len(o.Offset) == 2 {
|
if len(o.Offset) == 2 {
|
||||||
// for tap [x,y] offset
|
// for tap [x,y] offset
|
||||||
@@ -224,6 +228,12 @@ func (o *ActionOptions) Options() []ActionOption {
|
|||||||
if len(o.ScreenShotWithUITypes) > 0 {
|
if len(o.ScreenShotWithUITypes) > 0 {
|
||||||
options = append(options, WithScreenShotUITypes(o.ScreenShotWithUITypes...))
|
options = append(options, WithScreenShotUITypes(o.ScreenShotWithUITypes...))
|
||||||
}
|
}
|
||||||
|
if o.ScreenShotWithClosePopups {
|
||||||
|
options = append(options, WithScreenShotClosePopups(true))
|
||||||
|
}
|
||||||
|
if o.ScreenShotWithOCRCluster != "" {
|
||||||
|
options = append(options, WithScreenOCRCluster(o.ScreenShotWithOCRCluster))
|
||||||
|
}
|
||||||
|
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
@@ -472,6 +482,12 @@ func WithScreenShotClosePopups(closeOn bool) ActionOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithScreenOCRCluster(ocrCluster string) ActionOption {
|
||||||
|
return func(o *ActionOptions) {
|
||||||
|
o.ScreenShotWithOCRCluster = ocrCluster
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (dExt *DriverExt) ParseActionOptions(options ...ActionOption) []ActionOption {
|
func (dExt *DriverExt) ParseActionOptions(options ...ActionOption) []ActionOption {
|
||||||
actionOptions := NewActionOptions(options...)
|
actionOptions := NewActionOptions(options...)
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import (
|
|||||||
"github.com/httprunner/httprunner/v4/hrp/pkg/gadb"
|
"github.com/httprunner/httprunner/v4/hrp/pkg/gadb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const AdbKeyBoardPackageName = "com.android.adbkeyboard/.AdbIME"
|
||||||
|
|
||||||
type adbDriver struct {
|
type adbDriver struct {
|
||||||
Driver
|
Driver
|
||||||
|
|
||||||
@@ -327,6 +329,38 @@ func (ad *adbDriver) SendKeys(text string, options ...ActionOption) (err error)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) IsAdbKeyBoardInstalled() bool {
|
||||||
|
output, err := ad.adbClient.RunShellCommand("ime", "list", "-a")
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return strings.Contains(output, AdbKeyBoardPackageName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) SendKeysByAdbKeyBoard(text string) (err error) {
|
||||||
|
defer func() {
|
||||||
|
// Reset to default, don't care which keyboard was chosen before switch:
|
||||||
|
_, err = ad.adbClient.RunShellCommand("ime", "reset")
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Enable ADBKeyBoard from adb
|
||||||
|
if _, err = ad.adbClient.RunShellCommand("ime", "enable", AdbKeyBoardPackageName); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Switch to ADBKeyBoard from adb
|
||||||
|
if _, err = ad.adbClient.RunShellCommand("ime", "set", AdbKeyBoardPackageName); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
// input Quoted text
|
||||||
|
text = strings.ReplaceAll(text, " ", "\\ ")
|
||||||
|
if _, err = ad.adbClient.RunShellCommand("am", "broadcast", "-a", "ADB_INPUT_TEXT", "--es", "msg", text); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (ad *adbDriver) Input(text string, options ...ActionOption) (err error) {
|
func (ad *adbDriver) Input(text string, options ...ActionOption) (err error) {
|
||||||
return ad.SendKeys(text, options...)
|
return ad.SendKeys(text, options...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,10 +88,13 @@ func NewAndroidDevice(options ...AndroidDeviceOption) (device *AndroidDevice, er
|
|||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
option(device)
|
option(device)
|
||||||
}
|
}
|
||||||
|
|
||||||
deviceList, err := GetAndroidDevices(device.SerialNumber)
|
deviceList, err := GetAndroidDevices(device.SerialNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(code.AndroidDeviceConnectionError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if device.SerialNumber == "" && len(deviceList) > 1 {
|
||||||
|
return nil, errors.Wrap(code.AndroidDeviceConnectionError, "more than one device connected, please specify the serial")
|
||||||
}
|
}
|
||||||
|
|
||||||
dev := deviceList[0]
|
dev := deviceList[0]
|
||||||
|
|||||||
@@ -103,8 +103,8 @@ func (ud *uiaDriver) httpRequest(method string, rawURL string, rawBody []byte, d
|
|||||||
// wait for UIA2 server to resume automatically
|
// wait for UIA2 server to resume automatically
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
oldSessionID := ud.sessionId
|
oldSessionID := ud.sessionId
|
||||||
if err = ud.resetDriver(); err != nil {
|
if err2 := ud.resetDriver(); err2 != nil {
|
||||||
log.Err(err).Msgf("failed to reset uia2 driver, retry count: %v", retryCount)
|
log.Err(err2).Msgf("failed to reset uia2 driver, retry count: %v", retryCount)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log.Debug().Str("new session", ud.sessionId).Str("old session", oldSessionID).Msgf("successful to reset uia2 driver, retry count: %v", retryCount)
|
log.Debug().Str("new session", ud.sessionId).Str("old session", oldSessionID).Msgf("successful to reset uia2 driver, retry count: %v", retryCount)
|
||||||
@@ -426,6 +426,14 @@ func (ud *uiaDriver) SendKeys(text string, options ...ActionOption) (err error)
|
|||||||
actionOptions.updateData(data)
|
actionOptions.updateData(data)
|
||||||
|
|
||||||
_, err = ud.httpPOST(data, "/session", ud.sessionId, "keys")
|
_, err = ud.httpPOST(data, "/session", ud.sessionId, "keys")
|
||||||
|
if err != nil {
|
||||||
|
// use com.android.adbkeyboard if existed
|
||||||
|
if ud.IsAdbKeyBoardInstalled() {
|
||||||
|
err = ud.SendKeysByAdbKeyBoard(text)
|
||||||
|
} else {
|
||||||
|
_, err = ud.adbClient.RunShellCommand("input", "text", text)
|
||||||
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -237,6 +237,10 @@ func NewIOSDevice(options ...IOSDeviceOption) (device *IOSDevice, err error) {
|
|||||||
return nil, errors.Wrap(code.IOSDeviceConnectionError, err.Error())
|
return nil, errors.Wrap(code.IOSDeviceConnectionError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if device.UDID == "" && len(deviceList) > 1 {
|
||||||
|
return nil, errors.Wrap(code.IOSDeviceConnectionError, "more than one device connected, please specify the udid")
|
||||||
|
}
|
||||||
|
|
||||||
dev := deviceList[0]
|
dev := deviceList[0]
|
||||||
udid := dev.Properties().SerialNumber
|
udid := dev.Properties().SerialNumber
|
||||||
|
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ func (wd *wdaDriver) httpRequest(method string, rawURL string, rawBody []byte, d
|
|||||||
// TODO: polling WDA to check if resumed automatically
|
// TODO: polling WDA to check if resumed automatically
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
oldSessionID := wd.sessionId
|
oldSessionID := wd.sessionId
|
||||||
if err = wd.resetSession(); err != nil {
|
if err2 := wd.resetSession(); err2 != nil {
|
||||||
log.Err(err).Msgf("failed to reset wda driver, retry count: %v", retryCount)
|
log.Err(err2).Msgf("failed to reset wda driver, retry count: %v", retryCount)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log.Debug().Str("new session", wd.sessionId).Str("old session", oldSessionID).Msgf("successful to reset wda driver, retry count: %v", retryCount)
|
log.Debug().Str("new session", wd.sessionId).Str("old session", oldSessionID).Msgf("successful to reset wda driver, retry count: %v", retryCount)
|
||||||
|
|||||||
@@ -217,8 +217,13 @@ func (s *veDEMImageService) GetImage(imageBuf *bytes.Buffer, options ...ActionOp
|
|||||||
for _, uiType := range actionOptions.ScreenShotWithUITypes {
|
for _, uiType := range actionOptions.ScreenShotWithUITypes {
|
||||||
bodyWriter.WriteField("uiTypes", uiType)
|
bodyWriter.WriteField("uiTypes", uiType)
|
||||||
}
|
}
|
||||||
|
if actionOptions.ScreenShotWithOCRCluster != "" {
|
||||||
|
bodyWriter.WriteField("ocrCluster", actionOptions.ScreenShotWithOCRCluster)
|
||||||
|
}
|
||||||
|
|
||||||
bodyWriter.WriteField("ocrCluster", "highPrecision")
|
if actionOptions.Timeout > 0 {
|
||||||
|
bodyWriter.WriteField("timeout", fmt.Sprintf("%v", actionOptions.Timeout))
|
||||||
|
}
|
||||||
|
|
||||||
formWriter, err := bodyWriter.CreateFormFile("image", "screenshot.png")
|
formWriter, err := bodyWriter.CreateFormFile("image", "screenshot.png")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -407,7 +412,7 @@ func (dExt *DriverExt) GetScreenResult(options ...ActionOption) (screenResult *S
|
|||||||
screenResult.UploadedURL = imageResult.URL
|
screenResult.UploadedURL = imageResult.URL
|
||||||
screenResult.Icons = imageResult.UIResult
|
screenResult.Icons = imageResult.UIResult
|
||||||
|
|
||||||
if actionOptions.ScreenShotWithClosePopups {
|
if actionOptions.ScreenShotWithClosePopups && imageResult.CPResult != nil {
|
||||||
screenResult.Popup = &PopupInfo{
|
screenResult.Popup = &PopupInfo{
|
||||||
Type: imageResult.CPResult.Type,
|
Type: imageResult.CPResult.Type,
|
||||||
Text: imageResult.CPResult.Text,
|
Text: imageResult.CPResult.Text,
|
||||||
@@ -535,7 +540,7 @@ func (u UIResultMap) FilterUIResults(uiTypes []string) (uiResults UIResults, err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = errors.Errorf("UI types %v not detected", uiTypes)
|
err = errors.Wrap(code.CVResultNotFoundError, fmt.Sprintf("UI types %v not detected", uiTypes))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ func (dExt *DriverExt) prepareSwipeAction(options ...ActionOption) func(d *Drive
|
|||||||
log.Error().Err(err).Msgf("swipe %s failed", d)
|
log.Error().Err(err).Msgf("swipe %s failed", d)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if d, ok := swipeDirection.([]float64); ok {
|
} else if d, ok := swipeDirection.([]float64); ok && len(d) == 4 {
|
||||||
// custom direction: [fromX, fromY, toX, toY]
|
// custom direction: [fromX, fromY, toX, toY]
|
||||||
if err := dExt.SwipeRelative(d[0], d[1], d[2], d[3], options...); err != nil {
|
if err := dExt.SwipeRelative(d[0], d[1], d[2], d[3], options...); err != nil {
|
||||||
log.Error().Err(err).Msgf("swipe from (%v, %v) to (%v, %v) failed",
|
log.Error().Err(err).Msgf("swipe from (%v, %v) to (%v, %v) failed",
|
||||||
@@ -178,6 +178,11 @@ func (dExt *DriverExt) swipeToTapApp(appName string, options ...ActionOption) er
|
|||||||
return errors.Wrap(err, "go to home screen failed")
|
return errors.Wrap(err, "go to home screen failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// automatic handling popups before swipe
|
||||||
|
if err := dExt.ClosePopups(); err != nil {
|
||||||
|
log.Error().Err(err).Msg("auto handle popup failed")
|
||||||
|
}
|
||||||
|
|
||||||
// swipe to first screen
|
// swipe to first screen
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
dExt.SwipeRight()
|
dExt.SwipeRight()
|
||||||
|
|||||||
@@ -371,6 +371,7 @@ func convertCompatMobileStep(mobileStep *MobileStep) {
|
|||||||
if ma.Method == uixt.ACTION_TapByCV {
|
if ma.Method == uixt.ACTION_TapByCV {
|
||||||
uiTypes, _ := builtin.ConvertToStringSlice(ma.Params)
|
uiTypes, _ := builtin.ConvertToStringSlice(ma.Params)
|
||||||
ma.ActionOptions.ScreenShotWithUITypes = append(ma.ActionOptions.ScreenShotWithUITypes, uiTypes...)
|
ma.ActionOptions.ScreenShotWithUITypes = append(ma.ActionOptions.ScreenShotWithUITypes, uiTypes...)
|
||||||
|
ma.ActionOptions.ScreenShotWithUpload = true
|
||||||
}
|
}
|
||||||
// set default max_retry_times to 10 for swipe_to_tap_texts
|
// set default max_retry_times to 10 for swipe_to_tap_texts
|
||||||
if ma.Method == uixt.ACTION_SwipeToTapTexts && actionOptions.MaxRetryTimes == 0 {
|
if ma.Method == uixt.ACTION_SwipeToTapTexts && actionOptions.MaxRetryTimes == 0 {
|
||||||
@@ -380,6 +381,9 @@ func convertCompatMobileStep(mobileStep *MobileStep) {
|
|||||||
if ma.Method == uixt.ACTION_SwipeToTapText && actionOptions.MaxRetryTimes == 0 {
|
if ma.Method == uixt.ACTION_SwipeToTapText && actionOptions.MaxRetryTimes == 0 {
|
||||||
ma.ActionOptions.MaxRetryTimes = 10
|
ma.ActionOptions.MaxRetryTimes = 10
|
||||||
}
|
}
|
||||||
|
if ma.Method == uixt.ACTION_Swipe {
|
||||||
|
ma.ActionOptions.Direction = ma.Params
|
||||||
|
}
|
||||||
mobileStep.Actions[i] = ma
|
mobileStep.Actions[i] = ma
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user