bob.mazzo
bob.mazzo

Reputation: 5637

Using Protractor: Switch to iframe using browser.switchTo().frame

So I have already written the testing script which:

1) Logs into the application framework, then

2) Clicks menu to launch the app which I am testing ("MyAwesomeApp.html" for this post)

And my main problem is: In navpanel-spec.js below, I want to target the https://server/apps/Default.aspx?r=1 URL, then click within the iframe where MyAwesomeApp is running.

**** ERROR Trying to switch to the iframe this way, but it does NOT work:

browser.switchTo().frame(element(by.id('1')).getWebElement());

Error in cmd prompt:

 Started
 [15:43:29] E/launcher - No element found using locator: By(css selector, *[id="\31 "])
 ...
 sat-navpanel-spec.js:52:24)

So there are two URLs going on here:

1) https://server/apps/Default.aspx?r=1 (the main app framework with menu system in top nav).

2) https://server/apps/MyAwesomeApp.html (the web app which the test script launches within the <iframe> tag.

The html looks like this, where the application renders within the <iframe> :

<body>
<div id="top">
    <!-- top nav menu systems rendered here -->
</div>
<div id="middle">
    <div id="m1">
        <div id="m2" class="hidden">
            <div id="m3">
                <div id="right" class="hidden">
                    <div>
                        <div id="frame_holder" style="height: 940px;">
                            <iframe style="width: 100%; height: 100%;" name="1" id="1" src="https://server/apps/MyAwesomeApp.html">
                            </iframe>
                        </div>
                    </div>
                </div>
            </div>
            <div id="left" style="display: none;"></div>
        </div>
    </div>
</div>
</body>

In my Protractor.config.js file I have a few specs :

specs: [     
 'spec/login.js',
 'spec/launch-awesome-app.js',
 'spec/navpanel-spec.js',        
 'spec/another-spec.js',
 'spec/yet-another-spec.js'
]

login.js and launch-awesome-app.js work fine. They log into the menu system, then click thru the menus in order to launch myAwesomeapp - no problem.

MY PROBLEM:

In navpanel-spec.js I want to target the https://server/apps/Default.aspx?r=1 URL, then click within the iframe where MyAwesomeApp is running.

However, it is NOT selecting any of my elements.

If I target https://server/apps/MyAwesomeApp.html in navpanel-spec.js, of course it launches a new browser window and runs the test just fine.

Here's my navpanel-spec.js test spec:

describe('Testing My Awesome App', function () {
    
    var panelObj = new PanelObjects();
    
    var urlDefault = 'https://server/apps/Default.aspx?r=1';
    var urlApp = 'https://server/apps/MyAwesomeApp.html';

    browser.get(urlApp);    // Runs my AwesomeApp tests okay, HOWEVER it launches a new browser window.

    browser.get(urlDefault);    // Launches app framework with top nav menus and embedded <iframe>, 
                                // HOWEVER I cannot select iframe and successfully run tests here.

    beforeEach(function () {
        browser.sleep(5000);
        browser.waitForAngular();
    });    

    // USE-CASE OBJECT !!
    var items = browser.params.useCaseJsonFile["navigatePanels"];


    browser.getAllWindowHandles().then(function (handles) {
        handles.map(function (win, idx) {
    
            browser.driver.getCurrentUrl().then(function (curr) {
                if (curr.indexOf('Default.aspx') >= 0) {
                    browser.driver.switchTo().window(handles[idx]);        
                }
            });
        });

    });

    browser.switchTo().frame(element(by.id('1')).getWebElement());
    var testId =  element(by.id('middle'));
    console.log(testId);

    items.map(function (item) {
        if (item.enableTest) {
            var specItem = it(item.name, function () {

                console.log('------------------------------');
                console.log('---- ' + item.describe);

                browser.waitForAngular();

                // select panels, etc..
                panelObj.panelClick(item.panelName).then(function () {                    
                    // ...
                });
                
                panelObj.getPanelText(item.panelName).then(function (title) {
                    expect(title).toContain(item.panelTitle);
                });
                
            });
        }
    });

});

UPDATE

var LoginObjects = require('../pageObjects/login-objects.js');
describe('Testing My Awesome App', function () {

var panelObj = new PanelObjects();
var loginObj = new LoginObjects();

//var urlDefault = 'https://server/apps/Default.aspx?r=1';        
//browser.get(urlApp);    // Runs my AwesomeApp tests okay, HOWEVER it launches a new browser window.

browser.ignoreSynchronization = true;

// LOGIN AND LAUNCH APP !!!    
loginObj.Login();
loginObj.Launch();

beforeEach(function () {
    browser.sleep(5000);
    browser.waitForAngular();
});    

// USE-CASE OBJECT !!
var items = browser.params.useCaseJsonFile["navigatePanels"];

// SWITCH TO iframe ELEMENT
loginObj.switchWindowAndFrame();

items.map(function (item) {
    if (item.enableTest) {
	var specItem = it(item.name, function () {

	    console.log('------------------------------');
	    console.log('---- ' + item.describe);

	    browser.waitForAngular();

	    // select panels, etc..
	    panelObj.panelClick(item.panelName).then(function () {                    
		// ...
	    });

	    panelObj.getPanelText(item.panelName).then(function (title) {
		expect(title).toContain(item.panelTitle);
	    });

	});
    }
});

});

and my page objects :

module.exports = function(){
    this.Login = function(){

        var url = browser.params.loginUrl;        
        browser.driver.get(url);        
        browser.sleep(200);
        
        var userName = browser.params.credential.userId;
        var password = browser.params.credential.password;

        element(by.id('username')).clear().then(function(){
            element(by.id('username')).sendKeys(userName);
            element(by.id('password')).sendKeys(password);
        });
        
        browser.sleep(1000);

        var that = this;

        var submitElement = element(by.id('bthLogin')); 
        submitElement.click().then(function () {
            browser.getAllWindowHandles().then(function (handles) {
                        
                // LOGIN MESSAGE WINDOW
                browser.driver.getCurrentUrl().then(function(curr){                
                    if (curr.indexOf('LoginMsg.aspx') >= 0){
                        // Do we really need to close the login successful browser ???                    
                        browser.driver.close();
                    }
                });
                
                browser.driver.switchTo().window(handles[1]);
                
            });       
        });
        
    },

    this.Launch = function(){
        var sel = '#TheMenu1 > ul > li:first-child'; 

        var elem = element(by.css(sel));
        elem.click().then(function(){
            browser.sleep(1000);

            var elem2 = element(by.cssContainingText('.rmLink', 'The First Menu Item'));               
            elem2.click();  

            // Select menu item; sleep before attempting to click().
            var subElem = element(by.cssContainingText('.rmLink', 'My Awesome App'));
            browser.sleep(1000);
            
            subElem.click();
            browser.waitForAngular(); 
        });
    },

    this.switchWindowAndFrame = function(){

        browser.getAllWindowHandles().then(function (handles) {

            handles.map(function(win, idx){
                browser.driver.getCurrentUrl().then(function(curr){                    
                    if (curr.indexOf('Default.aspx') >= 0){                
                        browser.driver.switchTo().window(handles[idx]);                        
                    }
                });
            });

        });

        browser.switchTo().frame(element(by.css('[name="1"]')).getWebElement());
    }

};

Upvotes: 2

Views: 3528

Answers (1)

radio_head
radio_head

Reputation: 1375

As mentioned in the comments above, protractor has a bug which prefixes '\3' to your id element with number.

The temporary way is to change you locator. :P

Upvotes: 1

Related Questions