//go:build browser && darwin package callstest import ( "context" "encoding/json" "net/http" "net/http/httptest" "os" "os/exec" "path/filepath" "testing" "time" ) // The iPhone UI talks to the same temporary server as the browser suite. Email // is captured locally. Nothing contacts production or sends actual mail. func TestIPhoneSafariAuthentication(t *testing.T) { simulator := os.Getenv("CALLS_IOS_SIMULATOR") if simulator == "" { t.Skip("set CALLS_IOS_SIMULATOR to an available iPhone simulator UUID") } for _, guest := range []bool{false, true} { name := "member" if guest { name = "guest" } t.Run(name, func(t *testing.T) { rig := newBrowserRig(t) room, token := rig.createMeeting(t) target := "/m/" + room if guest { rig.ctl.SetAllowlist(memberA) target = "/j/" + token } before := rig.mail.count() control := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") link := "" if rig.mail.count() > before { to, value := rig.mail.last() if to == memberB { link = value } } json.NewEncoder(w).Encode(map[string]string{"link": link}) })) defer control.Close() root := repoRootForBrowser(t) ctx, cancel := context.WithTimeout(t.Context(), 4*time.Minute) defer cancel() results := filepath.Join(root, "native/build/iphone-auth-"+name+"-"+time.Now().Format("150405")+".xcresult") cmd := exec.CommandContext(ctx, "xcodebuild", "-project", filepath.Join(root, "native/ios/CallsPhone.xcodeproj"), "-scheme", "CallsPhone", "-destination", "platform=iOS Simulator,id="+simulator, "-derivedDataPath", filepath.Join(root, "native/build/ios-simulator"), "-resultBundlePath", results, "CODE_SIGNING_ALLOWED=NO", "-only-testing:CallsPhoneUITests/CallsPhoneUITests/testEmailBrowserHandoff", "test") // A member signs in to the server, which the app is pointed at for // this run with -CallsServer; a guest pastes the invitation into the // guest screen. guestFlag := "0" if guest { guestFlag = "1" } cmd.Env = append(os.Environ(), "TEST_RUNNER_CALLS_TEST_MEETING="+rig.origin+target, "TEST_RUNNER_CALLS_TEST_ORIGIN="+rig.origin, "TEST_RUNNER_CALLS_TEST_GUEST="+guestFlag, "TEST_RUNNER_CALLS_TEST_CONTROL="+control.URL, "TEST_RUNNER_CALLS_TEST_EMAIL="+memberB) // Xcode's detailed trace contains only synthetic test identities and is // retained locally for diagnosis, rather than flooding the normal gate log. logPath := filepath.Join(root, "native/build/iphone-auth-"+name+".log") log, err := os.Create(logPath) if err != nil { t.Fatal(err) } defer log.Close() cmd.Stdout = log cmd.Stderr = log if err := cmd.Run(); err != nil { t.Fatalf("iPhone Safari %s: %v (details: %s)", name, err, logPath) } t.Log("Safari email handoff passed on iPhone simulator:", name) }) } } func TestIPhoneNativeMedia(t *testing.T) { simulator := os.Getenv("CALLS_IOS_SIMULATOR") if simulator == "" { t.Skip("set CALLS_IOS_SIMULATOR to an available iPhone simulator UUID") } rig := newBrowserRig(t) room, _ := rig.createMeeting(t) rig.ctl.SetStreamTimings(time.Second, 3*time.Second) cookiesA, _ := json.Marshal([]map[string]string{{"name": rig.cookieName, "value": rig.cookieA}}) cookiesB, _ := json.Marshal([]map[string]string{{"name": rig.cookieName, "value": rig.cookieB}}) fixture, _ := json.Marshal(map[string]string{"origin": rig.origin, "room": room, "cookiesA": string(cookiesA), "cookiesB": string(cookiesB)}) root := repoRootForBrowser(t) ctx, cancel := context.WithTimeout(t.Context(), 4*time.Minute) defer cancel() cmd := exec.CommandContext(ctx, "xcodebuild", "-project", filepath.Join(root, "native/ios/CallsPhone.xcodeproj"), "-scheme", "CallsPhone", "-destination", "platform=iOS Simulator,id="+simulator, "-derivedDataPath", filepath.Join(root, "native/build/ios-simulator"), "CODE_SIGNING_ALLOWED=NO", "-only-testing:CallsPhoneTests/CallsPhoneTests/testNativeVideoAndRenewal", "test") cmd.Env = append(os.Environ(), "TEST_RUNNER_CALLS_TEST_MEDIA="+string(fixture)) logPath := filepath.Join(root, "native/build/iphone-media.log") log, err := os.Create(logPath) if err != nil { t.Fatal(err) } defer log.Close() cmd.Stdout = log cmd.Stderr = log if err := cmd.Run(); err != nil { t.Fatalf("iPhone native media: %v (details: %s)", err, logPath) } t.Log("Two iPhone-native WebRTC peers decoded video, kept their peers through stream renewals, and left cleanly") }