Selenium Webdriver Black Screenshot PhantomJS - javascript

Testing a site using Cucumber and Selenium. In my hooks.js file I have the following:
driver.get("https://localhost:8000/");
sleep(2000);
TakeScreenshot('./test_artifacts/img/', 'Load Success', driver);
var btn = this.driver.wait(selenium.until.elementLocated(By.css('#app > div > div > div.col-xs-6.textColumn > button'), seleniumTimeOut));
TakeScreenshot('./test_artifacts/img/', 'Load Success', driver);
this.driver.sleep(3000);
The objective here is to successfully load the page and to take a screenshot of it. The website is running off of localhost. The problem occurs when a screenshot is taken. No matter how long I get driver to sleep I get a black screenshot, indicating to me that the website is not 'building' in time (to use what may be an incorrect term, given the circumstances). I then get this error:
Waiting for element to be located By(css selector, #app > div > div > div.col-xs-6.textColumn > button)
Wait timed out after 20112ms
If I change the URL to https://google.com/ I get a screenshot of the site, no problem. Any ideas what is happening here? Is my above hypothesis correct?
Thanks in advance!

Please try to wait until some other elements to be available. Use xpath locator instead CSS. Is your machine behind proxy? if means please add the phantom browser in behind the proxy.
var phantom = require('phantom');
phantom.create(function(browser){
browser.createPage(function(page){
browser.setProxy('98.239.198.83','21320','http', null, null, function(){
page.open(
'http://example.com/req.php', function() {
});});});});

First, change the driver to chrome driver and see what is script is doing after changing the URL. The different environment some time have different id's and XPath which affect the script. so before moving to phantomjs directly first check the behaviour of your script with common drivers like chrome or firefox.
I have gone through the same scenario and I have experienced the same situation. It's a silly mistake which was wasted my half of the day :p
Hope it will help you :)

The problem seems to have been a certification problem. The tests would run on http but when localhost was using https the tests would fail.
I worked around it by adding the following to this.BeforeFreature in my hooks.js file:
this.driver = new selenium.Builder()
.withCapabilities({'phantomjs.cli.args': ['--ignore-ssl-errors=true']})
.forBrowser('phantomjs')
.build();

Related

Multiple screenshot with Firefox Developer Tools

I am trying take screenshots of a page that loads a series of content (slideshow) via Javascript. I can take screenshots of individual items with Firefox Devtools just fine. However it's tedious to do so by hand.
I can think of a few options-
Run the 'screenshot' command in a loop and call a JS function in each loop to load the next content. However I can't find any documentation to script the developer tools or call JS functions from within it.
Run a JS script on the page to load the contents at an interval and call the devtools to take a screenshot each time. But I can't find any documentation on calling devtools from JS in webpage.
Have Devtools take screenshots in response to a page event. But I can't find any documentation on this either.
How do I do this?
Your first questions is, how to take screenshots with javascript in a programmed way:
use selenium Webdriver to steer the browser instead of trying to script the developer tools of a specific browser.
Using WebdriverJS as framework you can script anything you need around the Webdriver itself.
Your second question is, how to script the FF dev tools:
- no answer from my side -
I will second Ralf R's recommendation to use webdriver instead of trying to wrangle the firefox devtools.
Here's a webdriverjs script that goes to a webpage with a slow loading carousel, and takes a screenshot as soon as the image I request is fully loaded (with this carousel, I tell it to wait until the css opacity is 1). You can just loop this through however many slide images you have.
var webdriver = require('selenium-webdriver');
var By = webdriver.By;
var until = webdriver.until;
var fs = require("fs");
var driver = new webdriver.Builder().forBrowser("chrome").build();
//Go to website
driver.get("http://output.jsbin.com/cerutusihe");
//Tell webdriver to wait until the opacity is 1
driver.wait(function(){
//first store the element you want to find in a variable.
var theEl = driver.findElement(By.css(".mySlides:nth-child(1)"));
//return the css value (it can be any value you like), then return a boolean (that the 'result' of the getCssValue request equals 1)
return theEl.getCssValue('opacity').then(function(result){
return result == 1;
})
}, 60000) //specify a wait of 60 seconds.
//call webdriver's takeScreenshot method.
driver.takeScreenshot().then(function(data) {
//use the node file system module 'fs' to write the file to your disk. In this case, it writes it to the root directory of my webdriver project.
fs.writeFileSync("pic2.png", data, 'base64');
});

Navigating inside website and taking screenshot through code

I need to take screenshots of multiple separate shopping websites for the final checkout page.
All selections of items in cart and other navigation to pages must be through code.
The output screenshots should be in image file(jpg,png) or inserted in a docx file(if possible)
What tool and technology can I use for this task?
I have a little idea about screen capture through php and phantomjs but for a static webpage only. I am a newbie and would be happy if someone guides me here.
For example:
To open google.com, search for "stackoverflow" and further opening stackoverflow.com and take a screenshot of the homepage. These steps must be done via code (i.e) automated. Thanks in advance guyz!!
The Selenium website has an example of how to do something similar to this from Java (using Firefox as the browser) at http://www.seleniumhq.org/docs/03_webdriver.jsp#introducing-the-selenium-webdriver-api-by-example
Here's a quick TL;DR version. It doesn't click through to Stack Overflow but instead should take a screenshot of the Google results for that term. Going via Google when you already know the URL of the site may be a redundant step anyway, I am sure you can modify this example to make it do what you need it to.
WebDriver driver = new FirefoxDriver();
driver.get("http://www.google.com");
// Find the text input element by its name
WebElement element = driver.findElement(By.name("q"));
element.sendKeys("Stack Overflow");
element.submit();
// Google's search is rendered dynamically with JavaScript.
// Wait for the page to load, timeout after 10 seconds
(new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
return d.getTitle().toLowerCase().startsWith("Stack Overflow");
}
});
// Screenshot of search results (screen not whole page)
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("c:\\screenshot.png"));
Screenshot code is from Sergii Pozharov's answer at Take a screenshot with Selenium WebDriver - see that for other considerations such as choice of driver.

Unable to load script from another server - Content Security Policy issue?

I have been trying to turn a bookmarklet into a small development environment that I can use for testing some javascript and sending commands easily on the fly and updating the code on my server quickly to see the result. This has half way worked using method's I have found in this site and google however it doesn't seem to work very well and sometimes randomly doesn't work. The end goal is to have a bookmarklet that I can click on from any page and it loads a javascript file I have saved on my server. I have created the following two bookmarklets to try and get this working:
Failed Method 1:
javascript:
var s = document.createElement('script');
s.type='text/javascript';
document.body.appendChild(s);
s.src='//smewth.com/test.js';
void(0);
Method 1 in one line bookmarklet form: javascript: var s = document.createElement('script'); s.type='text/javascript'; document.body.appendChild(s); s.src='//smewth.com/test.js'; void(0);
Failed Method 2:
javascript:(
function(){
var imported = document.createElement('script');
imported.type='text/javascript';
imported.src = 'https://smewth.com/test.js';
document.head.appendChild(imported);
})();
Method 2 in one line bookmarklet form: javascript:( function(){ var imported = document.createElement('script'); imported.type='text/javascript'; imported.src = 'https://smewth.com/test.js'; document.head.appendChild(imported); })();
I got method 1 by decomposing the kickass bookmarklet from (http://kickassapp.com/). The actual one I got from their site works fine on my browser no problems. I even did a direct substitution from the URL they were using to load with my URL. The second method I found while searching on this site and this actually worked for a small while and stopped working for some unknown reason (maybe different browsers). I tried appending this script object to the head and the body on each of them with no improved results.
I created the test.js script just for this post and it contains a simple alert box statement:
$$ [/]# cat test.js
alert("hi");
$$ [/]#
NOTE: When I do this with the code embedded within the the bookmarklet itself without appending it to a head/body object then it works fine such as this:
javascript:%20alert("hi");
I did notice that with both of these methods, the code is actually getting injected into the page however I am not seeing the code is ever executed when I click the bookmark. Does anyone know which method is the best or something similar to do this so I can have javascript load through a page which I update on a remote server (reliably)? Maybe I need to attach the to a different object?
Thank you for your help.
-Jeff
UPDATE: I am showing this works while this site is loaded but it doesn't work when your at a site like google.com. Not sure what the difference is or how to accomodate this, google.com has a head and a body object too. I am showing this works in some sites and in some it doesn't.
I figured this out. There were two things occurring which accounts for the intermittent symptom of this issue. The first issue was that the site which was hosting the code was on a self-signed certificate. I began to notice the issue was occurring only when trying to run this from within secure sites. Then in Chrome I saw a error show up in the console. It would be nice if Firefox gave me a error on the console or something as this was the root of the issue. The second thing I had to do was disable OCSP in Firefox as I used a free certificate for testing purposes.
I also had to use method 1 as described above. Firefox and Chrome both did not like the anonymous function call for some reason. From now on I will refer to Chrome to look for errors in the console as Firefox has proven itself not very useful for this.

Can I get the address bar url from the javascript console when the page has failed to load?

Just say I typed in a bad hostname in the address bar.
For example, say I wasn't running a local web server, and I load:
http://localhost/callback_url
In Chrome, this will give me a "This webpage is not available" message.
Is there anyway I can find out what the url is in the address bar from the Javascript console, even though the page failed to load?
I know I can normally use window.location.href to get this, but that returns "data:text/html,chromewebdata" in this instance.
So in this example, I'd like to know if there's some javascript that returns http://localohost/callback_url
EDIT: The main reason I'd like to do this is so I know if server side redirect failed when using ChromeDriver with Selenium. So I'd prefer to avoid using extensions if possible, and am open to Chrome and ChromeDriver specific solutions if applicable! The callback_url may have extra info in it, added by the server, and I'd like to see what this info is. I'd like to avoid running another server to get this data if possible.
The loadTimeData object included in the ERR_CONNECTION_REFUSED page has the failed URL:
> loadTimeData.data_.summary.failedUrl
"http://localhost/foo?request_url=bar"
You can get it from the title of the page.
By typing document.title and doing some regex you can get the URL.
Another way I found is by using the following
var data = loadTimeData.createJsEvalContext();
console.log(data.a.$top.summary.failedUrl);
If you open the developer tools and search for a part of the URL in source code, you will see that Chrome creates the loadTimeData in the "not available page".

Unable to post message to http://www.youtube.com. Recipient has origin https://www.youtube.com

My app at http://beta.billboard.fm is producing errors in my normal browsing session after playing a single song.
If i reload the page in incognito, the app works fully. I only recently starting experiencing these issues. I have completed cleared all of the cache and it works again, but only temporarily before throwing the same errors.
Additionally I have disable all browser extensions.
But, no matter what I do I can't get this error from being thrown by the Youtube API:
Unable to post message to http://www.youtube.com. Recipient has origin https://www.youtube.com
It looks like there is a mismatch in the security protocols. I tried changing them to https or just removing "http:" all together on my side. But it did not resolve the issue.
Any one have an idea what is happening here?
It is quite clear to me at this point that this is a major bug in Google/YouTube's API. They have written some bad code somewhere. This bug is not a consistent thing. This is well documented by the fact that everybody's code works just fine for an extended period of time, and then they discover that all of a sudden their sites stop working properly. Additionally, all of my websites that had this problem last week are now working without a glitch - again, without me altering code.
So while it sucks to say this - the onus is on Google & YouTube to fix this and provide APIs that actually work as advertised... It doesn't look to me like there's anything we can do about it on our own :(
I am having the same problem - I also tried changing my links to http: to https: and vice-versa with no luck. I found this tread on Google Groups, but so far there has been no response. https://code.google.com/p/gdata-issues/issues/detail?id=4697
Clearing my cache allowed the player to work for a few videos, but after 3 or 4, the same error pops back up.
UPDATE 2 - Dec. 24, 2013: This solution has not actually fixed the problem at all:
After following a thread that poulified referred me to in his answer, a user in the forum posted the following solution which seems to be doing the trick for me (UPDATE: Still experiencing issues on random page loads :/):
Hi all,
It is working for replacing http:// with https://
example: http://jsfiddle.net/8tkgW/29/
Please make sure the following tips
load iframe api https://www.youtube.com/player_api
load iframe src path: https://www.youtube.com/embed/0GN2kpBoFs4?rel=0
If load player via new YT.Player, you must check the iframe src path:
setTimeout(function(){
var url = $('#iframe_youtube').prop('src');
if (url.match('^http://') {
$('#iframe_youtube').prop('src', url.replace(/^http:\/\//i, 'https://'));
}
}, 500);
Please refer my github project:
https://github.com/appleboy/js-video-player/blob/master/js/jsplayer.js#L120

Categories