How to Automate Deep Link Testing on Emulators, Simulators and Real Devices
Sauce AI for Test Authoring: Move from purpose to executing in min.|xBack to ResourcesBlogPosted November 18, 2019
How to Automate Deep Link Testing on Emulators, Simulators and Existent Devices
This blog berth was originally authored by Wim Selles onAppium Pro Newsletter Edition 84and has since been edited to be used with the.
Recently I wanted to explore the possibleness of utilize deep links with Appium on real devices and I stumbled uponEdition 7 of Appium Pro, called Speeding Up Your Tests With Deep Links. In that edition, we hear how to use shortcuts to get execution speed less crucial by using deep links.
In order to demonstrate and use deep links together with Appium the following command was utilize:
driver.get (& # x27; & lt; app-identifier & gt;: // & lt; deep-link & gt; & # x27;)
During my research I launch out that this works dead for Android emulators and iOS simulator, but it didn & # x27; t work on real device. On iOS, Siri was opened, which is the native behavior for iOS (seethis issuefor more particular). In this edition, I require to show you a different method of triggering deep linkup that will work for emulator, simulators and existent devices, which you can use with our Sauce Labs Demo App (more information about how deep linking has been configured in our app can be found). Let & # x27; s start with the easy part, which will be Android.
Note: The codification examples are in JavaScript and can be used with WebdriverIO V5. I conceive the steps and code are self-explanatory, which makes it easy to translate it to your favorite speech / model.
Android and deep linking
Android has a specific mobile bidding to use deep linking, which can be basehere. We can use the deep tie-in command in the following way:
driver.execute (
& # x27; mobile: deepLink & # x27;,
{
url: & quot; & lt; deep-link-url & gt; & quot;,
package: & quot; & lt; package-name & gt; & quot;
}
);
For The Sauce Labs Demo Appwe postulate the next deep link formatting:
swaglabs: /// & lt; screen-name & gt; / & lt; ids & gt;
Based on this format it will arouse up the app, skip hallmark behind the view and jump the exploiter to the swag overview screen instantly. When the url, the Android software name ofThe Sauce Labs Demo App, and the bid are compound, we get this for Android:
driver.execute (
& # x27; mobile: deepLink & # x27;,
{
url: & quot; swaglabs: //swag-overview/0,2 & quot;,
package: & quot; com.swaglabsmobileapp & quot;
}
);
This bid will act for Android emulators and real devices, yet when the app is already opened. Pretty easy, isn & # x27; t it?
iOS deep linking
Now let & # x27; s take a look at the hardest component, which is making this work on iOS. There is no mobile bid for iOS so we need to take a look at a canonic flow on how to use a deep linkup with iOS. A deep link can be opened through the terminal with the following command:
xcrun simctl openurl boot swaglabs: //login/ & lt; screen-name & gt; / & lt; ids & gt;
But this will not be a cross-device solution, especially when you are apply a local grid or a cloud resolution, and hold no access to simctl.
Deep links can also be open from Safari, meaning that if the deep link is entered in the Safari speech bar it will trigger a confirmation pop-up with the question of whether the user does so want to open the 3rd-party app (see below).

When the pop-up has be confirmed, the app will be open and the deep connection will bring us to the screen we need to open. This is a fairly cross-device solution and manual examination have shew that this works for simulators and real device.
To be capable to automate this flow with Appium, we require to follow some simple steps:
Terminate the app under tryout (optional)
Launch Safari and enter the deep linkup in the address bar
Confirm the notification pop-up
Each step will be explained in point below.
Step 1: Terminate the app
This is an optional measure and only needed if you have flakiness when not terminating the app or if terminate the app is part of your flow.
For autonomous testing across multiple user personas, check out SUSATest — it explores your app like 10 different real users.
In Edition 6, Jonathan excuse how to test iOS upgrades and he mentioned that as of Appium 1.8.0 we have themobile: terminateApp command. The command demand the bundleId of the iOS app as an argument and when that is put together we get this command:
driver.execute (
& # x27; mobile: terminateApp,
{
bundleId: & quot; org.reactjs.native.example.SwagLabsMobileAppTests & quot;
}
);
Step 2: Launch Safari and enter the deep link in the address bar
As explained earlier, we now need to open Safari and set the deep connection address. It & # x27; s best to cut this footstep into 2 portion: opening Safari and then entering the deep link.
Opening an iOS app can be perform withmobile: launchApp. The command needs the bundleId of the iOS app, in this case the bundleId of Safari, as an argument and when that is put together we get this bidding.
(An overview of all bundleIds of the Apple apps can be planthere)
driver.execute (
& # x27; mobile: launchApp & # x27;,
{
bundleId: & # x27; com.apple.mobilesafari & # x27;
}
);
When the launchApp bid has successfully been executed Safari will be opened like this:

Now comes the tricky part. This component cost me some cephalalgia because it was the well-nigh flaky component of the deep link process, but I finally got it stable, so let & # x27; s check it out. First of all, we need to think about the step a normal user would take to enrol a url in Safari, which would be:
Click on the speech bar
Enter the url
Submit the url
Secondly, proceed in psyche that we get Appium withThe App in the capabilities, meaning we are in the native context. For the next step we need to stay in the aboriginal context, so we can use Appium Desktop to explain the step we need to direct.
When we depart Appium Desktop and open Safari we demand to cognize the selector of the address bar. Since we know that XPATH might be the dumb locater (seeHow to Speed Up Native Appium iOS Test Execution by Knowing How Appium Works), we want to use a faster locater. Because the reference bar has a name attribute with the value URL, you might think we can use the Accessibility ID locator (which we can), but that one will give us back two elements: both the XCUIElementTypeButton and the XCUIElementTypeOther (which will guide long to act with).

In this case I would advise that we use the iOS predicate string locator to specifically take the url-button ingredient. I would also apprise that we use a wait strategy to be certain that the element is visible and ready for interaction. The code would look something like this:
const urlButtonSelector = & # x27; type == \ & # x27; XCUIElementTypeButton\ & # x27; & amp; & amp; name CONTAINS \ & # x27; URL\ & # x27; & # x27;;
const urlButton = $ (` -ios predicate string: $ {urlButtonSelector} `);
// Wait for the url button to look and click on it so the text field will appear
urlButton.waitForDisplayed (DEFAULT_TIMEOUT);
urlButton.click ();
If we would now refresh the screen in Appium Desktop we would see that the XCUIElementTypeButton element is not there anymore, but change to a XCUIElementTypeTextField constituent with the like URL gens property. If we would get used the Accessibility ID locator, so this would have been the second point that could cause flakiness. The reason for this is that the shift of element might not be pick up at the same swiftness for Appium, create it refer to the already-disappeared XCUIElementTypeButton factor, and thus causing the script to fail to interact.

To set the value we & # x27; re going to use the iOS predicate string locator again. After setting the url we also need to submit the url. This can be execute by clicking on the Go push on the keyboard, but this can also turn flaky if the keyboard doesn & # x27; t look. Appium allows you to likewise use Unicode characters like Enter (delimitate as Unicode code point \uE007) when using setValue. This means we can set and state the url with one command:
const urlFieldSelector = & # x27; type == \ & # x27; XCUIElementTypeTextField\ & # x27; & amp; & amp; name CONTAINS \ & # x27; URL\ & # x27; & # x27;;
const urlField = $ (` -ios predicate twine: $ {urlFieldSelector} `);
// Submit the url and add a break
urlField.setValue (& # x27; theapp: //login/darlene/testing123\uE007 & # x27;);
When the url has been posit a notification pop-up appears. This brings us to our last step.
Note: Keep in nous that this script has been made on an English iOS simulator; if you have a different words, the selector text (URL) might be different.
Step 3: Confirm the notification pop-up
After state the url we alone need to wait for the notification pop-up to appear and click on the Open button. To keep the locator strategy align we are likewise going to use the iOS predicate twine locator hither.

With the postponement command the codification would look like this:
// Wait for the notification and accept it
const openSelector = & # x27; type == \ & # x27; XCUIElementTypeButton\ & # x27; & amp; & amp; name CONTAINS \Open\ & # x27; & # x27;;
const openButton = $ (` -ios predicate string: $ {openSelector} `);
openButton.waitForDisplayed (DEFAULT_TIMEOUT);
openButton.click ();
Note: Keep in head that this script has been made on an English iOS simulator; if you have a different words, the selector schoolbook (Open) might be different.
Making it crabby platform
We & # x27; ve created a deep link script for Android (a one-liner) and for iOS (more complex), so now let & # x27; s make it a cross platform helper method that can be utilize for both platforms. If we stitch all codification together we can make the next help:
1/**2* Create a cross platform solution for open a deep link3*4* @param{string}url5*/6exportfunctionopenDeepLinkUrl(url){7const prefix =& # x27; swaglabs: // & # x27;;89if(driver.isIOS){10// Launch Safari to open the deep connectedness11driver.execute(& # x27; mobile: launchApp & # x27;,{bundleId:& # x27; com.apple.mobilesafari & # x27;});1213// Add the deep nexus url in Safari in the ` URL ` -field14// This can be 2 different component, or the button, or the text field15// Use the predicate string because the availableness label will return 2 different case16// of elements making it flaky to use. With predicate string we can be more precise17consturlButtonSelector=& # x27; type == \ & # x27; XCUIElementTypeButton\ & # x27; & amp; & amp; gens CONTAINS \ & # x27; URL\ & # x27; & # x27;;18consturlFieldSelector=& # x27; type == \ & # x27; XCUIElementTypeTextField\ & # x27; & amp; & amp; gens CONTAINS \ & # x27; URL\ & # x27; & # x27;;19const urlButton =$(`-ios predicate string:${urlButtonSelector}`);20const urlField =$(`-ios connote string:${urlFieldSelector}`);2122// Wait for the url button to look and click on it so the textbook battleground will appear23// iOS 13 now has the keyboard open by default because the URL battleground has focus when open the Safari browser24if(!driver.isKeyboardShown()){25urlButton.waitForDisplayed(DEFAULT_TIMEOUT);26urlButton.click();27}2829// Submit the url and add a break30urlField.setValue(`${ prefix }${ url }\uE007`);3132// Wait for the notification and accept it33constopenSelector=& # x27; type == \ & # x27; XCUIElementTypeButton\ & # x27; & amp; & amp; name CONTAINS \ & # x27; Open\ & # x27; & # x27;;34constopenButton=$(`-ios predicate twine:${openSelector}`);35openButton.waitForDisplayed(DEFAULT_TIMEOUT);3637returnopenButton.click();38}3940// Life is so much easier41return driver.execute(& # x27; mobile: deepLink & # x27;,{42url:`${ prefix }${ url }`,43package:& # x27; com.swaglabsmobileapp & # x27;,44});45}
Note: Keep in judgement that this script has been made on an English iOS simulator; if you have a different language the selector text (URL/Open) might be different.
The assistant (which you can also see) can then be employ like this in some tryout code:
1describe(& # x27; Deep linking & # x27;,()=>{2it(& # x27; should be able to open the Swag overview screenlogin with a deep link & # x27;,()=>{3// ... do something before4openDeepLinkUrl(& # x27; plunder-overview/0,1,2login/alice/mypassword);56// ... do something after7});8});9
So now you never necessitate to worry on how to use deep linking for Android and iOS on emulators, simulator and real devices; they all work!
To try this out using Sauce Labs program, you cansign up for a gratuitous runstory and let me know how it goes. Happy examination!
Sauce Labs Senior Solutions Architect Wim Selles helps solve automation challenges by day—and practices his passion for front-end examination automation at nighttime. Wim enjoys make his own node.js modules and contributing to open root projects. You can find Wim on LinkedIn and Twittter @ wswebcreation.
Staff Product Manager at Sauce Labs
Share this situation
Automate This With SUSA
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts needed.
Try SUSA FreeTest Your App Autonomously
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.
Try SUSA Free