mirror of
https://github.com/httprunner/httprunner.git
synced 2026-09-05 23:51:25 +08:00
feat: 支持shoots协议, app_process获取前台应用, 修复部分bug
This commit is contained in:
@@ -1 +1 @@
|
|||||||
v4.6.0
|
v4.6.2
|
||||||
@@ -3,7 +3,7 @@ package server
|
|||||||
// 常见的错误代码和消息
|
// 常见的错误代码和消息
|
||||||
const (
|
const (
|
||||||
InternalServerErrorCode = 100001
|
InternalServerErrorCode = 100001
|
||||||
InternalServerErrorMsg = "Invalid Server Error"
|
InternalServerErrorMsg = "Internal Server Error"
|
||||||
|
|
||||||
InvalidParamErrorCode = 100002
|
InvalidParamErrorCode = 100002
|
||||||
InvalidParamErrorMsg = "Invalid %s Param"
|
InvalidParamErrorMsg = "Invalid %s Param"
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ type KeycodeRequest struct {
|
|||||||
Keycode int `json:"keycode"`
|
Keycode int `json:"keycode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AppClearRequest struct {
|
||||||
|
PackageName string `json:"packageName"`
|
||||||
|
}
|
||||||
|
|
||||||
type AppLaunchRequest struct {
|
type AppLaunchRequest struct {
|
||||||
PackageName string `json:"packageName"`
|
PackageName string `json:"packageName"`
|
||||||
}
|
}
|
||||||
@@ -42,3 +46,7 @@ type LoginRequest struct {
|
|||||||
PhoneNumber string `json:"phoneNumber"`
|
PhoneNumber string `json:"phoneNumber"`
|
||||||
Captcha string `json:"captcha"`
|
Captcha string `json:"captcha"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LogoutRequest struct {
|
||||||
|
PackageName string `json:"packageName"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,12 +24,14 @@ func NewServer(port int) error {
|
|||||||
router.POST("/api/v1/:platform/:serial/key/home", parseDeviceInfo(), homeHandler)
|
router.POST("/api/v1/:platform/:serial/key/home", parseDeviceInfo(), homeHandler)
|
||||||
router.POST("/api/v1/:platform/:serial/key", parseDeviceInfo(), keycodeHandler)
|
router.POST("/api/v1/:platform/:serial/key", parseDeviceInfo(), keycodeHandler)
|
||||||
router.GET("/api/v1/:platform/:serial/app/foreground", parseDeviceInfo(), foregroundAppHandler)
|
router.GET("/api/v1/:platform/:serial/app/foreground", parseDeviceInfo(), foregroundAppHandler)
|
||||||
|
router.POST("/api/v1/:platform/:serial/app/clear", parseDeviceInfo(), clearAppHandler)
|
||||||
router.POST("/api/v1/:platform/:serial/app/launch", parseDeviceInfo(), launchAppHandler)
|
router.POST("/api/v1/:platform/:serial/app/launch", parseDeviceInfo(), launchAppHandler)
|
||||||
router.POST("/api/v1/:platform/:serial/app/terminal", parseDeviceInfo(), terminalAppHandler)
|
router.POST("/api/v1/:platform/:serial/app/terminal", parseDeviceInfo(), terminalAppHandler)
|
||||||
router.GET("/api/v1/:platform/:serial/screenshot", parseDeviceInfo(), screenshotHandler)
|
router.GET("/api/v1/:platform/:serial/screenshot", parseDeviceInfo(), screenshotHandler)
|
||||||
router.GET("/api/v1/:platform/:serial/shoots/source", parseDeviceInfo(), sourceHandler)
|
router.GET("/api/v1/:platform/:serial/shoots/source", parseDeviceInfo(), sourceHandler)
|
||||||
router.GET("/api/v1/:platform/:serial/adb/source", parseDeviceInfo(), adbSourceHandler)
|
router.GET("/api/v1/:platform/:serial/adb/source", parseDeviceInfo(), adbSourceHandler)
|
||||||
router.POST("/api/v1/:platform/:serial/shoots/login", parseDeviceInfo(), loginHandler)
|
router.POST("/api/v1/:platform/:serial/shoots/login", parseDeviceInfo(), loginHandler)
|
||||||
|
router.POST("/api/v1/:platform/:serial/shoots/logout", parseDeviceInfo(), logoutHandler)
|
||||||
|
|
||||||
err := router.Run(fmt.Sprintf("127.0.0.1:%d", port))
|
err := router.Run(fmt.Sprintf("127.0.0.1:%d", port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -301,6 +303,35 @@ func foregroundAppHandler(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func clearAppHandler(c *gin.Context) {
|
||||||
|
var appClearReq AppClearRequest
|
||||||
|
if err := c.ShouldBindJSON(&appClearReq); err != nil {
|
||||||
|
log.Err(err).Msg(fmt.Sprintf("[%s]: Invalid Request", c.HandlerName()))
|
||||||
|
c.JSON(http.StatusBadRequest, HttpResponse{Result: "", ErrorCode: InvalidParamErrorCode, ErrorMsg: fmt.Sprintf(InvalidParamErrorMsg, "request")})
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
driverObj, exists := c.Get("driver")
|
||||||
|
if !exists {
|
||||||
|
log.Error().Msg(fmt.Sprintf("[%s]: Driver Not exsit", c.HandlerName()))
|
||||||
|
c.JSON(http.StatusBadRequest, HttpResponse{Result: false, ErrorCode: InvalidParamErrorCode, ErrorMsg: fmt.Sprintf(InvalidParamErrorMsg, "driver")})
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dExt := driverObj.(*uixt.DriverExt)
|
||||||
|
err := dExt.Driver.Clear(appClearReq.PackageName)
|
||||||
|
if err != nil {
|
||||||
|
log.Err(err).Msg(fmt.Sprintf("[%s]: failed to unlick screen", c.HandlerName()))
|
||||||
|
c.JSON(http.StatusInternalServerError, HttpResponse{Result: false, ErrorCode: InternalServerErrorCode, ErrorMsg: InternalServerErrorMsg})
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, HttpResponse{Result: true})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func launchAppHandler(c *gin.Context) {
|
func launchAppHandler(c *gin.Context) {
|
||||||
var appLaunchReq AppLaunchRequest
|
var appLaunchReq AppLaunchRequest
|
||||||
if err := c.ShouldBindJSON(&appLaunchReq); err != nil {
|
if err := c.ShouldBindJSON(&appLaunchReq); err != nil {
|
||||||
@@ -455,7 +486,36 @@ func loginHandler(c *gin.Context) {
|
|||||||
dExt := driverObj.(*uixt.DriverExt)
|
dExt := driverObj.(*uixt.DriverExt)
|
||||||
err := dExt.Driver.LoginNoneUI(loginReq.PackageName, loginReq.PhoneNumber, loginReq.Captcha)
|
err := dExt.Driver.LoginNoneUI(loginReq.PackageName, loginReq.PhoneNumber, loginReq.Captcha)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg(fmt.Sprintf("[%s]: failed to get foreground app", c.HandlerName()))
|
log.Err(err).Msg(fmt.Sprintf("[%s]: failed to login", c.HandlerName()))
|
||||||
|
c.JSON(http.StatusInternalServerError, HttpResponse{Result: "", ErrorCode: InternalServerErrorCode, ErrorMsg: InternalServerErrorMsg})
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, HttpResponse{Result: true})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func logoutHandler(c *gin.Context) {
|
||||||
|
var logoutReq LogoutRequest
|
||||||
|
if err := c.ShouldBindJSON(&logoutReq); err != nil {
|
||||||
|
log.Err(err).Msg(fmt.Sprintf("[%s]: Invalid Request", c.HandlerName()))
|
||||||
|
c.JSON(http.StatusBadRequest, HttpResponse{Result: "", ErrorCode: InvalidParamErrorCode, ErrorMsg: fmt.Sprintf(InvalidParamErrorMsg, "request")})
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
driverObj, exists := c.Get("driver")
|
||||||
|
if !exists {
|
||||||
|
log.Error().Msg(fmt.Sprintf("[%s]: Driver Not exsit", c.HandlerName()))
|
||||||
|
c.JSON(http.StatusBadRequest, HttpResponse{Result: "", ErrorCode: InvalidParamErrorCode, ErrorMsg: fmt.Sprintf(InvalidParamErrorMsg, "driver")})
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dExt := driverObj.(*uixt.DriverExt)
|
||||||
|
err := dExt.Driver.LogoutNoneUI(logoutReq.PackageName)
|
||||||
|
if err != nil {
|
||||||
|
log.Err(err).Msg(fmt.Sprintf("[%s]: failed to login", c.HandlerName()))
|
||||||
c.JSON(http.StatusInternalServerError, HttpResponse{Result: "", ErrorCode: InternalServerErrorCode, ErrorMsg: InternalServerErrorMsg})
|
c.JSON(http.StatusInternalServerError, HttpResponse{Result: "", ErrorCode: InternalServerErrorCode, ErrorMsg: InternalServerErrorMsg})
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -475,6 +475,15 @@ func (ad *adbDriver) Input(text string, options ...ActionOption) (err error) {
|
|||||||
return ad.SendKeys(text, options...)
|
return ad.SendKeys(text, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) Clear(packageName string) error {
|
||||||
|
if _, err := ad.adbClient.RunShellCommand("pm", "clear", packageName); err != nil {
|
||||||
|
log.Error().Str("packageName", packageName).Err(err).Msg("failed to clear package cache")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ad *adbDriver) PressButton(devBtn DeviceButton) (err error) {
|
func (ad *adbDriver) PressButton(devBtn DeviceButton) (err error) {
|
||||||
err = errDriverNotImplemented
|
err = errDriverNotImplemented
|
||||||
return
|
return
|
||||||
@@ -520,6 +529,10 @@ func (ad *adbDriver) LoginNoneUI(packageName, phoneNumber string, captcha string
|
|||||||
return errDriverNotImplemented
|
return errDriverNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) LogoutNoneUI(packageName string) error {
|
||||||
|
return errDriverNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func (ad *adbDriver) sourceTree(srcOpt ...SourceOption) (sourceTree *Hierarchy, err error) {
|
func (ad *adbDriver) sourceTree(srcOpt ...SourceOption) (sourceTree *Hierarchy, err error) {
|
||||||
source, err := ad.Source()
|
source, err := ad.Source()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -715,20 +728,6 @@ func (ad *adbDriver) GetForegroundApp() (app AppInfo, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ad *adbDriver) GetFocusedPackage() (packageName string, err error) {
|
|
||||||
res, err := ad.adbClient.RunShellCommand("dumpsys", "activity", "activities", "|", "grep", "-E", "'mResumedActivity'")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
match := regexp.MustCompile(`mResumedActivity:.*? (\S+)/`).FindStringSubmatch(res)
|
|
||||||
if len(match) > 1 {
|
|
||||||
packageName = match[1]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Error().Str("dumpsys", res).Msg("failed to get focused package")
|
|
||||||
return "", fmt.Errorf("failed to get focused package")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ad *adbDriver) SetIme(imeRegx string) error {
|
func (ad *adbDriver) SetIme(imeRegx string) error {
|
||||||
imeList := ad.ListIme()
|
imeList := ad.ListIme()
|
||||||
ime := ""
|
ime := ""
|
||||||
@@ -754,13 +753,13 @@ func (ad *adbDriver) SetIme(imeRegx string) error {
|
|||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
pid, _ := ad.adbClient.RunShellCommand("pidof", packageName)
|
pid, _ := ad.adbClient.RunShellCommand("pidof", packageName)
|
||||||
if strings.TrimSpace(pid) == "" {
|
if strings.TrimSpace(pid) == "" {
|
||||||
focusedPackage, err := ad.GetFocusedPackage()
|
appInfo, err := ad.GetForegroundApp()
|
||||||
_ = ad.AppLaunch(packageName)
|
_ = ad.AppLaunch(packageName)
|
||||||
if err == nil && packageName != UnicodeImePackageName {
|
if err == nil && packageName != UnicodeImePackageName {
|
||||||
time.Sleep(10 * time.Second)
|
time.Sleep(10 * time.Second)
|
||||||
currentPackage, err := ad.GetFocusedPackage()
|
nextAppInfo, err := ad.GetForegroundApp()
|
||||||
log.Info().Str("beforeFocusedPackage", focusedPackage).Str("afterFocusedPackage", currentPackage).Msg("")
|
log.Info().Str("beforeFocusedPackage", appInfo.PackageName).Str("afterFocusedPackage", nextAppInfo.PackageName).Msg("")
|
||||||
if err == nil && currentPackage != focusedPackage {
|
if err == nil && nextAppInfo.PackageName != appInfo.PackageName {
|
||||||
_ = ad.PressKeyCodes(KCBack, KMEmpty)
|
_ = ad.PressKeyCodes(KCBack, KMEmpty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
AdbServerHost = "localhost"
|
AdbServerHost = "localhost"
|
||||||
AdbServerPort = gadb.AdbServerPort // 5037
|
AdbServerPort = gadb.AdbServerPort // 5037
|
||||||
UIA2ServerHost = "localhost"
|
UIA2ServerHost = "localhost"
|
||||||
UIA2ServerPort = 6790
|
UIA2ServerPort = 6790
|
||||||
|
DouyinServerPort = 32316
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed eval_tool
|
//go:embed eval_tool
|
||||||
@@ -248,16 +249,27 @@ func (dev *AndroidDevice) NewUSBDriver(capabilities Capabilities) (driver WebDri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dev *AndroidDevice) NewShootsDriver(capabilities Capabilities) (driver *ShootsAndroidDriver, err error) {
|
func (dev *AndroidDevice) NewShootsDriver(capabilities Capabilities) (driver *ShootsAndroidDriver, err error) {
|
||||||
localPort, err := dev.d.Forward(ShootsSocketName)
|
socketLocalPort, err := dev.d.Forward(ShootsSocketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(code.AndroidDeviceConnectionError,
|
return nil, errors.Wrap(code.AndroidDeviceConnectionError,
|
||||||
fmt.Sprintf("forward port %d->%s failed: %v",
|
fmt.Sprintf("forward port %d->%s failed: %v",
|
||||||
localPort, ShootsSocketName, err))
|
socketLocalPort, ShootsSocketName, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
shootsDriver, err := newShootsAndroidDriver(fmt.Sprintf("127.0.0.1:%d", localPort))
|
serverLocalPort, err := dev.d.Forward(DouyinServerPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = dev.d.ForwardKill(localPort)
|
return nil, errors.Wrap(code.AndroidDeviceConnectionError,
|
||||||
|
fmt.Sprintf("forward port %d->%d failed: %v",
|
||||||
|
serverLocalPort, DouyinServerPort, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
rawURL := fmt.Sprintf("http://%s%d:%d",
|
||||||
|
forwardToPrefix, serverLocalPort, DouyinServerPort)
|
||||||
|
|
||||||
|
shootsDriver, err := newShootsAndroidDriver(fmt.Sprintf("127.0.0.1:%d", socketLocalPort), rawURL)
|
||||||
|
if err != nil {
|
||||||
|
_ = dev.d.ForwardKill(socketLocalPort)
|
||||||
|
_ = dev.d.ForwardKill(serverLocalPort)
|
||||||
return nil, errors.Wrap(code.AndroidDeviceConnectionError, err.Error())
|
return nil, errors.Wrap(code.AndroidDeviceConnectionError, err.Error())
|
||||||
}
|
}
|
||||||
shootsDriver.adbClient = dev.d
|
shootsDriver.adbClient = dev.d
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
@@ -25,7 +29,7 @@ const ShootsSocketName = "com.bytest.device"
|
|||||||
|
|
||||||
// newShootsAndroidDriver
|
// newShootsAndroidDriver
|
||||||
// 创建shoots Driver address为forward后的端口格式127.0.0.1:${port}
|
// 创建shoots Driver address为forward后的端口格式127.0.0.1:${port}
|
||||||
func newShootsAndroidDriver(address string, readTimeout ...time.Duration) (*ShootsAndroidDriver, error) {
|
func newShootsAndroidDriver(address string, urlPrefix string, readTimeout ...time.Duration) (*ShootsAndroidDriver, error) {
|
||||||
timeout := 10 * time.Second
|
timeout := 10 * time.Second
|
||||||
if len(readTimeout) > 0 {
|
if len(readTimeout) > 0 {
|
||||||
timeout = readTimeout[0]
|
timeout = readTimeout[0]
|
||||||
@@ -37,10 +41,59 @@ func newShootsAndroidDriver(address string, readTimeout ...time.Duration) (*Shoo
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ShootsAndroidDriver{
|
driver := &ShootsAndroidDriver{
|
||||||
socket: conn,
|
socket: conn,
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
}, nil
|
}
|
||||||
|
|
||||||
|
if driver.urlPrefix, err = url.Parse(urlPrefix); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return driver, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sad *ShootsAndroidDriver) httpGET(pathElem ...string) (rawResp rawResponse, err error) {
|
||||||
|
var localPort int
|
||||||
|
{
|
||||||
|
tmpURL, _ := url.Parse(sad.urlPrefix.String())
|
||||||
|
hostname := tmpURL.Hostname()
|
||||||
|
if strings.HasPrefix(hostname, forwardToPrefix) {
|
||||||
|
localPort, _ = strconv.Atoi(strings.TrimPrefix(hostname, forwardToPrefix))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := net.Dial("tcp", fmt.Sprintf(":%d", localPort))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("adb forward: %w", err)
|
||||||
|
}
|
||||||
|
sad.client = convertToHTTPClient(conn)
|
||||||
|
return sad.httpRequest(http.MethodGet, sad.concatURL(nil, pathElem...), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sad *ShootsAndroidDriver) httpPOST(data interface{}, pathElem ...string) (rawResp rawResponse, err error) {
|
||||||
|
var localPort int
|
||||||
|
{
|
||||||
|
tmpURL, _ := url.Parse(sad.urlPrefix.String())
|
||||||
|
hostname := tmpURL.Hostname()
|
||||||
|
if strings.HasPrefix(hostname, forwardToPrefix) {
|
||||||
|
localPort, _ = strconv.Atoi(strings.TrimPrefix(hostname, forwardToPrefix))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := net.Dial("tcp", fmt.Sprintf(":%d", localPort))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("adb forward: %w", err)
|
||||||
|
}
|
||||||
|
sad.client = convertToHTTPClient(conn)
|
||||||
|
|
||||||
|
var bsJSON []byte = nil
|
||||||
|
if data != nil {
|
||||||
|
if bsJSON, err = json.Marshal(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sad.httpRequest(http.MethodPost, sad.concatURL(nil, pathElem...), bsJSON)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sad *ShootsAndroidDriver) NewSession(capabilities Capabilities) (SessionInfo, error) {
|
func (sad *ShootsAndroidDriver) NewSession(capabilities Capabilities) (SessionInfo, error) {
|
||||||
@@ -197,9 +250,9 @@ func (sad *ShootsAndroidDriver) Source(srcOpt ...SourceOption) (source string, e
|
|||||||
return res.(string), nil
|
return res.(string), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sad *ShootsAndroidDriver) LoginNoneUI(packageName, phoneNumber string, captcha string) error {
|
func (sad *ShootsAndroidDriver) LoginNoneUIBak(packageName, phoneNumber, captcha string) error {
|
||||||
_, err := sad.adbClient.RunShellCommand("am", "broadcast", "-a", fmt.Sprintf("%s.util.crony.action_login", packageName), "-e", "phone", phoneNumber, "-e", "code", captcha)
|
_, err := sad.adbClient.RunShellCommand("am", "broadcast", "-a", fmt.Sprintf("%s.util.crony.action_login", packageName), "-e", "phone", phoneNumber, "-e", "code", captcha)
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(10 * time.Second)
|
||||||
login, err := sad.isLogin(packageName)
|
login, err := sad.isLogin(packageName)
|
||||||
if err != nil || !login {
|
if err != nil || !login {
|
||||||
log.Err(err).Msg("failed to login")
|
log.Err(err).Msg("failed to login")
|
||||||
@@ -208,7 +261,87 @@ func (sad *ShootsAndroidDriver) LoginNoneUI(packageName, phoneNumber string, cap
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sad *ShootsAndroidDriver) LoginNoneUI(packageName, phoneNumber, captcha string) error {
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"phone": phoneNumber,
|
||||||
|
"code": captcha,
|
||||||
|
}
|
||||||
|
resp, err := sad.httpPOST(params, "/host", "/login", "account")
|
||||||
|
res, err := resp.valueConvertToJsonObject()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info().Msgf("%v", res)
|
||||||
|
if res["isSuccess"] != true {
|
||||||
|
err = fmt.Errorf("falied to logout %s", res["data"])
|
||||||
|
log.Err(err).Msgf("%v", res)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
login, err := sad.isLogin(packageName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !login {
|
||||||
|
return fmt.Errorf("failed to login")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sad *ShootsAndroidDriver) LogoutNoneUI(packageName string) error {
|
||||||
|
resp, err := sad.httpGET("/host", "/logout")
|
||||||
|
res, err := resp.valueConvertToJsonObject()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info().Msgf("%v", res)
|
||||||
|
if res["isSuccess"] != true {
|
||||||
|
err = fmt.Errorf("falied to logout %s", res["data"])
|
||||||
|
log.Err(err).Msgf("%v", res)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("%v", resp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sad *ShootsAndroidDriver) LoginNoneUIDynamic(packageName, phoneNumber string, captcha string) error {
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"ClassName": "qe.python.test.LoginUtil",
|
||||||
|
"Method": "loginSync",
|
||||||
|
"RetType": "",
|
||||||
|
"Args": []string{phoneNumber, captcha},
|
||||||
|
}
|
||||||
|
res, err := sad.sendCommand(packageName, "CallStaticMethod", params)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info().Msg(res.(string))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (sad *ShootsAndroidDriver) isLogin(packageName string) (login bool, err error) {
|
func (sad *ShootsAndroidDriver) isLogin(packageName string) (login bool, err error) {
|
||||||
|
resp, err := sad.httpGET("/host", "/login", "/check")
|
||||||
|
res, err := resp.valueConvertToJsonObject()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
log.Info().Msgf("%v", res)
|
||||||
|
if res["isSuccess"] != true {
|
||||||
|
err = fmt.Errorf("falied to get is login %s", res["data"])
|
||||||
|
log.Err(err).Msgf("%v", res)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
fmt.Printf("%v", resp)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sad *ShootsAndroidDriver) isLoginBak(packageName string) (login bool, err error) {
|
||||||
params := map[string]interface{}{
|
params := map[string]interface{}{
|
||||||
"ClassName": "com.ss.android.ugc.aweme.account.AccountProxyService",
|
"ClassName": "com.ss.android.ugc.aweme.account.AccountProxyService",
|
||||||
"Method": "userService",
|
"Method": "userService",
|
||||||
@@ -222,10 +355,11 @@ func (sad *ShootsAndroidDriver) isLogin(packageName string) (login bool, err err
|
|||||||
}
|
}
|
||||||
|
|
||||||
params = map[string]interface{}{
|
params = map[string]interface{}{
|
||||||
"Method": "isLogin",
|
"ClassName": "com.ss.android.ugc.aweme.account.service.IAccountUserService",
|
||||||
"RetType": "",
|
"Method": "isLogin",
|
||||||
"Args": []string{},
|
"RetType": "",
|
||||||
"ObjectId": int(id.(float64)),
|
"Args": []string{},
|
||||||
|
"ObjectId": int(id.(float64)),
|
||||||
}
|
}
|
||||||
loginObj, err := sad.sendCommand(packageName, "CallMethod", params)
|
loginObj, err := sad.sendCommand(packageName, "CallMethod", params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -233,3 +367,15 @@ func (sad *ShootsAndroidDriver) isLogin(packageName string) (login bool, err err
|
|||||||
}
|
}
|
||||||
return loginObj.(bool), nil
|
return loginObj.(bool), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func calculatePortNumber(packageName string) int {
|
||||||
|
asciiSum := 0
|
||||||
|
for _, char := range packageName {
|
||||||
|
asciiSum += int(char)
|
||||||
|
}
|
||||||
|
|
||||||
|
portRange := 65536 - 30000
|
||||||
|
calculatedPortNumber := (asciiSum % portRange) + 30000
|
||||||
|
|
||||||
|
return calculatedPortNumber
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,19 +2,19 @@ package uixt
|
|||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
var driver *ShootsAndroidDriver
|
var shootsDriver *ShootsAndroidDriver
|
||||||
|
|
||||||
func setupAndroid(t *testing.T) {
|
func setupShootsDriver(t *testing.T) {
|
||||||
device, err := NewAndroidDevice()
|
device, err := NewAndroidDevice()
|
||||||
checkErr(t, err)
|
checkErr(t, err)
|
||||||
device.SHOOTS = true
|
device.SHOOTS = true
|
||||||
driver, err = device.NewShootsDriver(Capabilities{})
|
shootsDriver, err = device.NewShootsDriver(Capabilities{})
|
||||||
checkErr(t, err)
|
checkErr(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHello(t *testing.T) {
|
func TestHello(t *testing.T) {
|
||||||
setupAndroid(t)
|
setupShootsDriver(t)
|
||||||
status, err := driver.Status()
|
status, err := shootsDriver.Status()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -22,19 +22,35 @@ func TestHello(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSource(t *testing.T) {
|
func TestSource(t *testing.T) {
|
||||||
setupAndroid(t)
|
setupShootsDriver(t)
|
||||||
source, err := driver.Source()
|
source, err := shootsDriver.Source()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
t.Log(source)
|
t.Log(source)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLogin(t *testing.T) {
|
func TestIsLogin(t *testing.T) {
|
||||||
setupAndroid(t)
|
setupShootsDriver(t)
|
||||||
res, err := driver.isLogin("com.ss.android.ugc.aweme")
|
res, err := shootsDriver.isLogin("com.ss.android.ugc.aweme")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
t.Log(res)
|
t.Log(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLogin(t *testing.T) {
|
||||||
|
setupShootsDriver(t)
|
||||||
|
err := shootsDriver.LoginNoneUI("com.ss.android.ugc.aweme", "12342316231", "8517")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLogout(t *testing.T) {
|
||||||
|
setupShootsDriver(t)
|
||||||
|
err := shootsDriver.LogoutNoneUI("com.ss.android.ugc.aweme")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -125,12 +125,9 @@ func TestDriver_DeviceSize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDriver_Source(t *testing.T) {
|
func TestDriver_Source(t *testing.T) {
|
||||||
driver, err := NewUIADriver(nil, uiaServerURL)
|
setupAndroid(t)
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
source, err := driver.Source()
|
source, err := driverExt.Driver.Source()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -610,6 +610,8 @@ type WebDriver interface {
|
|||||||
// Input works like SendKeys
|
// Input works like SendKeys
|
||||||
Input(text string, options ...ActionOption) error
|
Input(text string, options ...ActionOption) error
|
||||||
|
|
||||||
|
Clear(packageName string) error
|
||||||
|
|
||||||
// PressButton Presses the corresponding hardware button on the device
|
// PressButton Presses the corresponding hardware button on the device
|
||||||
PressButton(devBtn DeviceButton) error
|
PressButton(devBtn DeviceButton) error
|
||||||
|
|
||||||
@@ -625,6 +627,8 @@ type WebDriver interface {
|
|||||||
|
|
||||||
LoginNoneUI(packageName, phoneNumber string, captcha string) error
|
LoginNoneUI(packageName, phoneNumber string, captcha string) error
|
||||||
|
|
||||||
|
LogoutNoneUI(packageName string) error
|
||||||
|
|
||||||
TapByText(text string, options ...ActionOption) error
|
TapByText(text string, options ...ActionOption) error
|
||||||
|
|
||||||
TapByTexts(actions ...TapTextAction) error
|
TapByTexts(actions ...TapTextAction) error
|
||||||
|
|||||||
@@ -615,6 +615,10 @@ func (wd *wdaDriver) Input(text string, options ...ActionOption) (err error) {
|
|||||||
return wd.SendKeys(text, options...)
|
return wd.SendKeys(text, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (wd *wdaDriver) Clear(packageName string) error {
|
||||||
|
return errDriverNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
// PressBack simulates a short press on the BACK button.
|
// PressBack simulates a short press on the BACK button.
|
||||||
func (wd *wdaDriver) PressBack(options ...ActionOption) (err error) {
|
func (wd *wdaDriver) PressBack(options ...ActionOption) (err error) {
|
||||||
actionOptions := NewActionOptions(options...)
|
actionOptions := NewActionOptions(options...)
|
||||||
@@ -663,6 +667,10 @@ func (wd *wdaDriver) LoginNoneUI(packageName, phoneNumber string, captcha string
|
|||||||
return errDriverNotImplemented
|
return errDriverNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (wd *wdaDriver) LogoutNoneUI(packageName string) error {
|
||||||
|
return errDriverNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func (wd *wdaDriver) StartCamera() (err error) {
|
func (wd *wdaDriver) StartCamera() (err error) {
|
||||||
// start camera, alias for app_launch com.apple.camera
|
// start camera, alias for app_launch com.apple.camera
|
||||||
return wd.AppLaunch("com.apple.camera")
|
return wd.AppLaunch("com.apple.camera")
|
||||||
@@ -958,6 +966,13 @@ func (r rawResponse) valueConvertToJsonRawMessage() (raw builtinJSON.RawMessage,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r rawResponse) valueConvertToJsonObject() (obj map[string]interface{}, err error) {
|
||||||
|
if err = json.Unmarshal(r, &obj); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (r rawResponse) valueDecodeAsBase64() (raw *bytes.Buffer, err error) {
|
func (r rawResponse) valueDecodeAsBase64() (raw *bytes.Buffer, err error) {
|
||||||
str, err := r.valueConvertToString()
|
str, err := r.valueConvertToString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user