I’m using Selenium for some browser-controlling stuff and mostly use Chrome with the ChromeDriver. But in Version 2.x, ChromeDriver only takes screenshots for the visible area of the screen.
So I created a Script in C# which scrolls around the page, taking screenshots and then stitches it all together.
The code should be easy to port into other languages.
// Get the Total Size of the Document int totalWidth = (int)EvalScript("return document.width"); int totalHeight = (int)EvalScript ("return document.height"); // Get the Size of the Viewport int viewportWidth = (int)EvalScript ("return document.body.clientWidth"); int viewportHeight = (int)EvalScript ("return document.body.clientHeight"); // Split the Screen in multiple Rectangles List rectangles = new List (); // Loop until the Total Height is reached for (int i = 0; i < totalHeight; i += viewportHeight) { int newHeight = viewportHeight; // Fix if the Height of the Element is too big if (i + viewportHeight > totalHeight) { newHeight = totalHeight - i; } // Loop until the Total Width is reached for (int ii = 0; ii < totalWidth; ii += viewportWidth) { int newWidth = viewportWidth; // Fix if the Width of the Element is too big if (ii + viewportWidth > totalWidth) { newWidth = totalWidth - ii; } // Create and add the Rectangle Rectangle currRect = new Rectangle(ii, i, newWidth, newHeight); rectangles.Add(currRect); } } // Build the Image var stitchedImage = new Bitmap(totalWidth, totalHeight); // Get all Screenshots and stitch them together Rectangle previous = Rectangle.Empty; foreach (var rectangle in rectangles) { // Calculate the Scrolling (if needed) if (previous != Rectangle.Empty) { int xDiff = rectangle.Right - previous.Right; int yDiff = rectangle.Bottom - previous.Bottom; // Scroll RunScript(String.Format("window.scrollBy({0}, {1})", xDiff, yDiff)); System.Threading.Thread.Sleep(200); } // Take Screenshot var screenshot = ((ITakesScreenshot)_driver).GetScreenshot(); // Build an Image out of the Screenshot Image screenshotImage; using (MemoryStream memStream = new MemoryStream(screenshot.AsByteArray)) { screenshotImage = Image.FromStream(memStream); } // Calculate the Source Rectangle Rectangle sourceRectangle = new Rectangle(viewportWidth - rectangle.Width, viewportHeight - rectangle.Height, rectangle.Width, rectangle.Height); // Copy the Image using (Graphics g = Graphics.FromImage(stitchedImage)) { g.DrawImage(screenshotImage, rectangle, sourceRectangle, GraphicsUnit.Pixel); } // Set the Previous Rectangle previous = rectangle; } // The full Screenshot is now in the Variable "stitchedImage"
The EvalScript just executes the Javascript and returns the Value, so it should look like:
public override T EvalScript(string script) { IJavaScriptExecutor js = (IJavaScriptExecutor)_driver; return (T)js.ExecuteScript(script); }