I'm trying to write e2e tests using Nightwatch for a chrome extension. The extension inserts an iframe onto certain pages. I'm able to start up chrome with the extension but run into an error when I try to switch into the frame
Here is my test:
module.exports = {
'My test' : function (browser) {
browser
.url('https://myurl.com')
.waitForElementVisible('iframe[id=my_frame]', 5000)
.frame('my_frame')
.end();
}
};
Here is the error message:
INFO Response 200 POST /session/b747140552587912484ec27e0d91cd27/frame
(6ms) { sessionId: 'b747140552587912484ec27e0d91cd27', status: 8,
value: { message: 'no such frame: element is not a frame
(Session
info: chrome=58.0.3029.96)\n (Driver info: chromedriver=2.29.461591
(62ebf098771772160f391d75e589dc567915b233),platform=Windows NT
6.1.7601 SP1 x86_64)' } }
LOG → Completed command frame (10 ms)
I know the frame is there, because I can pause the test and inspect the page. Also nightwatch successfully finds the frame element in the waitForElementVisible command.
Here's the html
<iframe id="my_frame" src="chrome-extension://honkfenocfnhdbpakgenabnlnpgccadm/html/iframe/test.html" scrolling="false" style="width: 440px; transform: translateX(0px);"></iframe>
What am I doing wrong?
This looks like a chromium bug in case others run into this issue:
https://bugs.chromium.org/p/chromedriver/issues/detail?id=1777
Have you tried adding a .pause(1000) before switching to the frame?
Related
Using "nightwatch": "^1.0.11" and "browserstack-local": "^1.3.4"
I have tried this many ways, but I cannot get the examples in the documentation to run.
I have a simple login page with a page object
module.exports = {
url: function() {
return this.api.launchUrl + '/login';
},
elements: {
email: {
selector: '#user_login_email'
},
password: {
selector: '#user_login_password'
},
button: {
selector: '#login-btn'
}
}
};
I then want to run a test to login into the site (NOTE: The first screenshot is fine)
module.exports = {
before(client) {
client.maximizeWindow();
},
'Login' : function (client) {
var login = client.page.login();
login.navigate();
client.waitForElementPresent('body', 500)
.saveScreenshot('tests_output/login.png');
login.setValue('#email', 'test#user.email')
.setValue('#password', 'Pa55w0rd')
.click('#button');
client.pause(1000)
.saveScreenshot('tests_output/login-complete.png');
},
after(client) {
client.end();
}
};
I get the following errors when trying to run the test through browserstack (with the local URL)
✖ login.test
– Login (5.196s)
An error occurred while running .setValue() command on <Element [name=#email]>: Error: First argument passed to .elementIdValue() should be a web element ID string. Received object.
at Function.validateElementId (node_modules/nightwatch/lib/api/protocol.js:36:19)
at ProtocolActions.elementIdValue (node_modules/nightwatch/lib/api/protocol.js:951:25)
at transport.locateElement.then.result (node_modules/nightwatch/lib/api-loader/element-command.js:106:54)
at process._tickCallback (internal/process/next_tick.js:68:7)
at process._tickCallback (internal/process/next_tick.js:68:7)
at process._tickCallback (internal/process/next_tick.js:68:7)
An error occurred while running .setValue() command on <Element [name=#password]>: Error: First argument passed to .elementIdValue() should be a web element ID string. Received object.
[...]
An error occurred while running .click() command on <Element [name=#button]>: Error: First argument passed to .elementIdClick() should be a web element ID string. Received object.
[...]
I have gotten successful tests to run; just not using the documented examples.
For example, the below code works fine to close a cookie message
client
.waitForElementPresent('.cookie-message__button', 5, true, function(result) {
client.elementIdClick(result.value[0].ELEMENT);
})
.saveScreenshot('tests_output/cookie-closed.png');
But obviously it's really long winded.
Any help for what I'm doing wrong would be awesome.
Using the following as an example for the Nightwatch config: https://github.com/browserstack/nightwatch-browserstack/blob/master/conf/local.conf.js with the local runner and running tests in parallel in 3 browsers: https://github.com/browserstack/nightwatch-browserstack/blob/master/scripts/local.runner.js
TL;DR: Documentation examples don't work with version 1.0.11; but Nightwatch and Browserstack are configured correctly as can get a suite to run (in Travis and locally), just with very long-winded code, which I hacked together.
I have created sample project for page objects model here. Also, sample login test is added using page_objects_path.
The compatibility for latest nightwatch version is also added. The latest version of nightwatch seems to have changes which are in compliant with w3c. So we need to use 'browserName' as capability instead of 'browser'
How can I switch to an IFrame with Codeception using ID? Actually I can use the name of the IFrame but not the ID -> Codeception SwitchToIFrame
IFrame Example:
<iframe id="iframeToolbar" src="link" frameborder="0" style="position: fixed; left: 0px; top: 0px; z-index: 998; width: 940px;" scrolling="no" width="100px" height="100%"></iframe>
Codeception Example:
<?php
# switch to iframe
$I->switchToIFrame("another_frame");
# switch to parent page
$I->switchToIFrame();
Is it maybe a Codeception <-> Facebook Webdriver Connection Problem?
EDIT: I reinstalled Codeception, followed the Quick Step Guide. Result - the Problem is still the same: Codeception and the Facebook Webdriver doesn't want to work together. My Codeception Code
acceptance.suite.yml:
actor: AcceptanceTester
modules:
enabled:
- \Helper\Acceptance
- WebDriver:
url: https://xxxxxxxxxxxxxx.com
browser: chrome
window_size: maximize
clear_cookies: true
codeception.yml:
paths:
tests: tests
output: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs
actor_suffix: Tester
extensions:
enabled:
- Codeception\Extension\RunFailed
settings:
colors: true
OS: Windows 10
PHP: 7.1.7
PHPUnit: 6.4.4
Selenium Server: 3.8.1
Codeception: 2.3.7
Chrome: 63.0.3239.108
I had this issue, testing a page with a Google reCaptcha in it ... the reCaptcha is in its own iframe, and since that iframe is generated by 3rd-party code, we have no control over its name attribute (at least when it's first generated).
What I ended up doing was running a javascript snippet which can find the iframe based on other things, and then giving it an id, so that Codeception Webdriver could switch to it:
public function _clickOnCaptcha(AcceptanceTester $I)
{
// give the recaptcha iframe a name so codeception webdriver can switch to it
$recaptcha_frame_name = 'recaptcha-frame';
$I->executeJS("$('.g-recaptcha iframe').attr('name', '$recaptcha_frame_name')");
$I->switchToIFrame($recaptcha_frame_name);
$I->see('not a robot');
$I->seeElement('.rc-anchor');
$I->click(['id' => 'recaptcha-anchor']);
$I->switchToIFrame(); // switch back to main window
}
I did have control over the containing elements, so in this case, it's contained within an element with class g-recaptcha ... so we use jquery to find the iframe inside that element: $('.g-recaptcha iframe'), and then give it a name attribute: .attr('name', '$recaptcha_frame_name').
Then we can use Codeception to switch to it and click the captcha checkbox:
$I->switchToIFrame($recaptcha_frame_name);
$I->click(['id' => 'recaptcha-anchor']);
Then, when we're done, switch back out to the main frame so we can submit our form:
$I->switchToIFrame(); // switch back to main window
NB, I'm using the reCaptcha test keys, as specified here, in the testing environment so that it will never actually ask to solve a captcha.
https://developers.google.com/recaptcha/docs/faq
With the following test keys, you will always get No CAPTCHA and all verification requests will pass.
Site key: 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
Secret key: 6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe
The reCAPTCHA widget will show a warning message to claim that it's only for testing purposes. Please do not use these keys for your production traffic.
First of all, in your case the problem might be that you're not calling the acceptance tester. You should start your script with this:
<?php
$I = /*am a */ new AcceptanceTester($scenario);
Now to get into an IFrame in Codeception using the WebDriver:
You just have to name the IFrame in a string, using EITHER the ID or the name. Here is an example:
There is a page with the IFrame:
<iframe name = "IFrameByName" id = "IFrameByID" width = "500" height = "300" src = "https://messagetothefish.com"></iframe>
This IFrame contains the string, "No one knows who discovered water" but the parent frame does not. I tested this Cept with PhantomJS and Selenium.
<?php
$I = /*am a */ new AcceptanceTester($scenario);
$I->wantTo('See how Iframes work');
$I->amOnUrl("https://wordpress-bdd.com/codeception-iframe/");
$I->dontSee("No one knows who discovered water");
//Switch by name
$I->switchToIFrame("IFrameByName");
$I->see("No one knows who discovered water");
//switch back to parent
$I->switchToIFrame();
$I->dontSee("No one knows who discovered water");
//Switch by ID
$I->switchToIFrame("IFrameByID");
$I->see("No one knows who discovered water");
$I->dontSee('Lorum Ipsum');
//switch back to parent
$I->switchToIFrame();
$I->dontSee("No one knows who discovered water");
My script has some syntax error but instead of showing the error, PhantomJS doesn't display anything. Why Phantom JS isn't showing parse error if he script has errors?
In the following PhantomJS script (running via windows CMD), phantomJs hangs instead of showing error if there is a parsing error in the script.
var system = require('system');
var webpage = require('webpage').create();
console.log('starting script');
if (system.args.length === 0) {
console.log('no args');
} else {
system.args.forEach(function(arg,index){
console.log('arg is '+arg+' at '+index);
});
}
webpage.open('http://localhost:3000/cookie-demo',function(status){
if (status === 'success'){
console.log('success in opening page');
phantom.cookies.forEach(function(cookie,index){
for ( var key in cookie){
/*if instead of index, I use i as variable (undefined), the script just hangs!*/
console.log('[cookie:'+index+']'+key+'='+'cookie[key]');
}
});
phantom.exit(0);
}
else{
console.log('could not open the page');
phantom.exit(1);
}
});
If there is no syntax error in the script, I get following output
C:\Users\Manu\Documents\manu\programs\random>phantomjs --cookies-file=cookie-jar.txt phantomTest.js
starting script
arg is phantomTest.js at 0
success in opening page
[cookie:0]domain=cookie[key]
[cookie:0]expires=cookie[key]
[cookie:0]expiry=cookie[key]
[cookie:0]httponly=cookie[key]
[cookie:0]name=cookie[key]
[cookie:0]path=cookie[key]
[cookie:0]secure=cookie[key]
[cookie:0]value=cookie[key]
[cookie:1]domain=cookie[key]
[cookie:1]expires=cookie[key]
[cookie:1]expiry=cookie[key]
[cookie:1]httponly=cookie[key]
[cookie:1]name=cookie[key]
[cookie:1]path=cookie[key]
[cookie:1]secure=cookie[key]
[cookie:1]value=cookie[key]
But if there is a syntax error, I see nothing on the console and it doesnt exit
C:\Users\Manu\Documents\manu\programs\random>phantomjs --cookies-file=cookie-jar.txt phantomTest.js
PhantomJS version 2.0 and 2.1 will silently fail and hang if there are syntax errors. Use versions 1.9.8 or 2.5 betas. All downloads are here: https://bitbucket.org/ariya/phantomjs/downloads/
Better still migrate to Puppeteer which is a project with very similar API that uses headless Google Chrome underneath.
I'm trying to make a test for a login webpage where there is the possibility of using Thirdparties social login. When you click on facebook icon, for example, a new popup appears asking for user/password. I'm using waitForPopup and withPopup as specified by the documentation to handle that, but is not working. Is never finding the element (via xpath) inside the xpath, so I can never log in using facebook in our test.
This is an example code that check if the facebook button is there, click on it and wait for the popup:
casper.then(function() {
test.comment("When we click facebook button");
casper.waitForSelector(x(facebookButton), function() {
test.assertExists(x(facebookButton), "Facebook icon is showing");
casper.click(x(facebookButton));
}, function timeout() { // step to execute if check has failed
casper.test.fail("Timeout loading login page");
});
});
casper.then(function() {
casper.waitForPopup(/facebook\.com\/login/, function() {
test.comment("And we fill facebook login info");
casper.withPopup(/facebook\.com\/login/, function() {
this.viewport(1600, 900);
casper.sendKeys(x(facebookEmail), facebookLogin[0]);
casper.sendKeys(x(facebookPassword), facebookLogin[1]);
casper.click(x(facebookLogin));
});
}, function timeout() { // step to execute if check has failed
casper.test.fail("Timeout loading faceebook login");
});
});
The output of the test is:
# When we click facebook button
PASS Facebook icon is showing
# And we fill facebook login info
FAIL Cannot get informations from xpath selector: //input[#id='email']: element not found.
# type: uncaughtError
# file: casper/import-login-testing.js:1058
# error: Cannot get informations from xpath selector: //input[#id='email']: element not found.
# CasperError: Cannot get informations from xpath selector: //input[#id='email']: element not found.
# at getElementInfo (/Users/ginogalotti/testing-presentation/node_modules/casperjs/modules/casper.js:1058)
# at /Users/ginogalotti/testing-presentation/node_modules/casperjs/modules/casper.js:1589
# at casper/import-login-testing.js:84
# at runStep (/Users/ginogalotti/testing-presentation/node_modules/casperjs/modules/casper.js:1553)
# at checkStep (/Users/ginogalotti/testing-presentation/node_modules/casperjs/modules/casper.js:399)
# stack: not provided
For me, that means that is finding the popup, the waitForPopup is triggering and is just not using the popup to look for the facebookEmail element. I'm still learning about casperjs, so probably this is not even the best way to approach the problem; but I would really thank some guidance.
Thanks in advance,
Example website that I'm testing: https://import.io/login
Am new to protractor. I found some errors while automating the URL using protractor. And I can access the URL manually and does not find any issues. Please find the code mentioned below and kindly clarify my concern.
Screenshot of cmd while executing the code
exports.config={
specs: ['try.js'],
//seleniumArgs: ['-browserTimeout=60']
capabilities:{
'browserName':'chrome',
},
baseUrl:'',
allScriptsTimeout:3000,
//getPageTimeout:5000,
framework:'jasmine2',
jasmineNodeOpts: {
defaultTimeoutInterval:56000,
isVerbose: true,
}
}
spec: try.js
===========
describe('first try',function(){
var EW=protractor.ExpectedConditions;
beforeEach(function(done){
ignoreSynchronization=true;
browser.get('');
});
it('open PO',function(){
//clicking login button
var login=element(by.linkText('Login'));
browser.wait(EW.presenceOf(login),10000);
login.click();
//clicking open Po dashboard icon/link
var po=element(by.linkText('Open PO'));
browser.wait(EW.presenceOf(po),20000);
po.click();
//entering value 100 in the fiter field
var e=element.all(by.repeater('colFilter in col.filters')).get(00).element(by.tagName('input'));
browser.wait(EW.presenceOf(e),10000);
e.sendKeys(100);
//selecting the filterd values and printing it in console
element.all(by.repeater('col in colContainer.renderedColumns track by col.uid').column('Entity')).getText().then(console.log);
});
});
Make sure you have ng-app defined on all of your pages. Protractor requires it to run. If the page has redirects or just takes some time before it loads, try something like this:
browser.get(websiteUrl);
browser.wait(function () {
return browser.executeScript('return !!window.angular');
}, 10000, 'Error: Angular was not found on the page within ten seconds');
This will wait up to ten seconds for angular to load up, and fail if it is not there.