refactor: move shoots driver to driver_ext

This commit is contained in:
lilong.129
2025-02-10 13:35:22 +08:00
parent 3038fb7430
commit 1ec383180b
19 changed files with 564 additions and 681 deletions

View File

@@ -153,8 +153,6 @@ func (dev *AndroidDevice) NewDriver() (driverExt IDriverExt, err error) {
var driver IDriver
if dev.UIA2 || dev.LogOn {
driver, err = NewUIA2Driver(dev)
} else if dev.STUB {
driver, err = NewStubAndroidDriver(dev)
} else {
driver, err = NewADBDriver(dev)
}

View File

@@ -34,14 +34,13 @@ func NewADBDriver(device *AndroidDevice) (*ADBDriver, error) {
AndroidDevice: device,
Session: &Session{},
}
driver.NewSession(nil)
driver.InitSession(nil)
return driver, nil
}
type ADBDriver struct {
*AndroidDevice
*Session
// DriverExt
Session *Session
}
func (ad *ADBDriver) runShellCommand(cmd string, args ...string) (output string, err error) {
@@ -59,7 +58,7 @@ func (ad *ADBDriver) runShellCommand(cmd string, args ...string) (output string,
} else {
driverResult.Success = true
}
ad.addRequestResult(driverResult)
ad.Session.addRequestResult(driverResult)
}()
// adb shell screencap -p
@@ -77,18 +76,18 @@ func (ad *ADBDriver) runShellCommand(cmd string, args ...string) (output string,
return output, err
}
func (ad *ADBDriver) NewSession(capabilities option.Capabilities) (sessionInfo Session, err error) {
ad.Reset()
err = errDriverNotImplemented
return
func (ad *ADBDriver) InitSession(capabilities option.Capabilities) error {
ad.Session = &Session{}
ad.Session.Reset()
return nil
}
func (ad *ADBDriver) DeleteSession() (err error) {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (ad *ADBDriver) Status() (deviceStatus types.DeviceStatus, err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
@@ -97,17 +96,17 @@ func (ad *ADBDriver) GetDevice() IDevice {
}
func (ad *ADBDriver) DeviceInfo() (deviceInfo types.DeviceInfo, err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
func (ad *ADBDriver) Location() (location types.Location, err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
func (ad *ADBDriver) BatteryInfo() (batteryInfo types.BatteryInfo, err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
@@ -145,9 +144,9 @@ func (ad *ADBDriver) getWindowSize() (size types.Size, err error) {
}
func (ad *ADBDriver) WindowSize() (size types.Size, err error) {
if !ad.windowSize.IsNil() {
if !ad.Session.windowSize.IsNil() {
// use cached window size
return ad.windowSize, nil
return ad.Session.windowSize, nil
}
size, err = ad.getWindowSize()
@@ -166,12 +165,12 @@ func (ad *ADBDriver) WindowSize() (size types.Size, err error) {
size.Width, size.Height = size.Height, size.Width
}
ad.windowSize = size // cache window size
ad.Session.windowSize = size // cache window size
return size, nil
}
func (ad *ADBDriver) Screen() (screen ai.Screen, err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
@@ -487,17 +486,17 @@ func (ad *ADBDriver) ForceTouch(x, y int, pressure float64, second ...float64) e
}
func (ad *ADBDriver) ForceTouchFloat(x, y, pressure float64, second ...float64) (err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
func (ad *ADBDriver) SetPasteboard(contentType types.PasteboardType, content string) (err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
func (ad *ADBDriver) GetPasteboard(contentType types.PasteboardType) (raw *bytes.Buffer, err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
@@ -620,17 +619,17 @@ func (ad *ADBDriver) Clear(packageName string) error {
}
func (ad *ADBDriver) PressButton(devBtn types.DeviceButton) (err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
func (ad *ADBDriver) Rotation() (rotation types.Rotation, err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
func (ad *ADBDriver) SetRotation(rotation types.Rotation) (err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
@@ -660,14 +659,6 @@ func (ad *ADBDriver) Source(srcOpt ...option.SourceOption) (source string, err e
return
}
func (ad *ADBDriver) LoginNoneUI(packageName, phoneNumber string, captcha, password string) (info AppLoginInfo, err error) {
return info, errDriverNotImplemented
}
func (ad *ADBDriver) LogoutNoneUI(packageName string) error {
return errDriverNotImplemented
}
func (ad *ADBDriver) sourceTree(srcOpt ...option.SourceOption) (sourceTree *Hierarchy, err error) {
source, err := ad.Source()
if err != nil {
@@ -750,27 +741,27 @@ func (ad *ADBDriver) searchNodes(nodes []Layout, text string, opts ...option.Act
}
func (ad *ADBDriver) AccessibleSource() (source string, err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
func (ad *ADBDriver) HealthCheck() (err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
func (ad *ADBDriver) GetAppiumSettings() (settings map[string]interface{}, err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
func (ad *ADBDriver) SetAppiumSettings(settings map[string]interface{}) (ret map[string]interface{}, err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
func (ad *ADBDriver) IsHealthy() (healthy bool, err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}

View File

@@ -1,144 +0,0 @@
package uixt
import (
"fmt"
"os"
"testing"
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
)
var androidStubDriver *StubAndroidDriver
func setupStubDriver(t *testing.T) {
device, err := NewAndroidDevice()
checkErr(t, err)
device.STUB = true
androidStubDriver, err = NewStubAndroidDriver(device)
checkErr(t, err)
}
func TestHello(t *testing.T) {
setupStubDriver(t)
status, err := androidStubDriver.Status()
if err != nil {
t.Fatal(err)
}
t.Log(status)
}
func TestSource(t *testing.T) {
setupStubDriver(t)
source, err := androidStubDriver.Source()
if err != nil {
t.Fatal(err)
}
t.Log(source)
}
func TestLogin(t *testing.T) {
setupStubDriver(t)
info, err := androidStubDriver.LoginNoneUI("com.ss.android.ugc.aweme", "12342316231", "8517", "")
if err != nil {
t.Fatal(err)
}
t.Log(info)
}
func TestLogout(t *testing.T) {
setupStubDriver(t)
err := androidStubDriver.LogoutNoneUI("com.ss.android.ugc.aweme")
if err != nil {
t.Fatal(err)
}
}
func TestSwipe(t *testing.T) {
setupStubDriver(t)
err := androidStubDriver.Swipe(878, 2375, 672, 2375)
if err != nil {
t.Fatal(err)
}
}
func TestTap(t *testing.T) {
setupStubDriver(t)
err := androidStubDriver.Tap(900, 400)
if err != nil {
t.Fatal(err)
}
}
func TestDoubleTap(t *testing.T) {
setupStubDriver(t)
err := androidStubDriver.DoubleTap(500, 500)
if err != nil {
t.Fatal(err)
}
}
func TestLongPress(t *testing.T) {
setupStubDriver(t)
err := androidStubDriver.Swipe(1036, 1076, 1036, 1076,
option.WithDuration(3))
if err != nil {
t.Fatal(err)
}
}
func TestInput(t *testing.T) {
setupStubDriver(t)
err := androidStubDriver.Input("\"哈哈\"")
if err != nil {
t.Fatal(err)
}
}
func TestSave(t *testing.T) {
setupStubDriver(t)
raw, err := androidStubDriver.Screenshot()
if err != nil {
t.Fatal(err)
}
source, err := androidStubDriver.Source()
if err != nil {
t.Fatal(err)
}
step := 14
file, err := os.Create(fmt.Sprintf("/Users/bytedance/workcode/wings_algorithm/testcases/data/cases/0/%d.jpg", step))
if err != nil {
t.Fatal(err)
}
file.Write(raw.Bytes())
file, err = os.Create(fmt.Sprintf("/Users/bytedance/workcode/wings_algorithm/testcases/data/cases/0/%d.json", step))
if err != nil {
t.Fatal(err)
}
file.Write([]byte(source))
}
func TestAppLaunch(t *testing.T) {
setupStubDriver(t)
err := androidStubDriver.AppLaunch("com.ss.android.ugc.aweme")
if err != nil {
t.Fatal(err)
}
}
func TestAppTerminal(t *testing.T) {
setupStubDriver(t)
_, err := androidStubDriver.AppTerminate("com.ss.android.ugc.aweme")
if err != nil {
t.Fatal(err)
}
}
func TestAppInfo(t *testing.T) {
setupStubDriver(t)
info, err := androidStubDriver.getLoginAppInfo("com.ss.android.ugc.aweme")
if err != nil {
t.Fatal(err)
}
t.Log(info)
}

View File

@@ -6,7 +6,6 @@ import (
"encoding/json"
"encoding/xml"
"fmt"
"net"
"net/http"
"strings"
"time"
@@ -20,10 +19,6 @@ import (
"github.com/httprunner/httprunner/v5/pkg/uixt/types"
)
var errDriverNotImplemented = errors.New("driver method not implemented")
const forwardToPrefix = "forward-to-"
func NewUIA2Driver(device *AndroidDevice) (*UIA2Driver, error) {
log.Info().Interface("device", device).Msg("init android UIA2 driver")
localPort, err := device.Forward(device.UIA2Port)
@@ -32,16 +27,15 @@ func NewUIA2Driver(device *AndroidDevice) (*UIA2Driver, error) {
fmt.Sprintf("forward port %d->%d failed: %v",
localPort, device.UIA2Port, err))
}
conn, err := net.Dial("tcp", fmt.Sprintf(":%d", localPort))
if err != nil {
return nil, fmt.Errorf("adb forward: %w", err)
}
driver := new(UIA2Driver)
driver.client = convertToHTTPClient(conn)
err = driver.Session.InitConnection(localPort)
if err != nil {
return nil, err
}
driver.Device = device.Device
driver.Logcat = device.Logcat
_, err = driver.NewSession(nil)
err = driver.InitSession(nil)
if err != nil {
return nil, errors.Wrap(err, "create UIA2 session failed")
}
@@ -53,81 +47,75 @@ type UIA2Driver struct {
}
func (ud *UIA2Driver) resetDriver() error {
session, err := ud.NewSession(option.NewCapabilities())
if err != nil {
return err
}
ud.sessionID = session.sessionID
return nil
return ud.InitSession(option.NewCapabilities())
}
func (ud *UIA2Driver) httpRequest(method string, rawURL string, rawBody []byte) (rawResp rawResponse, err error) {
func (ud *UIA2Driver) httpRequest(method string, rawURL string, rawBody []byte) (rawResp DriverRawResponse, err error) {
for retryCount := 1; retryCount <= 5; retryCount++ {
rawResp, err = ud.Request(method, rawURL, rawBody)
rawResp, err = ud.Session.Request(method, rawURL, rawBody)
if err == nil {
return
}
// wait for UIA2 server to resume automatically
time.Sleep(3 * time.Second)
oldSessionID := ud.sessionID
oldSessionID := ud.Session.ID
if err2 := ud.resetDriver(); err2 != nil {
log.Err(err2).Msgf("failed to reset uia2 driver, retry count: %v", retryCount)
continue
}
log.Debug().Str("new session", ud.sessionID).Str("old session", oldSessionID).Msgf("successful to reset uia2 driver, retry count: %v", retryCount)
log.Debug().Str("new session", ud.Session.ID).Str("old session", oldSessionID).Msgf("successful to reset uia2 driver, retry count: %v", retryCount)
if oldSessionID != "" {
rawURL = strings.Replace(rawURL, oldSessionID, ud.sessionID, 1)
rawURL = strings.Replace(rawURL, oldSessionID, ud.Session.ID, 1)
}
}
return
}
func (ud *UIA2Driver) httpGET(pathElem ...string) (rawResp rawResponse, err error) {
return ud.httpRequest(http.MethodGet, ud.concatURL(nil, pathElem...), nil)
func (ud *UIA2Driver) httpGET(pathElem ...string) (rawResp DriverRawResponse, err error) {
return ud.httpRequest(http.MethodGet, ud.Session.concatURL(nil, pathElem...), nil)
}
func (ud *UIA2Driver) httpPOST(data interface{}, pathElem ...string) (rawResp rawResponse, err error) {
func (ud *UIA2Driver) httpPOST(data interface{}, pathElem ...string) (rawResp DriverRawResponse, err error) {
var bsJSON []byte = nil
if data != nil {
if bsJSON, err = json.Marshal(data); err != nil {
return nil, err
}
}
return ud.httpRequest(http.MethodPost, ud.concatURL(nil, pathElem...), bsJSON)
return ud.httpRequest(http.MethodPost, ud.Session.concatURL(nil, pathElem...), bsJSON)
}
func (ud *UIA2Driver) httpDELETE(pathElem ...string) (rawResp rawResponse, err error) {
return ud.httpRequest(http.MethodDelete, ud.concatURL(nil, pathElem...), nil)
func (ud *UIA2Driver) httpDELETE(pathElem ...string) (rawResp DriverRawResponse, err error) {
return ud.httpRequest(http.MethodDelete, ud.Session.concatURL(nil, pathElem...), nil)
}
func (ud *UIA2Driver) NewSession(capabilities option.Capabilities) (sessionInfo Session, err error) {
// register(postHandler, new NewSession("/wd/hub/session"))
var rawResp rawResponse
func (ud *UIA2Driver) InitSession(capabilities option.Capabilities) (err error) {
// register(postHandler, new InitSession("/wd/hub/session"))
var rawResp DriverRawResponse
data := make(map[string]interface{})
if len(capabilities) == 0 {
data["capabilities"] = make(map[string]interface{})
} else {
data["capabilities"] = map[string]interface{}{"alwaysMatch": capabilities}
}
if rawResp, err = ud.POST(data, "/session"); err != nil {
return Session{sessionID: ""}, err
if rawResp, err = ud.Session.POST(data, "/session"); err != nil {
return err
}
reply := new(struct{ Value struct{ SessionId string } })
if err = json.Unmarshal(rawResp, reply); err != nil {
return Session{sessionID: ""}, err
return err
}
sessionID := reply.Value.SessionId
ud.Reset()
ud.sessionID = sessionID
return Session{sessionID: sessionID}, nil
ud.Session = &Session{ID: reply.Value.SessionId}
ud.Session.Reset()
return nil
}
func (ud *UIA2Driver) DeleteSession() (err error) {
if ud.sessionID == "" {
if ud.Session.ID == "" {
return nil
}
if _, err = ud.httpDELETE("/session", ud.sessionID); err == nil {
ud.sessionID = ""
if _, err = ud.httpDELETE("/session", ud.Session.ID); err == nil {
ud.Session.ID = ""
}
return err
@@ -135,9 +123,9 @@ func (ud *UIA2Driver) DeleteSession() (err error) {
func (ud *UIA2Driver) Status() (deviceStatus types.DeviceStatus, err error) {
// register(getHandler, new Status("/wd/hub/status"))
var rawResp rawResponse
var rawResp DriverRawResponse
// Notice: use Driver.GET instead of httpGET to avoid loop calling
if rawResp, err = ud.GET("/status"); err != nil {
if rawResp, err = ud.Session.GET("/status"); err != nil {
return types.DeviceStatus{Ready: false}, err
}
reply := new(struct {
@@ -154,8 +142,8 @@ func (ud *UIA2Driver) Status() (deviceStatus types.DeviceStatus, err error) {
func (ud *UIA2Driver) DeviceInfo() (deviceInfo types.DeviceInfo, err error) {
// register(getHandler, new GetDeviceInfo("/wd/hub/session/:sessionId/appium/device/info"))
var rawResp rawResponse
if rawResp, err = ud.httpGET("/session", ud.sessionID, "appium/device/info"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = ud.httpGET("/session", ud.Session.ID, "appium/device/info"); err != nil {
return types.DeviceInfo{}, err
}
reply := new(struct{ Value struct{ types.DeviceInfo } })
@@ -168,8 +156,8 @@ func (ud *UIA2Driver) DeviceInfo() (deviceInfo types.DeviceInfo, err error) {
func (ud *UIA2Driver) BatteryInfo() (batteryInfo types.BatteryInfo, err error) {
// register(getHandler, new GetBatteryInfo("/wd/hub/session/:sessionId/appium/device/battery_info"))
var rawResp rawResponse
if rawResp, err = ud.httpGET("/session", ud.sessionID, "appium/device/battery_info"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = ud.httpGET("/session", ud.Session.ID, "appium/device/battery_info"); err != nil {
return types.BatteryInfo{}, err
}
reply := new(struct{ Value struct{ types.BatteryInfo } })
@@ -185,13 +173,13 @@ func (ud *UIA2Driver) BatteryInfo() (batteryInfo types.BatteryInfo, err error) {
func (ud *UIA2Driver) WindowSize() (size types.Size, err error) {
// register(getHandler, new GetDeviceSize("/wd/hub/session/:sessionId/window/:windowHandle/size"))
if !ud.windowSize.IsNil() {
if !ud.Session.windowSize.IsNil() {
// use cached window size
return ud.windowSize, nil
return ud.Session.windowSize, nil
}
var rawResp rawResponse
if rawResp, err = ud.httpGET("/session", ud.sessionID, "window/:windowHandle/size"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = ud.httpGET("/session", ud.Session.ID, "window/:windowHandle/size"); err != nil {
return types.Size{}, errors.Wrap(err, "get window size failed by UIA2 request")
}
reply := new(struct{ Value struct{ types.Size } })
@@ -210,14 +198,14 @@ func (ud *UIA2Driver) WindowSize() (size types.Size, err error) {
size.Width, size.Height = size.Height, size.Width
}
ud.windowSize = size // cache window size
ud.Session.windowSize = size // cache window size
return size, nil
}
// PressBack simulates a short press on the BACK button.
func (ud *UIA2Driver) PressBack(opts ...option.ActionOption) (err error) {
// register(postHandler, new PressBack("/wd/hub/session/:sessionId/back"))
_, err = ud.httpPOST(nil, "/session", ud.sessionID, "back")
_, err = ud.httpPOST(nil, "/session", ud.Session.ID, "back")
return
}
@@ -240,14 +228,14 @@ func (ud *UIA2Driver) PressKeyCodes(keyCode KeyCode, metaState KeyMeta, flags ..
if len(flags) != 0 {
data["flags"] = flags[0]
}
_, err = ud.httpPOST(data, "/session", ud.sessionID, "appium/device/press_keycode")
_, err = ud.httpPOST(data, "/session", ud.Session.ID, "appium/device/press_keycode")
return
}
func (ud *UIA2Driver) Orientation() (orientation types.Orientation, err error) {
// [[FBRoute GET:@"/orientation"] respondWithTarget:self action:@selector(handleGetOrientation:)]
var rawResp rawResponse
if rawResp, err = ud.httpGET("/session", ud.sessionID, "/orientation"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = ud.httpGET("/session", ud.Session.ID, "/orientation"); err != nil {
return "", err
}
reply := new(struct{ Value types.Orientation })
@@ -280,7 +268,7 @@ func (ud *UIA2Driver) DoubleFloatTap(x, y float64) error {
},
}
_, err := ud.httpPOST(data, "/session", ud.sessionID, "actions/tap")
_, err := ud.httpPOST(data, "/session", ud.Session.ID, "actions/tap")
return err
}
@@ -318,7 +306,7 @@ func (ud *UIA2Driver) Tap(x, y float64, opts ...option.ActionOption) (err error)
// update data options in post data for extra uiautomator configurations
actionOptions.UpdateData(data)
_, err = ud.httpPOST(data, "/session", ud.sessionID, "actions/tap")
_, err = ud.httpPOST(data, "/session", ud.Session.ID, "actions/tap")
return err
}
@@ -336,7 +324,7 @@ func (ud *UIA2Driver) TouchAndHold(x, y float64, opts ...option.ActionOption) (e
"duration": int(duration * 1000),
},
}
_, err = ud.httpPOST(data, "/session", ud.sessionID, "touch/longclick")
_, err = ud.httpPOST(data, "/session", ud.Session.ID, "touch/longclick")
return
}
@@ -368,7 +356,7 @@ func (ud *UIA2Driver) Drag(fromX, fromY, toX, toY float64, opts ...option.Action
actionOptions.UpdateData(data)
// register(postHandler, new Drag("/wd/hub/session/:sessionId/touch/drag"))
_, err = ud.httpPOST(data, "/session", ud.sessionID, "touch/drag")
_, err = ud.httpPOST(data, "/session", ud.Session.ID, "touch/drag")
return
}
@@ -414,7 +402,7 @@ func (ud *UIA2Driver) Swipe(fromX, fromY, toX, toY float64, opts ...option.Actio
// update data options in post data for extra uiautomator configurations
actionOptions.UpdateData(data)
_, err := ud.httpPOST(data, "/session", ud.sessionID, "actions/swipe")
_, err := ud.httpPOST(data, "/session", ud.Session.ID, "actions/swipe")
return err
}
@@ -432,7 +420,7 @@ func (ud *UIA2Driver) SetPasteboard(contentType types.PasteboardType, content st
"content": base64.StdEncoding.EncodeToString([]byte(content)),
}
// register(postHandler, new SetClipboard("/wd/hub/session/:sessionId/appium/device/set_clipboard"))
_, err = ud.httpPOST(data, "/session", ud.sessionID, "appium/device/set_clipboard")
_, err = ud.httpPOST(data, "/session", ud.Session.ID, "appium/device/set_clipboard")
return
}
@@ -444,8 +432,8 @@ func (ud *UIA2Driver) GetPasteboard(contentType types.PasteboardType) (raw *byte
data := map[string]interface{}{
"contentType": contentType[0],
}
var rawResp rawResponse
if rawResp, err = ud.httpPOST(data, "/session", ud.sessionID, "appium/device/get_clipboard"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = ud.httpPOST(data, "/session", ud.Session.ID, "appium/device/get_clipboard"); err != nil {
return
}
reply := new(struct{ Value string })
@@ -475,7 +463,7 @@ func (ud *UIA2Driver) SendKeys(text string, opts ...option.ActionOption) (err er
// new data options in post data for extra uiautomator configurations
actionOptions.UpdateData(data)
_, err = ud.httpPOST(data, "/session", ud.sessionID, "/keys")
_, err = ud.httpPOST(data, "/session", ud.Session.ID, "/keys")
}
return
}
@@ -533,7 +521,7 @@ func (ud *UIA2Driver) SendActionKey(text string, opts ...option.ActionOption) (e
// new data options in post data for extra uiautomator configurations
actionOptions.UpdateData(data)
_, err = ud.httpPOST(data, "/session", ud.sessionID, "/actions/keys")
_, err = ud.httpPOST(data, "/session", ud.Session.ID, "/actions/keys")
return
}
@@ -543,8 +531,8 @@ func (ud *UIA2Driver) Input(text string, opts ...option.ActionOption) (err error
func (ud *UIA2Driver) Rotation() (rotation types.Rotation, err error) {
// register(getHandler, new GetRotation("/wd/hub/session/:sessionId/rotation"))
var rawResp rawResponse
if rawResp, err = ud.httpGET("/session", ud.sessionID, "rotation"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = ud.httpGET("/session", ud.Session.ID, "rotation"); err != nil {
return types.Rotation{}, err
}
reply := new(struct{ Value types.Rotation })
@@ -564,8 +552,8 @@ func (ud *UIA2Driver) Screenshot() (raw *bytes.Buffer, err error) {
func (ud *UIA2Driver) Source(srcOpt ...option.SourceOption) (source string, err error) {
// register(getHandler, new Source("/wd/hub/session/:sessionId/source"))
var rawResp rawResponse
if rawResp, err = ud.httpGET("/session", ud.sessionID, "source"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = ud.httpGET("/session", ud.Session.ID, "source"); err != nil {
return "", err
}
reply := new(struct{ Value string })

View File

@@ -30,8 +30,8 @@ var (
// current implemeted driver: ADBDriver, UIA2Driver, WDADriver, HDCDriver
type IDriver interface {
// NewSession starts a new session and returns the DriverSession.
NewSession(capabilities option.Capabilities) (Session, error)
// InitSession starts a new session
InitSession(capabilities option.Capabilities) error
// DeleteSession Kills application associated with that session and removes session
// 1) alertsMonitor disable
@@ -143,9 +143,6 @@ type IDriver interface {
// Source Return application elements tree
Source(srcOpt ...option.SourceOption) (string, error)
LoginNoneUI(packageName, phoneNumber string, captcha, password string) (info AppLoginInfo, err error)
LogoutNoneUI(packageName string) error
TapByText(text string, opts ...option.ActionOption) error
TapByTexts(actions ...TapTextAction) error
@@ -312,9 +309,9 @@ func (dExt *DriverExt) DoValidation(check, assert, expected string, message ...s
return nil
}
type rawResponse []byte
type DriverRawResponse []byte
func (r rawResponse) checkErr() (err error) {
func (r DriverRawResponse) CheckErr() (err error) {
reply := new(struct {
Value struct {
Err string `json:"error"`
@@ -338,7 +335,7 @@ func (r rawResponse) checkErr() (err error) {
return
}
func (r rawResponse) valueConvertToString() (s string, err error) {
func (r DriverRawResponse) ValueConvertToString() (s string, err error) {
reply := new(struct{ Value string })
if err = json.Unmarshal(r, reply); err != nil {
return "", errors.Wrapf(err, "json.Unmarshal failed, rawResponse: %s", string(r))
@@ -347,7 +344,7 @@ func (r rawResponse) valueConvertToString() (s string, err error) {
return
}
func (r rawResponse) valueConvertToBool() (b bool, err error) {
func (r DriverRawResponse) ValueConvertToBool() (b bool, err error) {
reply := new(struct{ Value bool })
if err = json.Unmarshal(r, reply); err != nil {
return false, err
@@ -356,7 +353,7 @@ func (r rawResponse) valueConvertToBool() (b bool, err error) {
return
}
func (r rawResponse) valueConvertToSessionInfo() (sessionInfo Session, err error) {
func (r DriverRawResponse) ValueConvertToSessionInfo() (sessionInfo Session, err error) {
reply := new(struct{ Value struct{ Session } })
if err = json.Unmarshal(r, reply); err != nil {
return Session{}, err
@@ -365,7 +362,7 @@ func (r rawResponse) valueConvertToSessionInfo() (sessionInfo Session, err error
return
}
func (r rawResponse) valueConvertToJsonRawMessage() (raw builtinJSON.RawMessage, err error) {
func (r DriverRawResponse) ValueConvertToJsonRawMessage() (raw builtinJSON.RawMessage, err error) {
reply := new(struct{ Value builtinJSON.RawMessage })
if err = json.Unmarshal(r, reply); err != nil {
return nil, err
@@ -374,15 +371,15 @@ func (r rawResponse) valueConvertToJsonRawMessage() (raw builtinJSON.RawMessage,
return
}
func (r rawResponse) valueConvertToJsonObject() (obj map[string]interface{}, err error) {
func (r DriverRawResponse) 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) {
str, err := r.valueConvertToString()
func (r DriverRawResponse) ValueDecodeAsBase64() (raw *bytes.Buffer, err error) {
str, err := r.ValueConvertToString()
if err != nil {
return nil, errors.Wrap(err, "failed to convert value to string")
}

View File

@@ -1,12 +1,8 @@
package uixt
package driver_ext
import (
"fmt"
"net"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/pkg/errors"
@@ -14,116 +10,59 @@ import (
"github.com/httprunner/httprunner/v5/code"
"github.com/httprunner/httprunner/v5/internal/json"
"github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
"github.com/httprunner/httprunner/v5/pkg/uixt/types"
)
const (
StubSocketName = "com.bytest.device"
DouyinServerPort = 32316
shootsSocketName = "com.bytest.device"
douyinServerPort = 32316
forwardToPrefix = "forward-to-"
)
func NewStubAndroidDriver(device *AndroidDevice) (driver *StubAndroidDriver, err error) {
socketLocalPort, err := device.Forward(StubSocketName)
func NewShootsAndroidDriver(device *uixt.AndroidDevice) (driver *ShootsAndroidDriver, err error) {
socketLocalPort, err := device.Forward(shootsSocketName)
if err != nil {
return nil, errors.Wrap(code.DeviceConnectionError,
fmt.Sprintf("forward port %d->%s failed: %v",
socketLocalPort, StubSocketName, err))
socketLocalPort, shootsSocketName, err))
}
serverLocalPort, err := device.Forward(DouyinServerPort)
if err != nil {
return nil, errors.Wrap(code.DeviceConnectionError,
fmt.Sprintf("forward port %d->%d failed: %v",
serverLocalPort, DouyinServerPort, err))
}
address := fmt.Sprintf("127.0.0.1:%d", socketLocalPort)
conn, err := net.Dial("tcp", address)
if err != nil {
log.Err(err).Msg(fmt.Sprintf("failed to connect %s", address))
return nil, err
}
driver = &StubAndroidDriver{
driver = &ShootsAndroidDriver{
socket: conn,
timeout: 10 * time.Second,
}
rawURL := fmt.Sprintf("http://forward-to-%d:%d",
serverLocalPort, DouyinServerPort)
if driver.baseURL, err = url.Parse(rawURL); err != nil {
return nil, err
driver.InitSession(nil)
serverLocalPort, err := device.Forward(douyinServerPort)
if err != nil {
return nil, errors.Wrap(code.DeviceConnectionError,
fmt.Sprintf("forward port %d->%d failed: %v",
serverLocalPort, douyinServerPort, err))
}
rawURL := fmt.Sprintf("http://forward-to-%d:%d",
serverLocalPort, douyinServerPort)
driver.Session.Init(rawURL)
driver.NewSession(nil)
driver.Device = device.Device
driver.Logcat = device.Logcat
return driver, nil
}
type StubAndroidDriver struct {
*ADBDriver
type ShootsAndroidDriver struct {
*uixt.ADBDriver
socket net.Conn
seq int
timeout time.Duration
}
type AppLoginInfo struct {
Did string `json:"did,omitempty" yaml:"did,omitempty"`
Uid string `json:"uid,omitempty" yaml:"uid,omitempty"`
IsLogin bool `json:"is_login,omitempty" yaml:"is_login,omitempty"`
}
func (sad *StubAndroidDriver) httpGET(pathElem ...string) (rawResp rawResponse, err error) {
var localPort int
{
tmpURL, _ := url.Parse(sad.baseURL.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.Request(http.MethodGet, sad.concatURL(nil, pathElem...), nil)
}
func (sad *StubAndroidDriver) httpPOST(data interface{}, pathElem ...string) (rawResp rawResponse, err error) {
var localPort int
{
tmpURL, _ := url.Parse(sad.baseURL.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.Request(http.MethodPost, sad.concatURL(nil, pathElem...), bsJSON)
}
func (sad *StubAndroidDriver) NewSession(capabilities option.Capabilities) (Session, error) {
sad.Reset()
return Session{}, errDriverNotImplemented
}
func (sad *StubAndroidDriver) sendCommand(packageName string, cmdType string, params map[string]interface{}, readTimeout ...time.Duration) (interface{}, error) {
func (sad *ShootsAndroidDriver) sendCommand(packageName string, cmdType string, params map[string]interface{}, readTimeout ...time.Duration) (interface{}, error) {
sad.seq++
packet := map[string]interface{}{
"Seq": sad.seq,
@@ -150,24 +89,24 @@ func (sad *StubAndroidDriver) sendCommand(packageName string, cmdType string, pa
return nil, err
}
if resultMap["Error"] != nil {
return nil, fmt.Errorf("failed to call stub command: %s", resultMap["Error"].(string))
return nil, fmt.Errorf("failed to call shoots command: %s", resultMap["Error"].(string))
}
return resultMap["Result"], nil
}
func (sad *StubAndroidDriver) DeleteSession() error {
func (sad *ShootsAndroidDriver) DeleteSession() error {
return sad.close()
}
func (sad *StubAndroidDriver) close() error {
func (sad *ShootsAndroidDriver) close() error {
if sad.socket != nil {
return sad.socket.Close()
}
return nil
}
func (sad *StubAndroidDriver) Status() (types.DeviceStatus, error) {
func (sad *ShootsAndroidDriver) Status() (types.DeviceStatus, error) {
app, err := sad.GetForegroundApp()
if err != nil {
return types.DeviceStatus{}, err
@@ -176,11 +115,11 @@ func (sad *StubAndroidDriver) Status() (types.DeviceStatus, error) {
if err != nil {
return types.DeviceStatus{}, err
}
log.Info().Msg(fmt.Sprintf("ping stub result :%v", res))
log.Info().Msg(fmt.Sprintf("ping shoots result :%v", res))
return types.DeviceStatus{}, nil
}
func (sad *StubAndroidDriver) Source(srcOpt ...option.SourceOption) (source string, err error) {
func (sad *ShootsAndroidDriver) Source(srcOpt ...option.SourceOption) (source string, err error) {
app, err := sad.GetForegroundApp()
if err != nil {
return "", err
@@ -198,7 +137,7 @@ func (sad *StubAndroidDriver) Source(srcOpt ...option.SourceOption) (source stri
return res.(string), nil
}
func (sad *StubAndroidDriver) LoginNoneUI(packageName, phoneNumber string, captcha, password string) (info AppLoginInfo, err error) {
func (sad *ShootsAndroidDriver) LoginNoneUI(packageName, phoneNumber string, captcha, password string) (info AppLoginInfo, err error) {
params := map[string]interface{}{
"phone": phoneNumber,
}
@@ -209,11 +148,11 @@ func (sad *StubAndroidDriver) LoginNoneUI(packageName, phoneNumber string, captc
} else {
return info, fmt.Errorf("password and capcha is empty")
}
resp, err := sad.httpPOST(params, "/host", "/login", "account")
resp, err := sad.Session.POST(params, "/host", "/login", "account")
if err != nil {
return info, err
}
res, err := resp.valueConvertToJsonObject()
res, err := resp.ValueConvertToJsonObject()
if err != nil {
return info, err
}
@@ -231,12 +170,12 @@ func (sad *StubAndroidDriver) LoginNoneUI(packageName, phoneNumber string, captc
return info, nil
}
func (sad *StubAndroidDriver) LogoutNoneUI(packageName string) error {
resp, err := sad.httpGET("/host", "/logout")
func (sad *ShootsAndroidDriver) LogoutNoneUI(packageName string) error {
resp, err := sad.Session.GET("/host", "/logout")
if err != nil {
return err
}
res, err := resp.valueConvertToJsonObject()
res, err := resp.ValueConvertToJsonObject()
if err != nil {
return err
}
@@ -254,7 +193,7 @@ func (sad *StubAndroidDriver) LogoutNoneUI(packageName string) error {
return nil
}
func (sad *StubAndroidDriver) LoginNoneUIDynamic(packageName, phoneNumber string, captcha string) error {
func (sad *ShootsAndroidDriver) LoginNoneUIDynamic(packageName, phoneNumber string, captcha string) error {
params := map[string]interface{}{
"ClassName": "qe.python.test.LoginUtil",
"Method": "loginSync",
@@ -269,7 +208,7 @@ func (sad *StubAndroidDriver) LoginNoneUIDynamic(packageName, phoneNumber string
return nil
}
func (sad *StubAndroidDriver) SetHDTStatus(status bool) error {
func (sad *ShootsAndroidDriver) SetHDTStatus(status bool) error {
_, err := sad.Device.RunShellCommand("settings", "put", "global", "feedbacker_sso_bypass_token", "default_sso_bypass_token")
if err != nil {
log.Warn().Msg(fmt.Sprintf("failed to disable sso, error: %v", err))
@@ -288,12 +227,12 @@ func (sad *StubAndroidDriver) SetHDTStatus(status bool) error {
return nil
}
func (sad *StubAndroidDriver) getLoginAppInfo(packageName string) (info AppLoginInfo, err error) {
resp, err := sad.httpGET("/host", "/app", "/info")
func (sad *ShootsAndroidDriver) getLoginAppInfo(packageName string) (info AppLoginInfo, err error) {
resp, err := sad.Session.GET("/host", "/app", "/info")
if err != nil {
return info, err
}
res, err := resp.valueConvertToJsonObject()
res, err := resp.ValueConvertToJsonObject()
if err != nil {
return info, err
}
@@ -310,3 +249,9 @@ func (sad *StubAndroidDriver) getLoginAppInfo(packageName string) (info AppLogin
}
return info, nil
}
type AppLoginInfo struct {
Did string `json:"did,omitempty" yaml:"did,omitempty"`
Uid string `json:"uid,omitempty" yaml:"uid,omitempty"`
IsLogin bool `json:"is_login,omitempty" yaml:"is_login,omitempty"`
}

View File

@@ -0,0 +1,154 @@
package driver_ext
import (
"fmt"
"os"
"testing"
"github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
)
var shootsAndroidDriver *ShootsAndroidDriver
func setupShootsAndroidDriver(t *testing.T) {
device, err := uixt.NewAndroidDevice()
checkErr(t, err)
shootsAndroidDriver, err = NewShootsAndroidDriver(device)
checkErr(t, err)
}
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 TestHello(t *testing.T) {
setupShootsAndroidDriver(t)
status, err := shootsAndroidDriver.Status()
if err != nil {
t.Fatal(err)
}
t.Log(status)
}
func TestSource(t *testing.T) {
setupShootsAndroidDriver(t)
source, err := shootsAndroidDriver.Source()
if err != nil {
t.Fatal(err)
}
t.Log(source)
}
func TestLogin(t *testing.T) {
setupShootsAndroidDriver(t)
info, err := shootsAndroidDriver.LoginNoneUI("com.ss.android.ugc.aweme", "12342316231", "8517", "")
if err != nil {
t.Fatal(err)
}
t.Log(info)
}
func TestLogout(t *testing.T) {
setupShootsAndroidDriver(t)
err := shootsAndroidDriver.LogoutNoneUI("com.ss.android.ugc.aweme")
if err != nil {
t.Fatal(err)
}
}
func TestSwipe(t *testing.T) {
setupShootsAndroidDriver(t)
err := shootsAndroidDriver.Swipe(878, 2375, 672, 2375)
if err != nil {
t.Fatal(err)
}
}
func TestTap(t *testing.T) {
setupShootsAndroidDriver(t)
err := shootsAndroidDriver.Tap(900, 400)
if err != nil {
t.Fatal(err)
}
}
func TestDoubleTap(t *testing.T) {
setupShootsAndroidDriver(t)
err := shootsAndroidDriver.DoubleTap(500, 500)
if err != nil {
t.Fatal(err)
}
}
func TestLongPress(t *testing.T) {
setupShootsAndroidDriver(t)
err := shootsAndroidDriver.Swipe(1036, 1076, 1036, 1076,
option.WithDuration(3))
if err != nil {
t.Fatal(err)
}
}
func TestInput(t *testing.T) {
setupShootsAndroidDriver(t)
err := shootsAndroidDriver.Input("\"哈哈\"")
if err != nil {
t.Fatal(err)
}
}
func TestSave(t *testing.T) {
setupShootsAndroidDriver(t)
raw, err := shootsAndroidDriver.Screenshot()
if err != nil {
t.Fatal(err)
}
source, err := shootsAndroidDriver.Source()
if err != nil {
t.Fatal(err)
}
step := 14
file, err := os.Create(fmt.Sprintf("/Users/bytedance/workcode/wings_algorithm/testcases/data/cases/0/%d.jpg", step))
if err != nil {
t.Fatal(err)
}
file.Write(raw.Bytes())
file, err = os.Create(fmt.Sprintf("/Users/bytedance/workcode/wings_algorithm/testcases/data/cases/0/%d.json", step))
if err != nil {
t.Fatal(err)
}
file.Write([]byte(source))
}
func TestAppLaunch(t *testing.T) {
setupShootsAndroidDriver(t)
err := shootsAndroidDriver.AppLaunch("com.ss.android.ugc.aweme")
if err != nil {
t.Fatal(err)
}
}
func TestAppTerminal(t *testing.T) {
setupShootsAndroidDriver(t)
_, err := shootsAndroidDriver.AppTerminate("com.ss.android.ugc.aweme")
if err != nil {
t.Fatal(err)
}
}
func TestAppInfo(t *testing.T) {
setupShootsAndroidDriver(t)
info, err := shootsAndroidDriver.getLoginAppInfo("com.ss.android.ugc.aweme")
if err != nil {
t.Fatal(err)
}
t.Log(info)
}

View File

@@ -1,4 +1,4 @@
package uixt
package driver_ext
import (
"bytes"
@@ -12,6 +12,7 @@ import (
"github.com/httprunner/httprunner/v5/code"
"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"
"github.com/httprunner/httprunner/v5/pkg/uixt/types"
@@ -22,14 +23,14 @@ const (
defaultDouyinServerPort = 32921
)
func NewStubIOSDriver(device *IOSDevice) (driver *StubIOSDriver, err error) {
localStubPort, err := builtin.GetFreePort()
func NewShootsIOSDriver(device *uixt.IOSDevice) (driver *ShootsIOSDriver, err error) {
localShootsPort, err := builtin.GetFreePort()
if err != nil {
return nil, errors.Wrap(code.DeviceHTTPDriverError,
fmt.Sprintf("get free port failed: %v", err))
}
if err = device.forward(localStubPort, defaultBightInsightPort); err != nil {
if err = device.Forward(localShootsPort, defaultBightInsightPort); err != nil {
return nil, errors.Wrap(code.DeviceHTTPDriverError,
fmt.Sprintf("forward tcp port failed: %v", err))
}
@@ -39,61 +40,54 @@ func NewStubIOSDriver(device *IOSDevice) (driver *StubIOSDriver, err error) {
return nil, errors.Wrap(code.DeviceHTTPDriverError,
fmt.Sprintf("get free port failed: %v", err))
}
if err = device.forward(localServerPort, defaultDouyinServerPort); err != nil {
if err = device.Forward(localServerPort, defaultDouyinServerPort); err != nil {
return nil, errors.Wrap(code.DeviceHTTPDriverError,
fmt.Sprintf("forward tcp port failed: %v", err))
}
host := "localhost"
timeout := 10 * time.Second
driver = &StubIOSDriver{}
driver = &ShootsIOSDriver{}
driver.device = device
driver.bightInsightPrefix = fmt.Sprintf("http://%s:%d", host, localStubPort)
driver.bightInsightPrefix = fmt.Sprintf("http://%s:%d", host, localShootsPort)
driver.serverPrefix = fmt.Sprintf("http://%s:%d", host, localServerPort)
driver.timeout = timeout
driver.client = &http.Client{
Timeout: time.Second * 10, // 设置超时时间为 10 秒
}
return driver, nil
}
type StubIOSDriver struct {
*WDADriver
type ShootsIOSDriver struct {
*uixt.WDADriver
bightInsightPrefix string
serverPrefix string
timeout time.Duration
device *IOSDevice
device *uixt.IOSDevice
}
func (s *StubIOSDriver) setUpWda() (err error) {
func (s *ShootsIOSDriver) setUpWda() (err error) {
if s.WDADriver == nil {
capabilities := option.NewCapabilities()
capabilities.WithDefaultAlertAction(option.AlertActionAccept)
driver, err := s.device.NewHTTPDriver(capabilities)
if err != nil {
log.Error().Err(err).Msg("stub driver failed to init wda driver")
log.Error().Err(err).Msg("failed to init WDA driver for shoots IOS")
return err
}
s.WDADriver = driver.(*WDADriver)
s.WDADriver = driver.(*uixt.WDADriver)
}
return nil
}
// NewSession starts a new session and returns the DriverSession.
func (s *StubIOSDriver) NewSession(capabilities option.Capabilities) (Session, error) {
err := s.setUpWda()
if err != nil {
return Session{}, err
}
return s.WDADriver.NewSession(capabilities)
// InitSession starts a new session and returns the DriverSession.
func (s *ShootsIOSDriver) InitSession(capabilities option.Capabilities) error {
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 {
func (s *ShootsIOSDriver) DeleteSession() error {
err := s.setUpWda()
if err != nil {
return err
@@ -101,7 +95,7 @@ func (s *StubIOSDriver) DeleteSession() error {
return s.WDADriver.DeleteSession()
}
func (s *StubIOSDriver) Status() (types.DeviceStatus, error) {
func (s *ShootsIOSDriver) Status() (types.DeviceStatus, error) {
err := s.setUpWda()
if err != nil {
return types.DeviceStatus{}, err
@@ -109,7 +103,7 @@ func (s *StubIOSDriver) Status() (types.DeviceStatus, error) {
return s.WDADriver.Status()
}
func (s *StubIOSDriver) DeviceInfo() (types.DeviceInfo, error) {
func (s *ShootsIOSDriver) DeviceInfo() (types.DeviceInfo, error) {
err := s.setUpWda()
if err != nil {
return types.DeviceInfo{}, err
@@ -117,7 +111,7 @@ func (s *StubIOSDriver) DeviceInfo() (types.DeviceInfo, error) {
return s.WDADriver.DeviceInfo()
}
func (s *StubIOSDriver) Location() (types.Location, error) {
func (s *ShootsIOSDriver) Location() (types.Location, error) {
err := s.setUpWda()
if err != nil {
return types.Location{}, err
@@ -125,7 +119,7 @@ func (s *StubIOSDriver) Location() (types.Location, error) {
return s.WDADriver.Location()
}
func (s *StubIOSDriver) BatteryInfo() (types.BatteryInfo, error) {
func (s *ShootsIOSDriver) BatteryInfo() (types.BatteryInfo, error) {
err := s.setUpWda()
if err != nil {
return types.BatteryInfo{}, err
@@ -136,7 +130,7 @@ func (s *StubIOSDriver) BatteryInfo() (types.BatteryInfo, error) {
// 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) {
func (s *ShootsIOSDriver) WindowSize() (types.Size, error) {
err := s.setUpWda()
if err != nil {
return types.Size{}, err
@@ -144,7 +138,7 @@ func (s *StubIOSDriver) WindowSize() (types.Size, error) {
return s.WDADriver.WindowSize()
}
func (s *StubIOSDriver) Screen() (ai.Screen, error) {
func (s *ShootsIOSDriver) Screen() (ai.Screen, error) {
err := s.setUpWda()
if err != nil {
return ai.Screen{}, err
@@ -152,7 +146,7 @@ func (s *StubIOSDriver) Screen() (ai.Screen, error) {
return s.WDADriver.Screen()
}
func (s *StubIOSDriver) Scale() (float64, error) {
func (s *ShootsIOSDriver) Scale() (float64, error) {
err := s.setUpWda()
if err != nil {
return 0, err
@@ -161,7 +155,7 @@ func (s *StubIOSDriver) Scale() (float64, error) {
}
// Homescreen Forces the device under test to switch to the home screen
func (s *StubIOSDriver) Homescreen() error {
func (s *ShootsIOSDriver) Homescreen() error {
err := s.setUpWda()
if err != nil {
return err
@@ -169,7 +163,7 @@ func (s *StubIOSDriver) Homescreen() error {
return s.WDADriver.Homescreen()
}
func (s *StubIOSDriver) Unlock() (err error) {
func (s *ShootsIOSDriver) Unlock() (err error) {
err = s.setUpWda()
if err != nil {
return err
@@ -179,7 +173,7 @@ func (s *StubIOSDriver) Unlock() (err error) {
// 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 {
func (s *ShootsIOSDriver) AppLaunch(packageName string) error {
err := s.setUpWda()
if err != nil {
return err
@@ -189,7 +183,7 @@ func (s *StubIOSDriver) AppLaunch(packageName string) error {
// 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) {
func (s *ShootsIOSDriver) AppTerminate(packageName string) (bool, error) {
err := s.setUpWda()
if err != nil {
return false, err
@@ -198,7 +192,7 @@ func (s *StubIOSDriver) AppTerminate(packageName string) (bool, error) {
}
// GetForegroundApp returns current foreground app package name and activity name
func (s *StubIOSDriver) GetForegroundApp() (app types.AppInfo, err error) {
func (s *ShootsIOSDriver) GetForegroundApp() (app types.AppInfo, err error) {
err = s.setUpWda()
if err != nil {
return types.AppInfo{}, err
@@ -207,7 +201,7 @@ func (s *StubIOSDriver) GetForegroundApp() (app types.AppInfo, err error) {
}
// StartCamera Starts a new camera for recording
func (s *StubIOSDriver) StartCamera() error {
func (s *ShootsIOSDriver) StartCamera() error {
err := s.setUpWda()
if err != nil {
return err
@@ -216,7 +210,7 @@ func (s *StubIOSDriver) StartCamera() error {
}
// StopCamera Stops the camera for recording
func (s *StubIOSDriver) StopCamera() error {
func (s *ShootsIOSDriver) StopCamera() error {
err := s.setUpWda()
if err != nil {
return err
@@ -224,7 +218,7 @@ func (s *StubIOSDriver) StopCamera() error {
return s.WDADriver.StopCamera()
}
func (s *StubIOSDriver) Orientation() (orientation types.Orientation, err error) {
func (s *ShootsIOSDriver) Orientation() (orientation types.Orientation, err error) {
err = s.setUpWda()
if err != nil {
return types.OrientationPortrait, err
@@ -233,7 +227,7 @@ func (s *StubIOSDriver) Orientation() (orientation types.Orientation, err error)
}
// Tap Sends a tap event at the coordinate.
func (s *StubIOSDriver) Tap(x, y float64, opts ...option.ActionOption) error {
func (s *ShootsIOSDriver) Tap(x, y float64, opts ...option.ActionOption) error {
err := s.setUpWda()
if err != nil {
return err
@@ -242,7 +236,7 @@ func (s *StubIOSDriver) Tap(x, y float64, opts ...option.ActionOption) error {
}
// DoubleTap Sends a double tap event at the coordinate.
func (s *StubIOSDriver) DoubleTap(x, y float64, opts ...option.ActionOption) error {
func (s *ShootsIOSDriver) DoubleTap(x, y float64, opts ...option.ActionOption) error {
err := s.setUpWda()
if err != nil {
return err
@@ -253,7 +247,7 @@ func (s *StubIOSDriver) DoubleTap(x, y float64, opts ...option.ActionOption) err
// 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 {
func (s *ShootsIOSDriver) TouchAndHold(x, y float64, opts ...option.ActionOption) error {
err := s.setUpWda()
if err != nil {
return err
@@ -263,7 +257,7 @@ func (s *StubIOSDriver) TouchAndHold(x, y float64, opts ...option.ActionOption)
// 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 {
func (s *ShootsIOSDriver) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionOption) error {
err := s.setUpWda()
if err != nil {
return err
@@ -272,7 +266,7 @@ func (s *StubIOSDriver) Drag(fromX, fromY, toX, toY float64, opts ...option.Acti
}
// SetPasteboard Sets data to the general pasteboard
func (s *StubIOSDriver) SetPasteboard(contentType types.PasteboardType, content string) error {
func (s *ShootsIOSDriver) SetPasteboard(contentType types.PasteboardType, content string) error {
err := s.setUpWda()
if err != nil {
return err
@@ -283,7 +277,7 @@ func (s *StubIOSDriver) SetPasteboard(contentType types.PasteboardType, 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) {
func (s *ShootsIOSDriver) GetPasteboard(contentType types.PasteboardType) (raw *bytes.Buffer, err error) {
err = s.setUpWda()
if err != nil {
return nil, err
@@ -291,7 +285,7 @@ func (s *StubIOSDriver) GetPasteboard(contentType types.PasteboardType) (raw *by
return s.WDADriver.GetPasteboard(contentType)
}
func (s *StubIOSDriver) SetIme(ime string) error {
func (s *ShootsIOSDriver) SetIme(ime string) error {
err := s.setUpWda()
if err != nil {
return err
@@ -302,7 +296,7 @@ func (s *StubIOSDriver) SetIme(ime string) error {
// SendKeys Types a string into active element. There must be element with keyboard focus,
// otherwise an error is raised.
// WithFrequency option can be used to set frequency of typing (letters per sec). The default value is 60
func (s *StubIOSDriver) SendKeys(text string, opts ...option.ActionOption) error {
func (s *ShootsIOSDriver) SendKeys(text string, opts ...option.ActionOption) error {
err := s.setUpWda()
if err != nil {
return err
@@ -311,7 +305,7 @@ func (s *StubIOSDriver) SendKeys(text string, opts ...option.ActionOption) error
}
// Input works like SendKeys
func (s *StubIOSDriver) Input(text string, opts ...option.ActionOption) error {
func (s *ShootsIOSDriver) Input(text string, opts ...option.ActionOption) error {
err := s.setUpWda()
if err != nil {
return err
@@ -319,7 +313,7 @@ func (s *StubIOSDriver) Input(text string, opts ...option.ActionOption) error {
return s.WDADriver.Input(text, opts...)
}
func (s *StubIOSDriver) Clear(packageName string) error {
func (s *ShootsIOSDriver) Clear(packageName string) error {
err := s.setUpWda()
if err != nil {
return err
@@ -328,7 +322,7 @@ func (s *StubIOSDriver) Clear(packageName string) error {
}
// PressButton Presses the corresponding hardware button on the device
func (s *StubIOSDriver) PressButton(devBtn types.DeviceButton) error {
func (s *ShootsIOSDriver) PressButton(devBtn types.DeviceButton) error {
err := s.setUpWda()
if err != nil {
return err
@@ -337,7 +331,7 @@ func (s *StubIOSDriver) PressButton(devBtn types.DeviceButton) error {
}
// PressBack Presses the back button
func (s *StubIOSDriver) PressBack(opts ...option.ActionOption) error {
func (s *ShootsIOSDriver) PressBack(opts ...option.ActionOption) error {
err := s.setUpWda()
if err != nil {
return err
@@ -345,7 +339,7 @@ func (s *StubIOSDriver) PressBack(opts ...option.ActionOption) error {
return s.WDADriver.PressBack(opts...)
}
func (s *StubIOSDriver) PressKeyCode(keyCode KeyCode) (err error) {
func (s *ShootsIOSDriver) PressKeyCode(keyCode uixt.KeyCode) (err error) {
err = s.setUpWda()
if err != nil {
return err
@@ -353,7 +347,7 @@ func (s *StubIOSDriver) PressKeyCode(keyCode KeyCode) (err error) {
return s.WDADriver.PressKeyCode(keyCode)
}
func (s *StubIOSDriver) Screenshot() (*bytes.Buffer, error) {
func (s *ShootsIOSDriver) Screenshot() (*bytes.Buffer, error) {
err := s.setUpWda()
if err != nil {
return nil, err
@@ -374,7 +368,7 @@ func (s *StubIOSDriver) Screenshot() (*bytes.Buffer, error) {
//return bytes.NewBuffer(imageBytes), nil
}
func (s *StubIOSDriver) TapByText(text string, opts ...option.ActionOption) error {
func (s *ShootsIOSDriver) TapByText(text string, opts ...option.ActionOption) error {
err := s.setUpWda()
if err != nil {
return err
@@ -382,7 +376,7 @@ func (s *StubIOSDriver) TapByText(text string, opts ...option.ActionOption) erro
return s.WDADriver.TapByText(text, opts...)
}
func (s *StubIOSDriver) TapByTexts(actions ...TapTextAction) error {
func (s *ShootsIOSDriver) TapByTexts(actions ...uixt.TapTextAction) error {
err := s.setUpWda()
if err != nil {
return err
@@ -391,7 +385,7 @@ func (s *StubIOSDriver) TapByTexts(actions ...TapTextAction) error {
}
// AccessibleSource Return application elements accessibility tree
func (s *StubIOSDriver) AccessibleSource() (string, error) {
func (s *ShootsIOSDriver) AccessibleSource() (string, error) {
err := s.setUpWda()
if err != nil {
return "", err
@@ -404,7 +398,7 @@ func (s *StubIOSDriver) AccessibleSource() (string, error) {
// Checks health of XCTest by:
// 1) Querying application for some elements,
// 2) Triggering some device events.
func (s *StubIOSDriver) HealthCheck() error {
func (s *ShootsIOSDriver) HealthCheck() error {
err := s.setUpWda()
if err != nil {
return err
@@ -412,7 +406,7 @@ func (s *StubIOSDriver) HealthCheck() error {
return s.WDADriver.HealthCheck()
}
func (s *StubIOSDriver) GetAppiumSettings() (map[string]interface{}, error) {
func (s *ShootsIOSDriver) GetAppiumSettings() (map[string]interface{}, error) {
err := s.setUpWda()
if err != nil {
return nil, err
@@ -420,7 +414,7 @@ func (s *StubIOSDriver) GetAppiumSettings() (map[string]interface{}, error) {
return s.WDADriver.GetAppiumSettings()
}
func (s *StubIOSDriver) SetAppiumSettings(settings map[string]interface{}) (map[string]interface{}, error) {
func (s *ShootsIOSDriver) SetAppiumSettings(settings map[string]interface{}) (map[string]interface{}, error) {
err := s.setUpWda()
if err != nil {
return nil, err
@@ -428,7 +422,7 @@ func (s *StubIOSDriver) SetAppiumSettings(settings map[string]interface{}) (map[
return s.WDADriver.SetAppiumSettings(settings)
}
func (s *StubIOSDriver) IsHealthy() (bool, error) {
func (s *ShootsIOSDriver) IsHealthy() (bool, error) {
err := s.setUpWda()
if err != nil {
return false, err
@@ -437,7 +431,7 @@ func (s *StubIOSDriver) IsHealthy() (bool, error) {
}
// triggers the log capture and returns the log entries
func (s *StubIOSDriver) StartCaptureLog(identifier ...string) (err error) {
func (s *ShootsIOSDriver) StartCaptureLog(identifier ...string) (err error) {
err = s.setUpWda()
if err != nil {
return err
@@ -445,7 +439,7 @@ func (s *StubIOSDriver) StartCaptureLog(identifier ...string) (err error) {
return s.WDADriver.StartCaptureLog(identifier...)
}
func (s *StubIOSDriver) StopCaptureLog() (result interface{}, err error) {
func (s *ShootsIOSDriver) StopCaptureLog() (result interface{}, err error) {
err = s.setUpWda()
if err != nil {
return nil, err
@@ -453,7 +447,7 @@ func (s *StubIOSDriver) StopCaptureLog() (result interface{}, err error) {
return s.WDADriver.StopCaptureLog()
}
func (s *StubIOSDriver) GetDriverResults() []*DriverRequests {
func (s *ShootsIOSDriver) GetDriverResults() []*uixt.DriverRequests {
err := s.setUpWda()
if err != nil {
return nil
@@ -461,7 +455,7 @@ func (s *StubIOSDriver) GetDriverResults() []*DriverRequests {
return s.WDADriver.GetDriverResults()
}
func (s *StubIOSDriver) Source(srcOpt ...option.SourceOption) (string, error) {
func (s *ShootsIOSDriver) Source(srcOpt ...option.SourceOption) (string, error) {
resp, err := s.Request(http.MethodGet, fmt.Sprintf("%s/source?format=json&onlyWeb=false", s.bightInsightPrefix), []byte{})
if err != nil {
return "", err
@@ -469,7 +463,7 @@ func (s *StubIOSDriver) Source(srcOpt ...option.SourceOption) (string, error) {
return string(resp), nil
}
func (s *StubIOSDriver) LoginNoneUI(packageName, phoneNumber string, captcha, password string) (info AppLoginInfo, err error) {
func (s *ShootsIOSDriver) LoginNoneUI(packageName, phoneNumber string, captcha, password string) (info AppLoginInfo, err error) {
params := map[string]interface{}{
"phone": phoneNumber,
}
@@ -488,7 +482,7 @@ func (s *StubIOSDriver) LoginNoneUI(packageName, phoneNumber string, captcha, pa
if err != nil {
return info, err
}
res, err := resp.valueConvertToJsonObject()
res, err := resp.ValueConvertToJsonObject()
if err != nil {
return info, err
}
@@ -507,12 +501,12 @@ func (s *StubIOSDriver) LoginNoneUI(packageName, phoneNumber string, captcha, pa
return info, nil
}
func (s *StubIOSDriver) LogoutNoneUI(packageName string) error {
func (s *ShootsIOSDriver) LogoutNoneUI(packageName string) error {
resp, err := s.Request(http.MethodGet, fmt.Sprintf("%s/host/loginout/", s.serverPrefix), []byte{})
if err != nil {
return err
}
res, err := resp.valueConvertToJsonObject()
res, err := resp.ValueConvertToJsonObject()
if err != nil {
return err
}
@@ -526,17 +520,17 @@ func (s *StubIOSDriver) LogoutNoneUI(packageName string) error {
return nil
}
func (s *StubIOSDriver) TearDown() error {
s.client.CloseIdleConnections()
func (s *ShootsIOSDriver) TearDown() error {
s.WDADriver.TearDown()
return nil
}
func (s *StubIOSDriver) getLoginAppInfo(packageName string) (info AppLoginInfo, err error) {
func (s *ShootsIOSDriver) getLoginAppInfo(packageName string) (info AppLoginInfo, err error) {
resp, err := s.Request(http.MethodGet, fmt.Sprintf("%s/host/app/info/", s.serverPrefix), []byte{})
if err != nil {
return info, err
}
res, err := resp.valueConvertToJsonObject()
res, err := resp.ValueConvertToJsonObject()
if err != nil {
return info, err
}
@@ -553,6 +547,6 @@ func (s *StubIOSDriver) getLoginAppInfo(packageName string) (info AppLoginInfo,
return info, nil
}
func (s *StubIOSDriver) GetSession() *Session {
func (s *ShootsIOSDriver) GetSession() *uixt.Session {
return s.Session
}

View File

@@ -1,4 +1,4 @@
package uixt
package driver_ext
import (
"fmt"
@@ -7,71 +7,71 @@ import (
"testing"
"github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/pkg/uixt"
"github.com/httprunner/httprunner/v5/pkg/uixt/option"
)
var (
iOSStubDriver IDriverExt
iOSDevice *IOSDevice
shootsIOSDriver uixt.IDriverExt
iOSDevice *uixt.IOSDevice
)
func setupiOSStubDriver(t *testing.T) {
func setupShootsIOSDriver(t *testing.T) {
var err error
iOSDevice, err = NewIOSDevice(
iOSDevice, err = uixt.NewIOSDevice(
option.WithWDAPort(8700),
option.WithWDAMjpegPort(8800),
option.WithIOSStub(false))
option.WithWDAMjpegPort(8800))
checkErr(t, err)
iOSStubDriver, err = iOSDevice.NewDriver()
shootsIOSDriver, err = iOSDevice.NewDriver()
checkErr(t, err)
}
func TestIOSLogin(t *testing.T) {
setupiOSStubDriver(t)
info, err := iOSStubDriver.GetDriver().LoginNoneUI("", "12342316231", "8517", "")
setupShootsIOSDriver(t)
info, err := shootsIOSDriver.(*ShootsIOSDriver).LoginNoneUI("", "12342316231", "8517", "")
checkErr(t, err)
t.Log(info)
}
func TestIOSLogout(t *testing.T) {
setupiOSStubDriver(t)
err := iOSStubDriver.GetDriver().LogoutNoneUI("")
setupShootsIOSDriver(t)
err := shootsIOSDriver.(*ShootsIOSDriver).LogoutNoneUI("")
checkErr(t, err)
}
func TestIOSIsLogin(t *testing.T) {
setupiOSStubDriver(t)
err := iOSStubDriver.GetDriver().LogoutNoneUI("")
setupShootsIOSDriver(t)
err := shootsIOSDriver.(*ShootsIOSDriver).LogoutNoneUI("")
checkErr(t, err)
}
func TestIOSSource(t *testing.T) {
setupiOSStubDriver(t)
source, err := iOSStubDriver.GetDriver().Source()
setupShootsIOSDriver(t)
source, err := shootsIOSDriver.GetDriver().Source()
checkErr(t, err)
t.Log(source)
}
func TestIOSForeground(t *testing.T) {
setupiOSStubDriver(t)
app, err := iOSStubDriver.GetDriver().GetForegroundApp()
setupShootsIOSDriver(t)
app, err := shootsIOSDriver.GetDriver().GetForegroundApp()
checkErr(t, err)
t.Log(app)
}
func TestIOSSwipe(t *testing.T) {
setupiOSStubDriver(t)
iOSStubDriver.GetDriver().Swipe(540, 0, 540, 1000)
setupShootsIOSDriver(t)
shootsIOSDriver.GetDriver().Swipe(540, 0, 540, 1000)
}
func TestIOSSave(t *testing.T) {
setupiOSStubDriver(t)
raw, err := iOSStubDriver.GetDriver().Screenshot()
setupShootsIOSDriver(t)
raw, err := shootsIOSDriver.GetDriver().Screenshot()
if err != nil {
t.Fatal(err)
}
source, err := iOSStubDriver.GetDriver().Source()
source, err := shootsIOSDriver.GetDriver().Source()
if err != nil {
t.Fatal(err)
}
@@ -90,12 +90,12 @@ func TestIOSSave(t *testing.T) {
}
func TestListen(t *testing.T) {
setupiOSStubDriver(t)
setupShootsIOSDriver(t)
localPort, err := builtin.GetFreePort()
if err != nil {
t.Fatal(err)
}
err = iOSDevice.forward(localPort, 8800)
err = iOSDevice.Forward(localPort, 8800)
if err != nil {
t.Fatal(err)
}

View File

@@ -3,6 +3,7 @@ package uixt
import (
"bytes"
"context"
"fmt"
"io"
"net"
"net/http"
@@ -19,9 +20,9 @@ import (
type Session struct {
// ctx context.Context
sessionID string
baseURL *url.URL
client *http.Client
ID string
baseURL *url.URL
client *http.Client
// cache to avoid repeated query
scale float64
@@ -43,14 +44,18 @@ func (d *Session) addRequestResult(driverResult *DriverRequests) {
d.requests = append(d.requests, driverResult)
}
func (d *Session) Init(baseUrl string) error {
var err error
d.baseURL, err = url.Parse(baseUrl)
return err
}
func (d *Session) Reset() {
d.screenResults = make([]*ScreenResult, 0)
d.requests = make([]*DriverRequests, 0)
d.e2eDelay = nil
}
type Attachments map[string]interface{}
func (d *Session) GetData(withReset bool) Attachments {
data := Attachments{
"screen_results": d.screenResults,
@@ -67,6 +72,8 @@ func (d *Session) GetData(withReset bool) Attachments {
return data
}
type Attachments map[string]interface{}
type DriverRequests struct {
RequestMethod string `json:"request_method"`
RequestUrl string `json:"request_url"`
@@ -91,11 +98,11 @@ func (wd *Session) concatURL(u *url.URL, elem ...string) string {
return tmp.String()
}
func (wd *Session) GET(pathElem ...string) (rawResp rawResponse, err error) {
func (wd *Session) GET(pathElem ...string) (rawResp DriverRawResponse, err error) {
return wd.Request(http.MethodGet, wd.concatURL(nil, pathElem...), nil)
}
func (wd *Session) POST(data interface{}, pathElem ...string) (rawResp rawResponse, err error) {
func (wd *Session) POST(data interface{}, pathElem ...string) (rawResp DriverRawResponse, err error) {
var bsJSON []byte = nil
if data != nil {
if bsJSON, err = json.Marshal(data); err != nil {
@@ -105,11 +112,11 @@ func (wd *Session) POST(data interface{}, pathElem ...string) (rawResp rawRespon
return wd.Request(http.MethodPost, wd.concatURL(nil, pathElem...), bsJSON)
}
func (wd *Session) DELETE(pathElem ...string) (rawResp rawResponse, err error) {
func (wd *Session) DELETE(pathElem ...string) (rawResp DriverRawResponse, err error) {
return wd.Request(http.MethodDelete, wd.concatURL(nil, pathElem...), nil)
}
func (wd *Session) Request(method string, rawURL string, rawBody []byte) (rawResp rawResponse, err error) {
func (wd *Session) Request(method string, rawURL string, rawBody []byte) (rawResp DriverRawResponse, err error) {
driverResult := &DriverRequests{
RequestMethod: method,
RequestUrl: rawURL,
@@ -179,7 +186,7 @@ func (wd *Session) Request(method string, rawURL string, rawBody []byte) (rawRes
return nil, err
}
if err = rawResp.checkErr(); err != nil {
if err = rawResp.CheckErr(); err != nil {
if resp.StatusCode == http.StatusOK {
return rawResp, nil
}
@@ -189,13 +196,22 @@ func (wd *Session) Request(method string, rawURL string, rawBody []byte) (rawRes
return
}
func convertToHTTPClient(conn net.Conn) *http.Client {
func (wd *Session) InitConnection(localPort int) error {
conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", localPort))
if err != nil {
return fmt.Errorf("create tcp connection error %v", err)
}
wd.client = NewHTTPClientWithConnection(conn, 30*time.Second)
return nil
}
func NewHTTPClientWithConnection(conn net.Conn, timeout time.Duration) *http.Client {
return &http.Client{
Transport: &http.Transport{
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
return conn, nil
},
},
Timeout: 30 * time.Second,
Timeout: timeout,
}
}

View File

@@ -41,18 +41,19 @@ func NewHDCDriver(device *HarmonyDevice) (driver *HDCDriver, err error) {
return nil, err
}
driver.uiDriver = uiDriver
driver.NewSession(nil)
driver.InitSession(nil)
return
}
func (hd *HDCDriver) NewSession(capabilities option.Capabilities) (Session, error) {
hd.Reset()
func (hd *HDCDriver) InitSession(capabilities option.Capabilities) error {
hd.Session = &Session{}
hd.Session.Reset()
hd.Unlock()
return Session{}, errDriverNotImplemented
return nil
}
func (hd *HDCDriver) DeleteSession() error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) GetSession() *Session {
@@ -60,7 +61,7 @@ func (hd *HDCDriver) GetSession() *Session {
}
func (hd *HDCDriver) Status() (types.DeviceStatus, error) {
return types.DeviceStatus{}, errDriverNotImplemented
return types.DeviceStatus{}, types.ErrDriverNotImplemented
}
func (hd *HDCDriver) GetDevice() IDevice {
@@ -68,15 +69,15 @@ func (hd *HDCDriver) GetDevice() IDevice {
}
func (hd *HDCDriver) DeviceInfo() (types.DeviceInfo, error) {
return types.DeviceInfo{}, errDriverNotImplemented
return types.DeviceInfo{}, types.ErrDriverNotImplemented
}
func (hd *HDCDriver) Location() (types.Location, error) {
return types.Location{}, errDriverNotImplemented
return types.Location{}, types.ErrDriverNotImplemented
}
func (hd *HDCDriver) BatteryInfo() (types.BatteryInfo, error) {
return types.BatteryInfo{}, errDriverNotImplemented
return types.BatteryInfo{}, types.ErrDriverNotImplemented
}
func (hd *HDCDriver) WindowSize() (size types.Size, err error) {
@@ -91,7 +92,7 @@ func (hd *HDCDriver) WindowSize() (size types.Size, err error) {
}
func (hd *HDCDriver) Screen() (ai.Screen, error) {
return ai.Screen{}, errDriverNotImplemented
return ai.Screen{}, types.ErrDriverNotImplemented
}
func (hd *HDCDriver) Scale() (float64, error) {
@@ -126,7 +127,7 @@ func (hd *HDCDriver) Unlock() (err error) {
func (hd *HDCDriver) AppLaunch(packageName string) error {
// Todo
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) AppTerminate(packageName string) (bool, error) {
@@ -140,7 +141,7 @@ func (hd *HDCDriver) AppTerminate(packageName string) (bool, error) {
func (hd *HDCDriver) GetForegroundApp() (app types.AppInfo, err error) {
// Todo
return types.AppInfo{}, errDriverNotImplemented
return types.AppInfo{}, types.ErrDriverNotImplemented
}
func (hd *HDCDriver) AssertForegroundApp(packageName string, activityType ...string) error {
@@ -149,11 +150,11 @@ func (hd *HDCDriver) AssertForegroundApp(packageName string, activityType ...str
}
func (hd *HDCDriver) StartCamera() error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) StopCamera() error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) Orientation() (orientation types.Orientation, err error) {
@@ -178,15 +179,15 @@ func (hd *HDCDriver) Tap(x, y float64, opts ...option.ActionOption) error {
}
func (hd *HDCDriver) DoubleTap(x, y float64, opts ...option.ActionOption) error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) TouchAndHold(x, y float64, opts ...option.ActionOption) (err error) {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionOption) error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
// Swipe works like Drag, but `pressForDuration` value is 0
@@ -215,15 +216,15 @@ func (hd *HDCDriver) Swipe(fromX, fromY, toX, toY float64, opts ...option.Action
}
func (hd *HDCDriver) SetPasteboard(contentType types.PasteboardType, content string) error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) GetPasteboard(contentType types.PasteboardType) (raw *bytes.Buffer, err error) {
return nil, errDriverNotImplemented
return nil, types.ErrDriverNotImplemented
}
func (hd *HDCDriver) SetIme(ime string) error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) SendKeys(text string, opts ...option.ActionOption) error {
@@ -235,11 +236,11 @@ func (hd *HDCDriver) Input(text string, opts ...option.ActionOption) error {
}
func (hd *HDCDriver) Clear(packageName string) error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) PressButton(devBtn types.DeviceButton) error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) PressBack(opts ...option.ActionOption) error {
@@ -251,7 +252,7 @@ func (hd *HDCDriver) Backspace(count int, opts ...option.ActionOption) (err erro
}
func (hd *HDCDriver) PressKeyCode(keyCode KeyCode) (err error) {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) PressHarmonyKeyCode(keyCode ghdc.KeyCode) (err error) {
@@ -282,45 +283,36 @@ func (hd *HDCDriver) Source(srcOpt ...option.SourceOption) (string, error) {
return "", nil
}
func (hd *HDCDriver) LoginNoneUI(packageName, phoneNumber string, captcha, password string) (info AppLoginInfo, err error) {
err = errDriverNotImplemented
return
}
func (hd *HDCDriver) LogoutNoneUI(packageName string) error {
return errDriverNotImplemented
}
func (hd *HDCDriver) TapByText(text string, opts ...option.ActionOption) error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) TapByTexts(actions ...TapTextAction) error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) AccessibleSource() (string, error) {
return "", errDriverNotImplemented
return "", types.ErrDriverNotImplemented
}
func (hd *HDCDriver) HealthCheck() error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) GetAppiumSettings() (map[string]interface{}, error) {
return nil, errDriverNotImplemented
return nil, types.ErrDriverNotImplemented
}
func (hd *HDCDriver) SetAppiumSettings(settings map[string]interface{}) (map[string]interface{}, error) {
return nil, errDriverNotImplemented
return nil, types.ErrDriverNotImplemented
}
func (hd *HDCDriver) IsHealthy() (bool, error) {
return false, errDriverNotImplemented
return false, types.ErrDriverNotImplemented
}
func (hd *HDCDriver) StartCaptureLog(identifier ...string) (err error) {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (hd *HDCDriver) StopCaptureLog() (result interface{}, err error) {
@@ -345,11 +337,11 @@ func (hd *HDCDriver) TearDown() error {
}
func (hd *HDCDriver) Rotation() (rotation types.Rotation, err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}
func (hd *HDCDriver) SetRotation(rotation types.Rotation) (err error) {
err = errDriverNotImplemented
err = types.ErrDriverNotImplemented
return
}

View File

@@ -228,35 +228,10 @@ func (dev *IOSDevice) getAppInfo(packageName string) (appInfo types.AppInfo, err
}
func (dev *IOSDevice) NewDriver() (driverExt IDriverExt, err error) {
var driver IDriver
if dev.STUB {
driver, err = NewStubIOSDriver(dev)
if err != nil {
return nil, errors.Wrap(err, "failed to init Stub driver")
}
} else {
driver, err := NewWDADriver(dev)
if err != nil {
return nil, errors.Wrap(err, "failed to init WDA driver")
}
settings, err := driver.SetAppiumSettings(map[string]interface{}{
"snapshotMaxDepth": dev.SnapshotMaxDepth,
"acceptAlertButtonSelector": dev.AcceptAlertButtonSelector,
})
if err != nil {
return nil, errors.Wrap(err, "failed to set appium WDA settings")
}
log.Info().Interface("appiumWDASettings", settings).Msg("set appium WDA settings")
driver, err := NewWDADriver(dev)
if err != nil {
return nil, errors.Wrap(err, "failed to init WDA driver")
}
if dev.ResetHomeOnStartup {
log.Info().Msg("go back to home screen")
if err = driver.Homescreen(); err != nil {
return nil, errors.Wrap(code.MobileUIDriverError,
fmt.Sprintf("go back to home screen failed: %v", err))
}
}
settings, err := driver.SetAppiumSettings(map[string]interface{}{
"snapshotMaxDepth": dev.SnapshotMaxDepth,
"acceptAlertButtonSelector": dev.AcceptAlertButtonSelector,
@@ -266,6 +241,13 @@ func (dev *IOSDevice) NewDriver() (driverExt IDriverExt, err error) {
}
log.Info().Interface("appiumWDASettings", settings).Msg("set appium WDA settings")
if dev.ResetHomeOnStartup {
log.Info().Msg("go back to home screen")
if err = driver.Homescreen(); err != nil {
return nil, errors.Wrap(code.MobileUIDriverError,
fmt.Sprintf("go back to home screen failed: %v", err))
}
}
if dev.LogOn {
err = driver.StartCaptureLog("hrp_wda_log")
if err != nil {
@@ -319,7 +301,7 @@ func (dev *IOSDevice) Uninstall(bundleId string) error {
return nil
}
func (dev *IOSDevice) forward(localPort, remotePort int) error {
func (dev *IOSDevice) Forward(localPort, remotePort int) error {
if dev.listeners[localPort] != nil {
log.Warn().Msg(fmt.Sprintf("local port :%d is already in use", localPort))
_ = dev.listeners[localPort].Close()
@@ -521,7 +503,7 @@ func (dev *IOSDevice) NewHTTPDriver(capabilities option.Capabilities) (driver ID
return nil, errors.Wrap(code.DeviceHTTPDriverError,
fmt.Sprintf("get free port failed: %v", err))
}
if err = dev.forward(localPort, dev.WDAPort); err != nil {
if err = dev.Forward(localPort, dev.WDAPort); err != nil {
return nil, errors.Wrap(code.DeviceHTTPDriverError,
fmt.Sprintf("forward tcp port failed: %v", err))
}
@@ -537,7 +519,7 @@ func (dev *IOSDevice) NewHTTPDriver(capabilities option.Capabilities) (driver ID
return nil, errors.Wrap(code.DeviceHTTPDriverError,
fmt.Sprintf("get free port failed: %v", err))
}
if err = dev.forward(localMjpegPort, dev.WDAMjpegPort); err != nil {
if err = dev.Forward(localMjpegPort, dev.WDAMjpegPort); err != nil {
return nil, errors.Wrap(code.DeviceHTTPDriverError,
fmt.Sprintf("forward tcp port failed: %v", err))
}
@@ -563,11 +545,9 @@ func (dev *IOSDevice) NewHTTPDriver(capabilities option.Capabilities) (driver ID
}
// create new session
var sessionInfo Session
if sessionInfo, err = wd.NewSession(capabilities); err != nil {
if err = wd.InitSession(capabilities); err != nil {
return nil, errors.Wrap(code.DeviceHTTPDriverError, err.Error())
}
wd.sessionID = sessionInfo.sessionID
if wd.mjpegHTTPConn, err = net.Dial(
"tcp",
@@ -575,7 +555,7 @@ func (dev *IOSDevice) NewHTTPDriver(capabilities option.Capabilities) (driver ID
); err != nil {
return nil, errors.Wrap(code.DeviceHTTPDriverError, err.Error())
}
wd.mjpegClient = convertToHTTPClient(wd.mjpegHTTPConn)
wd.mjpegClient = NewHTTPClientWithConnection(wd.mjpegHTTPConn, 30*time.Second)
wd.mjpegUrl = fmt.Sprintf("%s:%d", host, localMjpegPort)
// init WDA scale
if wd.scale, err = wd.Scale(); err != nil {

View File

@@ -34,7 +34,7 @@ func NewWDADriver(device *IOSDevice) (*WDADriver, error) {
IOSDevice: device,
Session: &Session{},
}
driver.NewSession(nil)
driver.InitSession(nil)
return driver, nil
}
@@ -63,16 +63,16 @@ func (wd *WDADriver) resetSession() error {
if err != nil {
return err
}
sessionInfo, err := rawResp.valueConvertToSessionInfo()
sessionInfo, err := rawResp.ValueConvertToSessionInfo()
if err != nil {
return err
}
// update session ID
wd.sessionID = sessionInfo.sessionID
wd.ID = sessionInfo.ID
return nil
}
func (wd *WDADriver) httpRequest(method string, rawURL string, rawBody []byte) (rawResp rawResponse, err error) {
func (wd *WDADriver) httpRequest(method string, rawURL string, rawBody []byte) (rawResp DriverRawResponse, err error) {
retryInterval := 3 * time.Second
for retryCount := 1; retryCount <= 3; retryCount++ {
rawResp, err = wd.Request(method, rawURL, rawBody)
@@ -92,25 +92,25 @@ func (wd *WDADriver) httpRequest(method string, rawURL string, rawBody []byte) (
retryInterval = retryInterval * 2
time.Sleep(retryInterval)
oldSessionID := wd.sessionID
oldSessionID := wd.ID
if err2 := wd.resetSession(); err2 != nil {
log.Err(err2).Msgf("failed to reset wda driver session, retry count: %v", retryCount)
continue
}
log.Debug().Str("new session", wd.sessionID).Str("old session", oldSessionID).
log.Debug().Str("new session", wd.ID).Str("old session", oldSessionID).
Msgf("reset wda driver session successfully, retry count: %v", retryCount)
if oldSessionID != "" {
rawURL = strings.Replace(rawURL, oldSessionID, wd.sessionID, 1)
rawURL = strings.Replace(rawURL, oldSessionID, wd.ID, 1)
}
}
return
}
func (wd *WDADriver) httpGET(pathElem ...string) (rawResp rawResponse, err error) {
func (wd *WDADriver) httpGET(pathElem ...string) (rawResp DriverRawResponse, err error) {
return wd.httpRequest(http.MethodGet, wd.concatURL(nil, pathElem...), nil)
}
func (wd *WDADriver) httpPOST(data interface{}, pathElem ...string) (rawResp rawResponse, err error) {
func (wd *WDADriver) httpPOST(data interface{}, pathElem ...string) (rawResp DriverRawResponse, err error) {
var bsJSON []byte = nil
if data != nil {
if bsJSON, err = json.Marshal(data); err != nil {
@@ -120,7 +120,7 @@ func (wd *WDADriver) httpPOST(data interface{}, pathElem ...string) (rawResp raw
return wd.httpRequest(http.MethodPost, wd.concatURL(nil, pathElem...), bsJSON)
}
func (wd *WDADriver) httpDELETE(pathElem ...string) (rawResp rawResponse, err error) {
func (wd *WDADriver) httpDELETE(pathElem ...string) (rawResp DriverRawResponse, err error) {
return wd.httpRequest(http.MethodDelete, wd.concatURL(nil, pathElem...), nil)
}
@@ -128,7 +128,7 @@ func (wd *WDADriver) GetMjpegClient() *http.Client {
return wd.mjpegClient
}
func (wd *WDADriver) NewSession(capabilities option.Capabilities) (sessionInfo Session, err error) {
func (wd *WDADriver) InitSession(capabilities option.Capabilities) error {
// [[FBRoute POST:@"/session"].withoutSession respondWithTarget:self action:@selector(handleCreateSession:)]
data := make(map[string]interface{})
if len(capabilities) == 0 {
@@ -139,14 +139,16 @@ func (wd *WDADriver) NewSession(capabilities option.Capabilities) (sessionInfo S
}
}
var rawResp rawResponse
if rawResp, err = wd.httpPOST(data, "/session"); err != nil {
return Session{}, err
rawResp, err := wd.httpPOST(data, "/session")
if err != nil {
return err
}
if sessionInfo, err = rawResp.valueConvertToSessionInfo(); err != nil {
return Session{}, err
sessionInfo, err := rawResp.ValueConvertToSessionInfo()
if err != nil {
return err
}
return
wd.Session = &sessionInfo
return nil
}
func (wd *WDADriver) DeleteSession() (err error) {
@@ -158,13 +160,13 @@ func (wd *WDADriver) DeleteSession() (err error) {
}
// [[FBRoute DELETE:@""] respondWithTarget:self action:@selector(handleDeleteSession:)]
_, err = wd.httpDELETE("/session", wd.sessionID)
_, err = wd.httpDELETE("/session", wd.ID)
return
}
func (wd *WDADriver) Status() (deviceStatus types.DeviceStatus, err error) {
// [[FBRoute GET:@"/status"].withoutSession respondWithTarget:self action:@selector(handleGetStatus:)]
var rawResp rawResponse
var rawResp DriverRawResponse
// Notice: use Driver.GET instead of httpGET to avoid loop calling
if rawResp, err = wd.GET("/status"); err != nil {
return types.DeviceStatus{}, err
@@ -184,8 +186,8 @@ func (wd *WDADriver) GetDevice() IDevice {
func (wd *WDADriver) DeviceInfo() (deviceInfo types.DeviceInfo, err error) {
// [[FBRoute GET:@"/wda/device/info"] respondWithTarget:self action:@selector(handleGetDeviceInfo:)]
// [[FBRoute GET:@"/wda/device/info"].withoutSession
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/wda/device/info"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/wda/device/info"); err != nil {
return types.DeviceInfo{}, err
}
reply := new(struct{ Value struct{ types.DeviceInfo } })
@@ -199,8 +201,8 @@ func (wd *WDADriver) DeviceInfo() (deviceInfo types.DeviceInfo, err error) {
func (wd *WDADriver) Location() (location types.Location, err error) {
// [[FBRoute GET:@"/wda/device/location"] respondWithTarget:self action:@selector(handleGetLocation:)]
// [[FBRoute GET:@"/wda/device/location"].withoutSession
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/wda/device/location"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/wda/device/location"); err != nil {
return types.Location{}, err
}
reply := new(struct{ Value struct{ types.Location } })
@@ -213,8 +215,8 @@ func (wd *WDADriver) Location() (location types.Location, err error) {
func (wd *WDADriver) BatteryInfo() (batteryInfo types.BatteryInfo, err error) {
// [[FBRoute GET:@"/wda/batteryInfo"] respondWithTarget:self action:@selector(handleGetBatteryInfo:)]
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/wda/batteryInfo"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/wda/batteryInfo"); err != nil {
return types.BatteryInfo{}, err
}
reply := new(struct{ Value struct{ types.BatteryInfo } })
@@ -232,8 +234,8 @@ func (wd *WDADriver) WindowSize() (size types.Size, err error) {
return wd.windowSize, nil
}
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/window/size"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/window/size"); err != nil {
return types.Size{}, errors.Wrap(err, "get window size failed by WDA request")
}
reply := new(struct{ Value struct{ types.Size } })
@@ -254,8 +256,8 @@ func (wd *WDADriver) WindowSize() (size types.Size, err error) {
func (wd *WDADriver) Screen() (screen ai.Screen, err error) {
// [[FBRoute GET:@"/wda/screen"] respondWithTarget:self action:@selector(handleGetScreen:)]
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/wda/screen"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/wda/screen"); err != nil {
return ai.Screen{}, err
}
reply := new(struct{ Value struct{ ai.Screen } })
@@ -285,8 +287,8 @@ func (wd *WDADriver) toScale(x float64) float64 {
func (wd *WDADriver) ActiveAppInfo() (info types.AppInfo, err error) {
// [[FBRoute GET:@"/wda/activeAppInfo"] respondWithTarget:self action:@selector(handleActiveAppInfo:)]
// [[FBRoute GET:@"/wda/activeAppInfo"].withoutSession
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/wda/activeAppInfo"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/wda/activeAppInfo"); err != nil {
return types.AppInfo{}, err
}
reply := new(struct{ Value struct{ types.AppInfo } })
@@ -299,8 +301,8 @@ func (wd *WDADriver) ActiveAppInfo() (info types.AppInfo, err error) {
func (wd *WDADriver) ActiveAppsList() (appsList []types.AppBaseInfo, err error) {
// [[FBRoute GET:@"/wda/apps/list"] respondWithTarget:self action:@selector(handleGetActiveAppsList:)]
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/wda/apps/list"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/wda/apps/list"); err != nil {
return nil, err
}
reply := new(struct{ Value []types.AppBaseInfo })
@@ -314,8 +316,8 @@ func (wd *WDADriver) ActiveAppsList() (appsList []types.AppBaseInfo, err error)
func (wd *WDADriver) AppState(bundleId string) (runState types.AppState, err error) {
// [[FBRoute POST:@"/wda/apps/state"] respondWithTarget:self action:@selector(handleSessionAppState:)]
data := map[string]interface{}{"bundleId": bundleId}
var rawResp rawResponse
if rawResp, err = wd.httpPOST(data, "/session", wd.sessionID, "/wda/apps/state"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpPOST(data, "/session", wd.ID, "/wda/apps/state"); err != nil {
return 0, err
}
reply := new(struct{ Value types.AppState })
@@ -330,11 +332,11 @@ func (wd *WDADriver) AppState(bundleId string) (runState types.AppState, err err
func (wd *WDADriver) IsLocked() (locked bool, err error) {
// [[FBRoute GET:@"/wda/locked"] respondWithTarget:self action:@selector(handleIsLocked:)]
// [[FBRoute GET:@"/wda/locked"].withoutSession
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/wda/locked"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/wda/locked"); err != nil {
return false, err
}
if locked, err = rawResp.valueConvertToBool(); err != nil {
if locked, err = rawResp.ValueConvertToBool(); err != nil {
return false, err
}
return
@@ -343,14 +345,14 @@ func (wd *WDADriver) IsLocked() (locked bool, err error) {
func (wd *WDADriver) Unlock() (err error) {
// [[FBRoute POST:@"/wda/unlock"] respondWithTarget:self action:@selector(handleUnlock:)]
// [[FBRoute POST:@"/wda/unlock"].withoutSession
_, err = wd.httpPOST(nil, "/session", wd.sessionID, "/wda/unlock")
_, err = wd.httpPOST(nil, "/session", wd.ID, "/wda/unlock")
return
}
func (wd *WDADriver) Lock() (err error) {
// [[FBRoute POST:@"/wda/lock"] respondWithTarget:self action:@selector(handleLock:)]
// [[FBRoute POST:@"/wda/lock"].withoutSession
_, err = wd.httpPOST(nil, "/session", wd.sessionID, "/wda/lock")
_, err = wd.httpPOST(nil, "/session", wd.ID, "/wda/lock")
return
}
@@ -363,11 +365,11 @@ func (wd *WDADriver) Homescreen() (err error) {
func (wd *WDADriver) AlertText() (text string, err error) {
// [[FBRoute GET:@"/alert/text"] respondWithTarget:self action:@selector(handleAlertGetTextCommand:)]
// [[FBRoute GET:@"/alert/text"].withoutSession
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/alert/text"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/alert/text"); err != nil {
return "", err
}
if text, err = rawResp.valueConvertToString(); err != nil {
if text, err = rawResp.ValueConvertToString(); err != nil {
return "", err
}
return
@@ -375,8 +377,8 @@ func (wd *WDADriver) AlertText() (text string, err error) {
func (wd *WDADriver) AlertButtons() (btnLabels []string, err error) {
// [[FBRoute GET:@"/wda/alert/buttons"] respondWithTarget:self action:@selector(handleGetAlertButtonsCommand:)]
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/wda/alert/buttons"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/wda/alert/buttons"); err != nil {
return nil, err
}
reply := new(struct{ Value []string })
@@ -412,7 +414,7 @@ func (wd *WDADriver) AlertDismiss(label ...string) (err error) {
func (wd *WDADriver) AlertSendKeys(text string) (err error) {
// [[FBRoute POST:@"/alert/text"] respondWithTarget:self action:@selector(handleAlertSetTextCommand:)]
data := map[string]interface{}{"value": strings.Split(text, "")}
_, err = wd.httpPOST(data, "/session", wd.sessionID, "/alert/text")
_, err = wd.httpPOST(data, "/session", wd.ID, "/alert/text")
return
}
@@ -423,7 +425,7 @@ func (wd *WDADriver) AppLaunch(bundleId string) (err error) {
data["environment"] = map[string]interface{}{
"SHOW_EXPLORER": "NO",
}
_, err = wd.httpPOST(data, "/session", wd.sessionID, "/wda/apps/launch")
_, err = wd.httpPOST(data, "/session", wd.ID, "/wda/apps/launch")
if err != nil {
return errors.Wrap(code.MobileUILaunchAppError,
fmt.Sprintf("wda launch failed: %v", err))
@@ -445,11 +447,11 @@ func (wd *WDADriver) AppLaunchUnattached(bundleId string) (err error) {
func (wd *WDADriver) AppTerminate(bundleId string) (successful bool, err error) {
// [[FBRoute POST:@"/wda/apps/terminate"] respondWithTarget:self action:@selector(handleSessionAppTerminate:)]
data := map[string]interface{}{"bundleId": bundleId}
var rawResp rawResponse
if rawResp, err = wd.httpPOST(data, "/session", wd.sessionID, "/wda/apps/terminate"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpPOST(data, "/session", wd.ID, "/wda/apps/terminate"); err != nil {
return false, err
}
if successful, err = rawResp.valueConvertToBool(); err != nil {
if successful, err = rawResp.ValueConvertToBool(); err != nil {
return false, err
}
return
@@ -458,7 +460,7 @@ func (wd *WDADriver) AppTerminate(bundleId string) (successful bool, err error)
func (wd *WDADriver) AppActivate(bundleId string) (err error) {
// [[FBRoute POST:@"/wda/apps/activate"] respondWithTarget:self action:@selector(handleSessionAppActivate:)]
data := map[string]interface{}{"bundleId": bundleId}
_, err = wd.httpPOST(data, "/session", wd.sessionID, "/wda/apps/activate")
_, err = wd.httpPOST(data, "/session", wd.ID, "/wda/apps/activate")
return
}
@@ -468,7 +470,7 @@ func (wd *WDADriver) AppDeactivate(second float64) (err error) {
second = 3.0
}
data := map[string]interface{}{"duration": second}
_, err = wd.httpPOST(data, "/session", wd.sessionID, "/wda/deactivateApp")
_, err = wd.httpPOST(data, "/session", wd.ID, "/wda/deactivateApp")
return
}
@@ -539,7 +541,7 @@ func (wd *WDADriver) Tap(x, y float64, opts ...option.ActionOption) (err error)
// update data options in post data for extra WDA configurations
actionOptions.UpdateData(data)
_, err = wd.httpPOST(data, "/session", wd.sessionID, "/wda/tap/0")
_, err = wd.httpPOST(data, "/session", wd.ID, "/wda/tap/0")
return
}
@@ -559,7 +561,7 @@ func (wd *WDADriver) DoubleTap(x, y float64, opts ...option.ActionOption) (err e
"x": x,
"y": y,
}
_, err = wd.httpPOST(data, "/session", wd.sessionID, "/wda/doubleTap")
_, err = wd.httpPOST(data, "/session", wd.ID, "/wda/doubleTap")
return
}
@@ -603,7 +605,7 @@ func (wd *WDADriver) Drag(fromX, fromY, toX, toY float64, opts ...option.ActionO
// update data options in post data for extra WDA configurations
actionOptions.UpdateData(data)
// wda 43 version
_, err = wd.httpPOST(data, "/session", wd.sessionID, "/wda/dragfromtoforduration")
_, err = wd.httpPOST(data, "/session", wd.ID, "/wda/dragfromtoforduration")
// _, err = wd.httpPOST(data, "/session", wd.ID, "/wda/drag")
return
}
@@ -618,29 +620,29 @@ func (wd *WDADriver) SetPasteboard(contentType types.PasteboardType, content str
"contentType": contentType,
"content": base64.StdEncoding.EncodeToString([]byte(content)),
}
_, err = wd.httpPOST(data, "/session", wd.sessionID, "/wda/setPasteboard")
_, err = wd.httpPOST(data, "/session", wd.ID, "/wda/setPasteboard")
return
}
func (wd *WDADriver) GetPasteboard(contentType types.PasteboardType) (raw *bytes.Buffer, err error) {
// [[FBRoute POST:@"/wda/getPasteboard"] respondWithTarget:self action:@selector(handleGetPasteboard:)]
data := map[string]interface{}{"contentType": contentType}
var rawResp rawResponse
if rawResp, err = wd.httpPOST(data, "/session", wd.sessionID, "/wda/getPasteboard"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpPOST(data, "/session", wd.ID, "/wda/getPasteboard"); err != nil {
return nil, err
}
if raw, err = rawResp.valueDecodeAsBase64(); err != nil {
if raw, err = rawResp.ValueDecodeAsBase64(); err != nil {
return nil, err
}
return
}
func (wd *WDADriver) SetIme(ime string) error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (wd *WDADriver) PressKeyCode(keyCode KeyCode) (err error) {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (wd *WDADriver) SendKeys(text string, opts ...option.ActionOption) (err error) {
@@ -651,7 +653,7 @@ func (wd *WDADriver) SendKeys(text string, opts ...option.ActionOption) (err err
// new data options in post data for extra WDA configurations
actionOptions.UpdateData(data)
_, err = wd.httpPOST(data, "/session", wd.sessionID, "/wda/keys")
_, err = wd.httpPOST(data, "/session", wd.ID, "/wda/keys")
return
}
@@ -674,7 +676,7 @@ func (wd *WDADriver) Input(text string, opts ...option.ActionOption) (err error)
}
func (wd *WDADriver) Clear(packageName string) error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
// PressBack simulates a short press on the BACK button.
@@ -710,25 +712,17 @@ func (wd *WDADriver) PressBack(opts ...option.ActionOption) (err error) {
// update data options in post data for extra WDA configurations
actionOptions.UpdateData(data)
_, err = wd.httpPOST(data, "/session", wd.sessionID, "/wda/dragfromtoforduration")
_, err = wd.httpPOST(data, "/session", wd.ID, "/wda/dragfromtoforduration")
return
}
func (wd *WDADriver) PressButton(devBtn types.DeviceButton) (err error) {
// [[FBRoute POST:@"/wda/pressButton"] respondWithTarget:self action:@selector(handlePressButtonCommand:)]
data := map[string]interface{}{"name": devBtn}
_, err = wd.httpPOST(data, "/session", wd.sessionID, "/wda/pressButton")
_, err = wd.httpPOST(data, "/session", wd.ID, "/wda/pressButton")
return
}
func (wd *WDADriver) LoginNoneUI(packageName, phoneNumber string, captcha, password string) (info AppLoginInfo, err error) {
return info, errDriverNotImplemented
}
func (wd *WDADriver) LogoutNoneUI(packageName string) error {
return errDriverNotImplemented
}
func (wd *WDADriver) StartCamera() (err error) {
// start camera, alias for app_launch com.apple.camera
return wd.AppLaunch("com.apple.camera")
@@ -748,8 +742,8 @@ func (wd *WDADriver) StopCamera() (err error) {
func (wd *WDADriver) Orientation() (orientation types.Orientation, err error) {
// [[FBRoute GET:@"/orientation"] respondWithTarget:self action:@selector(handleGetOrientation:)]
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/orientation"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/orientation"); err != nil {
return "", err
}
reply := new(struct{ Value types.Orientation })
@@ -763,14 +757,14 @@ func (wd *WDADriver) Orientation() (orientation types.Orientation, err error) {
func (wd *WDADriver) SetOrientation(orientation types.Orientation) (err error) {
// [[FBRoute POST:@"/orientation"] respondWithTarget:self action:@selector(handleSetOrientation:)]
data := map[string]interface{}{"orientation": orientation}
_, err = wd.httpPOST(data, "/session", wd.sessionID, "/orientation")
_, err = wd.httpPOST(data, "/session", wd.ID, "/orientation")
return
}
func (wd *WDADriver) Rotation() (rotation types.Rotation, err error) {
// [[FBRoute GET:@"/rotation"] respondWithTarget:self action:@selector(handleGetRotation:)]
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/rotation"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/rotation"); err != nil {
return types.Rotation{}, err
}
reply := new(struct{ Value types.Rotation })
@@ -783,20 +777,20 @@ func (wd *WDADriver) Rotation() (rotation types.Rotation, err error) {
func (wd *WDADriver) SetRotation(rotation types.Rotation) (err error) {
// [[FBRoute POST:@"/rotation"] respondWithTarget:self action:@selector(handleSetRotation:)]
_, err = wd.httpPOST(rotation, "/session", wd.sessionID, "/rotation")
_, err = wd.httpPOST(rotation, "/session", wd.ID, "/rotation")
return
}
func (wd *WDADriver) Screenshot() (raw *bytes.Buffer, err error) {
// [[FBRoute GET:@"/screenshot"] respondWithTarget:self action:@selector(handleGetScreenshot:)]
// [[FBRoute GET:@"/screenshot"].withoutSession respondWithTarget:self action:@selector(handleGetScreenshot:)]
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/screenshot"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/screenshot"); err != nil {
return nil, errors.Wrap(code.DeviceScreenShotError,
fmt.Sprintf("get WDA screenshot data failed: %v", err))
}
if raw, err = rawResp.valueDecodeAsBase64(); err != nil {
if raw, err = rawResp.ValueDecodeAsBase64(); err != nil {
return nil, errors.Wrap(code.DeviceScreenShotError,
fmt.Sprintf("decode WDA screenshot data failed: %v", err))
}
@@ -806,7 +800,7 @@ func (wd *WDADriver) Screenshot() (raw *bytes.Buffer, err error) {
func (wd *WDADriver) Source(srcOpt ...option.SourceOption) (source string, err error) {
// [[FBRoute GET:@"/source"] respondWithTarget:self action:@selector(handleGetSourceCommand:)]
// [[FBRoute GET:@"/source"].withoutSession
tmp, _ := url.Parse(wd.concatURL(nil, "/session", wd.sessionID))
tmp, _ := url.Parse(wd.concatURL(nil, "/session", wd.ID))
toJsonRaw := false
if len(srcOpt) != 0 {
q := tmp.Query()
@@ -820,40 +814,40 @@ func (wd *WDADriver) Source(srcOpt ...option.SourceOption) (source string, err e
tmp.RawQuery = q.Encode()
}
var rawResp rawResponse
var rawResp DriverRawResponse
if rawResp, err = wd.httpRequest(http.MethodGet, wd.concatURL(tmp, "/source"), nil); err != nil {
return "", nil
}
if toJsonRaw {
var jr builtinJSON.RawMessage
if jr, err = rawResp.valueConvertToJsonRawMessage(); err != nil {
if jr, err = rawResp.ValueConvertToJsonRawMessage(); err != nil {
return "", err
}
return string(jr), nil
}
if source, err = rawResp.valueConvertToString(); err != nil {
if source, err = rawResp.ValueConvertToString(); err != nil {
return "", err
}
return
}
func (wd *WDADriver) TapByText(text string, opts ...option.ActionOption) error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (wd *WDADriver) TapByTexts(actions ...TapTextAction) error {
return errDriverNotImplemented
return types.ErrDriverNotImplemented
}
func (wd *WDADriver) AccessibleSource() (source string, err error) {
// [[FBRoute GET:@"/wda/accessibleSource"] respondWithTarget:self action:@selector(handleGetAccessibleSourceCommand:)]
// [[FBRoute GET:@"/wda/accessibleSource"].withoutSession
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/wda/accessibleSource"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/wda/accessibleSource"); err != nil {
return "", err
}
var jr builtinJSON.RawMessage
if jr, err = rawResp.valueConvertToJsonRawMessage(); err != nil {
if jr, err = rawResp.ValueConvertToJsonRawMessage(); err != nil {
return "", err
}
source = string(jr)
@@ -868,8 +862,8 @@ func (wd *WDADriver) HealthCheck() (err error) {
func (wd *WDADriver) GetAppiumSettings() (settings map[string]interface{}, err error) {
// [[FBRoute GET:@"/appium/settings"] respondWithTarget:self action:@selector(handleGetSettings:)]
var rawResp rawResponse
if rawResp, err = wd.httpGET("/session", wd.sessionID, "/appium/settings"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/session", wd.ID, "/appium/settings"); err != nil {
return nil, err
}
reply := new(struct{ Value map[string]interface{} })
@@ -883,8 +877,8 @@ func (wd *WDADriver) GetAppiumSettings() (settings map[string]interface{}, err e
func (wd *WDADriver) SetAppiumSettings(settings map[string]interface{}) (ret map[string]interface{}, err error) {
// [[FBRoute POST:@"/appium/settings"] respondWithTarget:self action:@selector(handleSetSettings:)]
data := map[string]interface{}{"settings": settings}
var rawResp rawResponse
if rawResp, err = wd.httpPOST(data, "/session", wd.sessionID, "/appium/settings"); err != nil {
var rawResp DriverRawResponse
if rawResp, err = wd.httpPOST(data, "/session", wd.ID, "/appium/settings"); err != nil {
return nil, err
}
reply := new(struct{ Value map[string]interface{} })
@@ -896,7 +890,7 @@ func (wd *WDADriver) SetAppiumSettings(settings map[string]interface{}) (ret map
}
func (wd *WDADriver) IsHealthy() (healthy bool, err error) {
var rawResp rawResponse
var rawResp DriverRawResponse
if rawResp, err = wd.httpGET("/health"); err != nil {
return false, err
}

View File

@@ -4,7 +4,6 @@ import "github.com/httprunner/httprunner/v5/pkg/gadb"
type AndroidDeviceOptions struct {
SerialNumber string `json:"serial,omitempty" yaml:"serial,omitempty"`
STUB bool `json:"stub,omitempty" yaml:"stub,omitempty"` // use stub
LogOn bool `json:"log_on,omitempty" yaml:"log_on,omitempty"`
// adb
@@ -23,9 +22,6 @@ func (dev *AndroidDeviceOptions) Options() (deviceOptions []AndroidDeviceOption)
if dev.SerialNumber != "" {
deviceOptions = append(deviceOptions, WithSerialNumber(dev.SerialNumber))
}
if dev.STUB {
deviceOptions = append(deviceOptions, WithStub(true))
}
if dev.UIA2 {
deviceOptions = append(deviceOptions, WithUIA2(true))
}
@@ -87,12 +83,6 @@ func NewAndroidDeviceOptions(opts ...AndroidDeviceOption) *AndroidDeviceOptions
type AndroidDeviceOption func(*AndroidDeviceOptions)
func WithDriverTypeADB() AndroidDeviceOption {
return func(device *AndroidDeviceOptions) {
device.STUB = false
}
}
func WithSerialNumber(serial string) AndroidDeviceOption {
return func(device *AndroidDeviceOptions) {
device.SerialNumber = serial
@@ -105,12 +95,6 @@ func WithUIA2(uia2On bool) AndroidDeviceOption {
}
}
func WithStub(stubOn bool) AndroidDeviceOption {
return func(device *AndroidDeviceOptions) {
device.STUB = stubOn
}
}
func WithUIA2IP(ip string) AndroidDeviceOption {
return func(device *AndroidDeviceOptions) {
device.UIA2IP = ip

View File

@@ -4,7 +4,6 @@ type IOSDeviceOptions struct {
UDID string `json:"udid,omitempty" yaml:"udid,omitempty"`
WDAPort int `json:"port,omitempty" yaml:"port,omitempty"` // WDA remote port
WDAMjpegPort int `json:"mjpeg_port,omitempty" yaml:"mjpeg_port,omitempty"` // WDA remote MJPEG port
STUB bool `json:"stub,omitempty" yaml:"stub,omitempty"` // use stub
LogOn bool `json:"log_on,omitempty" yaml:"log_on,omitempty"`
// switch to iOS springboard before init WDA session
@@ -26,9 +25,6 @@ func (dev *IOSDeviceOptions) Options() (deviceOptions []IOSDeviceOption) {
if dev.WDAMjpegPort != 0 {
deviceOptions = append(deviceOptions, WithWDAMjpegPort(dev.WDAMjpegPort))
}
if dev.STUB {
deviceOptions = append(deviceOptions, WithIOSStub(true))
}
if dev.LogOn {
deviceOptions = append(deviceOptions, WithWDALogOn(true))
}
@@ -123,12 +119,6 @@ func WithWDALogOn(logOn bool) IOSDeviceOption {
}
}
func WithIOSStub(stub bool) IOSDeviceOption {
return func(device *IOSDeviceOptions) {
device.STUB = stub
}
}
func WithResetHomeOnStartup(reset bool) IOSDeviceOption {
return func(device *IOSDeviceOptions) {
device.ResetHomeOnStartup = reset

5
pkg/uixt/types/driver.go Normal file
View File

@@ -0,0 +1,5 @@
package types
import "errors"
var ErrDriverNotImplemented = errors.New("driver method not implemented")