mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-12 02:21:29 +08:00
feat: 修改ios_stub_driver。wda组合模式
This commit is contained in:
@@ -55,10 +55,6 @@ func (sad *StubAndroidDriver) Setup() error {
|
||||
fmt.Sprintf("forward port %d->%s failed: %v",
|
||||
socketLocalPort, StubSocketName, err))
|
||||
}
|
||||
err = sad.Session.SetupPortForward(socketLocalPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
douyinLocalPort, err := sad.Device.Forward(AndroidDouyinPort)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package driver_ext
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt/types"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
@@ -16,8 +18,9 @@ import (
|
||||
)
|
||||
|
||||
type StubIOSDriver struct {
|
||||
*uixt.WDADriver
|
||||
|
||||
Device *uixt.IOSDevice
|
||||
Session *uixt.DriverSession
|
||||
wdaDriver *uixt.WDADriver
|
||||
timeout time.Duration
|
||||
douyinUrlPrefix string
|
||||
douyinLiteUrlPrefix string
|
||||
@@ -30,13 +33,10 @@ const (
|
||||
)
|
||||
|
||||
func NewStubIOSDriver(dev *uixt.IOSDevice) (*StubIOSDriver, error) {
|
||||
wdaDriver, err := uixt.NewWDADriver(dev)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
driver := &StubIOSDriver{
|
||||
WDADriver: wdaDriver,
|
||||
timeout: 10 * time.Second,
|
||||
Device: dev,
|
||||
timeout: 10 * time.Second,
|
||||
Session: uixt.NewDriverSession(),
|
||||
}
|
||||
|
||||
// setup driver
|
||||
@@ -52,10 +52,6 @@ func (s *StubIOSDriver) Setup() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = s.Session.SetupPortForward(localPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Session.SetBaseURL(fmt.Sprintf("http://127.0.0.1:%d", localPort))
|
||||
|
||||
localDouyinPort, err := builtin.GetFreePort()
|
||||
@@ -82,6 +78,18 @@ func (s *StubIOSDriver) Setup() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) setUpWda() (err error) {
|
||||
if s.wdaDriver == nil {
|
||||
driver, err := uixt.NewWDADriver(s.Device)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("stub driver failed to init wda driver")
|
||||
return err
|
||||
}
|
||||
s.wdaDriver = driver
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) getLocalPort() (int, error) {
|
||||
localStubPort, err := builtin.GetFreePort()
|
||||
if err != nil {
|
||||
@@ -104,7 +112,7 @@ func (s *StubIOSDriver) Source(srcOpt ...option.SourceOption) (string, error) {
|
||||
return string(resp), nil
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) OpenUrl(urlStr string, options ...option.ActionOption) (err error) {
|
||||
func (s *StubIOSDriver) OpenUrl(urlStr string, opts ...option.ActionOption) (err error) {
|
||||
targetUrl := fmt.Sprintf("/openURL?url=%s", url.QueryEscape(urlStr))
|
||||
fmt.Sprintln(targetUrl)
|
||||
resp, err := s.Session.GET(targetUrl)
|
||||
@@ -154,17 +162,12 @@ func (s *StubIOSDriver) LoginDouyin(packageName, phoneNumber string, captcha, pa
|
||||
} else {
|
||||
return info, fmt.Errorf("password and capcha is empty")
|
||||
}
|
||||
bsJSON, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
urlPrefix, err := s.getUrlPrefix(packageName)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
fullUrl := urlPrefix + "/host/login/account/" + urlPrefix
|
||||
resp, err := s.Session.POST(bsJSON, fullUrl)
|
||||
fullUrl := urlPrefix + "/host/login/account/"
|
||||
resp, err := s.Session.POST(params, fullUrl)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
@@ -221,11 +224,7 @@ func (s *StubIOSDriver) EnableDevtool(packageName string, enable bool) (err erro
|
||||
params := map[string]interface{}{
|
||||
"enable": enable,
|
||||
}
|
||||
bsJSON, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := s.Session.POST(bsJSON, fullUrl)
|
||||
resp, err := s.Session.POST(params, fullUrl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -280,3 +279,389 @@ func (s *StubIOSDriver) getUrlPrefix(packageName string) (urlPrefix string, err
|
||||
}
|
||||
return urlPrefix, nil
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) TearDown() error {
|
||||
if s.wdaDriver != nil {
|
||||
_ = s.wdaDriver.TearDown()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewSession starts a new session and returns the SessionInfo.
|
||||
func (s *StubIOSDriver) InitSession(capabilities option.Capabilities) error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.InitSession(capabilities)
|
||||
}
|
||||
|
||||
// DeleteSession Kills application associated with that session and removes session
|
||||
// 1. alertsMonitor disable
|
||||
// 2. testedApplicationBundleId terminate
|
||||
func (s *StubIOSDriver) DeleteSession() error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.DeleteSession()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) Status() (types.DeviceStatus, error) {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return types.DeviceStatus{}, err
|
||||
}
|
||||
return s.wdaDriver.Status()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) GetDevice() uixt.IDevice {
|
||||
return s.Device
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) DeviceInfo() (types.DeviceInfo, error) {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return types.DeviceInfo{}, err
|
||||
}
|
||||
return s.wdaDriver.DeviceInfo()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) Location() (types.Location, error) {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return types.Location{}, err
|
||||
}
|
||||
return s.wdaDriver.Location()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) BatteryInfo() (types.BatteryInfo, error) {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return types.BatteryInfo{}, err
|
||||
}
|
||||
return s.wdaDriver.BatteryInfo()
|
||||
}
|
||||
|
||||
// WindowSize Return the width and height in portrait mode.
|
||||
// when getting the window size in wda/ui2/adb, if the device is in landscape mode,
|
||||
// the width and height will be reversed.
|
||||
func (s *StubIOSDriver) WindowSize() (types.Size, error) {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return types.Size{}, err
|
||||
}
|
||||
return s.wdaDriver.WindowSize()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) Screen() (uixt.Screen, error) {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return uixt.Screen{}, err
|
||||
}
|
||||
return s.wdaDriver.Screen()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) Scale() (float64, error) {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return s.wdaDriver.Scale()
|
||||
}
|
||||
|
||||
// Homescreen Forces the device under test to switch to the home screen
|
||||
func (s *StubIOSDriver) Home() error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.Home()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) Unlock() (err error) {
|
||||
err = s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.Unlock()
|
||||
}
|
||||
|
||||
// AppLaunch Launch an application with given bundle identifier in scope of current session.
|
||||
// !This method is only available since Xcode9 SDK
|
||||
func (s *StubIOSDriver) AppLaunch(packageName string) error {
|
||||
_ = s.EnableDevtool(packageName, true)
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.AppLaunch(packageName)
|
||||
}
|
||||
|
||||
// AppTerminate Terminate an application with the given package name.
|
||||
// Either `true` if the app has been successfully terminated or `false` if it was not running
|
||||
func (s *StubIOSDriver) AppTerminate(packageName string) (bool, error) {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return s.wdaDriver.AppTerminate(packageName)
|
||||
}
|
||||
|
||||
// GetForegroundApp returns current foreground app package name and activity name
|
||||
func (s *StubIOSDriver) ForegroundInfo() (appInfo types.AppInfo, err error) {
|
||||
err = s.setUpWda()
|
||||
if err != nil {
|
||||
return types.AppInfo{}, err
|
||||
}
|
||||
return s.wdaDriver.ForegroundInfo()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) Orientation() (orientation types.Orientation, err error) {
|
||||
err = s.setUpWda()
|
||||
if err != nil {
|
||||
return types.OrientationPortrait, err
|
||||
}
|
||||
return s.wdaDriver.Orientation()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) Rotation() (rotation types.Rotation, err error) {
|
||||
err = s.setUpWda()
|
||||
if err != nil {
|
||||
return types.Rotation{}, err
|
||||
}
|
||||
return s.wdaDriver.Rotation()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) SetRotation(rotation types.Rotation) (err error) {
|
||||
err = s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.SetRotation(rotation)
|
||||
}
|
||||
|
||||
// Tap Sends a tap event at the coordinate.
|
||||
func (s *StubIOSDriver) TapXY(x, y float64, opts ...option.ActionOption) error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.TapXY(x, y, opts...)
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) TapAbsXY(x, y float64, opts ...option.ActionOption) error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.TapAbsXY(x, y, opts...)
|
||||
}
|
||||
|
||||
// DoubleTap Sends a double tap event at the coordinate.
|
||||
func (s *StubIOSDriver) DoubleTapXY(x, y float64, opts ...option.ActionOption) error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.DoubleTapXY(x, y, opts...)
|
||||
}
|
||||
|
||||
// TouchAndHold Initiates a long-press gesture at the coordinate, holding for the specified duration.
|
||||
//
|
||||
// second: The default value is 1
|
||||
func (s *StubIOSDriver) TouchAndHold(x, y float64, opts ...option.ActionOption) error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.TouchAndHold(x, y, opts...)
|
||||
}
|
||||
|
||||
// Drag Initiates a press-and-hold gesture at the coordinate, then drags to another coordinate.
|
||||
// WithPressDurationOption option can be used to set pressForDuration (default to 1 second).
|
||||
func (s *StubIOSDriver) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionOption) error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.Drag(fromX, fromY, toX, toY, opts...)
|
||||
}
|
||||
|
||||
// Swipe works like Drag, but `pressForDuration` value is 0
|
||||
func (s *StubIOSDriver) Swipe(fromX, fromY, toX, toY float64, opts ...option.ActionOption) error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.Swipe(fromX, fromY, toX, toY, opts...)
|
||||
}
|
||||
|
||||
// SetPasteboard Sets data to the general pasteboard
|
||||
func (s *StubIOSDriver) SetPasteboard(contentType types.PasteboardType, content string) error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.SetPasteboard(contentType, content)
|
||||
}
|
||||
|
||||
// GetPasteboard Gets the data contained in the general pasteboard.
|
||||
//
|
||||
// It worked when `WDA` was foreground. https://github.com/appium/WebDriverAgent/issues/330
|
||||
func (s *StubIOSDriver) GetPasteboard(contentType types.PasteboardType) (raw *bytes.Buffer, err error) {
|
||||
err = s.setUpWda()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.wdaDriver.GetPasteboard(contentType)
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) SetIme(ime string) error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.SetIme(ime)
|
||||
}
|
||||
|
||||
// Input works like SendKeys
|
||||
func (s *StubIOSDriver) Input(text string, opts ...option.ActionOption) error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.Input(text, opts...)
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) Backspace(count int, opts ...option.ActionOption) (err error) {
|
||||
err = s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.Backspace(count, opts...)
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) AppClear(packageName string) error {
|
||||
return types.ErrDriverNotImplemented
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) Back() (err error) {
|
||||
err = s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.Back()
|
||||
}
|
||||
|
||||
// PressButton Presses the corresponding hardware button on the device
|
||||
func (s *StubIOSDriver) PressButton(devBtn types.DeviceButton) error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.PressButton(devBtn)
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) ScreenShot(opts ...option.ActionOption) (*bytes.Buffer, error) {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return s.Device.ScreenShot()
|
||||
}
|
||||
return s.wdaDriver.ScreenShot()
|
||||
}
|
||||
|
||||
// AccessibleSource Return application elements accessibility tree
|
||||
func (s *StubIOSDriver) AccessibleSource() (string, error) {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return s.wdaDriver.AccessibleSource()
|
||||
}
|
||||
|
||||
// HealthCheck Health check might modify simulator state so it should only be called in-between testing sessions
|
||||
//
|
||||
// Checks health of XCTest by:
|
||||
// 1) Querying application for some elements,
|
||||
// 2) Triggering some device events.
|
||||
func (s *StubIOSDriver) HealthCheck() error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.HealthCheck()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) GetAppiumSettings() (map[string]interface{}, error) {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.wdaDriver.GetAppiumSettings()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) SetAppiumSettings(settings map[string]interface{}) (map[string]interface{}, error) {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.wdaDriver.SetAppiumSettings(settings)
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) IsHealthy() (bool, error) {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return s.wdaDriver.IsHealthy()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) ScreenRecord(duration time.Duration) (videoPath string, err error) {
|
||||
err = s.setUpWda()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return s.wdaDriver.ScreenRecord(duration)
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) PushImage(localPath string) error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.PushImage(localPath)
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) ClearImages() error {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.ClearImages()
|
||||
}
|
||||
|
||||
// triggers the log capture and returns the log entries
|
||||
func (s *StubIOSDriver) StartCaptureLog(identifier ...string) (err error) {
|
||||
err = s.setUpWda()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.wdaDriver.StartCaptureLog(identifier...)
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) StopCaptureLog() (result interface{}, err error) {
|
||||
err = s.setUpWda()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.wdaDriver.StopCaptureLog()
|
||||
}
|
||||
|
||||
func (s *StubIOSDriver) GetSession() *uixt.DriverSession {
|
||||
err := s.setUpWda()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return s.wdaDriver.Session
|
||||
}
|
||||
|
||||
35
pkg/uixt/driver_ext/ios_stub_driver_test.go
Normal file
35
pkg/uixt/driver_ext/ios_stub_driver_test.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package driver_ext
|
||||
|
||||
import (
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt"
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
iOSStubDriver *StubIOSDriver
|
||||
)
|
||||
|
||||
func checkErr(t *testing.T, err error, msg ...string) {
|
||||
if err != nil {
|
||||
if len(msg) == 0 {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
t.Fatal(msg, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setupIOSStubDriver(t *testing.T) {
|
||||
iOSDevice, err := uixt.NewIOSDevice(option.WithWDAPort(8700), option.WithWDAMjpegPort(8800), option.WithResetHomeOnStartup(false))
|
||||
checkErr(t, err)
|
||||
iOSStubDriver, err = NewStubIOSDriver(iOSDevice)
|
||||
checkErr(t, err)
|
||||
}
|
||||
|
||||
func TestIOSStubDriver_LoginNoneUI(t *testing.T) {
|
||||
setupIOSStubDriver(t)
|
||||
info, err := iOSStubDriver.LoginNoneUI("com.ss.iphone.ugc.AwemeInhouse", "12343418541", "", "im112233")
|
||||
checkErr(t, err)
|
||||
t.Logf("login info: %+v", info)
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package uixt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -326,6 +327,22 @@ func (dev *IOSDevice) ListApps(appType ApplicationType) (apps []installationprox
|
||||
return apps, nil
|
||||
}
|
||||
|
||||
func (dev *IOSDevice) ScreenShot() (*bytes.Buffer, error) {
|
||||
screenshotService, err := instruments.NewScreenshotService(dev.DeviceEntry)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Starting screenshot service failed")
|
||||
return nil, err
|
||||
}
|
||||
defer screenshotService.Close()
|
||||
|
||||
imageBytes, err := screenshotService.TakeScreenshot()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to task screenshot")
|
||||
return nil, err
|
||||
}
|
||||
return bytes.NewBuffer(imageBytes), nil
|
||||
}
|
||||
|
||||
func (dev *IOSDevice) GetAppInfo(packageName string) (appInfo installationproxy.AppInfo, err error) {
|
||||
svc, _ := installationproxy.New(dev.DeviceEntry)
|
||||
defer svc.Close()
|
||||
|
||||
Reference in New Issue
Block a user