4

I am trying to write a test that needs to access elements in an iframe. (Picture a drawing of a room with 20 chairs, each of these chairs is its own object, I need to be able to access these chairs). Using developer tools and the element finder it only highlights the iframe but does not allow me access. I'm very very new to testing so I am at a loss.

The element in the html when highlighting the iframe is like this:

<iframe name="daasFrame" class="daas-surface" frameborder="0" width="100%" height="100%" ng-src="/Drawing/EventDiagram/e020c975-6f1f-4c6c-bf34-34fa7221c8f3/?venueId=&amp;seatingStyle=theater&amp;language=en&amp;units=Imperial&amp;theme=default&amp;shiftHeader=true"
src="/Drawing/EventDiagram/e020c975-6f1f-4c6c-bf34-34fa7221c8f3/?venueId=&amp;seatingStyle=theater&amp;language=en&amp;units=Imperial&amp;theme=default&amp;shiftHeader=true"></iframe>

I figured in the test alone I can do a switch to, however I have no idea what the elements would be called to interact.

giri-sh
  • 6,934
  • 2
  • 25
  • 50
Nicole Phillips
  • 753
  • 1
  • 18
  • 41
  • Take a look on http://stackoverflow.com/questions/16103407/get-html-inside-iframe-using-jquery – Joao Polo Sep 18 '15 at 13:16
  • You mean you want to get the elements inside iframe using protractor code? or you want to access them using developer tools so that you can code using those elements? – giri-sh Sep 18 '15 at 13:18
  • I use an inverse manner... On iframe, you can access functions on caller, using parent.anyFunction()... and then, on iframe init, I call something like parent.getConfig() and I do the actions needed. – Joao Polo Sep 18 '15 at 13:20
  • @Girish The way I have been writing tests is through the element picker on developer tools. Chrome has an element locator which allows me to click on an element and will bring me the code. However I cannot get the html for the iframe. I don't know how – Nicole Phillips Sep 18 '15 at 13:20
  • I understand, so you want to get the elements in the iframe so you can use them to automate something. right? If so, how you want to get it? Is it using element locator or using protractor code ? – giri-sh Sep 18 '15 at 13:23
  • @Girish yes I want to use protractor code for my tests so will need to be able to access the elements. However I cant even find what the elment names would even be as I don't know how to view them on the page. I right click in the iframe to view page source however it seems right click is disabled. – Nicole Phillips Sep 18 '15 at 13:24

4 Answers4

3

There are two ways of doing it. First using the developer tools in chrome (if use firefox then firebug plugin can help). If you open developer tools you can always access the whole html.

Open the webpage you want to test -> Click on the menu on the top right corner of chrome -> 
select more tools -> developer tools

You should be able to see complete html of your webpage including iframe. Now you can go to the iframe section and then search for body tag in that to see the elements loaded. Hovering on them will give you the elements.

Second way is a bit tough one where you can get the html elements using javascript code. Here's how -

browser.executeScript("return document.getElementsByTagName('iframe')[0].contentWindow.document.body.innerHTML;").then(function(html){
    console.log(html);
});

or use protractor code to get inner Html of the element, but do wait until the html inside iframe loads before using it:

var ele = $('.daas-surface body'); //Make sure iframe element has body tag if not use some main element's tag within which you want to access the elements.
browser.wait(protractor.ExpectedConditions.presenceOf(ele), 20000)
.then(function(){
    ele.getInnerHtml().then(function(html){
        console.log(html);
    });
});

getElementsByTagName returns all the element with that tag in the DOM in the form of an array, if you have more than one iframe then use a different value to get different element. Above line will print the complete html inside the iframe but again debugging will be a pain for you. I would suggest the first way. Hope this helps.

giri-sh
  • 6,934
  • 2
  • 25
  • 50
  • I get error: Failed: unknown error: Cannot read property 'contentWindow' of null – Nicole Phillips Sep 18 '15 at 13:45
  • @NicolePhillips Sorry that was my mistake. Use your element identifier in the javascript function that you execute. I updated it to get elements by html tag names. You can as well do it with class, etc... – giri-sh Sep 18 '15 at 14:17
  • I am able to switch to frame. Is there a function where I can just tell it to print the html using log? – Nicole Phillips Sep 18 '15 at 14:59
  • Yes.. try `$('.daas-surface').getInnerHtml().then(function(html){console.log(html);})`. Updated answer with this function too. Note - wait for few seconds before html inside iframe loads. It causes issues if its not loaded. Hope this helps. – giri-sh Sep 18 '15 at 15:01
  • I am getting a maximum call stack error when trying to access a different frame – Nicole Phillips Sep 18 '15 at 18:31
  • You mean there are more than one iframe and you are trying to access more than one to get the inner html of each one? What line are you getting that error? I believe its because your iframe hasn't loaded the data into itself or there is too much of html content that the `getInnerHtml()` function is trying to get. Try getting the data of body element inside iframe and see. – giri-sh Sep 19 '15 at 09:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/90096/discussion-between-girish-sortur-and-nicole-phillips). – giri-sh Sep 19 '15 at 09:11
3

While working on my Automation Test Suite I ran into an instance were I needed to take action outside of an iFrame and verify that the appropriate changes occurred inside of an iFrame. In order to facilitate this jumping back and forth between frames I setup 2 functions in my Page Objects, one to jump into an iFrame and another to jump back to the main window.


To jump into an iFrame I used this:

browser.switchTo().frame(0);

To switch back to the Main window I used this:

browser.switchTo().defaultContent();

Once I was inside of the iFrame I didn't have to do anything special as long as it's an AngularJS page. All element(by.___()) queries reference the iFrame and search from within it. If it's a standard website you'll want to use the unwrapped Selenium syntax in your tests (http://ng-learn.org/2014/02/Protractor_Testing_With_Angular_And_Non_Angular_Sites/).


You can also try this to switch to a particular frame:

browser.switchTo().frame(element(by.className('daas-surface')));
John Stennett
  • 546
  • 3
  • 9
2

Trying to execute a script to get the information you want is probably not the best approach here. If you are using protractor or selenium you can use switchTo to change the context of your selenium commands to the frame(s) you want.

browser.switchTo().frame($('[name=daasFrame]'))

$('#element-inside-frame').getText().then(function (text) {
 console.log(text)
});

// switch back to the "parent page" context
browser.switchTo().defaultContent()

If all you want is the HTML content of the iframe, this should suffice:

$('[name=daasFrame]').getText().then(function (text) {
  console.log(text)
})
Nick Tomlin
  • 28,402
  • 11
  • 61
  • 90
2

Since iframe is consider as a new window. First of all need to switch in to the iframe . The simple solution is

browser.switchTo().frame( element( by.tagName( 'iframe' )).getWebElement());

or else can use className to get the element instead of tagName. Then can get the any elements within the iframe.

after that if need to go back to parent frame

browser.driver.switchToParentFrame();

L Dinuka
  • 21
  • 3