feat(doctor): split iOS checks into simulator and physical-device paths

This commit is contained in:
pj committed 2026-06-06 23:45:13 +05:30
1 parent 30c84288f5
commit 02bbeb8190
2 files changed
+42 -9

No files matched your search

+21 -8
View File
@@ -33,6 +33,8 @@ func doctorChecksFor(platform string) []doctorCheck {
return androidChecks()
case "ios":
return iosChecks()
case "ios-device":
return append(iosChecks(), iosDeviceChecks()...)
case "all":
return allChecks()
default:
@@ -55,19 +57,30 @@ func androidChecks() []doctorCheck {
}
}
// iosChecks covers the simulator path, which the native companion drives with
// no JVM. A simulator host with no Java still passes. Physical-device runs
// additionally need java and the sidecar JAR, covered by iosDeviceChecks and
// surfaced through the "all" union.
func iosChecks() []doctorCheck {
return []doctorCheck{
{Name: "xcrun on PATH", Run: checkExecutableOnPath("xcrun")},
{Name: "simctl on PATH", Run: checkExecutableOnPath("simctl")},
{Name: "java 17+ on PATH", Run: checkJavaVersion},
{Name: "sidecar JAR is real (not placeholder)", Run: checkSidecarJAR},
{Name: "xcrun on PATH (ios simulator)", Run: checkExecutableOnPath("xcrun")},
{Name: "simctl on PATH (ios simulator)", Run: checkExecutableOnPath("simctl")},
}
}
// iosDeviceChecks covers the extra prerequisites a physical iOS device needs:
// the JVM and a real sidecar JAR for the sidecar driver path.
func iosDeviceChecks() []doctorCheck {
return []doctorCheck{
{Name: "java 17+ on PATH (ios physical device)", Run: checkJavaVersion},
{Name: "sidecar JAR is real (ios physical device)", Run: checkSidecarJAR},
}
}
func allChecks() []doctorCheck {
seen := map[string]bool{}
var combined []doctorCheck
for _, group := range [][]doctorCheck{webChecks(), androidChecks(), iosChecks()} {
for _, group := range [][]doctorCheck{webChecks(), androidChecks(), iosChecks(), iosDeviceChecks()} {
for _, c := range group {
if seen[c.Name] {
continue
@@ -116,15 +129,15 @@ func parseDoctorArgs(args []string, stderr io.Writer) (doctorOptions, error) {
flagSet := flag.NewFlagSet("doctor", flag.ContinueOnError)
flagSet.SetOutput(stderr)
var options doctorOptions
flagSet.StringVar(&options.platform, "platform", "all", "target platform: web, android, ios, all")
flagSet.StringVar(&options.platform, "platform", "all", "target platform: web, android, ios, ios-device, all")
if err := flagSet.Parse(args); err != nil {
return doctorOptions{}, err
}
switch options.platform {
case "web", "android", "ios", "all":
case "web", "android", "ios", "ios-device", "all":
return options, nil
default:
return doctorOptions{}, fmt.Errorf("unsupported platform: %q (web, android, ios, all)", options.platform)
return doctorOptions{}, fmt.Errorf("unsupported platform: %q (web, android, ios, ios-device, all)", options.platform)
}
}
+21 -1
View File
@@ -127,13 +127,33 @@ func TestDoctorChecksFor_All_IsUnion(t *testing.T) {
for _, c := range all {
names[c.Name]++
}
for _, name := range []string{"adb on PATH", "xcrun on PATH", "headless chromium can launch"} {
for _, name := range []string{"adb on PATH", "xcrun on PATH (ios simulator)", "headless chromium can launch"} {
if names[name] != 1 {
t.Errorf("expected %q in 'all' exactly once, got %d", name, names[name])
}
}
}
func TestDoctorChecksFor_iOSSimulator_OmitsJava(t *testing.T) {
for _, c := range doctorChecksFor("ios") {
if strings.Contains(c.Name, "java") || strings.Contains(c.Name, "sidecar") {
t.Errorf("ios simulator checks must omit %q; simulator runs need no JVM", c.Name)
}
}
}
func TestDoctorChecksFor_iOSDevice_IncludesJava(t *testing.T) {
found := false
for _, c := range doctorChecksFor("ios-device") {
if strings.Contains(c.Name, "java") {
found = true
}
}
if !found {
t.Error("ios-device checks must include java for the sidecar path")
}
}
func TestDoctorChecksFor_UnknownPlatform(t *testing.T) {
if got := doctorChecksFor("fuchsia"); got != nil {
t.Errorf("expected nil for unknown platform, got %+v", got)