Direkt zum Hauptbereich

C# .NET -- Make partial screenshots in Selenium with no effort

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

Beliebte Posts aus diesem Blog

DevOps Shorty - Validating Environment Variables in the Azure Build Pipeline

Validating Environment Variables in the Azure Build Pipeline Automated tests often require environment variables, e.g. to define the test browser, access data or the interval for the test. With a simple Powershell at the beginning of the pipeline these can be easily validated. $browsers = @("Chrome","IE","Edge", "Firefox") If ($browsers -NotContains $env:TEST_BROWSER) { Throw "$($env:TEST_BROWSER) is not a valid Browser or environment var 'TEST_BROWSER' is not set. Use $($Browsers) instead." } if($env:TEST_FILTER_CRITERIA.Length -lt 10) { Throw "$($env:TEST_FILTER_CRITERIA) is not a valid filter or environment var 'TEST_FILTER_CRITERIA' is not set. Use something like 'Category=basetest' instead." } This ensures that the required environment variables are set correctly at the beginning of the pipeline.