package ru.yandex.qatools.ashot.shooting.cutter; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebDriver; import ru.yandex.qatools.ashot.shooting.InvalidViewportHeightException; /** * Strategy for cutting header and footer with variable height.<br> * For example, Safari browser in iOS 8 introduced a feature (so called 'minimal-ui')<br> * when browser's header might be 65px or 41px (with address bar hidden).<br> * This strategy will get current height of browser's header and footer. * @author <a href="frolic@yandex-team.ru">Vyacheslav Frolov</a> */ public class VariableCutStrategy implements CutStrategy { public static final String SCRIPT = "var h = window.innerHeight || document.documentElement.clientHeight; return h;"; private final int headerMin; private final int headerMax; private final int windowInnerHeightMin; private final int footerMax; private final int footerMin; /** * @param headerMin - minimal header height (for Safari iOS 8 it is 41px) * @param headerMax - maximum header height (for Safari iOS 8 it is 65px) * @param footerMin - minimal footer height (for Safari iOS 8 it is 0px) * @param footerMax - maximum footer height (for Safari iOS 8 it is 89px) * @param windowInnerHeightMin - minimal height of viewportPasting (when header with address bar shown).<br /> * For real device iPad 2 it is 960px (portrait) and 674px (landscape).<br /> * For simulated iPad 2 it is 1225px (portrait) and 687px (landscape). */ public VariableCutStrategy(int headerMin, int headerMax, int footerMin, int footerMax, int windowInnerHeightMin) { this.headerMin = headerMin; this.headerMax = headerMax; this.footerMin = footerMin; this.footerMax = footerMax; this.windowInnerHeightMin = windowInnerHeightMin; } public VariableCutStrategy(int headerMin, int headerMax, int footerMax, int windowInnerHeightMin) { this(headerMin, headerMax, 0, footerMax, windowInnerHeightMin); } public VariableCutStrategy(int headerMin, int headerMax, int windowInnerHeightMin) { this(headerMin, headerMax, 0, windowInnerHeightMin); } @Override public int getHeaderHeight(WebDriver driver) { return getCutHeight((JavascriptExecutor) driver, headerMin, headerMax); } @Override public int getFooterHeight(WebDriver driver) { if (0 == footerMax && 0 == footerMin) { return 0; } return getCutHeight((JavascriptExecutor) driver, footerMin, footerMax); } private int getCutHeight(JavascriptExecutor driver, int heightMin, int heightMax) { final int innerHeight = getWindowInnerHeight(driver); return innerHeight > windowInnerHeightMin ? heightMin : heightMax; } private int getWindowInnerHeight(JavascriptExecutor driver) { final Number innerHeight; try { innerHeight = (Number) driver.executeScript(SCRIPT); } catch (ClassCastException e) { throw new InvalidViewportHeightException("Could not acquire window.innerHeight property!", e); } if (innerHeight == null) { throw new InvalidViewportHeightException("Could not acquire window.innerHeight property! Returned value is null."); } return innerHeight.intValue(); } }