使用 Protractor:使用 browser.switchTo().frame 切换到 iframe

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

所以我已经写好了测试脚本:

1) 登录到应用程序框架,然后

2) 单击菜单启动我正在测试的应用程序("MyAwesomeApp.html" 对于此 post)

我的主要问题是:在下面的 navpanel-spec.js 中,我想定位 https://server/apps/Default.aspx?r=1 URL,然后在 MyAwesomeApp 所在的 iframe 中单击 运行。

**** 错误 试图以这种方式切换到 iframe,但它不起作用:

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=" "])
 ...
 sat-navpanel-spec.js:52:24)

所以这里有两个 URL:

1) https://server/apps/Default.aspx?r=1(顶部导航菜单系统的主要应用程序框架)。

2) https://server/apps/MyAwesomeApp.html(测试脚本在 <iframe> 标签内启动的 Web 应用程序。

html 看起来像这样,其中应用程序在 <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>

在我的 Protractor.config.js 文件中,我有一些规格:

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

login.jslaunch-awesome-app.js 工作正常。他们登录到菜单系统,然后单击菜单以启动 myAwesomeapp - 没问题。

我的问题:

navpanel-spec.js 我想定位 https://server/apps/Default.aspx?r=1 URL,然后在 iframe 中单击 MyAwesomeApp 是 运行。

但是,它没有选择我的任何元素。

如果我在 navpanel-spec.js 中定位 https://server/apps/MyAwesomeApp.html,当然它会启动一个新的浏览器 window 并运行测试就好了。

这是我的 navpanel-spec.js 测试规范:

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);
                });
                
            });
        }
    });

});

更新

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);
     });

 });
    }
});

});

我的页面对象:

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());
    }

};

正如上面评论中提到的,量角器有一个错误,它会在您的 id 元素前加上数字前缀“\3”。

暂时的方法是改变你的定位器。 :P