Clicking on an intent url(non http link) inside a webview - SOLVED

When building some tests to check deep linking on Android I came across a problem; Clicking on an element with a browsable intent doesn’t work on appium. It does work, appium clicks on the element, but it doesn’t launch the intent.

Playing around a little bit I realize the intent would launch if instead of using an href="intent://...", I use an onclick="window.open('intent://...')" event, so I change my href to an onclick event. It work, but I wasn’t fulfill with this solution.

Creating an issue on github, @jonahss recommend that instead of clicking on the element directly on the browser, I should try clicking on the element coordinates in native contexts, and it works.

If you are tryning to launch an intent and know what your element is going to be in your webview, and it wont change along time or tests, you should search for the element in native contexts and use a touch action over this element.

In my case, I don’t know what the element containing the intent:// url would be, 'cause i’m testing many different sites, and dont know if the element would have an id or class to look for. Instead I search the element in webview that has the intent:// and get it’s location. Then I change to context, get the webview location in the native contexts, calculate the location of the element with the intent and use a touch action on the calculated location.

My test ends up looking like this;

import wd from 'wd';
import assert from 'assert';
export default function test(caps) {
   let browser = wd.remote('localhost', caps.port);
   let webViewXPath = '//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.webkit.WebView[1]/android.view.View[1]';

    let pressAction = (driver, coords) => {
        let action = new wd.TouchAction(driver);
        action.press({x:coords.x,y:coords.y}).wait(10).release()
       return action;
    }

    let localTest = (caps) => {
       browser.elementByLinkText('Open app', (err, el) => {
           log("Clicking on element");
           intentClick(browser, el);
       });
    }

    let intentClick = (driver, el) => {
        let elCoords;
        // get element location
        driver.getLocation(el, (err, coords) => {
            if(err) return error(err);
            elCoords = coords;
            driver.context('NATIVE_APP', (err) => {
                if(err) return error(err);
                driver.elementByXPath(webViewXPath, (err, el) => {
                  if(err) return error(err);
                  driver.getLocation(el, (err, coords) => {
                      if(err) return error(err);
                      let action = pressAction(driver, {x: elCoords.x, y: (coords.y + elCoords.y)});
                      action.perform( (err) => {
                          if(err) return error(err);
                          browser.quit();
                          caps.cb(true);
                     });
                 });
             });
         });
     });
   }

    let error = (caps, err) => {
        browser.quit();
        caps.cb(false, {error: err});
    }

    browser.init({browserName:'Chrome',deviceName:'Android',platformName: 'Android'}, 
        () => {
          log("Opening url: "+caps.url);
          browser.get(caps.url, () => {
              localTest(caps);  
          });
    });
}

Hope this helps.

1 Like

Thanks for the writeup :smile:

1 Like