- 首页
- 其他开发
- 使用量角器:使用 browser.switchTo().frame 切换到 iframe
使用量角器:使用 browser.switchTo().frame 切换到 iframe
[英] Using Protractor: Switch to iframe using browser.switchTo().frame
本文介绍了使用量角器:使用 browser.switchTo().frame 切换到 iframe的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
所以我已经编写了测试脚本:
1) 登录应用框架,然后
2) 单击菜单以启动我正在测试的应用程序(本文为MyAwesomeApp.html")
我的主要问题是:在下面的 navpanel-spec.js
中,我想针对 https://server/apps/Default.aspx?r=1 URL,然后在运行 MyAwesomeApp 的 iframe 中点击.
**** ERROR 尝试以这种方式切换到 iframe
,但它不起作用:
browser.switchTo().frame(element(by.id('1')).getWebElement());
cmd 提示错误:
开始[15:43:29] E/launcher - 使用定位器找不到元素:By(css selector, *[id="\31 "])...sat-navpanel-spec.js:52:24)
所以这里有两个 URL:
1) https://server/apps/Default.aspx?r=1(顶部导航中带有菜单系统的主要应用框架).
2) https://server/apps/MyAwesomeApp.html(测试脚本在
标签内启动.
html 看起来像这样,应用程序在
中呈现:
<div id="顶部"><!-- 在此处呈现的顶级导航菜单系统-->
<div id="中间"><div id="m1"><div id="m2" class="隐藏"><div id="m3"><div id="right" class="隐藏"><div><div id="frame_holder" style="height: 940px;"><iframe style="宽度:100%;高度:100%;"name="1" id="1" src="https://server/apps/MyAwesomeApp.html"></iframe>
<div id="left" style="display: none;"></div>
在我的 Protractor.config.js 文件中,我有一些规范:
规格:['规范/登录.js','spec/launch-awesome-app.js','spec/navpanel-spec.js','spec/another-spec.js','spec/yet-another-spec.js']
login.js
和 launch-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
,当然它会启动一个新的浏览器窗口并运行测试就好了.
这是我的 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);//运行我的 AwesomeApp 测试没问题,但是它会启动一个新的浏览器窗口.browser.get(urlDefault);//启动带有顶部导航菜单和嵌入式 <iframe> 的应用程序框架,//但是我无法选择 iframe 并在此处成功运行测试.beforeEach(函数(){浏览器睡眠(5000);browser.waitForAngular();});//用例对象!!var items = browser.params.useCaseJsonFile["navigatePanels"];browser.getAllWindowHandles().then(function (handles) {handles.map(function (win, idx) {browser.driver.getCurrentUrl().then(function (curr) {如果 (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'));控制台日志(testId);项目.地图(功能(项目){如果(item.enableTest){var specItem = it(item.name, function () {console.log('------------------------------');console.log('---- ' + item.describe);browser.waitForAngular();//选择面板等...panelObj.panelClick(item.panelName).then(function () {//...});panelObj.getPanelText(item.panelName).then(function (title) {期望(标题).toContain(item.panelTitle);});});}});});
更新
var LoginObjects = require('../pageObjects/login-objects.js');描述('测试我很棒的应用程序',函数(){var panelObj = new PanelObjects();var loginObj = new LoginObjects();//var urlDefault = 'https://server/apps/Default.aspx?r=1';//browser.get(urlApp);//运行我的 AwesomeApp 测试没问题,但是它会启动一个新的浏览器窗口.browser.ignoreSynchronization = true;//登录并启动应用程序!!!loginObj.Login();loginObj.Launch();beforeEach(函数(){浏览器睡眠(5000);browser.waitForAngular();});//用例对象!!var items = browser.params.useCaseJsonFile["navigatePanels"];//切换到 iframe 元素loginObj.switchWindowAndFrame();项目.地图(功能(项目){如果(item.enableTest){var specItem = it(item.name, function () {console.log('------------------------------');console.log('---- ' + item.describe);browser.waitForAngular();//选择面板等...panelObj.panelClick(item.panelName).then(function () {//...});panelObj.getPanelText(item.panelName).then(function (title) {期望(标题).toContain(item.panelTitle);});});}});});
和我的页面对象:
module.exports = function(){this.Login = function(){var url = browser.params.loginUrl;browser.driver.get(url);浏览器睡眠(200);var userName = browser.params.credential.userId;var 密码 = browser.params.credential.password;element(by.id('username')).clear().then(function(){element(by.id('username')).sendKeys(userName);element(by.id('password')).sendKeys(password);});浏览器睡眠(1000);var that = this;var submitElement = element(by.id('bthLogin'));submitElement.click().then(function () {browser.getAllWindowHandles().then(function (handles) {//登录消息窗口browser.driver.getCurrentUrl().then(function(curr){如果 (curr.indexOf('LoginMsg.aspx') >= 0){//我们真的需要关闭登录成功的浏览器吗???browser.driver.close();}});browser.driver.switchTo().window(handles[1]);});});},this.Launch = 函数(){var sel = '#TheMenu1 >升 >li:第一个孩子';var elem = element(by.css(sel));elem.click().then(function(){浏览器睡眠(1000);var elem2 = element(by.cssContainingText('.rmLink', '第一个菜单项'));elem2.click();//选择菜单项;在尝试 click() 之前先休眠.var subElem = element(by.cssContainingText('.rmLink', 'My Awesome App'));浏览器睡眠(1000);subElem.click();browser.waitForAngular();});},this.switchWindowAndFrame = function(){browser.getAllWindowHandles().then(function (handles) {handles.map(function(win, idx){browser.driver.getCurrentUrl().then(function(curr){如果 (curr.indexOf('Default.aspx') >= 0){browser.driver.switchTo().window(handles[idx]);}});});});browser.switchTo().frame(element(by.css('[name="1"]')).getWebElement());}};
解决方案
正如在上面的评论中提到的,量角器有一个错误,它在你的 id 元素前加上数字前缀 '\3'.
临时方法是更改您的定位器.:P
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());
}
};
解决方案
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
这篇关于使用量角器:使用 browser.switchTo().frame 切换到 iframe的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文