mirror of
https://github.com/httprunner/httprunner.git
synced 2026-08-25 01:59:52 +08:00
Merge pull request #1541 from httprunner/gadb
feat: run Android UI automation with adb by default, add `uixt.WithUIA2(true)` option to use uiautomator2
This commit is contained in:
@@ -1,5 +1,14 @@
|
|||||||
# Release History
|
# Release History
|
||||||
|
|
||||||
|
## v4.3.2 (2022-12-26)
|
||||||
|
|
||||||
|
**go version**
|
||||||
|
|
||||||
|
- feat: run Android UI automation with adb by default, add `uixt.WithUIA2(true)` option to use uiautomator2
|
||||||
|
- refactor: remove unused APIs in UI automation
|
||||||
|
- refactor: convert cases by specifying from/to format
|
||||||
|
- change: remove traceroute/curl sub commands
|
||||||
|
|
||||||
## v4.3.1 (2022-12-22)
|
## v4.3.1 (2022-12-22)
|
||||||
|
|
||||||
**go version**
|
**go version**
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
func TestAndroidDouYinLive(t *testing.T) {
|
func TestAndroidDouYinLive(t *testing.T) {
|
||||||
testCase := &hrp.TestCase{
|
testCase := &hrp.TestCase{
|
||||||
Config: hrp.NewConfig("通过 feed 头像进入抖音直播间").
|
Config: hrp.NewConfig("通过 feed 头像进入抖音直播间").
|
||||||
SetAndroid(uixt.WithAdbLogOn(true)),
|
SetAndroid(uixt.WithUIA2(false), uixt.WithAdbLogOn(true)),
|
||||||
TestSteps: []hrp.IStep{
|
TestSteps: []hrp.IStep{
|
||||||
hrp.NewStep("启动抖音").
|
hrp.NewStep("启动抖音").
|
||||||
Android().
|
Android().
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v4.3.1
|
v4.3.2
|
||||||
@@ -4,10 +4,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
const AdbServerPort = 5037
|
const (
|
||||||
const AdbDaemonPort = 5555
|
AdbServerPort = 5037
|
||||||
|
AdbDaemonPort = 5555
|
||||||
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
host string
|
host string
|
||||||
@@ -86,7 +90,7 @@ func (c Client) DeviceList() (devices []Device, err error) {
|
|||||||
|
|
||||||
fields := strings.Fields(line)
|
fields := strings.Fields(line)
|
||||||
if len(fields) < 5 || len(fields[0]) == 0 {
|
if len(fields) < 5 || len(fields[0]) == 0 {
|
||||||
debugLog(fmt.Sprintf("can't parse: %s", line))
|
log.Error().Str("line", line).Msg("get unexpected line")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestClient_ServerVersion(t *testing.T) {
|
func TestClient_ServerVersion(t *testing.T) {
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
adbClient, err := NewClient()
|
adbClient, err := NewClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -23,8 +21,6 @@ func TestClient_ServerVersion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestClient_DeviceSerialList(t *testing.T) {
|
func TestClient_DeviceSerialList(t *testing.T) {
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
adbClient, err := NewClient()
|
adbClient, err := NewClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -41,8 +37,6 @@ func TestClient_DeviceSerialList(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestClient_DeviceList(t *testing.T) {
|
func TestClient_DeviceList(t *testing.T) {
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
adbClient, err := NewClient()
|
adbClient, err := NewClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -59,8 +53,6 @@ func TestClient_DeviceList(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestClient_ForwardList(t *testing.T) {
|
func TestClient_ForwardList(t *testing.T) {
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
adbClient, err := NewClient()
|
adbClient, err := NewClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -77,8 +69,6 @@ func TestClient_ForwardList(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestClient_ForwardKillAll(t *testing.T) {
|
func TestClient_ForwardKillAll(t *testing.T) {
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
adbClient, err := NewClient()
|
adbClient, err := NewClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -96,8 +86,6 @@ func TestClient_Connect(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
err = adbClient.Connect("192.168.1.28")
|
err = adbClient.Connect("192.168.1.28")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -110,8 +98,6 @@ func TestClient_Disconnect(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
err = adbClient.Disconnect("192.168.1.28")
|
err = adbClient.Disconnect("192.168.1.28")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -124,8 +110,6 @@ func TestClient_DisconnectAll(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
err = adbClient.DisconnectAll()
|
err = adbClient.DisconnectAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -133,8 +117,6 @@ func TestClient_DisconnectAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestClient_KillServer(t *testing.T) {
|
func TestClient_KillServer(t *testing.T) {
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
adbClient, err := NewClient()
|
adbClient, err := NewClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeviceFileInfo struct {
|
type DeviceFileInfo struct {
|
||||||
@@ -20,7 +22,7 @@ func (info DeviceFileInfo) IsDir() bool {
|
|||||||
return (info.Mode & (1 << 14)) == (1 << 14)
|
return (info.Mode & (1 << 14)) == (1 << 14)
|
||||||
}
|
}
|
||||||
|
|
||||||
const DefaultFileMode = os.FileMode(0664)
|
const DefaultFileMode = os.FileMode(0o664)
|
||||||
|
|
||||||
type DeviceState string
|
type DeviceState string
|
||||||
|
|
||||||
@@ -147,6 +149,9 @@ func (d Device) RunShellCommandWithBytes(cmd string, args ...string) ([]byte, er
|
|||||||
if strings.TrimSpace(cmd) == "" {
|
if strings.TrimSpace(cmd) == "" {
|
||||||
return nil, errors.New("adb shell: command cannot be empty")
|
return nil, errors.New("adb shell: command cannot be empty")
|
||||||
}
|
}
|
||||||
|
log.Debug().Str("cmd",
|
||||||
|
fmt.Sprintf("adb -s %s shell %s", d.serial, cmd)).
|
||||||
|
Msg("run adb command")
|
||||||
raw, err := d.executeCommand(fmt.Sprintf("shell:%s", cmd))
|
raw, err := d.executeCommand(fmt.Sprintf("shell:%s", cmd))
|
||||||
return raw, err
|
return raw, err
|
||||||
}
|
}
|
||||||
@@ -156,6 +161,9 @@ func (d Device) EnableAdbOverTCP(port ...int) (err error) {
|
|||||||
port = []int{AdbDaemonPort}
|
port = []int{AdbDaemonPort}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info().Str("cmd",
|
||||||
|
fmt.Sprintf("adb -s %s tcpip %d", d.serial, port[0])).
|
||||||
|
Msg("enable adb over tcp")
|
||||||
_, err = d.executeCommand(fmt.Sprintf("tcpip:%d", port[0]), true)
|
_, err = d.executeCommand(fmt.Sprintf("tcpip:%d", port[0]), true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,6 @@ func TestDevice_Usb(t *testing.T) {
|
|||||||
dev := devices[i]
|
dev := devices[i]
|
||||||
t.Log(dev.Serial(), dev.Usb(), dev.IsUsb())
|
t.Log(dev.Serial(), dev.Usb(), dev.IsUsb())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDevice_DeviceInfo(t *testing.T) {
|
func TestDevice_DeviceInfo(t *testing.T) {
|
||||||
@@ -134,8 +133,6 @@ func TestDevice_Forward(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
localPort := 61000
|
localPort := 61000
|
||||||
err = devices[0].Forward(localPort, 6790)
|
err = devices[0].Forward(localPort, 6790)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -159,8 +156,6 @@ func TestDevice_ForwardList(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
for i := range devices {
|
for i := range devices {
|
||||||
dev := devices[i]
|
dev := devices[i]
|
||||||
forwardList, err := dev.ForwardList()
|
forwardList, err := dev.ForwardList()
|
||||||
@@ -182,8 +177,6 @@ func TestDevice_ForwardKill(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
err = devices[0].ForwardKill(6790)
|
err = devices[0].ForwardKill(6790)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -213,8 +206,6 @@ func TestDevice_RunShellCommand(t *testing.T) {
|
|||||||
// t.Log("\n"+dev.serial, cmdOutput)
|
// t.Log("\n"+dev.serial, cmdOutput)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// SetDebug(true)
|
|
||||||
|
|
||||||
dev := devices[len(devices)-1]
|
dev := devices[len(devices)-1]
|
||||||
dev = devices[0]
|
dev = devices[0]
|
||||||
|
|
||||||
@@ -225,7 +216,6 @@ func TestDevice_RunShellCommand(t *testing.T) {
|
|||||||
t.Fatal(dev.serial, err)
|
t.Fatal(dev.serial, err)
|
||||||
}
|
}
|
||||||
t.Log("\n⬇️"+dev.serial+"⬇️\n", cmdOutput)
|
t.Log("\n⬇️"+dev.serial+"⬇️\n", cmdOutput)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDevice_EnableAdbOverTCP(t *testing.T) {
|
func TestDevice_EnableAdbOverTCP(t *testing.T) {
|
||||||
@@ -242,8 +232,6 @@ func TestDevice_EnableAdbOverTCP(t *testing.T) {
|
|||||||
dev := devices[len(devices)-1]
|
dev := devices[len(devices)-1]
|
||||||
dev = devices[0]
|
dev = devices[0]
|
||||||
|
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
err = dev.EnableAdbOverTCP()
|
err = dev.EnableAdbOverTCP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -264,8 +252,6 @@ func TestDevice_List(t *testing.T) {
|
|||||||
dev := devices[len(devices)-1]
|
dev := devices[len(devices)-1]
|
||||||
dev = devices[0]
|
dev = devices[0]
|
||||||
|
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
// fileEntries, err := dev.List("/sdcard")
|
// fileEntries, err := dev.List("/sdcard")
|
||||||
fileEntries, err := dev.List("/sdcard/Download")
|
fileEntries, err := dev.List("/sdcard/Download")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -291,8 +277,6 @@ func TestDevice_Push(t *testing.T) {
|
|||||||
dev := devices[len(devices)-1]
|
dev := devices[len(devices)-1]
|
||||||
dev = devices[0]
|
dev = devices[0]
|
||||||
|
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
file, _ := os.Open("/Users/hero/Documents/temp/MuMu共享文件夹/test.txt")
|
file, _ := os.Open("/Users/hero/Documents/temp/MuMu共享文件夹/test.txt")
|
||||||
err = dev.PushFile(file, "/sdcard/Download/push.txt", time.Now())
|
err = dev.PushFile(file, "/sdcard/Download/push.txt", time.Now())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -319,8 +303,6 @@ func TestDevice_Pull(t *testing.T) {
|
|||||||
dev := devices[len(devices)-1]
|
dev := devices[len(devices)-1]
|
||||||
dev = devices[0]
|
dev = devices[0]
|
||||||
|
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
buffer := bytes.NewBufferString("")
|
buffer := bytes.NewBufferString("")
|
||||||
err = dev.Pull("/sdcard/Download/hello.txt", buffer)
|
err = dev.Pull("/sdcard/Download/hello.txt", buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
package gadb
|
|
||||||
|
|
||||||
import "log"
|
|
||||||
|
|
||||||
var debugFlag = false
|
|
||||||
|
|
||||||
// SetDebug set debug mode
|
|
||||||
func SetDebug(debug bool) {
|
|
||||||
debugFlag = debug
|
|
||||||
}
|
|
||||||
|
|
||||||
func debugLog(msg string) {
|
|
||||||
if !debugFlag {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Println("[DEBUG] [gadb] " + msg)
|
|
||||||
}
|
|
||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type syncTransport struct {
|
type syncTransport struct {
|
||||||
@@ -29,7 +31,7 @@ func (sync syncTransport) Send(command, data string) (err error) {
|
|||||||
}
|
}
|
||||||
msg.WriteString(data)
|
msg.WriteString(data)
|
||||||
|
|
||||||
debugLog(fmt.Sprintf("--> %s", msg.String()))
|
log.Debug().Str("msg", msg.String()).Msg("sync run adb command")
|
||||||
return _send(sync.sock, msg.Bytes())
|
return _send(sync.sock, msg.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +58,7 @@ func (sync syncTransport) SendStatus(statusCode string, n uint32) (err error) {
|
|||||||
if err = binary.Write(msg, binary.LittleEndian, n); err != nil {
|
if err = binary.Write(msg, binary.LittleEndian, n); err != nil {
|
||||||
return fmt.Errorf("sync transport write: %w", err)
|
return fmt.Errorf("sync transport write: %w", err)
|
||||||
}
|
}
|
||||||
debugLog(fmt.Sprintf("--> %s", msg.String()))
|
log.Debug().Str("msg", msg.String()).Msg("sync send adb status")
|
||||||
return _send(sync.sock, msg.Bytes())
|
return _send(sync.sock, msg.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +67,6 @@ func (sync syncTransport) sendChunk(buffer []byte) (err error) {
|
|||||||
if err = binary.Write(msg, binary.LittleEndian, int32(len(buffer))); err != nil {
|
if err = binary.Write(msg, binary.LittleEndian, int32(len(buffer))); err != nil {
|
||||||
return fmt.Errorf("sync transport write: %w", err)
|
return fmt.Errorf("sync transport write: %w", err)
|
||||||
}
|
}
|
||||||
debugLog(fmt.Sprintf("--> %s ......", msg.String()))
|
|
||||||
msg.Write(buffer)
|
msg.Write(buffer)
|
||||||
return _send(sync.sock, msg.Bytes())
|
return _send(sync.sock, msg.Bytes())
|
||||||
}
|
}
|
||||||
@@ -76,22 +77,22 @@ func (sync syncTransport) VerifyStatus() (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log := bytes.NewBufferString(fmt.Sprintf("<-- %s", status))
|
logs := bytes.NewBufferString(fmt.Sprintf("<-- %s", status))
|
||||||
defer func() {
|
defer func() {
|
||||||
debugLog(log.String())
|
fmt.Println(logs.String())
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var tmpUint32 uint32
|
var tmpUint32 uint32
|
||||||
if tmpUint32, err = sync.ReadUint32(); err != nil {
|
if tmpUint32, err = sync.ReadUint32(); err != nil {
|
||||||
return fmt.Errorf("sync transport read (status): %w", err)
|
return fmt.Errorf("sync transport read (status): %w", err)
|
||||||
}
|
}
|
||||||
log.WriteString(fmt.Sprintf(" %d\t", tmpUint32))
|
logs.WriteString(fmt.Sprintf(" %d\t", tmpUint32))
|
||||||
|
|
||||||
var msg string
|
var msg string
|
||||||
if msg, err = sync.ReadStringN(int(tmpUint32)); err != nil {
|
if msg, err = sync.ReadStringN(int(tmpUint32)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.WriteString(msg)
|
logs.WriteString(msg)
|
||||||
|
|
||||||
if status == "FAIL" {
|
if status == "FAIL" {
|
||||||
err = fmt.Errorf("sync verify status (fail): %s", msg)
|
err = fmt.Errorf("sync verify status (fail): %s", msg)
|
||||||
@@ -139,8 +140,10 @@ func (sync syncTransport) readChunk() (chunk []byte, err error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log := bytes.NewBufferString("")
|
logs := bytes.NewBufferString("")
|
||||||
defer func() { debugLog(log.String()) }()
|
defer func() {
|
||||||
|
fmt.Println(logs.String())
|
||||||
|
}()
|
||||||
|
|
||||||
var tmpUint32 uint32
|
var tmpUint32 uint32
|
||||||
if tmpUint32, err = sync.ReadUint32(); err != nil {
|
if tmpUint32, err = sync.ReadUint32(); err != nil {
|
||||||
@@ -148,35 +151,34 @@ func (sync syncTransport) readChunk() (chunk []byte, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if status == "FAIL" {
|
if status == "FAIL" {
|
||||||
log.WriteString(fmt.Sprintf("<-- %s\t%d\t", status, tmpUint32))
|
logs.WriteString(fmt.Sprintf("<-- %s\t%d\t", status, tmpUint32))
|
||||||
var sError string
|
var sError string
|
||||||
if sError, err = sync.ReadStringN(int(tmpUint32)); err != nil {
|
if sError, err = sync.ReadStringN(int(tmpUint32)); err != nil {
|
||||||
return nil, fmt.Errorf("read chunk (error message): %w", err)
|
return nil, fmt.Errorf("read chunk (error message): %w", err)
|
||||||
}
|
}
|
||||||
err = fmt.Errorf("status (fail): %s", sError)
|
err = fmt.Errorf("status (fail): %s", sError)
|
||||||
log.WriteString(sError)
|
logs.WriteString(sError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch status {
|
switch status {
|
||||||
case "DONE":
|
case "DONE":
|
||||||
log.WriteString(fmt.Sprintf("<-- %s", status))
|
logs.WriteString(fmt.Sprintf("<-- %s", status))
|
||||||
err = syncReadChunkDone
|
err = syncReadChunkDone
|
||||||
return
|
return
|
||||||
case "DATA":
|
case "DATA":
|
||||||
log.WriteString(fmt.Sprintf("<-- %s\t%d\t", status, tmpUint32))
|
logs.WriteString(fmt.Sprintf("<-- %s\t%d\t", status, tmpUint32))
|
||||||
if chunk, err = sync.ReadBytesN(int(tmpUint32)); err != nil {
|
if chunk, err = sync.ReadBytesN(int(tmpUint32)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
log.WriteString(fmt.Sprintf("<-- %s\t%d\t", status, tmpUint32))
|
logs.WriteString(fmt.Sprintf("<-- %s\t%d\t", status, tmpUint32))
|
||||||
err = errors.New("unknown error")
|
err = errors.New("unknown error")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.WriteString("......")
|
logs.WriteString("......")
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sync syncTransport) ReadDirectoryEntry() (entry DeviceFileInfo, err error) {
|
func (sync syncTransport) ReadDirectoryEntry() (entry DeviceFileInfo, err error) {
|
||||||
@@ -185,43 +187,43 @@ func (sync syncTransport) ReadDirectoryEntry() (entry DeviceFileInfo, err error)
|
|||||||
return DeviceFileInfo{}, err
|
return DeviceFileInfo{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log := bytes.NewBufferString(fmt.Sprintf("<-- %s", status))
|
logs := bytes.NewBufferString(fmt.Sprintf("<-- %s", status))
|
||||||
defer func() {
|
defer func() {
|
||||||
debugLog(log.String())
|
fmt.Println(logs.String())
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if status == "DONE" {
|
if status == "DONE" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log = bytes.NewBufferString(fmt.Sprintf("<-- %s\t", status))
|
logs = bytes.NewBufferString(fmt.Sprintf("<-- %s\t", status))
|
||||||
|
|
||||||
if err = binary.Read(sync.sock, binary.LittleEndian, &entry.Mode); err != nil {
|
if err = binary.Read(sync.sock, binary.LittleEndian, &entry.Mode); err != nil {
|
||||||
return DeviceFileInfo{}, fmt.Errorf("sync transport read (mode): %w", err)
|
return DeviceFileInfo{}, fmt.Errorf("sync transport read (mode): %w", err)
|
||||||
}
|
}
|
||||||
log.WriteString(entry.Mode.String() + "\t")
|
logs.WriteString(entry.Mode.String() + "\t")
|
||||||
|
|
||||||
if entry.Size, err = sync.ReadUint32(); err != nil {
|
if entry.Size, err = sync.ReadUint32(); err != nil {
|
||||||
return DeviceFileInfo{}, fmt.Errorf("sync transport read (size): %w", err)
|
return DeviceFileInfo{}, fmt.Errorf("sync transport read (size): %w", err)
|
||||||
}
|
}
|
||||||
log.WriteString(fmt.Sprintf("%10d", entry.Size) + "\t")
|
logs.WriteString(fmt.Sprintf("%10d", entry.Size) + "\t")
|
||||||
|
|
||||||
var tmpUint32 uint32
|
var tmpUint32 uint32
|
||||||
if tmpUint32, err = sync.ReadUint32(); err != nil {
|
if tmpUint32, err = sync.ReadUint32(); err != nil {
|
||||||
return DeviceFileInfo{}, fmt.Errorf("sync transport read (time): %w", err)
|
return DeviceFileInfo{}, fmt.Errorf("sync transport read (time): %w", err)
|
||||||
}
|
}
|
||||||
entry.LastModified = time.Unix(int64(tmpUint32), 0)
|
entry.LastModified = time.Unix(int64(tmpUint32), 0)
|
||||||
log.WriteString(entry.LastModified.String() + "\t")
|
logs.WriteString(entry.LastModified.String() + "\t")
|
||||||
|
|
||||||
if tmpUint32, err = sync.ReadUint32(); err != nil {
|
if tmpUint32, err = sync.ReadUint32(); err != nil {
|
||||||
return DeviceFileInfo{}, fmt.Errorf("sync transport read (file name length): %w", err)
|
return DeviceFileInfo{}, fmt.Errorf("sync transport read (file name length): %w", err)
|
||||||
}
|
}
|
||||||
log.WriteString(fmt.Sprintf("%d\t", tmpUint32))
|
logs.WriteString(fmt.Sprintf("%d\t", tmpUint32))
|
||||||
|
|
||||||
if entry.Name, err = sync.ReadStringN(int(tmpUint32)); err != nil {
|
if entry.Name, err = sync.ReadStringN(int(tmpUint32)); err != nil {
|
||||||
return DeviceFileInfo{}, fmt.Errorf("sync transport read (file name): %w", err)
|
return DeviceFileInfo{}, fmt.Errorf("sync transport read (file name): %w", err)
|
||||||
}
|
}
|
||||||
log.WriteString(entry.Name + "\t")
|
logs.WriteString(entry.Name + "\t")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrConnBroken = errors.New("socket connection broken")
|
var ErrConnBroken = errors.New("socket connection broken")
|
||||||
@@ -32,7 +34,6 @@ func newTransport(address string, readTimeout ...time.Duration) (tp transport, e
|
|||||||
|
|
||||||
func (t transport) Send(command string) (err error) {
|
func (t transport) Send(command string) (err error) {
|
||||||
msg := fmt.Sprintf("%04x%s", len(command), command)
|
msg := fmt.Sprintf("%04x%s", len(command), command)
|
||||||
debugLog(fmt.Sprintf("--> %s", command))
|
|
||||||
return _send(t.sock, []byte(msg))
|
return _send(t.sock, []byte(msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +43,6 @@ func (t transport) VerifyResponse() (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if status == "OKAY" {
|
if status == "OKAY" {
|
||||||
debugLog(fmt.Sprintf("<-- %s", status))
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ func (t transport) VerifyResponse() (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = fmt.Errorf("command failed: %s", sError)
|
err = fmt.Errorf("command failed: %s", sError)
|
||||||
debugLog(fmt.Sprintf("<-- %s %s", status, sError))
|
log.Error().Str("status", status).Str("err", sError).Msg("verify adb response failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,6 @@ func (t transport) ReadStringAll() (s string, err error) {
|
|||||||
|
|
||||||
func (t transport) ReadBytesAll() (raw []byte, err error) {
|
func (t transport) ReadBytesAll() (raw []byte, err error) {
|
||||||
raw, err = ioutil.ReadAll(t.sock)
|
raw, err = ioutil.ReadAll(t.sock)
|
||||||
debugLog(fmt.Sprintf("\r%s", raw))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +83,6 @@ func (t transport) UnpackBytes() (raw []byte, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
raw, err = t.ReadBytesN(int(size))
|
raw, err = t.ReadBytesN(int(size))
|
||||||
debugLog(fmt.Sprintf("\r%s", raw))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Test_transport_VerifyResponse(t *testing.T) {
|
func Test_transport_VerifyResponse(t *testing.T) {
|
||||||
SetDebug(true)
|
|
||||||
|
|
||||||
transport, err := newTransport("localhost:5037")
|
transport, err := newTransport("localhost:5037")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
337
hrp/pkg/uixt/android_adb_driver.go
Normal file
337
hrp/pkg/uixt/android_adb_driver.go
Normal file
@@ -0,0 +1,337 @@
|
|||||||
|
package uixt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp/internal/code"
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp/pkg/gadb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type adbDriver struct {
|
||||||
|
Driver
|
||||||
|
|
||||||
|
adbClient gadb.Device
|
||||||
|
logcat *AdbLogcat
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAdbDriver() *adbDriver {
|
||||||
|
log.Info().Msg("init adb driver")
|
||||||
|
return &adbDriver{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) NewSession(capabilities Capabilities) (sessionInfo SessionInfo, err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) DeleteSession() (err error) {
|
||||||
|
return errDriverNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) Status() (deviceStatus DeviceStatus, err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) DeviceInfo() (deviceInfo DeviceInfo, err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) Location() (location Location, err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) BatteryInfo() (batteryInfo BatteryInfo, err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) WindowSize() (size Size, err error) {
|
||||||
|
// adb shell wm size
|
||||||
|
resp, err := ad.adbClient.RunShellCommand("wm", "size")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Physical size: 1080x2340
|
||||||
|
s := strings.Trim(strings.Split(resp, ": ")[1], "\n")
|
||||||
|
ss := strings.Split(s, "x")
|
||||||
|
width, _ := strconv.Atoi(ss[0])
|
||||||
|
height, _ := strconv.Atoi(ss[1])
|
||||||
|
size = Size{Width: width, Height: height}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) Screen() (screen Screen, err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) Scale() (scale float64, err error) {
|
||||||
|
return 1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PressBack simulates a short press on the BACK button.
|
||||||
|
func (ad *adbDriver) PressBack(options ...DataOption) (err error) {
|
||||||
|
// adb shell input keyevent 4
|
||||||
|
_, err = ad.adbClient.RunShellCommand("input", "keyevent", fmt.Sprintf("%d", KCBack))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) StartCamera() (err error) {
|
||||||
|
if _, err = ad.adbClient.RunShellCommand("rm", "-r", "/sdcard/DCIM/Camera"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
var version string
|
||||||
|
if version, err = ad.adbClient.RunShellCommand("getprop", "ro.build.version.release"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if version == "11" || version == "12" {
|
||||||
|
if _, err = ad.adbClient.RunShellCommand("am", "start", "-a", "android.media.action.STILL_IMAGE_CAMERA"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
if _, err = ad.adbClient.RunShellCommand("input", "swipe", "750", "1000", "250", "1000"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
if _, err = ad.adbClient.RunShellCommand("input", "keyevent", fmt.Sprintf("%d", KCCamera)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
if _, err = ad.adbClient.RunShellCommand("am", "start", "-a", "android.media.action.VIDEO_CAPTURE"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
if _, err = ad.adbClient.RunShellCommand("input", "keyevent", fmt.Sprintf("%d", KCCamera)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) StopCamera() (err error) {
|
||||||
|
err = ad.PressBack()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ad.Homescreen()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// kill samsung shell command
|
||||||
|
if _, err = ad.AppTerminate("com.sec.android.app.camera"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// kill other camera (huawei mi)
|
||||||
|
if _, err = ad.AppTerminate("com.android.camera2"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) Homescreen() (err error) {
|
||||||
|
return ad.PressKeyCode(KCHome, KMEmpty)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) PressKeyCode(keyCode KeyCode, metaState KeyMeta) (err error) {
|
||||||
|
// adb shell input keyevent <keyCode>
|
||||||
|
_, err = ad.adbClient.RunShellCommand(
|
||||||
|
"input", "keyevent", fmt.Sprintf("%d", keyCode))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) AppLaunch(bundleId string) (err error) {
|
||||||
|
// 不指定 Activity 名称启动(启动主 Activity)
|
||||||
|
// adb shell monkey -p <packagename> -c android.intent.category.LAUNCHER 1
|
||||||
|
sOutput, err := ad.adbClient.RunShellCommand(
|
||||||
|
"monkey", "-p", bundleId, "-c", "android.intent.category.LAUNCHER", "1",
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if strings.Contains(sOutput, "monkey aborted") {
|
||||||
|
return fmt.Errorf("app launch: %s", strings.TrimSpace(sOutput))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) AppTerminate(bundleId string) (successful bool, err error) {
|
||||||
|
// 强制停止应用,停止 <packagename> 相关的进程
|
||||||
|
// adb shell am force-stop <packagename>
|
||||||
|
_, err = ad.adbClient.RunShellCommand("am", "force-stop", bundleId)
|
||||||
|
return err == nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) Tap(x, y int, options ...DataOption) error {
|
||||||
|
return ad.TapFloat(float64(x), float64(y), options...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) TapFloat(x, y float64, options ...DataOption) (err error) {
|
||||||
|
// adb shell input tap x y
|
||||||
|
_, err = ad.adbClient.RunShellCommand(
|
||||||
|
"input", "tap", fmt.Sprintf("%.1f", x), fmt.Sprintf("%.1f", y))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) DoubleTap(x, y int) error {
|
||||||
|
return ad.DoubleTapFloat(float64(x), float64(y))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) DoubleTapFloat(x, y float64) (err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) TouchAndHold(x, y int, second ...float64) (err error) {
|
||||||
|
return ad.TouchAndHoldFloat(float64(x), float64(y), second...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) TouchAndHoldFloat(x, y float64, second ...float64) (err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) Drag(fromX, fromY, toX, toY int, options ...DataOption) error {
|
||||||
|
return ad.DragFloat(float64(fromX), float64(fromY), float64(toX), float64(toY), options...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) DragFloat(fromX, fromY, toX, toY float64, options ...DataOption) (err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) Swipe(fromX, fromY, toX, toY int, options ...DataOption) error {
|
||||||
|
return ad.SwipeFloat(float64(fromX), float64(fromY), float64(toX), float64(toY), options...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) SwipeFloat(fromX, fromY, toX, toY float64, options ...DataOption) error {
|
||||||
|
// adb shell input swipe fromX fromY toX toY
|
||||||
|
_, err := ad.adbClient.RunShellCommand(
|
||||||
|
"input", "swipe",
|
||||||
|
fmt.Sprintf("%.1f", fromX), fmt.Sprintf("%.1f", fromY),
|
||||||
|
fmt.Sprintf("%.1f", toX), fmt.Sprintf("%.1f", toY),
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) ForceTouch(x, y int, pressure float64, second ...float64) error {
|
||||||
|
return ad.ForceTouchFloat(float64(x), float64(y), pressure, second...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) ForceTouchFloat(x, y, pressure float64, second ...float64) (err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) SetPasteboard(contentType PasteboardType, content string) (err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) GetPasteboard(contentType PasteboardType) (raw *bytes.Buffer, err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) SendKeys(text string, options ...DataOption) (err error) {
|
||||||
|
// adb shell input text <text>
|
||||||
|
_, err = ad.adbClient.RunShellCommand("input", "text", text)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) Input(text string, options ...DataOption) (err error) {
|
||||||
|
return ad.SendKeys(text, options...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) PressButton(devBtn DeviceButton) (err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) Rotation() (rotation Rotation, err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) SetRotation(rotation Rotation) (err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) Screenshot() (raw *bytes.Buffer, err error) {
|
||||||
|
// adb shell screencap -p
|
||||||
|
resp, err := ad.adbClient.RunShellCommandWithBytes(
|
||||||
|
"screencap", "-p",
|
||||||
|
)
|
||||||
|
if err == nil {
|
||||||
|
return bytes.NewBuffer(resp), nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) Source(srcOpt ...SourceOption) (source string, err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) AccessibleSource() (source string, err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) HealthCheck() (err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) GetAppiumSettings() (settings map[string]interface{}, err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) SetAppiumSettings(settings map[string]interface{}) (ret map[string]interface{}, err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) IsHealthy() (healthy bool, err error) {
|
||||||
|
err = errDriverNotImplemented
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) StartCaptureLog(identifier ...string) (err error) {
|
||||||
|
log.Info().Msg("start adb log recording")
|
||||||
|
err = ad.logcat.CatchLogcat()
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Wrap(code.AndroidCaptureLogError,
|
||||||
|
fmt.Sprintf("start adb log recording failed: %v", err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *adbDriver) StopCaptureLog() (result interface{}, err error) {
|
||||||
|
log.Info().Msg("stop adb log recording")
|
||||||
|
err = ad.logcat.Stop()
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("failed to get adb log recording")
|
||||||
|
err = errors.Wrap(code.AndroidCaptureLogError,
|
||||||
|
fmt.Sprintf("get adb log recording failed: %v", err))
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
content := ad.logcat.logBuffer.String()
|
||||||
|
return ConvertPoints(content), nil
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
AdbServerHost = "localhost"
|
AdbServerHost = "localhost"
|
||||||
AdbServerPort = gadb.AdbServerPort // 5037
|
AdbServerPort = gadb.AdbServerPort // 5037
|
||||||
|
UIA2ServerHost = "localhost"
|
||||||
UIA2ServerPort = 6790
|
UIA2ServerPort = 6790
|
||||||
DeviceTempPath = "/data/local/tmp"
|
DeviceTempPath = "/data/local/tmp"
|
||||||
)
|
)
|
||||||
@@ -34,15 +35,21 @@ func WithSerialNumber(serial string) AndroidDeviceOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithAdbIP(ip string) AndroidDeviceOption {
|
func WithUIA2(uia2On bool) AndroidDeviceOption {
|
||||||
return func(device *AndroidDevice) {
|
return func(device *AndroidDevice) {
|
||||||
device.IP = ip
|
device.UIA2 = uia2On
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithAdbPort(port int) AndroidDeviceOption {
|
func WithUIA2IP(ip string) AndroidDeviceOption {
|
||||||
return func(device *AndroidDevice) {
|
return func(device *AndroidDevice) {
|
||||||
device.Port = port
|
device.UIA2IP = ip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithUIA2Port(port int) AndroidDeviceOption {
|
||||||
|
return func(device *AndroidDevice) {
|
||||||
|
device.UIA2Port = port
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,11 +63,14 @@ func GetAndroidDeviceOptions(dev *AndroidDevice) (deviceOptions []AndroidDeviceO
|
|||||||
if dev.SerialNumber != "" {
|
if dev.SerialNumber != "" {
|
||||||
deviceOptions = append(deviceOptions, WithSerialNumber(dev.SerialNumber))
|
deviceOptions = append(deviceOptions, WithSerialNumber(dev.SerialNumber))
|
||||||
}
|
}
|
||||||
if dev.IP != "" {
|
if dev.UIA2 {
|
||||||
deviceOptions = append(deviceOptions, WithAdbIP(dev.IP))
|
deviceOptions = append(deviceOptions, WithUIA2(true))
|
||||||
}
|
}
|
||||||
if dev.Port != 0 {
|
if dev.UIA2IP != "" {
|
||||||
deviceOptions = append(deviceOptions, WithAdbPort(dev.Port))
|
deviceOptions = append(deviceOptions, WithUIA2IP(dev.UIA2IP))
|
||||||
|
}
|
||||||
|
if dev.UIA2Port != 0 {
|
||||||
|
deviceOptions = append(deviceOptions, WithUIA2Port(dev.UIA2Port))
|
||||||
}
|
}
|
||||||
if dev.LogOn {
|
if dev.LogOn {
|
||||||
deviceOptions = append(deviceOptions, WithAdbLogOn(true))
|
deviceOptions = append(deviceOptions, WithAdbLogOn(true))
|
||||||
@@ -81,8 +91,8 @@ func NewAndroidDevice(options ...AndroidDeviceOption) (device *AndroidDevice, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
device = &AndroidDevice{
|
device = &AndroidDevice{
|
||||||
Port: UIA2ServerPort,
|
UIA2IP: UIA2ServerHost,
|
||||||
IP: AdbServerHost,
|
UIA2Port: UIA2ServerPort,
|
||||||
}
|
}
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
option(device)
|
option(device)
|
||||||
@@ -118,9 +128,9 @@ type AndroidDevice struct {
|
|||||||
d gadb.Device
|
d gadb.Device
|
||||||
logcat *AdbLogcat
|
logcat *AdbLogcat
|
||||||
SerialNumber string `json:"serial,omitempty" yaml:"serial,omitempty"`
|
SerialNumber string `json:"serial,omitempty" yaml:"serial,omitempty"`
|
||||||
IP string `json:"ip,omitempty" yaml:"ip,omitempty"`
|
UIA2 bool `json:"uia2,omitempty" yaml:"uia2,omitempty"` // use uiautomator2
|
||||||
Port int `json:"port,omitempty" yaml:"port,omitempty"`
|
UIA2IP string `json:"uia2_ip,omitempty" yaml:"uia2_ip,omitempty"` // uiautomator2 server ip
|
||||||
MjpegPort int `json:"mjpeg_port,omitempty" yaml:"mjpeg_port,omitempty"`
|
UIA2Port int `json:"uia2_port,omitempty" yaml:"uia2_port,omitempty"` // uiautomator2 server port
|
||||||
LogOn bool `json:"log_on,omitempty" yaml:"log_on,omitempty"`
|
LogOn bool `json:"log_on,omitempty" yaml:"log_on,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +139,12 @@ func (dev *AndroidDevice) UUID() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dev *AndroidDevice) NewDriver(capabilities Capabilities) (driverExt *DriverExt, err error) {
|
func (dev *AndroidDevice) NewDriver(capabilities Capabilities) (driverExt *DriverExt, err error) {
|
||||||
driver, err := dev.NewUSBDriver(capabilities)
|
var driver WebDriver
|
||||||
|
if dev.UIA2 {
|
||||||
|
driver, err = dev.NewUSBDriver(capabilities)
|
||||||
|
} else {
|
||||||
|
driver, err = dev.NewAdbDriver()
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to init UIA driver")
|
return nil, errors.Wrap(err, "failed to init UIA driver")
|
||||||
}
|
}
|
||||||
@@ -155,8 +170,7 @@ func (dev *AndroidDevice) NewDriver(capabilities Capabilities) (driverExt *Drive
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewUSBDriver creates new client via USB connected device, this will also start a new session.
|
// NewUSBDriver creates new client via USB connected device, this will also start a new session.
|
||||||
// TODO: replace uiaDriver with WebDriver
|
func (dev *AndroidDevice) NewUSBDriver(capabilities Capabilities) (driver WebDriver, err error) {
|
||||||
func (dev *AndroidDevice) NewUSBDriver(capabilities Capabilities) (driver *uiaDriver, err error) {
|
|
||||||
var localPort int
|
var localPort int
|
||||||
if localPort, err = getFreePort(); err != nil {
|
if localPort, err = getFreePort(); err != nil {
|
||||||
return nil, errors.Wrap(code.AndroidDeviceUSBDriverError,
|
return nil, errors.Wrap(code.AndroidDeviceUSBDriverError,
|
||||||
@@ -168,28 +182,37 @@ func (dev *AndroidDevice) NewUSBDriver(capabilities Capabilities) (driver *uiaDr
|
|||||||
localPort, UIA2ServerPort, err))
|
localPort, UIA2ServerPort, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
rawURL := fmt.Sprintf("http://%s%d:6790/wd/hub", forwardToPrefix, localPort)
|
rawURL := fmt.Sprintf("http://%s%d:%d/wd/hub",
|
||||||
driver, err = NewUIADriver(capabilities, rawURL)
|
forwardToPrefix, localPort, UIA2ServerPort)
|
||||||
|
uiaDriver, err := NewUIADriver(capabilities, rawURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = dev.d.ForwardKill(localPort)
|
_ = dev.d.ForwardKill(localPort)
|
||||||
return nil, errors.Wrap(code.AndroidDeviceUSBDriverError, err.Error())
|
return nil, errors.Wrap(code.AndroidDeviceUSBDriverError, err.Error())
|
||||||
}
|
}
|
||||||
driver.adbDevice = dev.d
|
uiaDriver.adbClient = dev.d
|
||||||
driver.logcat = dev.logcat
|
uiaDriver.logcat = dev.logcat
|
||||||
driver.localPort = localPort
|
|
||||||
|
|
||||||
return driver, nil
|
return uiaDriver, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHTTPDriver creates new remote HTTP client, this will also start a new session.
|
// NewHTTPDriver creates new remote HTTP client, this will also start a new session.
|
||||||
// TODO: replace uiaDriver with WebDriver
|
func (dev *AndroidDevice) NewHTTPDriver(capabilities Capabilities) (driver WebDriver, err error) {
|
||||||
func (dev *AndroidDevice) NewHTTPDriver(capabilities Capabilities) (driver *uiaDriver, err error) {
|
rawURL := fmt.Sprintf("http://%s:%d/wd/hub", dev.UIA2IP, dev.UIA2Port)
|
||||||
rawURL := fmt.Sprintf("http://%s:%d/wd/hub", dev.IP, dev.Port)
|
uiaDriver, err := NewUIADriver(capabilities, rawURL)
|
||||||
if driver, err = NewUIADriver(capabilities, rawURL); err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
driver.adbDevice = dev.d
|
|
||||||
return driver, nil
|
uiaDriver.adbClient = dev.d
|
||||||
|
uiaDriver.logcat = dev.logcat
|
||||||
|
return uiaDriver, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dev *AndroidDevice) NewAdbDriver() (driver WebDriver, err error) {
|
||||||
|
adbDriver := NewAdbDriver()
|
||||||
|
adbDriver.adbClient = dev.d
|
||||||
|
adbDriver.logcat = dev.logcat
|
||||||
|
return adbDriver, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dev *AndroidDevice) StartPerf() error {
|
func (dev *AndroidDevice) StartPerf() error {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package uixt
|
package uixt
|
||||||
|
|
||||||
|
// See https://developer.android.com/reference/android/view/KeyEvent
|
||||||
|
|
||||||
type KeyMeta int
|
type KeyMeta int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ func TestDriver_Quit(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = driver.Close(); err != nil {
|
if err = driver.DeleteSession(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,43 +66,6 @@ func TestDriver_Status(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDriver_SessionIDs(t *testing.T) {
|
|
||||||
driver, err := NewUIADriver(nil, uiaServerURL)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sessions, err := driver.SessionIDs()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if len(sessions) == 0 {
|
|
||||||
t.Fatal("should have at least one")
|
|
||||||
}
|
|
||||||
t.Log(len(sessions), sessions)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDriver_SessionDetails(t *testing.T) {
|
|
||||||
// firstMatchEntry := make(map[string]interface{})
|
|
||||||
// firstMatchEntry["package"] = "com.android.settings"
|
|
||||||
// firstMatchEntry["activity"] = "com.android.settings/.Settings"
|
|
||||||
// caps = Capabilities{
|
|
||||||
// "firstMatch": []interface{}{firstMatchEntry},
|
|
||||||
// "alwaysMatch": struct{}{},
|
|
||||||
// }
|
|
||||||
driver, err := NewUIADriver(nil, uiaServerURL)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
scrollData, err := driver.SessionDetails()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Log(scrollData)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDriver_Screenshot(t *testing.T) {
|
func TestDriver_Screenshot(t *testing.T) {
|
||||||
driver, err := NewUIADriver(nil, uiaServerURL)
|
driver, err := NewUIADriver(nil, uiaServerURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -372,17 +335,17 @@ func TestDeviceList(t *testing.T) {
|
|||||||
|
|
||||||
func TestDriver_AppLaunch(t *testing.T) {
|
func TestDriver_AppLaunch(t *testing.T) {
|
||||||
device, _ := NewAndroidDevice()
|
device, _ := NewAndroidDevice()
|
||||||
driver, err := device.NewUSBDriver(nil)
|
driver, err := device.NewDriver(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = driver.AppLaunch("com.android.settings")
|
err = driver.Driver.AppLaunch("com.android.settings")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
raw, err := driver.Screenshot()
|
raw, err := driver.Driver.Screenshot()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -392,24 +355,24 @@ func TestDriver_AppLaunch(t *testing.T) {
|
|||||||
|
|
||||||
func TestDriver_KeepAlive(t *testing.T) {
|
func TestDriver_KeepAlive(t *testing.T) {
|
||||||
device, _ := NewAndroidDevice()
|
device, _ := NewAndroidDevice()
|
||||||
driver, err := device.NewUSBDriver(nil)
|
driver, err := device.NewDriver(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = driver.AppLaunch("com.android.settings")
|
err = driver.Driver.AppLaunch("com.android.settings")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = driver.Screenshot()
|
_, err = driver.Driver.Screenshot()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(60 * time.Second)
|
time.Sleep(60 * time.Second)
|
||||||
|
|
||||||
_, err = driver.Screenshot()
|
_, err = driver.Driver.Screenshot()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -417,12 +380,12 @@ func TestDriver_KeepAlive(t *testing.T) {
|
|||||||
|
|
||||||
func TestDriver_AppTerminate(t *testing.T) {
|
func TestDriver_AppTerminate(t *testing.T) {
|
||||||
device, _ := NewAndroidDevice()
|
device, _ := NewAndroidDevice()
|
||||||
driver, err := device.NewUSBDriver(nil)
|
driver, err := device.NewDriver(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = driver.AppTerminate("tv.danmaku.bili")
|
_, err = driver.Driver.AppTerminate("tv.danmaku.bili")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,37 +9,21 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/code"
|
"github.com/httprunner/httprunner/v4/hrp/internal/code"
|
||||||
"github.com/httprunner/httprunner/v4/hrp/pkg/gadb"
|
|
||||||
)
|
|
||||||
|
|
||||||
// See https://developer.android.com/reference/android/view/KeyEvent
|
|
||||||
const (
|
|
||||||
KEYCODE_BACK string = "4"
|
|
||||||
KEYCODE_CAMERA string = "27"
|
|
||||||
KEYCODE_ALT_LEFT string = "57"
|
|
||||||
KEYCODE_ALT_RIGHT string = "58"
|
|
||||||
KEYCODE_MENU string = "82"
|
|
||||||
KEYCODE_BREAK string = "121"
|
|
||||||
KEYCODE_ALL_APPS string = "284"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var errDriverNotImplemented = errors.New("driver method not implemented")
|
var errDriverNotImplemented = errors.New("driver method not implemented")
|
||||||
|
|
||||||
type uiaDriver struct {
|
type uiaDriver struct {
|
||||||
Driver
|
adbDriver
|
||||||
|
|
||||||
adbDevice gadb.Device
|
|
||||||
logcat *AdbLogcat
|
|
||||||
localPort int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUIADriver(capabilities Capabilities, urlPrefix string) (driver *uiaDriver, err error) {
|
func NewUIADriver(capabilities Capabilities, urlPrefix string) (driver *uiaDriver, err error) {
|
||||||
|
log.Info().Msg("init uiautomator2 driver")
|
||||||
if capabilities == nil {
|
if capabilities == nil {
|
||||||
capabilities = NewCapabilities()
|
capabilities = NewCapabilities()
|
||||||
}
|
}
|
||||||
@@ -60,12 +44,15 @@ func NewUIADriver(capabilities Capabilities, urlPrefix string) (driver *uiaDrive
|
|||||||
return nil, fmt.Errorf("adb forward: %w", err)
|
return nil, fmt.Errorf("adb forward: %w", err)
|
||||||
}
|
}
|
||||||
driver.client = convertToHTTPClient(conn)
|
driver.client = convertToHTTPClient(conn)
|
||||||
if session, err := driver.NewSession(capabilities); err != nil {
|
|
||||||
return nil, err
|
session, err := driver.NewSession(capabilities)
|
||||||
} else {
|
if err == nil {
|
||||||
driver.sessionId = session.SessionId
|
driver.sessionId = session.SessionId
|
||||||
|
} else {
|
||||||
|
log.Warn().Msg(
|
||||||
|
"create UIAutomator session failed, use adb driver instead")
|
||||||
}
|
}
|
||||||
return
|
return driver, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type BatteryStatus int
|
type BatteryStatus int
|
||||||
@@ -96,17 +83,6 @@ func (bs BatteryStatus) String() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) Close() (err error) {
|
|
||||||
if ud.sessionId == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if _, err = ud.httpDELETE("/session", ud.sessionId); err == nil {
|
|
||||||
ud.sessionId = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) NewSession(capabilities Capabilities) (sessionInfo SessionInfo, err error) {
|
func (ud *uiaDriver) NewSession(capabilities Capabilities) (sessionInfo SessionInfo, err error) {
|
||||||
// register(postHandler, new NewSession("/wd/hub/session"))
|
// register(postHandler, new NewSession("/wd/hub/session"))
|
||||||
var rawResp rawResponse
|
var rawResp rawResponse
|
||||||
@@ -123,47 +99,15 @@ func (ud *uiaDriver) NewSession(capabilities Capabilities) (sessionInfo SessionI
|
|||||||
return SessionInfo{SessionId: sessionID}, nil
|
return SessionInfo{SessionId: sessionID}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) ActiveSession() (sessionInfo SessionInfo, err error) {
|
|
||||||
// [[FBRoute GET:@""] respondWithTarget:self action:@selector(handleGetActiveSession:)]
|
|
||||||
return SessionInfo{SessionId: ud.sessionId}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) SessionIDs() (sessionIDs []string, err error) {
|
|
||||||
// register(getHandler, new GetSessions("/wd/hub/sessions"))
|
|
||||||
var rawResp rawResponse
|
|
||||||
if rawResp, err = ud.httpGET("/sessions"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
reply := new(struct{ Value []struct{ SessionId string } })
|
|
||||||
if err = json.Unmarshal(rawResp, reply); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionIDs = make([]string, len(reply.Value))
|
|
||||||
for i := range reply.Value {
|
|
||||||
sessionIDs[i] = reply.Value[i].SessionId
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) SessionDetails() (scrollData map[string]interface{}, err error) {
|
|
||||||
// register(getHandler, new GetSessionDetails("/wd/hub/session/:sessionId"))
|
|
||||||
var rawResp rawResponse
|
|
||||||
if rawResp, err = ud.httpGET("/session", ud.sessionId); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
reply := new(struct{ Value map[string]interface{} })
|
|
||||||
if err = json.Unmarshal(rawResp, reply); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
scrollData = reply.Value
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) DeleteSession() (err error) {
|
func (ud *uiaDriver) DeleteSession() (err error) {
|
||||||
// TODO
|
if ud.sessionId == "" {
|
||||||
return errDriverNotImplemented
|
return nil
|
||||||
|
}
|
||||||
|
if _, err = ud.httpDELETE("/session", ud.sessionId); err == nil {
|
||||||
|
ud.sessionId = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) Status() (deviceStatus DeviceStatus, err error) {
|
func (ud *uiaDriver) Status() (deviceStatus DeviceStatus, err error) {
|
||||||
@@ -198,11 +142,6 @@ func (ud *uiaDriver) DeviceInfo() (deviceInfo DeviceInfo, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) Location() (location Location, err error) {
|
|
||||||
// TODO
|
|
||||||
return location, errDriverNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) BatteryInfo() (batteryInfo BatteryInfo, err error) {
|
func (ud *uiaDriver) BatteryInfo() (batteryInfo BatteryInfo, err error) {
|
||||||
// register(getHandler, new GetBatteryInfo("/wd/hub/session/:sessionId/appium/device/battery_info"))
|
// register(getHandler, new GetBatteryInfo("/wd/hub/session/:sessionId/appium/device/battery_info"))
|
||||||
var rawResp rawResponse
|
var rawResp rawResponse
|
||||||
@@ -234,78 +173,10 @@ func (ud *uiaDriver) WindowSize() (size Size, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) Screen() (screen Screen, err error) {
|
|
||||||
// TODO
|
|
||||||
return screen, errDriverNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) Scale() (scale float64, err error) {
|
|
||||||
return 1, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PressBack simulates a short press on the BACK button.
|
// PressBack simulates a short press on the BACK button.
|
||||||
func (ud *uiaDriver) PressBack(options ...DataOption) (err error) {
|
func (ud *uiaDriver) PressBack(options ...DataOption) (err error) {
|
||||||
// register(postHandler, new PressBack("/wd/hub/session/:sessionId/back"))
|
// register(postHandler, new PressBack("/wd/hub/session/:sessionId/back"))
|
||||||
_, err = ud.httpPOST(nil, "/session", ud.sessionId, "back")
|
_, err = ud.httpPOST(nil, "/session", ud.sessionId, "back")
|
||||||
if err != nil {
|
|
||||||
_, err = ud.adbDevice.RunShellCommand("input", "keyevent", KEYCODE_BACK)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) StartCamera() (err error) {
|
|
||||||
if _, err = ud.adbDevice.RunShellCommand("rm", "-r", "/sdcard/DCIM/Camera"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
var version string
|
|
||||||
if version, err = ud.adbDevice.RunShellCommand("getprop", "ro.build.version.release"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if version == "11" || version == "12" {
|
|
||||||
if _, err = ud.adbDevice.RunShellCommand("am", "start", "-a", "android.media.action.STILL_IMAGE_CAMERA"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
if _, err = ud.adbDevice.RunShellCommand("input", "swipe", "750", "1000", "250", "1000"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
if _, err = ud.adbDevice.RunShellCommand("input", "keyevent", KEYCODE_CAMERA); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
if _, err = ud.adbDevice.RunShellCommand("am", "start", "-a", "android.media.action.VIDEO_CAPTURE"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
if _, err = ud.adbDevice.RunShellCommand("input", "keyevent", KEYCODE_CAMERA); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) StopCamera() (err error) {
|
|
||||||
err = ud.PressBack()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = ud.Homescreen()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// kill samsung shell command
|
|
||||||
if _, err = ud.adbDevice.RunShellCommand("am", "force-stop", "com.sec.android.app.camera"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// kill other camera (huawei mi)
|
|
||||||
if _, err = ud.adbDevice.RunShellCommand("am", "force-stop", "com.android.camera2"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,10 +185,6 @@ func (ud *uiaDriver) Homescreen() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) PressKeyCode(keyCode KeyCode, metaState KeyMeta, flags ...KeyFlag) (err error) {
|
func (ud *uiaDriver) PressKeyCode(keyCode KeyCode, metaState KeyMeta, flags ...KeyFlag) (err error) {
|
||||||
return ud._pressKeyCode(keyCode, metaState, flags...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) _pressKeyCode(keyCode KeyCode, metaState KeyMeta, flags ...KeyFlag) (err error) {
|
|
||||||
// register(postHandler, new PressKeyCodeAsync("/wd/hub/session/:sessionId/appium/device/press_keycode"))
|
// register(postHandler, new PressKeyCodeAsync("/wd/hub/session/:sessionId/appium/device/press_keycode"))
|
||||||
data := map[string]interface{}{
|
data := map[string]interface{}{
|
||||||
"keycode": keyCode,
|
"keycode": keyCode,
|
||||||
@@ -332,28 +199,6 @@ func (ud *uiaDriver) _pressKeyCode(keyCode KeyCode, metaState KeyMeta, flags ...
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) AppLaunch(bundleId string) (err error) {
|
|
||||||
// 不指定 Activity 名称启动(启动主 Activity)
|
|
||||||
// adb shell monkey -p <packagename> -c android.intent.category.LAUNCHER 1
|
|
||||||
sOutput, err := ud.adbDevice.RunShellCommand(
|
|
||||||
"monkey", "-p", bundleId, "-c", "android.intent.category.LAUNCHER", "1",
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if strings.Contains(sOutput, "monkey aborted") {
|
|
||||||
return fmt.Errorf("app launch: %s", strings.TrimSpace(sOutput))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) AppTerminate(bundleId string) (successful bool, err error) {
|
|
||||||
// 强制停止应用,停止 <packagename> 相关的进程
|
|
||||||
// adb shell am force-stop <packagename>
|
|
||||||
_, err = ud.adbDevice.RunShellCommand("am", "force-stop", bundleId)
|
|
||||||
return err == nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) Tap(x, y int, options ...DataOption) error {
|
func (ud *uiaDriver) Tap(x, y int, options ...DataOption) error {
|
||||||
return ud.TapFloat(float64(x), float64(y), options...)
|
return ud.TapFloat(float64(x), float64(y), options...)
|
||||||
}
|
}
|
||||||
@@ -371,15 +216,6 @@ func (ud *uiaDriver) TapFloat(x, y float64, options ...DataOption) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) DoubleTap(x, y int) error {
|
|
||||||
return ud.DoubleTapFloat(float64(x), float64(y))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) DoubleTapFloat(x, y float64) (err error) {
|
|
||||||
// TODO
|
|
||||||
return errDriverNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) TouchAndHold(x, y int, second ...float64) (err error) {
|
func (ud *uiaDriver) TouchAndHold(x, y int, second ...float64) (err error) {
|
||||||
return ud.TouchAndHoldFloat(float64(x), float64(y), second...)
|
return ud.TouchAndHoldFloat(float64(x), float64(y), second...)
|
||||||
}
|
}
|
||||||
@@ -400,12 +236,6 @@ func (ud *uiaDriver) TouchAndHoldFloat(x, y float64, second ...float64) (err err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) _drag(data map[string]interface{}) (err error) {
|
|
||||||
// register(postHandler, new Drag("/wd/hub/session/:sessionId/touch/drag"))
|
|
||||||
_, err = ud.httpPOST(data, "/session", ud.sessionId, "touch/drag")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drag performs a swipe from one coordinate to another coordinate. You can control
|
// Drag performs a swipe from one coordinate to another coordinate. You can control
|
||||||
// the smoothness and speed of the swipe by specifying the number of steps.
|
// the smoothness and speed of the swipe by specifying the number of steps.
|
||||||
// Each step execution is throttled to 5 milliseconds per step, so for a 100
|
// Each step execution is throttled to 5 milliseconds per step, so for a 100
|
||||||
@@ -425,22 +255,8 @@ func (ud *uiaDriver) DragFloat(fromX, fromY, toX, toY float64, options ...DataOp
|
|||||||
// new data options in post data for extra uiautomator configurations
|
// new data options in post data for extra uiautomator configurations
|
||||||
newData := NewData(data, options...)
|
newData := NewData(data, options...)
|
||||||
|
|
||||||
return ud._drag(newData)
|
// register(postHandler, new Drag("/wd/hub/session/:sessionId/touch/drag"))
|
||||||
}
|
_, err = ud.httpPOST(newData, "/session", ud.sessionId, "touch/drag")
|
||||||
|
|
||||||
func (ud *uiaDriver) _swipe(startX, startY, endX, endY interface{}, options ...DataOption) (err error) {
|
|
||||||
// register(postHandler, new Swipe("/wd/hub/session/:sessionId/touch/perform"))
|
|
||||||
data := map[string]interface{}{
|
|
||||||
"startX": startX,
|
|
||||||
"startY": startY,
|
|
||||||
"endX": endX,
|
|
||||||
"endY": endY,
|
|
||||||
}
|
|
||||||
|
|
||||||
// new data options in post data for extra uiautomator configurations
|
|
||||||
newData := NewData(data, options...)
|
|
||||||
|
|
||||||
_, err = ud.httpPOST(newData, "/session", ud.sessionId, "touch/perform")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,16 +269,19 @@ func (ud *uiaDriver) Swipe(fromX, fromY, toX, toY int, options ...DataOption) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) SwipeFloat(fromX, fromY, toX, toY float64, options ...DataOption) error {
|
func (ud *uiaDriver) SwipeFloat(fromX, fromY, toX, toY float64, options ...DataOption) error {
|
||||||
return ud._swipe(fromX, fromY, toX, toY, options...)
|
// register(postHandler, new Swipe("/wd/hub/session/:sessionId/touch/perform"))
|
||||||
}
|
data := map[string]interface{}{
|
||||||
|
"startX": fromX,
|
||||||
|
"startY": fromY,
|
||||||
|
"endX": toX,
|
||||||
|
"endY": toY,
|
||||||
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) ForceTouch(x, y int, pressure float64, second ...float64) error {
|
// new data options in post data for extra uiautomator configurations
|
||||||
return ud.ForceTouchFloat(float64(x), float64(y), pressure, second...)
|
newData := NewData(data, options...)
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) ForceTouchFloat(x, y, pressure float64, second ...float64) (err error) {
|
_, err := ud.httpPOST(newData, "/session", ud.sessionId, "touch/perform")
|
||||||
// TODO
|
return err
|
||||||
return errDriverNotImplemented
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) SetPasteboard(contentType PasteboardType, content string) (err error) {
|
func (ud *uiaDriver) SetPasteboard(contentType PasteboardType, content string) (err error) {
|
||||||
@@ -525,11 +344,6 @@ func (ud *uiaDriver) Input(text string, options ...DataOption) (err error) {
|
|||||||
return ud.SendKeys(text, options...)
|
return ud.SendKeys(text, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) PressButton(devBtn DeviceButton) (err error) {
|
|
||||||
// TODO
|
|
||||||
return errDriverNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) Rotation() (rotation Rotation, err error) {
|
func (ud *uiaDriver) Rotation() (rotation Rotation, err error) {
|
||||||
// register(getHandler, new GetRotation("/wd/hub/session/:sessionId/rotation"))
|
// register(getHandler, new GetRotation("/wd/hub/session/:sessionId/rotation"))
|
||||||
var rawResp rawResponse
|
var rawResp rawResponse
|
||||||
@@ -545,11 +359,6 @@ func (ud *uiaDriver) Rotation() (rotation Rotation, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) SetRotation(rotation Rotation) (err error) {
|
|
||||||
// TODO
|
|
||||||
return errDriverNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) Screenshot() (raw *bytes.Buffer, err error) {
|
func (ud *uiaDriver) Screenshot() (raw *bytes.Buffer, err error) {
|
||||||
// register(getHandler, new CaptureScreenshot("/wd/hub/session/:sessionId/screenshot"))
|
// register(getHandler, new CaptureScreenshot("/wd/hub/session/:sessionId/screenshot"))
|
||||||
var rawResp rawResponse
|
var rawResp rawResponse
|
||||||
@@ -586,92 +395,3 @@ func (ud *uiaDriver) Source(srcOpt ...SourceOption) (source string, err error) {
|
|||||||
source = reply.Value
|
source = reply.Value
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ud *uiaDriver) AccessibleSource() (source string, err error) {
|
|
||||||
// TODO
|
|
||||||
return source, errDriverNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) HealthCheck() (err error) {
|
|
||||||
// TODO
|
|
||||||
return errDriverNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) GetAppiumSettings() (settings map[string]interface{}, err error) {
|
|
||||||
// register(getHandler, new GetSettings("/wd/hub/session/:sessionId/appium/settings"))
|
|
||||||
var rawResp rawResponse
|
|
||||||
if rawResp, err = ud.httpGET("/session", ud.sessionId, "appium/settings"); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
reply := new(struct{ Value map[string]interface{} })
|
|
||||||
if err = json.Unmarshal(rawResp, reply); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
settings = reply.Value
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) SetAppiumSettings(settings map[string]interface{}) (ret map[string]interface{}, err error) {
|
|
||||||
data := map[string]interface{}{
|
|
||||||
"settings": settings,
|
|
||||||
}
|
|
||||||
// register(postHandler, new UpdateSettings("/wd/hub/session/:sessionId/appium/settings"))
|
|
||||||
_, err = ud.httpPOST(data, "/session", ud.sessionId, "appium/settings")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) IsHealthy() (healthy bool, err error) {
|
|
||||||
// TODO
|
|
||||||
return healthy, errDriverNotImplemented
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) WaitWithTimeoutAndInterval(condition Condition, timeout, interval time.Duration) error {
|
|
||||||
startTime := time.Now()
|
|
||||||
for {
|
|
||||||
done, err := condition(ud)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if done {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if elapsed := time.Since(startTime); elapsed > timeout {
|
|
||||||
return fmt.Errorf("timeout after %v", elapsed)
|
|
||||||
}
|
|
||||||
time.Sleep(interval)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) WaitWithTimeout(condition Condition, timeout time.Duration) error {
|
|
||||||
return ud.WaitWithTimeoutAndInterval(condition, timeout, DefaultWaitInterval)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) Wait(condition Condition) error {
|
|
||||||
return ud.WaitWithTimeoutAndInterval(condition, DefaultWaitTimeout, DefaultWaitInterval)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) StartCaptureLog(identifier ...string) (err error) {
|
|
||||||
log.Info().Msg("start adb log recording")
|
|
||||||
err = ud.logcat.CatchLogcat()
|
|
||||||
if err != nil {
|
|
||||||
err = errors.Wrap(code.AndroidCaptureLogError,
|
|
||||||
fmt.Sprintf("start adb log recording failed: %v", err))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ud *uiaDriver) StopCaptureLog() (result interface{}, err error) {
|
|
||||||
log.Info().Msg("stop adb log recording")
|
|
||||||
err = ud.logcat.Stop()
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("failed to get adb log recording")
|
|
||||||
err = errors.Wrap(code.AndroidCaptureLogError,
|
|
||||||
fmt.Sprintf("get adb log recording failed: %v", err))
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
content := ud.logcat.logBuffer.String()
|
|
||||||
return ConvertPoints(content), nil
|
|
||||||
}
|
|
||||||
@@ -595,7 +595,6 @@ type WebDriver interface {
|
|||||||
// NewSession starts a new session and returns the SessionInfo.
|
// NewSession starts a new session and returns the SessionInfo.
|
||||||
NewSession(capabilities Capabilities) (SessionInfo, error)
|
NewSession(capabilities Capabilities) (SessionInfo, error)
|
||||||
|
|
||||||
ActiveSession() (SessionInfo, error)
|
|
||||||
// DeleteSession Kills application associated with that session and removes session
|
// DeleteSession Kills application associated with that session and removes session
|
||||||
// 1) alertsMonitor disable
|
// 1) alertsMonitor disable
|
||||||
// 2) testedApplicationBundleId terminate
|
// 2) testedApplicationBundleId terminate
|
||||||
@@ -696,9 +695,6 @@ type WebDriver interface {
|
|||||||
|
|
||||||
IsHealthy() (bool, error)
|
IsHealthy() (bool, error)
|
||||||
|
|
||||||
// Close inner connections properly
|
|
||||||
Close() error
|
|
||||||
|
|
||||||
// triggers the log capture and returns the log entries
|
// triggers the log capture and returns the log entries
|
||||||
StartCaptureLog(identifier ...string) (err error)
|
StartCaptureLog(identifier ...string) (err error)
|
||||||
StopCaptureLog() (result interface{}, err error)
|
StopCaptureLog() (result interface{}, err error)
|
||||||
|
|||||||
@@ -35,20 +35,6 @@ func (wd *wdaDriver) GetMjpegClient() *http.Client {
|
|||||||
return wd.mjpegClient
|
return wd.mjpegClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wd *wdaDriver) Close() error {
|
|
||||||
if wd.defaultConn != nil {
|
|
||||||
wd.defaultConn.Close()
|
|
||||||
}
|
|
||||||
if wd.mjpegUSBConn != nil {
|
|
||||||
wd.mjpegUSBConn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
if wd.mjpegClient != nil {
|
|
||||||
wd.mjpegClient.CloseIdleConnections()
|
|
||||||
}
|
|
||||||
return wd.mjpegHTTPConn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wd *wdaDriver) NewSession(capabilities Capabilities) (sessionInfo SessionInfo, err error) {
|
func (wd *wdaDriver) NewSession(capabilities Capabilities) (sessionInfo SessionInfo, err error) {
|
||||||
// [[FBRoute POST:@"/session"].withoutSession respondWithTarget:self action:@selector(handleCreateSession:)]
|
// [[FBRoute POST:@"/session"].withoutSession respondWithTarget:self action:@selector(handleCreateSession:)]
|
||||||
data := make(map[string]interface{})
|
data := make(map[string]interface{})
|
||||||
@@ -69,19 +55,21 @@ func (wd *wdaDriver) NewSession(capabilities Capabilities) (sessionInfo SessionI
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wd *wdaDriver) ActiveSession() (sessionInfo SessionInfo, err error) {
|
|
||||||
// [[FBRoute GET:@""] respondWithTarget:self action:@selector(handleGetActiveSession:)]
|
|
||||||
var rawResp rawResponse
|
|
||||||
if rawResp, err = wd.httpGET("/session", wd.sessionId); err != nil {
|
|
||||||
return SessionInfo{}, err
|
|
||||||
}
|
|
||||||
if sessionInfo, err = rawResp.valueConvertToSessionInfo(); err != nil {
|
|
||||||
return SessionInfo{}, err
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wd *wdaDriver) DeleteSession() (err error) {
|
func (wd *wdaDriver) DeleteSession() (err error) {
|
||||||
|
if wd.defaultConn != nil {
|
||||||
|
wd.defaultConn.Close()
|
||||||
|
}
|
||||||
|
if wd.mjpegUSBConn != nil {
|
||||||
|
wd.mjpegUSBConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
if wd.mjpegClient != nil {
|
||||||
|
wd.mjpegClient.CloseIdleConnections()
|
||||||
|
}
|
||||||
|
if wd.mjpegHTTPConn != nil {
|
||||||
|
wd.mjpegHTTPConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
// [[FBRoute DELETE:@""] respondWithTarget:self action:@selector(handleDeleteSession:)]
|
// [[FBRoute DELETE:@""] respondWithTarget:self action:@selector(handleDeleteSession:)]
|
||||||
_, err = wd.httpDELETE("/session", wd.sessionId)
|
_, err = wd.httpDELETE("/session", wd.sessionId)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -68,18 +68,6 @@ func TestNewUSBDriver(t *testing.T) {
|
|||||||
// t.Log(driver.IsWdaHealthy())
|
// t.Log(driver.IsWdaHealthy())
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_remoteWD_ActiveSession(t *testing.T) {
|
|
||||||
setup(t)
|
|
||||||
|
|
||||||
sessionInfo, err := driver.ActiveSession()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if len(sessionInfo.SessionId) == 0 {
|
|
||||||
t.Fatal(sessionInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_remoteWD_DeleteSession(t *testing.T) {
|
func Test_remoteWD_DeleteSession(t *testing.T) {
|
||||||
setup(t)
|
setup(t)
|
||||||
|
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ func checkOCR(buff *bytes.Buffer) error {
|
|||||||
|
|
||||||
func TestOCRWithScreenshot(t *testing.T) {
|
func TestOCRWithScreenshot(t *testing.T) {
|
||||||
device, _ := NewAndroidDevice()
|
device, _ := NewAndroidDevice()
|
||||||
driver, err := device.NewUSBDriver(nil)
|
driver, err := device.NewDriver(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
raw, err := driver.Screenshot()
|
raw, err := driver.Driver.Screenshot()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user