Reputation: 1253
I upgraded my Watir / Firefox automation stack to the latest version, and added geckodriver with it. I was surprised to see that now screenshots are of the viewport only by default.
require 'watir'
require 'mini_magick'
b = Watir::Browser.new :firefox
b.goto "https://daringfireball.net"
base = b.screenshot.base64
blob = Base64.decode64(base)
image = MiniMagick::Image.read(blob)
image.height
=> 1760 # macOS 'Retina' resolution doubling
b.execute_script "return window.innerHeight"
=> 880 # 880 * 2 = 1760
b.execute_script "return document.documentElement.scrollHeight"
=> 34692
How can I take screenshots of the full page with Watir driving Firefox without rolling back my environment?
Upvotes: 2
Views: 1383
Reputation: 1253
It is now possible to do this in Firefox, employing a geckodriver feature. As far as I know, this feature is not baked into Selenium / probably not a part of the W3C spec.
require 'watir'
browser = Watir::Browser.new :firefox
bridge = browser.driver.session_storage.instance_variable_get(:@bridge)
server_uri = bridge.instance_variable_get(:@http).instance_variable_get(:@server_url)
sid = bridge.instance_variable_get(:@session_id)
driver_path = "session/#{sid}/moz/screenshot/full"
request_url = server_uri.to_s + driver_path
url = URI.parse(request_url)
req = Net::HTTP::Get.new(request_url)
raw = Net::HTTP.start(url.host, url.port) {|http| http.request(req) }.body
base64_screenshot = JSON.parse(raw, symbolize_names: true)[:value]
This approach is also now an option in the watir-screenshot-stitch gem:
require 'watir-screenshot-stitch'
b = Watir::Browser.new :firefox
b.goto "https://github.com/mozilla/geckodriver/issues/570"
base64_screenshot = b.base64_geckodriver
Upvotes: 0
Reputation: 1713
I solved the problem in C#. But the solution I guess can be rewritten on any language. I used a JavaScript library called HTML2Canvas to generate the full page screenshots. Here is the C# code:
[Test]
public void TakingHTML2CanvasFullPageScreenshot()
{
using (var driver = new ChromeDriver())
{
driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(5);
driver.Navigate().GoToUrl(@"https://automatetheplanet.com");
IJavaScriptExecutor js = driver;
var html2canvasJs = File.ReadAllText($"{GetAssemblyDirectory()}html2canvas.js");
js.ExecuteScript(html2canvasJs);
string generateScreenshotJS = @"function genScreenshot () {
var canvasImgContentDecoded;
html2canvas(document.body, {
onrendered: function (canvas) {
window.canvasImgContentDecoded = canvas.toDataURL(""image/png"");
}});
}
genScreenshot();";
js.ExecuteScript(generateScreenshotJS);
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.IgnoreExceptionTypes(typeof(InvalidOperationException));
wait.Until(
wd =>
{
string response = (string)js.ExecuteScript
("return (typeof canvasImgContentDecoded === 'undefined' || canvasImgContentDecoded === null)");
if (string.IsNullOrEmpty(response))
{
return false;
}
return bool.Parse(response);
});
wait.Until(wd => !string.IsNullOrEmpty((string)js.ExecuteScript("return canvasImgContentDecoded;")));
var pngContent = (string)js.ExecuteScript("return canvasImgContentDecoded;");
pngContent = pngContent.Replace("data:image/png;base64,", string.Empty);
byte[] data = Convert.FromBase64String(pngContent);
var tempFilePath = Path.GetTempFileName().Replace(".tmp", ".png");
Image image;
using (var ms = new MemoryStream(data))
{
image = Image.FromStream(ms);
}
image.Save(tempFilePath, ImageFormat.Png);
}
}
You can find more examples and explanations in the article.
Upvotes: 1
Reputation: 1253
Using Watir's .execute_script
, it is possible to repeatedly take screenshots of the viewport while moving the scroll position. It is then possible to stitch images together using MiniMagick.
I developed the watir-screenshot-stitch gem to encapsulate my best approach to solving this problem, though it comes with caveats, which you can read about there. It is also memory intensive and can be slow.
This is not a true full-page screenshot solution, and I would gladly accept any alternative approaches that improve on this.
Upvotes: 1