Skip to content
This repository has been archived by the owner on Dec 24, 2023. It is now read-only.

Commit

Permalink
fix: address bar height is falsely calculated with hybrid apps making…
Browse files Browse the repository at this point in the history
… the blockout statusbar fail for Android

This also fixes the calculation of the height of the toolbar for Android
  • Loading branch information
wswebcreation committed Feb 18, 2020
1 parent 7a636dd commit d3f836a
Show file tree
Hide file tree
Showing 20 changed files with 64 additions and 14 deletions.
7 changes: 7 additions & 0 deletions docs/OPTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ The timeout in milliseconds to wait after a scroll. This might help identifying
- **Mandatory:** No
- **Default:** `true`

Tell the module if the used app is an Hybrid app, this will not calculate the address bar height because it is not there.

#### `isHybridApp`
- **Type:** `boolean`
- **Mandatory:** No
- **Default:** `false`

Hide scrollbars in the application. If set to true all scrollbars will be disabled before taking a screenshot. This is set to default `true` to prevent extra issues.

### `savePerInstance`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ describe('getAndroidStatusAddressToolBarHeight', () => {
it('should the the android status, address and toolbar height with only a major version in the navigator', () => {
Object.defineProperty(navigator, 'appVersion', {value: NAVIGATOR_APP_VERSIONS.ANDROID['9'], ...CONFIGURABLE});

expect(getAndroidStatusAddressToolBarHeight(OFFSETS.ANDROID)).toMatchSnapshot();
expect(getAndroidStatusAddressToolBarHeight(OFFSETS.ANDROID, false)).toMatchSnapshot();
});

it('should the the android status, address and toolbar height with major and minor version in the navigator', () => {
Object.defineProperty(navigator, 'appVersion', {value: NAVIGATOR_APP_VERSIONS.ANDROID['8'], ...CONFIGURABLE});

expect(getAndroidStatusAddressToolBarHeight(OFFSETS.ANDROID)).toMatchSnapshot();
expect(getAndroidStatusAddressToolBarHeight(OFFSETS.ANDROID, false)).toMatchSnapshot();
});

it('should the the android status, address and toolbar height with major, minor and patch version in the navigator', () => {
Object.defineProperty(navigator, 'appVersion', {value: NAVIGATOR_APP_VERSIONS.ANDROID['7'], ...CONFIGURABLE});

expect(getAndroidStatusAddressToolBarHeight(OFFSETS.ANDROID)).toMatchSnapshot();
expect(getAndroidStatusAddressToolBarHeight(OFFSETS.ANDROID, false)).toMatchSnapshot();
});
});
7 changes: 4 additions & 3 deletions lib/clientSideScripts/getAndroidStatusAddressToolBarHeight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ import {AndroidOffsets} from '../helpers/constants.interfaces';
* Get the current height of the Android status and address bar
*/
export default function getAndroidStatusAddressToolBarHeight(
androidOffsets: AndroidOffsets
androidOffsets: AndroidOffsets,
isHybridApp: boolean,
): StatusAddressToolBarHeight {
// Determine version for the right offsets
const {height, width} = window.screen;
const {innerHeight} = window;
const match = (navigator.appVersion).match(/Android (\d+).?(\d+)?.?(\d+)?/);
const majorVersion = parseInt(match[1], 10);
const versionOffsets = androidOffsets[majorVersion];
const statusAddressBarHeight = versionOffsets.STATUS_BAR + versionOffsets.ADDRESS_BAR;
const toolBarHeight = height - innerHeight - statusAddressBarHeight;
const statusAddressBarHeight = versionOffsets.STATUS_BAR + (isHybridApp ? 0 : versionOffsets.ADDRESS_BAR);
const toolBarHeight = versionOffsets.TOOL_BAR;

// Determine status, address and tool bar height
return {
Expand Down
1 change: 1 addition & 0 deletions lib/commands/checkElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export default async function checkElement(
savePerInstance: checkElementOptions.wic.savePerInstance,
},
isAndroidNativeWebScreenshot: instanceData.nativeWebScreenshot,
isHybridApp: checkElementOptions.wic.isHybridApp,
platformName: instanceData.platformName,
};

Expand Down
1 change: 1 addition & 0 deletions lib/commands/checkFullPageScreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export default async function checkFullPageScreen(
savePerInstance: checkFullPageOptions.wic.savePerInstance,
},
isAndroidNativeWebScreenshot: instanceData.nativeWebScreenshot,
isHybridApp: checkFullPageOptions.wic.isHybridApp,
platformName: instanceData.platformName,
};

Expand Down
1 change: 1 addition & 0 deletions lib/commands/checkScreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export default async function checkScreen(
savePerInstance: checkScreenOptions.wic.savePerInstance,
},
isAndroidNativeWebScreenshot: instanceData.nativeWebScreenshot,
isHybridApp: checkScreenOptions.wic.isHybridApp,
platformName: instanceData.platformName,
};

Expand Down
10 changes: 9 additions & 1 deletion lib/commands/saveFullPageScreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,14 @@ export default async function saveFullPageScreen(
): Promise<ScreenshotOutput> {

// 1a. Set some variables
const {addressBarShadowPadding, autoSaveBaseline, formatImageName, savePerInstance, toolBarShadowPadding} = saveFullPageOptions.wic;
const {
addressBarShadowPadding,
autoSaveBaseline,
formatImageName,
isHybridApp,
savePerInstance,
toolBarShadowPadding,
} = saveFullPageOptions.wic;

// 1b. Set the method options to the right values
const disableCSSAnimation: boolean = 'disableCSSAnimation' in saveFullPageOptions.method
Expand Down Expand Up @@ -60,6 +67,7 @@ export default async function saveFullPageScreen(
isAndroid: enrichedInstanceData.isAndroid,
isAndroidChromeDriverScreenshot: enrichedInstanceData.isAndroidChromeDriverScreenshot,
isAndroidNativeWebScreenshot: enrichedInstanceData.isAndroidNativeWebScreenshot,
isHybridApp,
isIos: enrichedInstanceData.isIos,
toolBarShadowPadding: enrichedInstanceData.toolBarShadowPadding,
};
Expand Down
2 changes: 2 additions & 0 deletions lib/helpers/__snapshots__/options.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Object {
"formatImageName": "{tag}-{browserName}-{width}x{height}-dpr-{dpr}",
"fullPageScrollTimeout": 1500,
"hideScrollBars": true,
"isHybridApp": false,
"savePerInstance": false,
"toolBarShadowPadding": 6,
}
Expand Down Expand Up @@ -51,6 +52,7 @@ Object {
"formatImageName": "{foo}-{bar}",
"fullPageScrollTimeout": 12345,
"hideScrollBars": true,
"isHybridApp": false,
"savePerInstance": true,
"toolBarShadowPadding": 1,
}
Expand Down
2 changes: 2 additions & 0 deletions lib/helpers/constants.interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export interface AndroidOffsets {
STATUS_BAR: number;
// The height of the address bar
ADDRESS_BAR: number;
// The height of the tool bar
TOOL_BAR: number;
};
}

Expand Down
3 changes: 3 additions & 0 deletions lib/helpers/options.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export interface ClassOptions{
debug?: boolean;
// The naming of the saved images can be customized by passing the parameter `formatImageName` with a format string
formatImageName?: string;
// Is it an hybrid app or not
isHybridApp?: boolean;
// Save the images per instance in a separate folder.
savePerInstance?: boolean;
// The directory that will hold all the actual / difference screenshots
Expand Down Expand Up @@ -65,6 +67,7 @@ export interface DefaultOptions {
clearFolder: boolean;
debug: boolean;
formatImageName: string;
isHybridApp: boolean;
savePerInstance: boolean;
toolBarShadowPadding: number;
disableCSSAnimation: boolean;
Expand Down
1 change: 1 addition & 0 deletions lib/helpers/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export function defaultOptions(options: ClassOptions): DefaultOptions {
clearFolder: options.clearRuntimeFolder || false,
debug: options.debug || false,
formatImageName: options.formatImageName || DEFAULT_FORMAT_STRING,
isHybridApp: options.isHybridApp || false,
savePerInstance: options.savePerInstance || false,
toolBarShadowPadding: options.toolBarShadowPadding || DEFAULT_SHADOW.TOOL_BAR,

Expand Down
4 changes: 3 additions & 1 deletion lib/methods/elementPosition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ export async function getElementPositionAndroid(
): Promise<ElementPosition> {
// This is the native webscreenshot
if (isNativeWebScreenshot) {
const {height} = (<StatusAddressToolBarHeight>(await executor(getAndroidStatusAddressToolBarHeight, OFFSETS.ANDROID))).statusAddressBar;
const {height} = (<StatusAddressToolBarHeight>(
await executor(getAndroidStatusAddressToolBarHeight, OFFSETS.ANDROID, false)
)).statusAddressBar;

return executor(getElementPositionTopScreenNativeMobile, height, element);
}
Expand Down
2 changes: 2 additions & 0 deletions lib/methods/images.interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export interface ImageCompareOptions {
fileName: string;
// The folders object
folderOptions: ImageCompareFolderOptions;
// Is it an hybrid app or not
isHybridApp: boolean;
// The name of the platform
platformName: string;
// If this is a native web screenshot
Expand Down
9 changes: 5 additions & 4 deletions lib/methods/images.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ export async function checkBaselineImageExists(
copySync(actualFilePath, baselineFilePath);
console.log(yellow(`
#####################################################################################
INFO:
Autosaved the image to
INFO:
Autosaved the image to
${baselineFilePath}
#####################################################################################
`));
} catch (error) {
/* istanbul ignore next */
reject(red(`
#####################################################################################
Image could not be copied. The following error was thrown:
Image could not be copied. The following error was thrown:
${error}
#####################################################################################
`));
Expand Down Expand Up @@ -72,7 +72,7 @@ export async function executeImageCompare(
): Promise<ImageCompareResult | number> {

// 1. Set some variables
const {debug, devicePixelRatio, fileName, isAndroidNativeWebScreenshot, platformName} = options;
const {debug, devicePixelRatio, fileName, isAndroidNativeWebScreenshot, isHybridApp, platformName} = options;
const {
actualFolder,
autoSaveBaseline,
Expand Down Expand Up @@ -108,6 +108,7 @@ export async function executeImageCompare(
// 4b. Determine the ignore rectangles for the blockouts
const blockOut = 'blockOut' in imageCompareOptions ? imageCompareOptions.blockOut : [];
const statusAddressToolBarOptions = {
isHybridApp,
isMobile,
isViewPortScreenshot,
platformName,
Expand Down
2 changes: 2 additions & 0 deletions lib/methods/rectangles.interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export interface RectanglesOutput {
}

export interface StatusAddressToolBarRectanglesOptions {
// Is it an hybrid app or not
isHybridApp: boolean;
// If the instance is a mobile phone
isMobile: boolean;
// If the comparison needs to be done for a viewport screenshot or not
Expand Down
4 changes: 4 additions & 0 deletions lib/methods/rectangles.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ describe('rectangles', () => {
describe('determineStatusAddressToolBarRectangles', () => {
it('should determine the rectangles for the iOS with a status and toolbar blockout', async () => {
const options = {
isHybridApp: false,
isMobile: true,
isViewPortScreenshot: true,
platformName: 'iOS',
Expand Down Expand Up @@ -194,6 +195,7 @@ describe('rectangles', () => {

it('should determine the rectangles for the iOS without a status and toolbar blockout', async () => {
const options = {
isHybridApp: false,
isMobile: true,
isViewPortScreenshot: true,
platformName: 'iOS',
Expand Down Expand Up @@ -224,6 +226,7 @@ describe('rectangles', () => {

it('should determine the rectangles for Android with a status and toolbar blockout', async () => {
const options = {
isHybridApp:false,
isMobile: true,
isViewPortScreenshot: true,
platformName: 'Android',
Expand Down Expand Up @@ -254,6 +257,7 @@ describe('rectangles', () => {

it('should determine the rectangles that there are no rectangles for this device', async () => {
const options = {
isHybridApp: false,
isMobile: true,
isViewPortScreenshot: false,
platformName: 'Android',
Expand Down
3 changes: 2 additions & 1 deletion lib/methods/rectangles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export async function determineStatusAddressToolBarRectangles(
const {
blockOutStatusBar,
blockOutToolBar,
isHybridApp,
isMobile,
isViewPortScreenshot,
platformName,
Expand All @@ -93,7 +94,7 @@ export async function determineStatusAddressToolBarRectangles(
) {
const {statusAddressBar, toolBar} = await (checkIsIos(platformName) ?
executor(getIosStatusAddressToolBarHeight, OFFSETS.IOS) :
executor(getAndroidStatusAddressToolBarHeight, OFFSETS.ANDROID));
executor(getAndroidStatusAddressToolBarHeight, OFFSETS.ANDROID, isHybridApp));

if (blockOutStatusBar) {
rectangles.push(statusAddressBar);
Expand Down
2 changes: 2 additions & 0 deletions lib/methods/screenshots.interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export interface FullPageScreenshotDataOptions {
isAndroidNativeWebScreenshot: boolean;
// If this is an Android ChromeDriver screenshot
isAndroidChromeDriverScreenshot: boolean;
// Is it an hybrid app or not
isHybridApp: boolean;
// If the instance is an iOS device
isIos: boolean;
// The address bar padding for iOS or Android
Expand Down
8 changes: 8 additions & 0 deletions lib/methods/screenshots.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ describe('screenshots', () => {
isAndroid: true,
isAndroidNativeWebScreenshot: true,
isAndroidChromeDriverScreenshot: false,
isHybridApp: false,
isIos: false,
toolBarShadowPadding: 6,
hideAfterFirstScroll: [],
Expand Down Expand Up @@ -52,6 +53,7 @@ describe('screenshots', () => {
isAndroid: true,
isAndroidNativeWebScreenshot: true,
isAndroidChromeDriverScreenshot: false,
isHybridApp: false,
isIos: false,
toolBarShadowPadding: 6,
hideAfterFirstScroll: [<HTMLElement><unknown>'<div/>'],
Expand Down Expand Up @@ -98,6 +100,7 @@ describe('screenshots', () => {
isAndroid: true,
isAndroidNativeWebScreenshot: false,
isAndroidChromeDriverScreenshot: true,
isHybridApp: false,
isIos: false,
toolBarShadowPadding: 6,
hideAfterFirstScroll: [],
Expand Down Expand Up @@ -138,6 +141,7 @@ describe('screenshots', () => {
isAndroid: true,
isAndroidNativeWebScreenshot: false,
isAndroidChromeDriverScreenshot: true,
isHybridApp: false,
isIos: false,
toolBarShadowPadding: 6,
hideAfterFirstScroll: [<HTMLElement><unknown>'<div/>'],
Expand Down Expand Up @@ -182,6 +186,7 @@ describe('screenshots', () => {
isAndroid: false,
isAndroidNativeWebScreenshot: false,
isAndroidChromeDriverScreenshot: false,
isHybridApp: false,
isIos: true,
toolBarShadowPadding: 6,
hideAfterFirstScroll: [],
Expand Down Expand Up @@ -223,6 +228,7 @@ describe('screenshots', () => {
isAndroid: false,
isAndroidNativeWebScreenshot: false,
isAndroidChromeDriverScreenshot: false,
isHybridApp: false,
isIos: true,
toolBarShadowPadding: 6,
hideAfterFirstScroll: [<HTMLElement><unknown>'<div/>'],
Expand Down Expand Up @@ -268,6 +274,7 @@ describe('screenshots', () => {
isAndroid: false,
isAndroidNativeWebScreenshot: false,
isAndroidChromeDriverScreenshot: false,
isHybridApp: false,
isIos: false,
toolBarShadowPadding: 6,
hideAfterFirstScroll: [],
Expand Down Expand Up @@ -315,6 +322,7 @@ describe('screenshots', () => {
isAndroid: false,
isAndroidNativeWebScreenshot: false,
isAndroidChromeDriverScreenshot: false,
isHybridApp: false,
isIos: false,
toolBarShadowPadding: 6,
hideAfterFirstScroll: [<HTMLElement><unknown>'<div/>'],
Expand Down
3 changes: 2 additions & 1 deletion lib/methods/screenshots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export async function getBase64FullPageScreenshotsData(
isAndroid,
isAndroidNativeWebScreenshot,
isAndroidChromeDriverScreenshot,
isHybridApp,
isIos,
toolBarShadowPadding,
} = options;
Expand All @@ -50,7 +51,7 @@ export async function getBase64FullPageScreenshotsData(
if (isAndroid && isAndroidNativeWebScreenshot) {
// Create a fullpage screenshot for Android when native screenshot (so including status, address and toolbar) is created
const statusAddressBarHeight = (
<StatusAddressToolBarHeight>(await executor(getAndroidStatusAddressToolBarHeight, OFFSETS.ANDROID))
<StatusAddressToolBarHeight>(await executor(getAndroidStatusAddressToolBarHeight, OFFSETS.ANDROID, isHybridApp))
).statusAddressBar.height;
const androidNativeMobileOptions = {...nativeMobileOptions, statusAddressBarHeight};

Expand Down

0 comments on commit d3f836a

Please sign in to comment.