Selenium - 通过 BrowserStack 获取整页移动屏幕截图

Selenium - Taking full-page mobile screenshots via BrowserStack

我创建了一个工具,可以在许多桌面和设备配置上的 URL 列表上截取整页屏幕截图。在桌面上,这一切都可以顺利进行,我得到了整页屏幕截图,在所有浏览器和 OS 版本上都没有问题。

尝试在移动设备上执行此操作时出现问题,我猜这是由于我 运行 使用的设备的像素比率所致。

我的方法获取页面的总高度和宽度,以及视口的高度和宽度,基本上获取视口的图像,在必要时滚动,然后在最后,将所有这些拼接成一张图片。

但是,根据我通过 JavaScript 检索的像素比例,屏幕截图从未正确捕获并且无法正确滚动 and/or 未捕获整个页面.横向没关系,它总是高度。好像计算滚动不正确

令我震惊的是,我在网上找不到任何 post 有相同或相似问题的人。所以要么我把它复杂化了,它是如此微不足道以至于它永远不需要 post,要么这比我想象的要难得多,人们没有这样做是有充分理由的

如果有人有任何想法或想法,他们将不胜感激

谢谢!

该方法的代码如下:

public Image GetEntireScreenshot(ArrayList hiddenElementListAfterFirstViewport = null, bool isMobile = false)
        {
            var pixelRatio = 1; 
            if (isMobile) pixelRatio = (int) (long) ((IJavaScriptExecutor) driver).ExecuteScript("return window.devicePixelRatio");

            // Size of page
            var totalWidth = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.offsetWidth") * pixelRatio);
            var totalHeight = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return  document.body.parentNode.scrollHeight") * pixelRatio);

            // Size of the viewport
            var viewportWidth = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.clientWidth") * pixelRatio);
            var viewportHeight = Convert.ToInt32((int)(long)((IJavaScriptExecutor)driver).ExecuteScript("return window.innerHeight") * pixelRatio);


            var screenshot = (ITakesScreenshot)driver;
            ((IJavaScriptExecutor)driver).ExecuteScript("window.scrollTo(0, 0)");

            if (hiddenElementListAfterFirstViewport != null)
            {
                foreach (string hiddenElementXPath in hiddenElementListAfterFirstViewport)
                {
                    IList<IWebElement> elements = driver.FindElements(By.XPath(hiddenElementXPath));
                    foreach (var element in elements)
                    {
                        ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].style.visibility='hidden'", element);
                    }
                }
            }

            if (totalWidth <= viewportWidth && totalHeight <= viewportHeight) return ScreenshotToImage(screenshot.GetScreenshot());

            var rectangles = new List<Rectangle>();

            // Loop until the totalHeight is reached
            for (var y = 0; y < totalHeight; y += viewportHeight)
            {
                var newHeight = viewportHeight;

                // Fix if the height of the element is too big
                if (y + viewportHeight > totalHeight) newHeight = totalHeight - y;

                // Loop until the totalWidth is reached
                for (var x = 0; x < totalWidth; x += viewportWidth)
                {
                    var newWidth = viewportWidth;
                    // Fix if the Width of the Element is too big
                    if (x + viewportWidth > totalWidth) newWidth = totalWidth - x;

                    // Create and add the Rectangle
                    rectangles.Add(new Rectangle(x, y, newWidth, newHeight));
                }
            }

            var stitchedImage = new Bitmap(totalWidth, totalHeight);
            var previous = Rectangle.Empty;
            foreach (var rectangle in rectangles)
            {
                // Calculate scrolling (if needed)
                if (previous != Rectangle.Empty) ((IJavaScriptExecutor) driver).ExecuteScript($"window.scrollBy({rectangle.Right - previous.Right}, {rectangle.Bottom - previous.Bottom})");

                // Calculate the source Rectangle
                var sourceRectangle = new Rectangle(viewportWidth - rectangle.Width,
                                                    viewportHeight - rectangle.Height,
                                                    rectangle.Width, rectangle.Height);

                // Copy the Image
                using (var graphics = Graphics.FromImage(stitchedImage))
                {
                    graphics.DrawImage(ScreenshotToImage(screenshot.GetScreenshot()), rectangle, sourceRectangle, GraphicsUnit.Pixel);
                }

                previous = rectangle;
            }
            return stitchedImage;
        }

您可以使用 ShutterBug 等工具在移动设备上捕获整页屏幕截图,http://automationtesting.in/take-full-page-screenshot-using-shutterbug/

我解决了这个问题,post如果有同样问题的人看到这个 post:

问题出在代码的滚动部分:

if (previous != Rectangle.Empty) ((IJavaScriptExecutor) driver).ExecuteScript($"window.scrollBy({rectangle.Right - previous.Right}, {rectangle.Bottom - previous.Bottom})");

我滚动的是之前乘以像素比率的值,这意味着它们太多了,因为滚动 X 和 Y 值不受设备像素比率的影响。

因此,代码应该是:

if (previous != Rectangle.Empty) ((IJavaScriptExecutor) driver).ExecuteScript($"window.scrollBy({(rectangle.Right - previous.Right) / pixelRatio}, {(rectangle.Bottom - previous.Bottom) / pixelRatio})");