RobotiumTech / robotium

Android UI Testing
http://www.robotium.org
Apache License 2.0
2.86k stars 786 forks source link

Accessing an iFrame inside a WebView #794

Open mimo84 opened 9 years ago

mimo84 commented 9 years ago

In Selenium it is possible to switch context to move to an iFrame and click/perform actions at the iFrame level. For example we might have a webpage like:

<body>
  <input type="text" />
  <iframe>
     <body>
        <button></button>
     <body>
  </iframe>
</body>

In selenium is possible to do something like:

WebElement iframe = driver.findElement(By.cssSelector("iframe"));
driver.switchTo().frame(iframe);
// At this point is possible to interact with the elements within the iFrame.

Is it possible to do the same with Robotium? We're currently evaluating Robotium as testing framework and this feature is vital to us.

renas commented 9 years ago

Yes. Please use Solo.Config.webframe. An example:

solo.getConfig().webFrame = "iframe_a";

On Sun, Nov 8, 2015 at 7:04 PM, Maurizio notifications@github.com wrote:

In Selenium it is possible to switch context to move to an iFrame and click/perform actions at the iFrame level. For example we might have a webpage like:

In selenium is possible to do something like: WebElement iframe = driver.findElement(By.cssSelector("iframe")); driver.switchTo().frame(iframe); // At this point is possible to interact with the elements within the iFrame. Is it possible to do the same with Robotium? We're currently evaluating Robotium as testing framework and this feature is vital to us. — Reply to this email directly or view it on GitHub https://github.com/RobotiumTech/robotium/issues/794.
mimo84 commented 9 years ago

Thanks, it works perfectly, I can't find any documentation about it though. What if I have multiple iframes in the page or I have to switch back and forth between the main document and the iframes?

Thank you for your help though!

renas commented 9 years ago

If you want to go back to default you can just set the string to empty: solo .getConfig().webFrame = "";

You can switch between frames and document at any time.

On Mon, Nov 9, 2015 at 1:29 PM, Maurizio notifications@github.com wrote:

Thanks, it works perfectly, I can't find any documentation about it though. What if I have multiple iframes in the page or I have to switch back and forth between the main document and the iframes?

Thank you for your help though!

— Reply to this email directly or view it on GitHub https://github.com/RobotiumTech/robotium/issues/794#issuecomment-155202896 .

mimo84 commented 9 years ago

I rectify what I said previously. I have something like this:

<!doctype html>
<html>
    <head>
      <title>iFrame Test</title>
    </head>
    <body>
        <p>This is outside of the iframe</p>

        <p>Outside of the iframe again</p>

        <input type="text" id="outsideinput" placeholer="out">

        <iframe id="myiframe" frameborder="0" style="height:100vh; width:100vw; "></iframe>

        <script>
        window.onload = function () {
          var doc = document.getElementById('myiframe').contentWindow.document;
          doc.open();
          doc.write('<html><head><title></title></head><body><input id="insideinput"  placeholer="in" /></body></html>');
          doc.close();
        }
        </script>
    </body>
</html>

In Robotium test I have:

   WebElement input = solo.getWebElement(By.cssSelector("input#outsideinput"), 0);
    solo.clickOnWebElement(input);
    solo.typeTextInWebElement(input, "Outside the iframe");

    solo.getConfig().webFrame = "frame_a"; // tried iframe, myiframe

    WebElement insideInput = solo.getWebElement(By.cssSelector("input#insideinput"), 0);
    solo.clickOnWebElement(insideInput);
    solo.typeTextInWebElement(insideInput, "Inside the iFrame");

However it seems that the driver cannot find the contents of the iFrame. What am I doing wrong?

mimo84 commented 9 years ago

I've got it to work by using a different By.locatorMethod. Quickly skimming the code it appears that the config.webframe substitution doesn't happen for all the methods in the JavaScript. For example in:

function id(id, click) {
  var element = document.getElementById(id);
  ...
}

But looking by using the className function you have:

function className(nameOfClass, click) {
    var walk=document.createTreeWalker(document.getElementById("myiframe").contentDocument, NodeFilter.SHOW_ELEMENT, null, false);
}

I hope this makes sense to you.