How to Switch Between Native App and Safari : Appium iOS Automation

How to Switch Between Native App and Safari : Appium iOS Automation

When automating iOS applications with Appium, you may encounter scenarios where an action within your app opens a web page in Safari, pushing your iOS app to the background. In such cases, the challenge is to automate the web process and then seamlessly switch back to your iOS app to continue the automation from where it left off.

Appium does not offer a direct method to handle this scenario natively, which necessitates a manual approach. This involves managing the transition between the iOS app and Safari manually by terminating and reinitializing driver sessions. In this article, we'll guide you through this process using Selenium WebDriver and demonstrate how to automate the entire workflow effectively.

Understanding the Automation Flow

1. Starting with the iOS App: The process begins by initializing an IOSDriver, which controls the automation within your native iOS app. You can perform any required actions, such as interacting with UI elements, until the point where the app triggers the opening of Safari.

2. Transitioning to the Web Process: When an action in your app opens Safari, the iOS app goes into the background. At this point, you need to switch your automation focus to the web process. This is done by terminating the IOSDriver session and starting a new session using WebDriver configured for Safari.

3. Automating in Safari: Once the WebDriver is initialized, you can automate interactions within the web page opened in Safari. This could include clicking buttons, filling out forms, or any other required tasks.

4. Returning to the Native App: After completing the automation in Safari, the next step is to terminate the WebDriver session and reinitialize the IOSDriver. This allows you to return to your native app and continue the automation from where it was paused, ensuring a smooth transition back to the app environment.

5. Final Cleanup: As a best practice, both the IOSDriver and WebDriver sessions should be terminated at the end of your test to avoid any lingering sessions that might affect future tests.

Code Snippet

Here is a complete code snippet illustrating the process:

import io.appium.java_client.ios.IOSDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import java.io.IOException;
import java.net.URL;

public class AppToSafariTest {
    private static IOSDriver iosDriver;
    private static WebDriver safariDriver;

    private final By safariElement = By.id("safariElement");
    private final By loginBtn =    By.xpath("native_element1");
    private final By menuIcon = By.xpath("native_element2");

    @BeforeTest
    public static void setUp() throws IOException {
        // Initial setup for iOS driver
        startIOSDriver();
    }

    public static void startIOSDriver() throws IOException {

        // Set up iOSDriver with required capabilities
        DesiredCapabilities appCaps = new DesiredCapabilities();
        appCaps.setCapability("platformName", "iOS");
        appCaps.setCapability("platformVersion", "Your_Version");
        appCaps.setCapability("deviceName", "Your_Name");
        appCaps.setCapability("udid", "Your_UDID");
        appCaps.setCapability("bundleId", "Your_Bundle_ID");
        appCaps.setCapability("xcodeOrgId", "Your_Org_ID");
        appCaps.setCapability("xcodeSigningId", "Your_Signing_ID");
        appCaps.setCapability("appium:noReset", true);
        appCaps.setCapability("appium:automationName", "XCUITest");

        iosDriver = new IOSDriver(new URL("https://127.0.0.1:4723/wd/hub"), appCaps);
    }

    private void setUpSafariDriver() throws IOException {

        // Set up SafariDriver with required capabilities
        DesiredCapabilities safariCaps = new DesiredCapabilities();
        safariCaps.setCapability("platformName", "iOS");
        safariCaps.setCapability("platformVersion", "Your_Version");
        safariCaps.setCapability("deviceName", "Your_Name");
        safariCaps.setCapability("udid", "Your_UDID");
        safariCaps.setCapability("xcodeOrgId", "Your_Org_ID");
        safariCaps.setCapability("xcodeSigningId", "Your_ID");
        safariCaps.setCapability("appium:noReset", true);
        safariCaps.setCapability("appium:automationName", "XCUITest");
        safariCaps.setCapability("appium:includeSafariInWebviews", true);
        safariCaps.setCapability("browserName", "safari");

        safariDriver = new IOSDriver(new URL("https://127.0.0.1:4723/wd/hub"), safariCaps);
    }

    @Test
    public void testAppToSafariAndBack() throws IOException {

        // Perform some actions in the iOS app
        try {
            iosDriver.findElement(loginBtn).click();
        } catch (Exception e) {
            throw new AssertionError("Element not clickable: " + loginBtn, e);
        }

        // Stop the current iOS driver session before starting Safari
        if (iosDriver != null) {
            iosDriver.quit();
        }

        // Initialize Safari driver session
        setUpSafariDriver();

        // Perform actions in Safari
        try {
            safariDriver.findElement(safariElement).click();
        } catch (Exception e) {
            throw new AssertionError("Element not found: " + safariElement, e);
        }

        // Tear down Safari driver session
        if (safariDriver != null) {
            safariDriver.quit();
        }

        // Restart iOS driver session
        startIOSDriver();

        // Continue with the app actions
        try {
            iosDriver.findElement(menuIcon).click();
        } catch (Exception e) {
            throw new AssertionError("Element not clickable: " + menuIcon, e);
        }
    }

    @AfterTest
    public static void tearDown() {
        if (iosDriver != null) {
            iosDriver.quit();
        }
        if (safariDriver != null) {
            safariDriver.quit();
        }
    }
}
        

Key Considerations:

  • Seamless Transition: The key to success in this automation scenario is ensuring a seamless transition between the web process in Safari and the native app. This requires careful management of driver sessions and maintaining the app’s state throughout the process.
  • Handling Navigation Manually: If Safari opens automatically from the native app and navigates to the required web page, you do not need to handle it manually. However, if the app does not open Safari and navigate to the required web page automatically, you can handle this manually. Set the bundleId for Safari when initializing the WebDriver capabilities, and manually navigate to the desired URL using

safariCaps.setCapability("bundleId", "com.apple.mobilesafari");
safariDriver.get("https://www.dhirubhai.net");        

Conclusion:

Automating iOS apps that interact with Safari introduces complexity due to the need to switch contexts and manage multiple driver sessions. While Appium doesn’t provide a direct way to handle this scenario, by following the steps outlined above, you can effectively automate workflows that span both native apps and web processes on iOS. This method ensures that you can resume your automation in the native app right where you left off, maintaining the continuity of your test flow.

要查看或添加评论,请登录

社区洞察

其他会员也浏览了