Make it short and simple
Issue
For automated tests on a visual level -- e.g. against a style guide -- there is always the requirement to compare screenshots. The problems are:
- Selenium only understands the possibility to get the current screen as a screenshot.
- If the element is not directly on the view, you have to scroll horizontally to see the element.
- If a new element is inserted later before the element to be tested, the test breaks because the position is no longer correct.
Resolution
So we need a solution that will:
- scrolls dynamically to the position of the element
- returns only the part of the element as a partial screenshot
Code
In the function we first fetch the IWebDriver from the element. Then we move the screen with a Selenium Action to the desired element.
To ensure that the whole element is in the visible area, we also scroll the height and width of the element using Javascript.
Then we take the complete screenshot and cut out the desired area.
Function
public static Bitmap GetElementScreenshot(IWebElement element) {
IWebDriver driver = ((IWrapsDriver)element).WrappedDriver;
Actions actions = new Actions(driver);
actions.MoveToElement(element);
actions.Perform();
IJavaScriptExecutor executor = (IJavaScriptExecutor)driver;
int yOffset = Convert.ToInt32(executor.ExecuteScript($"window.scrollBy({element.Size.Width}, {element.Size.Height}); return window.pageYOffset;"));
Screenshot sc = ((ITakesScreenshot)driver).GetScreenshot();
var img = Image.FromStream(new MemoryStream(sc.AsByteArray)) as Bitmap;
return img.Clone(new Rectangle(element.Location.X, element.Location.Y - yOffset, element.Size.Width, element.Size.Height), img.PixelFormat);
}
You can also implement the code as an IWebDriver extension
IWebDriver Extension
public static Bitmap GetElementScreenshot(this IWebDriver driver, IWebElement element) {
Actions actions = new Actions(driver);
actions.MoveToElement(element);
actions.Perform();
IJavaScriptExecutor executor = (IJavaScriptExecutor)driver;
int yOffset = Convert.ToInt32(executor.ExecuteScript($"window.scrollBy({element.Size.Width}, {element.Size.Height}); return window.pageYOffset;"));
Screenshot sc = ((ITakesScreenshot)driver).GetScreenshot();
var img = Image.FromStream(new MemoryStream(sc.AsByteArray)) as Bitmap;
return img.Clone(new Rectangle(element.Location.X, element.Location.Y - yOffset, element.Size.Width, element.Size.Height), img.PixelFormat);
}
Kommentare
Kommentar veröffentlichen