使用 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.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
,当然它会启动一个新的浏览器 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
所以我已经写好了测试脚本:
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.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
,当然它会启动一个新的浏览器 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