mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-04 20:17:09 +00:00
feat(testrun): add Preflight() before sidecar/driver setup
Mobile platforms get a friendly install hint pointing at `sanderling doctor --platform=<p>` instead of `fork/exec java: not found`. Web is a no-op.
This commit is contained in:
1 parent
039c8ab226
commit
f850e573f8
3 files changed
+146
No files matched your search
@@ -21,6 +21,9 @@ import (
|
|||||||
// a cleanup function. For web, ChromeDriver is used directly; for android/ios
|
// a cleanup function. For web, ChromeDriver is used directly; for android/ios
|
||||||
// the JVM sidecar is extracted, spawned, and dialed.
|
// the JVM sidecar is extracted, spawned, and dialed.
|
||||||
func buildDriver(ctx context.Context, options Options, stdout io.Writer) (driver.DeviceDriver, func(), error) {
|
func buildDriver(ctx context.Context, options Options, stdout io.Writer) (driver.DeviceDriver, func(), error) {
|
||||||
|
if err := Preflight(ctx, options.Platform); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
if options.Platform == "web" {
|
if options.Platform == "web" {
|
||||||
d := chrome.New()
|
d := chrome.New()
|
||||||
return d, func() { _ = d.Terminate(context.Background()) }, nil
|
return d, func() { _ = d.Terminate(context.Background()) }, nil
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package testrun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Preflight runs platform-specific host checks before sidecar/driver setup.
|
||||||
|
// On failure it returns a wrapped error pointing the user at the matching
|
||||||
|
// `sanderling doctor --platform=<p>` command. Web returns nil (no host
|
||||||
|
// prerequisites beyond a working chromium, which the driver will surface
|
||||||
|
// itself if missing).
|
||||||
|
func Preflight(ctx context.Context, platform string) error {
|
||||||
|
check := preflightCheck
|
||||||
|
return runPreflight(ctx, platform, check)
|
||||||
|
}
|
||||||
|
|
||||||
|
type preflightFunc func(name string) error
|
||||||
|
|
||||||
|
func preflightCheck(name string) error {
|
||||||
|
if _, err := exec.LookPath(name); err != nil {
|
||||||
|
return fmt.Errorf("%s not found on PATH: %w", name, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func runPreflight(ctx context.Context, platform string, check preflightFunc) error {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch platform {
|
||||||
|
case "web":
|
||||||
|
return nil
|
||||||
|
case "android":
|
||||||
|
if err := check("adb"); err != nil {
|
||||||
|
return preflightFailure("android", err)
|
||||||
|
}
|
||||||
|
if err := check("java"); err != nil {
|
||||||
|
return preflightFailure("android", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case "ios":
|
||||||
|
if err := check("xcrun"); err != nil {
|
||||||
|
return preflightFailure("ios", err)
|
||||||
|
}
|
||||||
|
if err := check("java"); err != nil {
|
||||||
|
return preflightFailure("ios", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("preflight: unknown platform %q", platform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func preflightFailure(platform string, cause error) error {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"preflight: %w\nrun `sanderling doctor --platform=%s` for full host-readiness checks",
|
||||||
|
cause, platform,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package testrun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPreflight_WebSkips(t *testing.T) {
|
||||||
|
called := 0
|
||||||
|
check := func(name string) error {
|
||||||
|
called++
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := runPreflight(context.Background(), "web", check); err != nil {
|
||||||
|
t.Fatalf("web preflight should be no-op, got %v", err)
|
||||||
|
}
|
||||||
|
if called != 0 {
|
||||||
|
t.Errorf("web preflight ran %d binary checks; expected 0", called)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPreflight_AndroidNeedsAdbAndJava(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
missing string
|
||||||
|
wantInErr string
|
||||||
|
}{
|
||||||
|
{name: "missing adb", missing: "adb", wantInErr: "adb"},
|
||||||
|
{name: "missing java", missing: "java", wantInErr: "java"},
|
||||||
|
}
|
||||||
|
for _, testCase := range cases {
|
||||||
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
|
check := func(name string) error {
|
||||||
|
if name == testCase.missing {
|
||||||
|
return errors.New(name + " not found")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := runPreflight(context.Background(), "android", check)
|
||||||
|
if err == nil || !strings.Contains(err.Error(), testCase.wantInErr) {
|
||||||
|
t.Fatalf("expected error mentioning %q, got %v", testCase.wantInErr, err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "sanderling doctor --platform=android") {
|
||||||
|
t.Errorf("error missing doctor hint: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPreflight_iOSNeedsXcrunAndJava(t *testing.T) {
|
||||||
|
check := func(name string) error {
|
||||||
|
if name == "xcrun" {
|
||||||
|
return errors.New("xcrun not found")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := runPreflight(context.Background(), "ios", check)
|
||||||
|
if err == nil || !strings.Contains(err.Error(), "xcrun") {
|
||||||
|
t.Fatalf("expected xcrun error, got %v", err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "sanderling doctor --platform=ios") {
|
||||||
|
t.Errorf("error missing doctor hint: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPreflight_AllOK(t *testing.T) {
|
||||||
|
check := func(name string) error { return nil }
|
||||||
|
for _, platform := range []string{"web", "android", "ios"} {
|
||||||
|
if err := runPreflight(context.Background(), platform, check); err != nil {
|
||||||
|
t.Errorf("%s: unexpected error %v", platform, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPreflight_UnknownPlatform(t *testing.T) {
|
||||||
|
check := func(string) error { return nil }
|
||||||
|
if err := runPreflight(context.Background(), "fuchsia", check); err == nil {
|
||||||
|
t.Error("expected error for unknown platform")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user