From 8d6478a137e790e28d993e7431329f8ee249edaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=99=E6=B3=93=E9=93=AE?= Date: Wed, 19 Feb 2025 20:54:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20server=E6=94=AF=E6=8C=81=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E5=85=AC=E5=85=B1=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/uixt/driver_ext/ios_stub_driver.go | 408 +------------------------ pkg/uixt/ios_device.go | 22 ++ server/context.go | 7 +- server/ext/context.go | 2 +- server/ext/main.go | 14 +- server/main.go | 12 +- 6 files changed, 54 insertions(+), 411 deletions(-) diff --git a/pkg/uixt/driver_ext/ios_stub_driver.go b/pkg/uixt/driver_ext/ios_stub_driver.go index 3ed07896..2515b7d4 100644 --- a/pkg/uixt/driver_ext/ios_stub_driver.go +++ b/pkg/uixt/driver_ext/ios_stub_driver.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/httprunner/httprunner/v5/pkg/uixt/types" "net/url" "os" "time" @@ -19,9 +18,8 @@ import ( ) type StubIOSDriver struct { - Device *uixt.IOSDevice - Session *uixt.DriverSession - wdaDriver *uixt.WDADriver + Session *uixt.DriverSession + *uixt.WDADriver timeout time.Duration douyinUrlPrefix string douyinLiteUrlPrefix string @@ -42,9 +40,9 @@ func NewStubIOSDriver(dev *uixt.IOSDevice) (*StubIOSDriver, error) { return nil, err } driver := &StubIOSDriver{ - Device: dev, - timeout: 10 * time.Second, - Session: uixt.NewDriverSession(), + WDADriver: wdaDriver, + timeout: 10 * time.Second, + Session: uixt.NewDriverSession(), } // setup driver @@ -86,18 +84,6 @@ 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 { @@ -286,391 +272,9 @@ 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) { if os.Getenv("WINGS_LOCAL") == "true" { return s.Device.ScreenShot() } - err := s.setUpWda() - if err != nil { - return nil, err - } - 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 + return s.WDADriver.ScreenShot() } diff --git a/pkg/uixt/ios_device.go b/pkg/uixt/ios_device.go index c3ed4968..c404f895 100644 --- a/pkg/uixt/ios_device.go +++ b/pkg/uixt/ios_device.go @@ -167,6 +167,28 @@ func (dev *IOSDevice) Setup() error { } } + if version.GreaterThan(semver.MustParse("17.4.0")) { + info, err := tunnel.TunnelInfoForDevice(dev.DeviceEntry.Properties.SerialNumber, ios.HttpApiHost(), ios.HttpApiPort()) + if err != nil { + return err + } + dev.DeviceEntry.UserspaceTUNPort = info.UserspaceTUNPort + dev.DeviceEntry.UserspaceTUN = info.UserspaceTUN + rsdService, err := ios.NewWithAddrPortDevice(info.Address, info.RsdPort, dev.DeviceEntry) + defer rsdService.Close() + rsdProvider, err := rsdService.Handshake() + if err != nil { + return err + } + device, err := ios.GetDeviceWithAddress(dev.DeviceEntry.Properties.SerialNumber, info.Address, rsdProvider) + if err != nil { + return err + } + device.UserspaceTUN = dev.DeviceEntry.UserspaceTUN + device.UserspaceTUNPort = dev.DeviceEntry.UserspaceTUNPort + dev.DeviceEntry = device + } + return nil } diff --git a/server/context.go b/server/context.go index 4cf82f96..f729638b 100644 --- a/server/context.go +++ b/server/context.go @@ -14,7 +14,7 @@ import ( "github.com/httprunner/httprunner/v5/pkg/uixt/option" ) -func (r *Router) GetDriver(c *gin.Context) (driverExt uixt.IXTDriver, err error) { +func (p RouterBaseMethod) GetDriver(c *gin.Context) (driverExt uixt.IXTDriver, err error) { deviceObj, exists := c.Get("device") var device uixt.IDevice var driver uixt.IDriver @@ -54,7 +54,6 @@ func GetDevice(c *gin.Context) (device uixt.IDevice, err error) { RenderErrorInitDriver(c, err) return } - _ = device.Setup() case "ios": device, err = uixt.NewIOSDevice( option.WithUDID(serial), @@ -70,6 +69,10 @@ func GetDevice(c *gin.Context) (device uixt.IDevice, err error) { err = fmt.Errorf("[%s]: invalid platform", c.HandlerName()) return } + err = device.Setup() + if err != nil { + log.Error().Err(err).Msg("setup device failed") + } c.Set("device", device) return device, nil } diff --git a/server/ext/context.go b/server/ext/context.go index c539687e..08d99895 100644 --- a/server/ext/context.go +++ b/server/ext/context.go @@ -11,7 +11,7 @@ import ( "github.com/httprunner/httprunner/v5/server" ) -func (r *RouterExt) GetDriver(c *gin.Context) (driverExt uixt.IXTDriver, err error) { +func (p RouterBaseMethodExt) GetDriver(c *gin.Context) (driverExt uixt.IXTDriver, err error) { platform := c.Param("platform") deviceObj, exists := c.Get("device") var device uixt.IDevice diff --git a/server/ext/main.go b/server/ext/main.go index 91b398c5..e8855f24 100644 --- a/server/ext/main.go +++ b/server/ext/main.go @@ -1,6 +1,7 @@ package server_ext import ( + "github.com/gin-gonic/gin" "github.com/httprunner/httprunner/v5/server" ) @@ -8,15 +9,22 @@ type RouterExt struct { *server.Router } +type RouterBaseMethodExt struct { + server.RouterBaseMethod +} + func NewExtRouter() *RouterExt { router := &RouterExt{ - Router: server.NewRouter(), + Router: &server.Router{ + Engine: gin.Default(), + IRouterBaseMethod: &RouterBaseMethodExt{}, + }, } - router.Setup() + router.Init() return router } -func (r *RouterExt) Setup() { +func (r *RouterExt) Init() { r.Router.Init() apiV1PlatformSerial := r.Group("/api/v1").Group("/:platform").Group("/:serial") diff --git a/server/main.go b/server/main.go index 32a0605f..e9bb2d06 100644 --- a/server/main.go +++ b/server/main.go @@ -11,21 +11,27 @@ import ( ) func NewRouter() *Router { - router := &Router{} + router := &Router{ + Engine: gin.Default(), + IRouterBaseMethod: &RouterBaseMethod{}, + } router.Init() return router } type Router struct { *gin.Engine + IRouterBaseMethod } -type IRouter interface { +type RouterBaseMethod struct { +} + +type IRouterBaseMethod interface { GetDriver(c *gin.Context) (driver uixt.IXTDriver, err error) } func (r *Router) Init() { - r.Engine = gin.Default() r.Engine.Use(teardown()) r.Engine.GET("/ping", r.pingHandler) r.Engine.GET("/", r.pingHandler)