mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 19:17:10 +00:00
feat(testrun): launch iOS app via XCTest with env vars instead of simctl
This commit is contained in:
1 parent
003aba9ea2
commit
bff3a49324
3 files changed
+40
-19
No files matched your search
@@ -69,6 +69,15 @@ func LaunchApp(ctx context.Context, bundleID string, env map[string]string) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BootedUDID returns the UDID of the currently booted iOS simulator, or "" if none is booted.
|
||||||
|
func BootedUDID(ctx context.Context) string {
|
||||||
|
d, _ := bootedSimulator(ctx)
|
||||||
|
if d == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return d.UDID
|
||||||
|
}
|
||||||
|
|
||||||
func bootedSimulator(ctx context.Context) (*simDevice, error) {
|
func bootedSimulator(ctx context.Context) (*simDevice, error) {
|
||||||
out, err := exec.CommandContext(ctx, "xcrun", "simctl", "list", "devices", "booted", "--json").Output()
|
out, err := exec.CommandContext(ctx, "xcrun", "simctl", "list", "devices", "booted", "--json").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/priyanshujain/sanderling/internal/driver"
|
"github.com/priyanshujain/sanderling/internal/driver"
|
||||||
"github.com/priyanshujain/sanderling/internal/driver/chrome"
|
"github.com/priyanshujain/sanderling/internal/driver/chrome"
|
||||||
driverSidecar "github.com/priyanshujain/sanderling/internal/driver/sidecar"
|
driverSidecar "github.com/priyanshujain/sanderling/internal/driver/sidecar"
|
||||||
|
"github.com/priyanshujain/sanderling/internal/ios"
|
||||||
"github.com/priyanshujain/sanderling/internal/sidecar"
|
"github.com/priyanshujain/sanderling/internal/sidecar"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,10 +36,16 @@ func buildDriver(ctx context.Context, options Options, stdout io.Writer) (driver
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
sidecarCommand := exec.CommandContext(ctx, "java", "-jar", jarPath,
|
sidecarArgs := []string{"-jar", jarPath,
|
||||||
"--port", strconv.Itoa(sidecarPort),
|
"--port", strconv.Itoa(sidecarPort),
|
||||||
"--platform", options.Platform,
|
"--platform", options.Platform,
|
||||||
)
|
}
|
||||||
|
if options.Platform == "ios" {
|
||||||
|
if udid := ios.BootedUDID(ctx); udid != "" {
|
||||||
|
sidecarArgs = append(sidecarArgs, "--udid", udid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sidecarCommand := exec.CommandContext(ctx, "java", sidecarArgs...)
|
||||||
sidecarCommand.Stdout = stdout
|
sidecarCommand.Stdout = stdout
|
||||||
sidecarCommand.Stderr = stdout
|
sidecarCommand.Stderr = stdout
|
||||||
sidecarCommand.Env = android.EnvWithAndroidPlatformTools(os.Environ())
|
sidecarCommand.Env = android.EnvWithAndroidPlatformTools(os.Environ())
|
||||||
|
|||||||
+22
-17
@@ -110,7 +110,7 @@ func Execute(ctx context.Context, options Options, stdout io.Writer) error {
|
|||||||
acceptChannel <- acceptResult{conn: conn, err: acceptErr}
|
acceptChannel <- acceptResult{conn: conn, err: acceptErr}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := activeDriver.Launch(ctx, options.BundleID, false); err != nil {
|
if err := activeDriver.Launch(ctx, options.BundleID, false, nil); err != nil {
|
||||||
return fmt.Errorf("launch app: %w", err)
|
return fmt.Errorf("launch app: %w", err)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(stdout, "launched %s; waiting for SDK to connect (%.0fs timeout)\n", options.BundleID, sdkAcceptTimeout.Seconds())
|
fmt.Fprintf(stdout, "launched %s; waiting for SDK to connect (%.0fs timeout)\n", options.BundleID, sdkAcceptTimeout.Seconds())
|
||||||
@@ -133,35 +133,40 @@ func Execute(ctx context.Context, options Options, stdout io.Writer) error {
|
|||||||
defer listener.Close()
|
defer listener.Close()
|
||||||
agentPort := listener.Addr().(*net.TCPAddr).Port
|
agentPort := listener.Addr().(*net.TCPAddr).Port
|
||||||
|
|
||||||
// Launch app via simctl with SANDERLING_PORT so the SDK can connect.
|
agentServer := agent.NewServer(listener)
|
||||||
if err := ios.LaunchApp(ctx, options.BundleID, map[string]string{
|
|
||||||
|
type acceptResult struct {
|
||||||
|
conn *agent.Conn
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
acceptChannel := make(chan acceptResult, 1)
|
||||||
|
go func() {
|
||||||
|
acceptCtx, cancel := context.WithTimeout(ctx, sdkAcceptTimeout)
|
||||||
|
defer cancel()
|
||||||
|
conn, acceptErr := agentServer.Accept(acceptCtx)
|
||||||
|
acceptChannel <- acceptResult{conn: conn, err: acceptErr}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Launch app via XCTest with SANDERLING_PORT so the SDK can connect.
|
||||||
|
if err := activeDriver.Launch(ctx, options.BundleID, false, map[string]string{
|
||||||
"SANDERLING_PORT": strconv.Itoa(agentPort),
|
"SANDERLING_PORT": strconv.Itoa(agentPort),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("launch app: %w", err)
|
return fmt.Errorf("launch app: %w", err)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(stdout, "iOS app launched with SANDERLING_PORT=%d; waiting for SDK (%.0fs timeout)\n", agentPort, sdkAcceptTimeout.Seconds())
|
fmt.Fprintf(stdout, "iOS app launched with SANDERLING_PORT=%d; waiting for SDK (%.0fs timeout)\n", agentPort, sdkAcceptTimeout.Seconds())
|
||||||
|
|
||||||
agentServer := agent.NewServer(listener)
|
result := <-acceptChannel
|
||||||
acceptCtx, acceptCancel := context.WithTimeout(ctx, sdkAcceptTimeout)
|
if result.err != nil {
|
||||||
conn, acceptErr := agentServer.Accept(acceptCtx)
|
return fmt.Errorf("accept SDK: %w", result.err)
|
||||||
acceptCancel()
|
|
||||||
if acceptErr != nil {
|
|
||||||
return fmt.Errorf("accept SDK: %w", acceptErr)
|
|
||||||
}
|
}
|
||||||
connection = conn
|
connection = result.conn
|
||||||
defer connection.Close()
|
defer connection.Close()
|
||||||
hello := connection.Hello()
|
hello := connection.Hello()
|
||||||
fmt.Fprintf(stdout, "SDK connected: platform=%s app=%s sdk=%s\n", hello.Platform, hello.AppPackage, hello.Version)
|
fmt.Fprintf(stdout, "SDK connected: platform=%s app=%s sdk=%s\n", hello.Platform, hello.AppPackage, hello.Version)
|
||||||
|
|
||||||
// Initialize Maestro XCTest session after the app is running.
|
|
||||||
// clearState=false avoids relaunching the already-connected app.
|
|
||||||
if err := activeDriver.Launch(ctx, options.BundleID, false); err != nil {
|
|
||||||
fmt.Fprintf(stdout, "warn: maestro launch: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
case "web":
|
case "web":
|
||||||
fmt.Fprintln(stdout, "web mode: skipping SDK")
|
fmt.Fprintln(stdout, "web mode: skipping SDK")
|
||||||
if err := activeDriver.Launch(ctx, options.BundleID, false); err != nil {
|
if err := activeDriver.Launch(ctx, options.BundleID, false, nil); err != nil {
|
||||||
return fmt.Errorf("launch app: %w", err)
|
return fmt.Errorf("launch app: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user