mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-26 01:51:29 +08:00
feat: 支持tunnel, 优化server结构。
This commit is contained in:
39
cmd/ios/tunnel.go
Normal file
39
cmd/ios/tunnel.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package ios
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/danielpaulus/go-ios/ios"
|
||||
"github.com/httprunner/httprunner/v5/internal/sdk"
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var tunnelCmd = &cobra.Command{
|
||||
Use: "tunnel",
|
||||
Short: "tunnel start",
|
||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
startTime := time.Now()
|
||||
defer func() {
|
||||
sdk.SendGA4Event("hrp_ios_tunnel", map[string]interface{}{
|
||||
"args": strings.Join(args, "-"),
|
||||
"success": err == nil,
|
||||
"engagement_time_msec": time.Since(startTime).Milliseconds(),
|
||||
})
|
||||
}()
|
||||
ctx := context.TODO()
|
||||
err = uixt.StartTunnel(ctx, os.TempDir(), ios.HttpApiPort(), true)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to start tunnel")
|
||||
}
|
||||
<-ctx.Done()
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
iosRootCmd.AddCommand(tunnelCmd)
|
||||
}
|
||||
@@ -5,16 +5,13 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"crypto/sha256"
|
||||
"encoding/csv"
|
||||
builtinJSON "encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -23,7 +20,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/BurntSushi/locker"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog/log"
|
||||
"gopkg.in/yaml.v3"
|
||||
@@ -382,7 +378,7 @@ func GetCurrentDay() string {
|
||||
return formattedDate
|
||||
}
|
||||
|
||||
func fileExists(filepath string) bool {
|
||||
func FileExists(filepath string) bool {
|
||||
_, err := os.Stat(filepath)
|
||||
if os.IsNotExist(err) {
|
||||
return false // 文件不存在
|
||||
@@ -390,61 +386,6 @@ func fileExists(filepath string) bool {
|
||||
return err == nil // 文件存在,且没有其他错误
|
||||
}
|
||||
|
||||
func DownloadFileByUrl(fileUrl string) (filePath string, err error) {
|
||||
// 使用 UUID 生成唯一文件名
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
hash := md5.Sum([]byte(fileUrl))
|
||||
fileName := fmt.Sprintf("%x", hash)
|
||||
filePath = filepath.Join(cwd, fileName)
|
||||
locker.Lock(filePath)
|
||||
defer locker.Unlock(filePath)
|
||||
if fileExists(filePath) {
|
||||
return filePath, nil
|
||||
}
|
||||
|
||||
fmt.Printf("Downloading file to %s from URL %s\n", filePath, fileUrl)
|
||||
|
||||
// Create an HTTP client with default settings.
|
||||
client := &http.Client{}
|
||||
|
||||
// Build the HTTP GET request.
|
||||
req, err := http.NewRequest("GET", fileUrl, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Perform the request.
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Check the HTTP status code.
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("failed to download file: %s", resp.Status)
|
||||
}
|
||||
|
||||
// Create the output file.
|
||||
outFile, err := os.Create(fileName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer outFile.Close()
|
||||
|
||||
// Copy the response body to the file.
|
||||
_, err = io.Copy(outFile, resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
fmt.Printf("File downloaded successfully: %s\n", fileName)
|
||||
return filePath, nil
|
||||
}
|
||||
|
||||
func RunCommand(cmdName string, args ...string) error {
|
||||
cmd := exec.Command(cmdName, args...)
|
||||
log.Info().Str("command", cmd.String()).Msg("exec command")
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
const (
|
||||
ResultsDirName = "results"
|
||||
DownloadsDirName = "downloads"
|
||||
ScreenshotsDirName = "screenshots"
|
||||
ActionLogDirName = "action_log"
|
||||
)
|
||||
@@ -20,6 +21,7 @@ var (
|
||||
RootDir string
|
||||
ResultsDir string
|
||||
ResultsPath string
|
||||
DownloadsPath string
|
||||
ScreenShotsPath string
|
||||
StartTime = time.Now()
|
||||
StartTimeStr = StartTime.Format("20060102150405")
|
||||
@@ -36,6 +38,7 @@ func init() {
|
||||
|
||||
ResultsDir = filepath.Join(ResultsDirName, StartTimeStr)
|
||||
ResultsPath = filepath.Join(RootDir, ResultsDir)
|
||||
DownloadsPath = filepath.Join(RootDir, filepath.Join(DownloadsDirName, StartTimeStr))
|
||||
ScreenShotsPath = filepath.Join(ResultsPath, ScreenshotsDirName)
|
||||
ActionLogFilePath = filepath.Join(ResultsDir, ActionLogDirName)
|
||||
DeviceActionLogFilePath = "/sdcard/Android/data/io.appium.uiautomator2.server/files/hodor"
|
||||
|
||||
@@ -96,3 +96,14 @@ type XTDriver struct {
|
||||
// cache screenshot results
|
||||
screenResults []*ScreenResult
|
||||
}
|
||||
|
||||
func (dExt *XTDriver) GetIDriver() IDriver {
|
||||
return dExt.IDriver
|
||||
}
|
||||
|
||||
type IXTDriver interface {
|
||||
IDriver
|
||||
GetIDriver() IDriver
|
||||
GetScreenResult(opts ...option.ActionOption) (screenResult *ScreenResult, err error)
|
||||
DoAction(action MobileAction) (err error)
|
||||
}
|
||||
|
||||
@@ -50,9 +50,6 @@ func NewStubAndroidDriver(dev *uixt.AndroidDevice) (*StubAndroidDriver, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// register driver session reset handler
|
||||
driver.Session.RegisterResetHandler(driver.Setup)
|
||||
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/httprunner/httprunner/v5/internal/builtin"
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt"
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt/ai"
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
|
||||
@@ -34,7 +33,7 @@ type XTDriver struct {
|
||||
}
|
||||
|
||||
func (dExt *XTDriver) InstallByUrl(url string, opts ...option.InstallOption) error {
|
||||
appPath, err := builtin.DownloadFileByUrl(url)
|
||||
appPath, err := uixt.DownloadFileByUrl(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt/types"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/httprunner/httprunner/v5/code"
|
||||
@@ -44,9 +45,6 @@ func NewStubIOSDriver(dev *uixt.IOSDevice) (*StubIOSDriver, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// register driver session reset handler
|
||||
driver.Session.RegisterResetHandler(driver.Setup)
|
||||
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
@@ -565,9 +563,12 @@ func (s *StubIOSDriver) PressButton(devBtn types.DeviceButton) error {
|
||||
}
|
||||
|
||||
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 s.Device.ScreenShot()
|
||||
return nil, err
|
||||
}
|
||||
return s.wdaDriver.ScreenShot()
|
||||
}
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
package uixt
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"github.com/BurntSushi/locker"
|
||||
"github.com/httprunner/httprunner/v5/internal/builtin"
|
||||
"github.com/httprunner/httprunner/v5/internal/config"
|
||||
"io"
|
||||
"math"
|
||||
"math/rand/v2"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@@ -259,3 +267,53 @@ func sleepStrict(startTime time.Time, strictMilliseconds int64) {
|
||||
Msg("sleep remaining duration time")
|
||||
time.Sleep(time.Duration(dur) * time.Millisecond)
|
||||
}
|
||||
|
||||
func DownloadFileByUrl(fileUrl string) (filePath string, err error) {
|
||||
hash := md5.Sum([]byte(fileUrl))
|
||||
fileName := fmt.Sprintf("%x", hash)
|
||||
filePath = filepath.Join(config.DownloadsPath, fileName)
|
||||
locker.Lock(filePath)
|
||||
defer locker.Unlock(filePath)
|
||||
if builtin.FileExists(filePath) {
|
||||
return filePath, nil
|
||||
}
|
||||
|
||||
fmt.Printf("Downloading file to %s from URL %s\n", filePath, fileUrl)
|
||||
|
||||
// Create an HTTP client with default settings.
|
||||
client := &http.Client{}
|
||||
|
||||
// Build the HTTP GET request.
|
||||
req, err := http.NewRequest("GET", fileUrl, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Perform the request.
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Check the HTTP status code.
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", fmt.Errorf("failed to download file: %s", resp.Status)
|
||||
}
|
||||
|
||||
// Create the output file.
|
||||
outFile, err := os.Create(fileName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer outFile.Close()
|
||||
|
||||
// Copy the response body to the file.
|
||||
_, err = io.Copy(outFile, resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
fmt.Printf("File downloaded successfully: %s\n", fileName)
|
||||
return filePath, nil
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt/types"
|
||||
)
|
||||
|
||||
func StartTunnel(recordsPath string, tunnelInfoPort int, userspaceTUN bool) (err error) {
|
||||
func StartTunnel(ctx context.Context, recordsPath string, tunnelInfoPort int, userspaceTUN bool) (err error) {
|
||||
pm, err := tunnel.NewPairRecordManager(recordsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -38,7 +38,7 @@ func StartTunnel(recordsPath string, tunnelInfoPort int, userspaceTUN bool) (err
|
||||
ticker := time.NewTicker(1 * time.Second)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
err := tm.UpdateTunnels(context.Background())
|
||||
err := tm.UpdateTunnels(ctx)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to update tunnels")
|
||||
}
|
||||
@@ -62,7 +62,7 @@ func RebootTunnel() (err error) {
|
||||
if tunnelManager != nil {
|
||||
_ = tunnelManager.Close()
|
||||
}
|
||||
return StartTunnel(os.TempDir(), ios.HttpApiPort(), true)
|
||||
return StartTunnel(context.Background(), os.TempDir(), ios.HttpApiPort(), true)
|
||||
}
|
||||
|
||||
func NewIOSDevice(opts ...option.IOSDeviceOption) (device *IOSDevice, err error) {
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt"
|
||||
)
|
||||
|
||||
func foregroundAppHandler(c *gin.Context) {
|
||||
driver, err := GetDriver(c)
|
||||
func (r *Router) foregroundAppHandler(c *gin.Context) {
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -18,7 +18,7 @@ func foregroundAppHandler(c *gin.Context) {
|
||||
RenderSuccess(c, appInfo)
|
||||
}
|
||||
|
||||
func appInfoHandler(c *gin.Context) {
|
||||
func (r *Router) appInfoHandler(c *gin.Context) {
|
||||
var appInfoReq AppInfoRequest
|
||||
if err := c.ShouldBindQuery(&appInfoReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
@@ -47,18 +47,18 @@ func appInfoHandler(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func clearAppHandler(c *gin.Context) {
|
||||
func (r *Router) clearAppHandler(c *gin.Context) {
|
||||
var appClearReq AppClearRequest
|
||||
if err := c.ShouldBindJSON(&appClearReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = driver.IDriver.(*uixt.ADBDriver).AppClear(appClearReq.PackageName)
|
||||
err = driver.GetIDriver().(*uixt.ADBDriver).AppClear(appClearReq.PackageName)
|
||||
if err != nil {
|
||||
RenderError(c, err)
|
||||
return
|
||||
@@ -66,13 +66,13 @@ func clearAppHandler(c *gin.Context) {
|
||||
RenderSuccess(c, true)
|
||||
}
|
||||
|
||||
func launchAppHandler(c *gin.Context) {
|
||||
func (r *Router) launchAppHandler(c *gin.Context) {
|
||||
var appLaunchReq AppLaunchRequest
|
||||
if err := c.ShouldBindJSON(&appLaunchReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
}
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -84,13 +84,13 @@ func launchAppHandler(c *gin.Context) {
|
||||
RenderSuccess(c, true)
|
||||
}
|
||||
|
||||
func terminalAppHandler(c *gin.Context) {
|
||||
func (r *Router) terminalAppHandler(c *gin.Context) {
|
||||
var appTerminalReq AppTerminalRequest
|
||||
if err := c.ShouldBindJSON(&appTerminalReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
}
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -102,13 +102,13 @@ func terminalAppHandler(c *gin.Context) {
|
||||
RenderSuccess(c, true)
|
||||
}
|
||||
|
||||
func uninstallAppHandler(c *gin.Context) {
|
||||
func (r *Router) uninstallAppHandler(c *gin.Context) {
|
||||
var appUninstallReq AppUninstallRequest
|
||||
if err := c.ShouldBindJSON(&appUninstallReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
}
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
|
||||
)
|
||||
|
||||
func GetDriver(c *gin.Context) (driverExt *uixt.XTDriver, err error) {
|
||||
func (r *Router) GetDriver(c *gin.Context) (driverExt uixt.IXTDriver, err error) {
|
||||
deviceObj, exists := c.Get("device")
|
||||
var device uixt.IDevice
|
||||
var driver uixt.IDriver
|
||||
|
||||
@@ -7,14 +7,13 @@ import (
|
||||
"github.com/Masterminds/semver"
|
||||
"github.com/danielpaulus/go-ios/ios"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/httprunner/httprunner/v5/internal/builtin"
|
||||
"github.com/httprunner/httprunner/v5/pkg/gadb"
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt"
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func listDeviceHandler(c *gin.Context) {
|
||||
func (r *Router) listDeviceHandler(c *gin.Context) {
|
||||
var deviceList []interface{}
|
||||
client, err := gadb.NewClient()
|
||||
if err == nil {
|
||||
@@ -88,17 +87,17 @@ func listDeviceHandler(c *gin.Context) {
|
||||
RenderSuccess(c, deviceList)
|
||||
}
|
||||
|
||||
func pushImageHandler(c *gin.Context) {
|
||||
func (r *Router) pushImageHandler(c *gin.Context) {
|
||||
var pushMediaReq PushMediaRequest
|
||||
if err := c.ShouldBindJSON(&pushMediaReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
}
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
imagePath, err := builtin.DownloadFileByUrl(pushMediaReq.ImageUrl)
|
||||
imagePath, err := uixt.DownloadFileByUrl(pushMediaReq.ImageUrl)
|
||||
if path.Ext(imagePath) == "" {
|
||||
err = os.Rename(imagePath, imagePath+".png")
|
||||
if err != nil {
|
||||
@@ -122,8 +121,8 @@ func pushImageHandler(c *gin.Context) {
|
||||
RenderSuccess(c, true)
|
||||
}
|
||||
|
||||
func clearImageHandler(c *gin.Context) {
|
||||
driver, err := GetDriver(c)
|
||||
func (r *Router) clearImageHandler(c *gin.Context) {
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -135,6 +134,6 @@ func clearImageHandler(c *gin.Context) {
|
||||
RenderSuccess(c, true)
|
||||
}
|
||||
|
||||
func videoHandler(c *gin.Context) {
|
||||
func (r *Router) videoHandler(c *gin.Context) {
|
||||
RenderSuccess(c, "")
|
||||
}
|
||||
|
||||
@@ -2,26 +2,26 @@ package server_ext
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt/driver_ext"
|
||||
"os"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/httprunner/httprunner/v5/internal/builtin"
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt"
|
||||
"github.com/httprunner/httprunner/v5/server"
|
||||
)
|
||||
|
||||
func installAppHandler(c *gin.Context) {
|
||||
func (r *RouterExt) installAppHandler(c *gin.Context) {
|
||||
var appInstallReq AppInstallRequest
|
||||
if err := c.ShouldBindJSON(&appInstallReq); err != nil {
|
||||
server.RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
}
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = driver.InstallByUrl(appInstallReq.AppUrl)
|
||||
err = driver.(*driver_ext.XTDriver).InstallByUrl(appInstallReq.AppUrl)
|
||||
if err != nil {
|
||||
server.RenderError(c, err)
|
||||
return
|
||||
@@ -32,7 +32,7 @@ func installAppHandler(c *gin.Context) {
|
||||
server.RenderSuccess(c, true)
|
||||
return
|
||||
}
|
||||
localMappingPath, err := builtin.DownloadFileByUrl(appInstallReq.MappingUrl)
|
||||
localMappingPath, err := uixt.DownloadFileByUrl(appInstallReq.MappingUrl)
|
||||
if err != nil {
|
||||
server.RenderError(c, err)
|
||||
}
|
||||
@@ -45,7 +45,7 @@ func installAppHandler(c *gin.Context) {
|
||||
server.RenderError(c, err)
|
||||
return
|
||||
}
|
||||
localResourceMappingPath, err := builtin.DownloadFileByUrl(
|
||||
localResourceMappingPath, err := uixt.DownloadFileByUrl(
|
||||
appInstallReq.ResourceMappingUrl)
|
||||
if err != nil {
|
||||
server.RenderError(c, err)
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/httprunner/httprunner/v5/server"
|
||||
)
|
||||
|
||||
func GetDriver(c *gin.Context) (driverExt *driver_ext.XTDriver, err error) {
|
||||
func (r *RouterExt) GetDriver(c *gin.Context) (driverExt uixt.IXTDriver, err error) {
|
||||
platform := c.Param("platform")
|
||||
deviceObj, exists := c.Get("device")
|
||||
var device uixt.IDevice
|
||||
|
||||
@@ -8,18 +8,18 @@ import (
|
||||
"github.com/httprunner/httprunner/v5/server"
|
||||
)
|
||||
|
||||
func loginHandler(c *gin.Context) {
|
||||
func (r *RouterExt) loginHandler(c *gin.Context) {
|
||||
var loginReq LoginRequest
|
||||
if err := c.ShouldBindJSON(&loginReq); err != nil {
|
||||
server.RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
info, err := driver.IDriver.(driver_ext.IStubDriver).
|
||||
info, err := driver.GetIDriver().(driver_ext.IStubDriver).
|
||||
LoginNoneUI(loginReq.PackageName, loginReq.PhoneNumber,
|
||||
loginReq.Captcha, loginReq.Password)
|
||||
if err != nil {
|
||||
@@ -29,18 +29,18 @@ func loginHandler(c *gin.Context) {
|
||||
server.RenderSuccess(c, info)
|
||||
}
|
||||
|
||||
func logoutHandler(c *gin.Context) {
|
||||
func (r *RouterExt) logoutHandler(c *gin.Context) {
|
||||
var logoutReq LogoutRequest
|
||||
if err := c.ShouldBindJSON(&logoutReq); err != nil {
|
||||
server.RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = driver.IDriver.(driver_ext.IStubDriver).
|
||||
err = driver.GetIDriver().(driver_ext.IStubDriver).
|
||||
LogoutNoneUI(logoutReq.PackageName)
|
||||
if err != nil {
|
||||
server.RenderError(c, err)
|
||||
@@ -49,8 +49,8 @@ func logoutHandler(c *gin.Context) {
|
||||
server.RenderSuccess(c, true)
|
||||
}
|
||||
|
||||
func sourceHandler(c *gin.Context) {
|
||||
driver, err := GetDriver(c)
|
||||
func (r *RouterExt) sourceHandler(c *gin.Context) {
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4,13 +4,24 @@ import (
|
||||
"github.com/httprunner/httprunner/v5/server"
|
||||
)
|
||||
|
||||
func NewExtRouter() *server.Router {
|
||||
router := server.NewRouter()
|
||||
apiV1PlatformSerial := router.Group("/api/v1").Group("/:platform").Group("/:serial")
|
||||
type RouterExt struct {
|
||||
*server.Router
|
||||
}
|
||||
|
||||
apiV1PlatformSerial.GET("/stub/source", sourceHandler)
|
||||
apiV1PlatformSerial.POST("/stub/login", loginHandler)
|
||||
apiV1PlatformSerial.POST("/stub/logout", logoutHandler)
|
||||
apiV1PlatformSerial.POST("/app/install", installAppHandler)
|
||||
func NewExtRouter() *RouterExt {
|
||||
router := &RouterExt{
|
||||
Router: server.NewRouter(),
|
||||
}
|
||||
router.Setup()
|
||||
return router
|
||||
}
|
||||
|
||||
func (r *RouterExt) Setup() {
|
||||
r.Router.Init()
|
||||
apiV1PlatformSerial := r.Group("/api/v1").Group("/:platform").Group("/:serial")
|
||||
|
||||
apiV1PlatformSerial.GET("/stub/source", r.sourceHandler)
|
||||
apiV1PlatformSerial.POST("/stub/login", r.loginHandler)
|
||||
apiV1PlatformSerial.POST("/stub/logout", r.logoutHandler)
|
||||
apiV1PlatformSerial.POST("/app/install", r.installAppHandler)
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt"
|
||||
)
|
||||
|
||||
func unlockHandler(c *gin.Context) {
|
||||
driver, err := GetDriver(c)
|
||||
func (r *Router) unlockHandler(c *gin.Context) {
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -19,8 +19,8 @@ func unlockHandler(c *gin.Context) {
|
||||
RenderSuccess(c, true)
|
||||
}
|
||||
|
||||
func homeHandler(c *gin.Context) {
|
||||
driver, err := GetDriver(c)
|
||||
func (r *Router) homeHandler(c *gin.Context) {
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func homeHandler(c *gin.Context) {
|
||||
RenderSuccess(c, true)
|
||||
}
|
||||
|
||||
func backspaceHandler(c *gin.Context) {
|
||||
func (r *Router) backspaceHandler(c *gin.Context) {
|
||||
var deleteReq DeleteRequest
|
||||
if err := c.ShouldBindJSON(&deleteReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
@@ -41,7 +41,7 @@ func backspaceHandler(c *gin.Context) {
|
||||
if deleteReq.Count == 0 {
|
||||
deleteReq.Count = 20
|
||||
}
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -53,18 +53,18 @@ func backspaceHandler(c *gin.Context) {
|
||||
RenderSuccess(c, true)
|
||||
}
|
||||
|
||||
func keycodeHandler(c *gin.Context) {
|
||||
func (r *Router) keycodeHandler(c *gin.Context) {
|
||||
var keycodeReq KeycodeRequest
|
||||
if err := c.ShouldBindJSON(&keycodeReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
}
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// TODO FIXME
|
||||
err = driver.IDriver.(*uixt.ADBDriver).
|
||||
err = driver.GetIDriver().(*uixt.ADBDriver).
|
||||
PressKeyCode(uixt.KeyCode(keycodeReq.Keycode), uixt.KMEmpty)
|
||||
if err != nil {
|
||||
RenderError(c, err)
|
||||
|
||||
@@ -20,47 +20,51 @@ type Router struct {
|
||||
*gin.Engine
|
||||
}
|
||||
|
||||
type IRouter 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", pingHandler)
|
||||
r.Engine.GET("/", pingHandler)
|
||||
r.Engine.POST("/", pingHandler)
|
||||
r.Engine.GET("/api/v1/devices", listDeviceHandler)
|
||||
r.Engine.GET("/ping", r.pingHandler)
|
||||
r.Engine.GET("/", r.pingHandler)
|
||||
r.Engine.POST("/", r.pingHandler)
|
||||
r.Engine.GET("/api/v1/devices", r.listDeviceHandler)
|
||||
|
||||
apiV1PlatformSerial := r.Group("/api/v1").Group("/:platform").Group("/:serial")
|
||||
|
||||
// UI operations
|
||||
apiV1PlatformSerial.POST("/ui/tap", tapHandler)
|
||||
apiV1PlatformSerial.POST("/ui/double_tap", doubleTapHandler)
|
||||
apiV1PlatformSerial.POST("/ui/drag", dragHandler)
|
||||
apiV1PlatformSerial.POST("/ui/input", inputHandler)
|
||||
apiV1PlatformSerial.POST("/ui/home", homeHandler)
|
||||
apiV1PlatformSerial.POST("/ui/tap", r.tapHandler)
|
||||
apiV1PlatformSerial.POST("/ui/double_tap", r.doubleTapHandler)
|
||||
apiV1PlatformSerial.POST("/ui/drag", r.dragHandler)
|
||||
apiV1PlatformSerial.POST("/ui/input", r.inputHandler)
|
||||
apiV1PlatformSerial.POST("/ui/home", r.homeHandler)
|
||||
|
||||
// Key operations
|
||||
apiV1PlatformSerial.POST("/key/unlock", unlockHandler)
|
||||
apiV1PlatformSerial.POST("/key/home", homeHandler)
|
||||
apiV1PlatformSerial.POST("/key/backspace", backspaceHandler)
|
||||
apiV1PlatformSerial.POST("/key", keycodeHandler)
|
||||
apiV1PlatformSerial.POST("/key/unlock", r.unlockHandler)
|
||||
apiV1PlatformSerial.POST("/key/home", r.homeHandler)
|
||||
apiV1PlatformSerial.POST("/key/backspace", r.backspaceHandler)
|
||||
apiV1PlatformSerial.POST("/key", r.keycodeHandler)
|
||||
|
||||
// APP operations
|
||||
apiV1PlatformSerial.GET("/app/foreground", foregroundAppHandler)
|
||||
apiV1PlatformSerial.GET("/app/appInfo", appInfoHandler)
|
||||
apiV1PlatformSerial.POST("/app/clear", clearAppHandler)
|
||||
apiV1PlatformSerial.POST("/app/launch", launchAppHandler)
|
||||
apiV1PlatformSerial.POST("/app/terminal", terminalAppHandler)
|
||||
apiV1PlatformSerial.POST("/app/uninstall", uninstallAppHandler)
|
||||
apiV1PlatformSerial.GET("/app/foreground", r.foregroundAppHandler)
|
||||
apiV1PlatformSerial.GET("/app/appInfo", r.appInfoHandler)
|
||||
apiV1PlatformSerial.POST("/app/clear", r.clearAppHandler)
|
||||
apiV1PlatformSerial.POST("/app/launch", r.launchAppHandler)
|
||||
apiV1PlatformSerial.POST("/app/terminal", r.terminalAppHandler)
|
||||
apiV1PlatformSerial.POST("/app/uninstall", r.uninstallAppHandler)
|
||||
|
||||
// Device operations
|
||||
apiV1PlatformSerial.GET("/screenshot", screenshotHandler)
|
||||
apiV1PlatformSerial.GET("/video", videoHandler)
|
||||
apiV1PlatformSerial.POST("/device/push_image", pushImageHandler)
|
||||
apiV1PlatformSerial.POST("/device/clear_image", clearImageHandler)
|
||||
apiV1PlatformSerial.GET("/adb/source", adbSourceHandler)
|
||||
apiV1PlatformSerial.GET("/screenshot", r.screenshotHandler)
|
||||
apiV1PlatformSerial.GET("/video", r.videoHandler)
|
||||
apiV1PlatformSerial.POST("/device/push_image", r.pushImageHandler)
|
||||
apiV1PlatformSerial.POST("/device/clear_image", r.clearImageHandler)
|
||||
apiV1PlatformSerial.GET("/adb/source", r.adbSourceHandler)
|
||||
|
||||
// uixt operations
|
||||
apiV1PlatformSerial.POST("/uixt/action", uixtActionHandler)
|
||||
apiV1PlatformSerial.POST("/uixt/actions", uixtActionsHandler)
|
||||
apiV1PlatformSerial.POST("/uixt/action", r.uixtActionHandler)
|
||||
apiV1PlatformSerial.POST("/uixt/actions", r.uixtActionsHandler)
|
||||
}
|
||||
|
||||
func (r *Router) Run(port int) error {
|
||||
@@ -72,7 +76,7 @@ func (r *Router) Run(port int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func pingHandler(c *gin.Context) {
|
||||
func (r *Router) pingHandler(c *gin.Context) {
|
||||
RenderSuccess(c, true)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
|
||||
)
|
||||
|
||||
func screenshotHandler(c *gin.Context) {
|
||||
driver, err := GetDriver(c)
|
||||
func (r *Router) screenshotHandler(c *gin.Context) {
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -23,8 +23,8 @@ func screenshotHandler(c *gin.Context) {
|
||||
RenderSuccess(c, base64.StdEncoding.EncodeToString(raw.Bytes()))
|
||||
}
|
||||
|
||||
func screenResultHandler(c *gin.Context) {
|
||||
dExt, err := GetDriver(c)
|
||||
func (r *Router) screenResultHandler(c *gin.Context) {
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -40,7 +40,7 @@ func screenResultHandler(c *gin.Context) {
|
||||
actionOptions = screenReq.Options.Options()
|
||||
}
|
||||
|
||||
screenResult, err := dExt.GetScreenResult(actionOptions...)
|
||||
screenResult, err := driver.GetScreenResult(actionOptions...)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("get screen result failed")
|
||||
RenderError(c, err)
|
||||
@@ -49,8 +49,8 @@ func screenResultHandler(c *gin.Context) {
|
||||
RenderSuccess(c, screenResult)
|
||||
}
|
||||
|
||||
func adbSourceHandler(c *gin.Context) {
|
||||
dExt, err := GetDriver(c)
|
||||
func (r *Router) adbSourceHandler(c *gin.Context) {
|
||||
dExt, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
16
server/ui.go
16
server/ui.go
@@ -5,13 +5,13 @@ import (
|
||||
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
|
||||
)
|
||||
|
||||
func tapHandler(c *gin.Context) {
|
||||
func (r *Router) tapHandler(c *gin.Context) {
|
||||
var tapReq TapRequest
|
||||
if err := c.ShouldBindJSON(&tapReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
}
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -29,14 +29,14 @@ func tapHandler(c *gin.Context) {
|
||||
RenderSuccess(c, true)
|
||||
}
|
||||
|
||||
func doubleTapHandler(c *gin.Context) {
|
||||
func (r *Router) doubleTapHandler(c *gin.Context) {
|
||||
var tapReq TapRequest
|
||||
if err := c.ShouldBindJSON(&tapReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -55,7 +55,7 @@ func doubleTapHandler(c *gin.Context) {
|
||||
RenderSuccess(c, true)
|
||||
}
|
||||
|
||||
func dragHandler(c *gin.Context) {
|
||||
func (r *Router) dragHandler(c *gin.Context) {
|
||||
var dragReq DragRequest
|
||||
if err := c.ShouldBindJSON(&dragReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
@@ -64,7 +64,7 @@ func dragHandler(c *gin.Context) {
|
||||
if dragReq.Duration == 0 {
|
||||
dragReq.Duration = 1
|
||||
}
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -79,13 +79,13 @@ func dragHandler(c *gin.Context) {
|
||||
RenderSuccess(c, true)
|
||||
}
|
||||
|
||||
func inputHandler(c *gin.Context) {
|
||||
func (r *Router) inputHandler(c *gin.Context) {
|
||||
var inputReq InputRequest
|
||||
if err := c.ShouldBindJSON(&inputReq); err != nil {
|
||||
RenderErrorValidateRequest(c, err)
|
||||
return
|
||||
}
|
||||
driver, err := GetDriver(c)
|
||||
driver, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
)
|
||||
|
||||
// exec a single uixt action
|
||||
func uixtActionHandler(c *gin.Context) {
|
||||
dExt, err := GetDriver(c)
|
||||
func (r *Router) uixtActionHandler(c *gin.Context) {
|
||||
dExt, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -29,8 +29,8 @@ func uixtActionHandler(c *gin.Context) {
|
||||
}
|
||||
|
||||
// exec multiple uixt actions
|
||||
func uixtActionsHandler(c *gin.Context) {
|
||||
dExt, err := GetDriver(c)
|
||||
func (r *Router) uixtActionsHandler(c *gin.Context) {
|
||||
dExt, err := r.GetDriver(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user