Как я могу снять скриншот с полной высоты мобильного форм-фактора?

При тестировании мобильных форм-факторов Chrome скриншоты - только видимое окно. Я в порядке с тем, что это стандартное и ожидаемое поведение. Тем не менее, я также хочу захватить полную прокручиваемую высоту страницы, чтобы я мог проверить рендеринг всей страницы.

Я подумал, что самым простым решением было установить высоту окна хром как достаточно большое значение и выполнить работу. Тем не менее, высота окна Chrome кажется связанной моей физической высотой экрана, т.е. Я установил его на 5000 с browser.manage().window().setSize(375,5000);, но он изменился только до высоты 1200.

Я уже знаю [Согласно спецификации WebDriver] [1], функция [ takeScreenshot()] [2] не должна захватывать всю страницу, но должна делать снимок только видимой области.

Ответ 1

ED EDIT: я пошел с окончательным вариантом, ниже которого я назвал "Рабочее решение!!"

Ниже приведены различные стратегии группировки по типу для решения проблемы.


Прокрутка, снимок экрана, добавление

Цитата автора системы скриншотов на сайте CrossBrowserTesting.com:

Как автор системы скриншотов для CrossBrowserTesting.com, я могу сказать вам, что единственный способ, которым мы могли получить полные скриншоты страниц последовательно и надежно в браузерах, - это прокручивать, захватывать и добавлять изображения.

Вот пример рабочей реализации прокрутки и снятия видимых снимков области с помощью cnn.com в качестве примера. Используя scrollHeight, clientHeight и scrollTop, чтобы определить, где мы находимся в вертикальной позиции прокрутки, и о том, сколько прокрутить вниз. Поскольку мы имеем дело с promises в цикле, мы должны сделать рекурсивную функцию с базовым условием "мы находимся внизу":

var fs = require('fs'),
    Utils = {
        screenShotDirectory: '',

        writeScreenShot: function (data, filename) {
            var stream = fs.createWriteStream(this.screenShotDirectory + filename);

            stream.write(new Buffer(data, 'base64'));
            stream.end();
        },

        getSizes: function () {
            return browser.executeScript("return {scrollHeight: document.body.scrollHeight, clientHeight: document.body.clientHeight, scrollTop: document.body.scrollTop};");
        },

        scrollToBottom: function (height, index) {
            var self = this;

            self.getSizes().then(function (data) {
                // continue only if we are not at the bottom of the page
                if (data.scrollTop + data.clientHeight < data.scrollHeight) {
                    browser.executeScript("window.scrollTo(0, arguments[0]);", height).then(function () {
                        browser.takeScreenshot().then(function (png) {
                            self.writeScreenShot(png, "test" + index + ".png");
                        });
                    });
                    self.scrollToBottom(height + data.clientHeight, index + 1);
                }
            });
        }
    };

describe("Scrolling and saving screenshots", function () {
    beforeEach(function () {
        browser.ignoreSynchronization = true;
        browser.get("http://www.cnn.com/");
    });

    it("should capture an entire page", function () {
        Utils.getSizes().then(function (data) {
            Utils.scrollToBottom(data.clientHeight * 2, 1);
        });
    });
});

Он будет создавать несколько изображений test<index>.png, которые вы затем можете склеить вместе.

Чтобы объединить изображения в виде "одного столбца", вы можете, например, использовать GraphicsMagick систему обработки изображений через gm nodejs module. .montage() метод с опцией concatenate в режиме 1x было бы полезно. Пример кода:

var gm = require('gm');

Utils.getSizes().then(function (data) {
    var index = Utils.scrollToBottom(data.clientHeight * 2, 1);

    var op = gm();
    for (var i = 1; i <= index; i++) {
        op = op.in("test" + i + ".png");
    }

    op = op.montage().mode("concatenate").tile("1x");

    op.write('output.png', function (err) {
        if (err) console.log(err);
    });
});

Изменить браузер

В Chrome вы всегда получите только видимую область на скриншоте, вот соответствующая проблема chromedriver с большой информацией об этой проблеме и множестве обходных решений:

Несколько удивительно, он должен работать в Firefox - переключитесь на него, если это возможно:

Скриншоты Chrome, которые занимают весь экран, не похожи на Firefox. Firefox будет захватывать весь экран, даже его части, которые в настоящее время недоступны для просмотра. Chrome не будет!


Изменить размер экрана

Другим вариантом будет использование таких сервисов, как BrowserStack или SauceLabs, чтобы начать тесты на определенной платформе в определенном браузере и, используя определенное достаточно большое разрешение. Транспортир поддерживает Sauce Labs и BrowserStack из коробки.

Пример конфигурации для браузера:

exports.config: {
  browserstackUser: "user",
  browserstackKey: "key",

  capabilities: {
    'browserstack.local': true,
    'browserstack.debug': true,

    browserName: "Chrome",
    os: "Windows",
    os_version: "8",
    resolution: "2048x1536"
  },
}

Затем увеличьте окно браузера (например, внутри onPrepare()):

browser.driver.manage().window().maximize();

И сделайте снимок экрана.


Рабочее решение!!!

Другим вариантом может быть запуск тестов на виртуальном дисплее. Я бы следовал этот блогпост и использовал Xvfb, когда вы запустите сервер Xvfb, вы можете указать разрешение:

/usr/bin/Xvfb :99 -ac -screen 0 2048x6000x24 &

Также см. соответствующую информацию по этой теме:


Вы также можете использовать docker-selenium решение, которое позволяет для настройки размера экрана.