【发布时间】:2016-11-19 04:34:01
【问题描述】:
所以我已经编写了测试脚本:
1) 登录应用框架,然后
2) 点击菜单启动我正在测试的应用程序(本文为“MyAwesomeApp.html”)
我的主要问题是:在下面的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="\31 "])
...
sat-navpanel-spec.js:52:24)
所以这里有两个 URL:
1) https://server/apps/Default.aspx?r=1(顶部导航中带有菜单系统的主应用程序框架)。
2) https://server/apps/MyAwesomeApp.html(测试脚本在<iframe> 标签内启动的网络应用程序。
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.js 和 launch-awesome-app.js 工作正常。他们登录菜单系统,然后单击菜单以启动myAwesomeapp - 没问题。
我的问题:
在navpanel-spec.js 中,我想定位https://server/apps/Default.aspx?r=1 URL,然后在运行MyAwesomeApp 的iframe 中单击。
但是,它没有选择我的任何元素。
如果我在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); // 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' 为前缀。这个bug还在。尝试使用其他定位器
-
好的,我试试css定位器。谢谢。
-
我还尝试将
name和id值从1更改为其他值。在 HTML4 及更低版本中,这 2 个属性不能以数字开头。 -
@finspin - 这也是我想到的第一件事。但是当然,该应用程序已经以这种方式推出了;但是,嘿,值得一试。我总是可以要求我们更改 div ID 属性。感谢您的意见。
-
这与 iframe 的问题没有直接关系,但您的规范文件似乎是耦合在一起的。你应该避免这种情况,因为你会遇到各种各样的问题。将登录/启动功能直接包含到您的
navpanel-spec.js中,或者使用 PageObject 模式 stackoverflow.com/a/31624445/932210 从单独的节点包中调用它。