Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protractor: Testing Angular App in an Iframe

I've got an interesting setup here.

I have an Angular App that loads another Angular App inside an iframe. I'm interested in testing the iframed-in Angular app with Protractor.

Protractor is waiting for the first Angular app to load, but when I switch the iframe with

ptor.switchTo().frame('experience');

I can see that Protractor is not waiting for the iframed Angular app before making assertions. I have tried adding

ptor.waitForAngular();

After switching to the iframe with no luck. Anybody have any ideas what is going on here?

Thanks!

If it helps, I'm running my tests through the Saucelabs ssh tunnel on Chrome. I can tell that the tunneling is working because I see the resources for the iframed app being requested and downloading.

like image 692
Josh Minzner Avatar asked Dec 06 '13 14:12

Josh Minzner


People also ask

Can Protractor be used for Angular?

Protractor is an open-source automation testing framework that is written using NodeJS. It offers combined end to end testing for web applications that are built using AngularJS. It supports both Angular and Non-Angular applications.

Is Angular Protractor deprecated?

Protractor Will Be Deprecated The Angular team has announced the deprecation of Protractor in May 2021.


3 Answers

Testing iframes with protractor is a little bit tricky. It took me a while and a lot of patience to sort of understand what was going on. I hope this helps!

Protrator is built upon WebdriverJS, so you can use the whole package to test iframes. When you start testing with protractor, the first thing you do is get an instance of protractor:

var ptor = protractor.getInstance();

But to test what you have inside the iframe you will need ptor.driver instead of ptor!

var driver = ptor.driver;

Then, when you start writing the test, you find the iframe, you switch to it, you test it with 'driver' and you switch back to the initial frame.

ptor.switchTo().frame(driver.findElement(protractor.By.xpath('xpath-to-iframe')));

// Test iframe with driver
driver.findElement(protractor.By.xpath('some-sort-of-input')).sendKeys('username');
driver.findElement(protractor.By.xpath('other-sort-of-input')).sendKeys('password');
driver.findElement(protractor.By.xpath('other-sort-of-button')).click();

// Switch back to Default Content
ptor.switchTo().defaultContent();

// And WAIT for angular!!
ptor.waitForAngular();

The code that follows is a general example of what I mentioned above:

describe('Protractor iframe Test', function(){

  var ptor, driver;

  beforeEach(function(){
    ptor = protractor.getInstance();
    driver = ptor.driver;
  });

  it('should test the iframe', function(){

    ptor.switchTo().frame(driver.findElement(protractor.By.xpath('xpath-to-iframe')));

    // Test iframe with driver
    driver.findElement(protractor.By.xpath('some-sort-of-input')).sendKeys('username');
    driver.findElement(protractor.By.xpath('other-sort-of-input')).sendKeys('password');
    driver.findElement(protractor.By.xpath('other-sort-of-button')).click();

    // At this point, you can expect() things to happen to the iframe app

    // Switch back to Default Content
    ptor.switchTo().defaultContent();

    // And WAIT for angular!!
    ptor.waitForAngular();

    // Then you can keep testing (or expecting something!)
    expect('this answer').toBe('useful');

  });

});
like image 97
Ithilon Avatar answered Sep 21 '22 05:09

Ithilon


With protractor 2.5.1, @lthilon's answer was giving an 'Invalid Locator' error.

The following syntax resolved that though:

    var driver = browser.driver;
    var loc = by.tagName('iframe');
    var el = driver.findElement(loc);
    browser.switchTo().frame(el);

    driver.findElement(by.tagName('body')).sendKeys('my test string');

    browser.switchTo().defaultContent();
    browser.waitForAngular();
like image 30
stevejpurves Avatar answered Sep 19 '22 05:09

stevejpurves


Switching to an iframe is very simple according to latest protractor API docs 5.4.1:

await browser.switchTo().frame(element(by.xpath('//iframe')).getWebElement());

The context switches to the specified iframe, now every command that you run will be executed on the iframe. Now you can even switch to nested iframes. To switch back to parent iframe:

 driver.switchTo().parentFrame();
like image 20
Bilal Alam Avatar answered Sep 21 '22 05:09

Bilal Alam