mirror of
https://github.com/httprunner/httprunner.git
synced 2026-09-05 07:26:55 +08:00
feat: auto handle popups on each step finished
This commit is contained in:
@@ -506,7 +506,7 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
|
|||||||
case ACTION_ScreenShot:
|
case ACTION_ScreenShot:
|
||||||
// take screenshot
|
// take screenshot
|
||||||
log.Info().Msg("take screenshot for current screen")
|
log.Info().Msg("take screenshot for current screen")
|
||||||
_, _, err := dExt.TakeScreenShot(builtin.GenNameWithTimestamp("%d_screenshot"))
|
_, _, err := dExt.takeScreenShot(builtin.GenNameWithTimestamp("%d_screenshot"))
|
||||||
return err
|
return err
|
||||||
case ACTION_StartCamera:
|
case ACTION_StartCamera:
|
||||||
return dExt.Driver.StartCamera()
|
return dExt.Driver.StartCamera()
|
||||||
|
|||||||
+8
-13
@@ -124,9 +124,8 @@ func NewDriverExt(device Device, driver WebDriver) (dExt *DriverExt, err error)
|
|||||||
return dExt, nil
|
return dExt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TakeScreenShot takes screenshot and saves image file to $CWD/screenshots/ folder
|
// takeScreenShot takes screenshot and saves image file to $CWD/screenshots/ folder
|
||||||
// if fileName is empty, it will not save image file and only return raw image data
|
func (dExt *DriverExt) takeScreenShot(fileName string) (raw *bytes.Buffer, path string, err error) {
|
||||||
func (dExt *DriverExt) TakeScreenShot(fileName ...string) (raw *bytes.Buffer, path string, err error) {
|
|
||||||
// iOS 优先使用 MJPEG 流进行截图,性能最优
|
// iOS 优先使用 MJPEG 流进行截图,性能最优
|
||||||
// 如果 MJPEG 流未开启,则使用 WebDriver 的截图接口
|
// 如果 MJPEG 流未开启,则使用 WebDriver 的截图接口
|
||||||
if dExt.frame != nil {
|
if dExt.frame != nil {
|
||||||
@@ -145,17 +144,13 @@ func (dExt *DriverExt) TakeScreenShot(fileName ...string) (raw *bytes.Buffer, pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// save screenshot to file
|
// save screenshot to file
|
||||||
if len(fileName) > 0 && fileName[0] != "" {
|
path = filepath.Join(env.ScreenShotsPath, fileName)
|
||||||
path := filepath.Join(env.ScreenShotsPath, fileName[0])
|
path, err = dExt.saveScreenShot(compressed, path)
|
||||||
path, err := dExt.saveScreenShot(compressed, path)
|
if err != nil {
|
||||||
if err != nil {
|
log.Error().Err(err).Msg("save screenshot file failed")
|
||||||
log.Error().Err(err).Msg("save screenshot file failed")
|
return nil, "", err
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
return compressed, path, nil
|
|
||||||
}
|
}
|
||||||
|
return compressed, path, nil
|
||||||
return compressed, "", nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func compressImageBuffer(raw *bytes.Buffer) (compressed *bytes.Buffer, err error) {
|
func compressImageBuffer(raw *bytes.Buffer) (compressed *bytes.Buffer, err error) {
|
||||||
|
|||||||
+17
-11
@@ -59,7 +59,7 @@ type ImageResult struct {
|
|||||||
LiveType string `json:"liveType"` // 直播间类型
|
LiveType string `json:"liveType"` // 直播间类型
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImageResponse struct {
|
type APIResponseImage struct {
|
||||||
Code int `json:"code"`
|
Code int `json:"code"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
Result ImageResult `json:"result"`
|
Result ImageResult `json:"result"`
|
||||||
@@ -279,7 +279,7 @@ func (s *veDEMImageService) GetImage(imageBuf *bytes.Buffer) (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var imageResponse ImageResponse
|
var imageResponse APIResponseImage
|
||||||
err = json.Unmarshal(results, &imageResponse)
|
err = json.Unmarshal(results, &imageResponse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).
|
log.Error().Err(err).
|
||||||
@@ -334,19 +334,20 @@ type IImageService interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetScreenResult takes a screenshot, returns the image recognization result
|
// GetScreenResult takes a screenshot, returns the image recognization result
|
||||||
func (dExt *DriverExt) GetScreenResult() (imageResult ImageResult, err error) {
|
func (dExt *DriverExt) GetScreenResult() (screenResult *ScreenResult, err error) {
|
||||||
var bufSource *bytes.Buffer
|
var bufSource *bytes.Buffer
|
||||||
var imagePath string
|
var imagePath string
|
||||||
if bufSource, imagePath, err = dExt.TakeScreenShot(
|
if bufSource, imagePath, err = dExt.takeScreenShot(
|
||||||
builtin.GenNameWithTimestamp("%d_ocr")); err != nil {
|
builtin.GenNameWithTimestamp("%d_ocr")); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
imageResult, err = dExt.ImageService.GetImage(bufSource)
|
imageResult, err := dExt.ImageService.GetImage(bufSource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("GetScreenResult failed")
|
log.Error().Err(err).Msg("GetScreenResult failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
imageResult.imagePath = imagePath
|
||||||
|
|
||||||
imageUrl := imageResult.URL
|
imageUrl := imageResult.URL
|
||||||
if imageUrl != "" {
|
if imageUrl != "" {
|
||||||
@@ -354,20 +355,25 @@ func (dExt *DriverExt) GetScreenResult() (imageResult ImageResult, err error) {
|
|||||||
log.Debug().Str("imagePath", imagePath).Str("imageUrl", imageUrl).Msg("log screenshot")
|
log.Debug().Str("imagePath", imagePath).Str("imageUrl", imageUrl).Msg("log screenshot")
|
||||||
}
|
}
|
||||||
|
|
||||||
dExt.cacheStepData.screenResults[imagePath] = &ScreenResult{
|
screenResult = &ScreenResult{
|
||||||
Texts: imageResult.OCRResult.ToOCRTexts(),
|
Texts: imageResult.OCRResult.ToOCRTexts(),
|
||||||
|
Tags: nil,
|
||||||
|
Popularity: Popularity{},
|
||||||
}
|
}
|
||||||
|
if imageResult.LiveType != "" {
|
||||||
|
screenResult.Tags = []string{imageResult.LiveType}
|
||||||
|
}
|
||||||
|
dExt.cacheStepData.screenResults[imagePath] = screenResult
|
||||||
|
|
||||||
imageResult.imagePath = imagePath
|
return screenResult, nil
|
||||||
return imageResult, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dExt *DriverExt) GetScreenTexts() (ocrTexts OCRTexts, err error) {
|
func (dExt *DriverExt) GetScreenTexts() (ocrTexts OCRTexts, err error) {
|
||||||
imageResult, err := dExt.GetScreenResult()
|
screenResult, err := dExt.GetScreenResult()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return imageResult.OCRResult.ToOCRTexts(), nil
|
return screenResult.Texts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dExt *DriverExt) FindScreenText(text string, options ...ActionOption) (point PointF, err error) {
|
func (dExt *DriverExt) FindScreenText(text string, options ...ActionOption) (point PointF, err error) {
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ func (dExt *DriverExt) FindAllImageRect(search string) (rects []image.Rectangle,
|
|||||||
if bufSearch, err = getBufFromDisk(search); err != nil {
|
if bufSearch, err = getBufFromDisk(search); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if bufSource, _, err = dExt.TakeScreenShot(builtin.GenNameWithTimestamp("%d_cv")); err != nil {
|
if bufSource, _, err = dExt.takeScreenShot(builtin.GenNameWithTimestamp("%d_cv")); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,16 +24,16 @@ var popups = [][]string{
|
|||||||
{"管理使用时间", ".*忽略.*"},
|
{"管理使用时间", ".*忽略.*"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dExt *DriverExt) autoPopupHandler(screenResult *ScreenResult) error {
|
func (dExt *DriverExt) AutoPopupHandler(screenTexts OCRTexts) error {
|
||||||
for _, popup := range popups {
|
for _, popup := range popups {
|
||||||
if len(popup) != 2 {
|
if len(popup) != 2 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
points, err := screenResult.Texts.FindTexts([]string{popup[0], popup[1]}, WithRegex(true))
|
points, err := screenTexts.FindTexts([]string{popup[0], popup[1]}, WithRegex(true))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Warn().Interface("popup", popup).
|
log.Warn().Interface("popup", popup).
|
||||||
Interface("texts", screenResult.Texts).Msg("text popup found")
|
Interface("texts", screenTexts).Msg("text popup found")
|
||||||
point := points[1].Center()
|
point := points[1].Center()
|
||||||
log.Info().Str("text", points[1].Text).Msg("close popup")
|
log.Info().Str("text", points[1].Text).Msg("close popup")
|
||||||
if err := dExt.TapAbsXY(point.X, point.Y); err != nil {
|
if err := dExt.TapAbsXY(point.X, point.Y); err != nil {
|
||||||
|
|||||||
@@ -250,17 +250,13 @@ func (l *LiveCrawler) Run(driver *DriverExt, enterPoint PointF) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// take screenshot and get screen texts by OCR
|
// take screenshot and get screen texts by OCR
|
||||||
imageResult, err := l.driver.GetScreenResult()
|
screenResult, err := l.driver.GetScreenResult()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("OCR GetTexts failed")
|
log.Error().Err(err).Msg("OCR GetTexts failed")
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
screenResult := l.driver.cacheStepData.screenResults[imageResult.imagePath]
|
screenResult.Tags = append([]string{"live"}, screenResult.Tags...)
|
||||||
screenResult.Tags = []string{"live"}
|
|
||||||
if imageResult.LiveType != "" {
|
|
||||||
screenResult.Tags = append(screenResult.Tags, imageResult.LiveType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check live type and incr live count
|
// check live type and incr live count
|
||||||
if err := l.currentStat.incrLive(screenResult, l.driver); err != nil {
|
if err := l.currentStat.incrLive(screenResult, l.driver); err != nil {
|
||||||
@@ -364,7 +360,7 @@ func (dExt *DriverExt) VideoCrawler(configs *VideoCrawlerConfigs) (err error) {
|
|||||||
return errors.Wrap(code.InterruptError, "feed crawler interrupted")
|
return errors.Wrap(code.InterruptError, "feed crawler interrupted")
|
||||||
default:
|
default:
|
||||||
// take screenshot and get screen texts by OCR
|
// take screenshot and get screen texts by OCR
|
||||||
imageResult, err := dExt.GetScreenResult()
|
screenResult, err := dExt.GetScreenResult()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "connect: connection refused") {
|
if strings.Contains(err.Error(), "connect: connection refused") {
|
||||||
return err
|
return err
|
||||||
@@ -373,17 +369,15 @@ func (dExt *DriverExt) VideoCrawler(configs *VideoCrawlerConfigs) (err error) {
|
|||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
screenResult := dExt.cacheStepData.screenResults[imageResult.imagePath]
|
|
||||||
|
|
||||||
// automatic handling of pop-up windows
|
// automatic handling of pop-up windows
|
||||||
if err := dExt.autoPopupHandler(screenResult); err != nil {
|
if err := dExt.AutoPopupHandler(screenResult.Texts); err != nil {
|
||||||
log.Error().Err(err).Msg("auto handle popup failed")
|
log.Error().Err(err).Msg("auto handle popup failed")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if live video && run live crawler
|
// check if live video && run live crawler
|
||||||
texts := imageResult.OCRResult.ToOCRTexts()
|
if enterPoint, isLive := liveCrawler.checkLiveVideo(screenResult.Texts); isLive {
|
||||||
if enterPoint, isLive := liveCrawler.checkLiveVideo(texts); isLive {
|
|
||||||
log.Info().Msg("live video found")
|
log.Info().Msg("live video found")
|
||||||
if !liveCrawler.currentStat.isLiveTargetAchieved() {
|
if !liveCrawler.currentStat.isLiveTargetAchieved() {
|
||||||
if err := liveCrawler.Run(dExt, enterPoint); err != nil {
|
if err := liveCrawler.Run(dExt, enterPoint); err != nil {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/code"
|
"github.com/httprunner/httprunner/v4/hrp/internal/code"
|
||||||
"github.com/httprunner/httprunner/v4/hrp/pkg/uixt"
|
"github.com/httprunner/httprunner/v4/hrp/pkg/uixt"
|
||||||
)
|
)
|
||||||
@@ -598,12 +597,17 @@ func runStepMobileUI(s *SessionRunner, step *TStep) (stepResult *StepResult, err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// take screenshot after each step
|
// take screenshot and get screen texts by OCR
|
||||||
if _, _, err2 := uiDriver.TakeScreenShot(
|
screenResult, err2 := uiDriver.GetScreenResult()
|
||||||
builtin.GenNameWithTimestamp("%d_step_") + step.Name); err2 != nil {
|
if err2 != nil {
|
||||||
log.Error().Err(err2).Str("step", step.Name).Msg("take screenshot failed on step finished")
|
log.Error().Err(err2).Str("step", step.Name).Msg("take screenshot failed on step finished")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// automatic handling of pop-up windows on each step finished
|
||||||
|
if err3 := uiDriver.AutoPopupHandler(screenResult.Texts); err3 != nil {
|
||||||
|
log.Error().Err(err3).Msg("auto handle popup failed")
|
||||||
|
}
|
||||||
|
|
||||||
// save attachments
|
// save attachments
|
||||||
cacheData := uiDriver.GetStepCacheData()
|
cacheData := uiDriver.GetStepCacheData()
|
||||||
for key, value := range cacheData {
|
for key, value := range cacheData {
|
||||||
|
|||||||
Reference in New Issue
Block a user