Skip to content

Commit 2a1b642

Browse files
authored
Merge pull request #19 from gemini-testing/fix-toolbar
feat: support screenshot cropping for safari15
2 parents 74f9114 + 6be0f85 commit 2a1b642

File tree

26 files changed

+440
-225
lines changed

26 files changed

+440
-225
lines changed

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module.exports = {
22
extends: 'gemini-testing',
33
env: {browser: true},
4+
parserOptions: {ecmaVersion: 2018},
45
root: true
56
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
'use strict';
2+
3+
const CommonUtils = require('../common');
4+
5+
const {withExisting, withNativeCtx, withTestCtxMemo} = require('../decorators');
6+
const {TOP_TOOLBAR_SIZE} = require('../../test-context');
7+
8+
module.exports = class SafariOldUtils extends CommonUtils {
9+
async getTopToolbarHeight(browser) {
10+
const {TOP_TOOLBAR} = this._nativeLocators;
11+
const action = {fn: browser.getElementSize, args: TOP_TOOLBAR, default: {width: 0, height: 0}};
12+
const existingWrapper = {fn: withExisting, args: action};
13+
const inNativeCtxWrapper = {fn: withNativeCtx, args: existingWrapper};
14+
15+
return (await withTestCtxMemo.call(browser, inNativeCtxWrapper, TOP_TOOLBAR_SIZE)).height;
16+
}
17+
};
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
'use strict';
2+
3+
const _ = require('lodash');
4+
const {withExisting, withNativeCtx, withTestCtxMemo} = require('../decorators');
5+
const {WEB_VIEW_SIZE, BOTTOM_TOOLBAR_LOCATION, PIXEL_RATIO} = require('../../test-context');
6+
const {isWdioLatest} = require('../../../utils');
7+
8+
module.exports = class CommonUtils {
9+
constructor(nativeLocators) {
10+
this._nativeLocators = nativeLocators;
11+
}
12+
13+
async getBottomToolbarY(browser) {
14+
const {BOTTOM_TOOLBAR} = this._nativeLocators;
15+
const action = {fn: browser.getLocation, args: BOTTOM_TOOLBAR, default: {x: 0, y: 0}};
16+
const existingWrapper = {fn: withExisting, args: action};
17+
const inNativeCtxWrapper = {fn: withNativeCtx, args: existingWrapper};
18+
19+
return (await withTestCtxMemo.call(browser, inNativeCtxWrapper, BOTTOM_TOOLBAR_LOCATION)).y;
20+
}
21+
22+
async getWebViewSize(browser) {
23+
const {WEB_VIEW} = this._nativeLocators;
24+
const action = {fn: browser.getElementSize, args: WEB_VIEW};
25+
const inNativeCtxWrapper = {fn: withNativeCtx, args: action};
26+
27+
return await withTestCtxMemo.call(browser, inNativeCtxWrapper, WEB_VIEW_SIZE);
28+
}
29+
30+
async getElemCoords(browser, selector) {
31+
const [size, location] = await Promise.all([browser.getElementSize(selector), browser.getLocation(selector)]);
32+
const {width, height} = _.isArray(size) ? size[0] : size;
33+
// wdio returns elements in reverse order, so we need to take the last element in the array to pick first element on the page
34+
// https://github.com/webdriverio/webdriverio/blob/v4.14.1/lib/commands/getLocation.js#L48.
35+
const {x, y} = _.isArray(location) ? location[location.length - 1] : location;
36+
37+
const topToolbarHeight = await this.getTopToolbarHeight(browser);
38+
39+
return {width, height, x, y: y + topToolbarHeight};
40+
}
41+
42+
async getElemCenterLocation(browser, selector) {
43+
const {width, height, x, y} = await this.getElemCoords(browser, selector);
44+
45+
return {
46+
x: Math.round(x + width / 2),
47+
y: Math.round(y + height / 2)
48+
};
49+
}
50+
51+
async getPixelRatio(browser) {
52+
const action = {fn: async () => {
53+
const result = await browser.execute(() => window.devicePixelRatio);
54+
55+
return isWdioLatest(browser) ? result : result.value;
56+
}};
57+
58+
return await withTestCtxMemo.call(browser, action, PIXEL_RATIO);
59+
}
60+
61+
async calcWebViewCoords(browser, {bodyWidth, pixelRatio = 1} = {}) {
62+
const [topToolbarHeight, bottomToolbarY, webViewSize] = await Promise.all([
63+
this.getTopToolbarHeight(browser),
64+
this.getBottomToolbarY(browser),
65+
this.getWebViewSize(browser)
66+
]);
67+
68+
const bottomToolbarHeight = bottomToolbarY > 0 ? webViewSize.height - bottomToolbarY : 0;
69+
70+
return {
71+
width: Math.ceil(Math.min(webViewSize.width, bodyWidth) * pixelRatio),
72+
height: Math.ceil((webViewSize.height - topToolbarHeight - bottomToolbarHeight) * pixelRatio),
73+
left: Math.max(Math.floor((webViewSize.width - bodyWidth) / 2 * pixelRatio), 0),
74+
top: Math.max(Math.floor(topToolbarHeight * pixelRatio), 0)
75+
};
76+
}
77+
78+
getTopToolbarHeight() {
79+
throw new Error('Not implemented');
80+
}
81+
};
Lines changed: 10 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,17 @@
11
'use strict';
22

3-
const _ = require('lodash');
4-
const {withExisting, withNativeCtx, withTestCtxMemo} = require('./decorators');
5-
const {TOP_TOOLBAR_SIZE, BOTTOM_TOOLBAR_LOCATION, WEB_VIEW_SIZE, PIXEL_RATIO} = require('../test-context');
6-
const {TOP_TOOLBAR, BOTTOM_TOOLBAR, WEB_VIEW} = require('../../native-locators');
7-
const {isWdioLatest} = require('../../utils');
3+
const {getSafariVersion} = require('../../utils');
4+
const {NEW_SAFARI_VERSION} = require('../../constants');
85

9-
exports.getTopToolbarHeight = async (browser) => {
10-
const action = {fn: browser.getElementSize, args: TOP_TOOLBAR, default: {width: 0, height: 0}};
11-
const existingWrapper = {fn: withExisting, args: action};
12-
const inNativeCtxWrapper = {fn: withNativeCtx, args: existingWrapper};
6+
const Safari15Utils = require('./v15.0');
7+
const SafariOldUtils = require('./<v15.0');
138

14-
return (await withTestCtxMemo.call(browser, inNativeCtxWrapper, TOP_TOOLBAR_SIZE)).height;
15-
};
16-
17-
exports.getBottomToolbarY = async (browser) => {
18-
const action = {fn: browser.getLocation, args: BOTTOM_TOOLBAR, default: {x: 0, y: 0}};
19-
const existingWrapper = {fn: withExisting, args: action};
20-
const inNativeCtxWrapper = {fn: withNativeCtx, args: existingWrapper};
21-
22-
return (await withTestCtxMemo.call(browser, inNativeCtxWrapper, BOTTOM_TOOLBAR_LOCATION)).y;
23-
};
24-
25-
exports.getWebViewSize = async (browser) => {
26-
const action = {fn: browser.getElementSize, args: WEB_VIEW};
27-
const inNativeCtxWrapper = {fn: withNativeCtx, args: action};
28-
29-
return await withTestCtxMemo.call(browser, inNativeCtxWrapper, WEB_VIEW_SIZE);
30-
};
31-
32-
exports.getElemCoords = async (browser, selector) => {
33-
const [size, location] = await Promise.all([browser.getElementSize(selector), browser.getLocation(selector)]);
34-
const {width, height} = _.isArray(size) ? size[0] : size;
35-
// wdio returns elements in reverse order, so we need to take the last element in the array to pick first element on the page
36-
// https://github.com/webdriverio/webdriverio/blob/v4.14.1/lib/commands/getLocation.js#L48.
37-
const {x, y} = _.isArray(location) ? location[location.length - 1] : location;
38-
39-
const topToolbarHeight = await exports.getTopToolbarHeight(browser);
40-
41-
return {width, height, x, y: y + topToolbarHeight};
42-
};
43-
44-
exports.getElemCenterLocation = async (browser, selector) => {
45-
const {width, height, x, y} = await exports.getElemCoords(browser, selector);
46-
47-
return {
48-
x: Math.round(x + width / 2),
49-
y: Math.round(y + height / 2)
50-
};
51-
};
52-
53-
exports.getPixelRatio = async (browser) => {
54-
const action = {fn: async () => {
55-
const result = await browser.execute(() => window.devicePixelRatio);
56-
57-
return isWdioLatest(browser) ? result : result.value;
58-
}};
59-
60-
return await withTestCtxMemo.call(browser, action, PIXEL_RATIO);
61-
};
9+
exports.getElementUtils = (broConfig, nativeLocators) => {
10+
const currentVersion = getSafariVersion(broConfig);
6211

63-
exports.calcWebViewCoords = async (browser, {bodyWidth, pixelRatio = 1} = {}) => {
64-
const [topToolbarHeight, bottomToolbarY, webViewSize] = await Promise.all([
65-
exports.getTopToolbarHeight(browser),
66-
exports.getBottomToolbarY(browser),
67-
exports.getWebViewSize(browser)
68-
]);
69-
const bottomToolbarHeight = bottomToolbarY > 0 ? webViewSize.height - bottomToolbarY : 0;
12+
if (currentVersion < NEW_SAFARI_VERSION) {
13+
return new SafariOldUtils(nativeLocators);
14+
}
7015

71-
return {
72-
width: Math.ceil(Math.min(webViewSize.width, bodyWidth) * pixelRatio),
73-
height: Math.ceil((webViewSize.height - topToolbarHeight - bottomToolbarHeight) * pixelRatio),
74-
left: Math.max(Math.floor((webViewSize.width - bodyWidth) / 2 * pixelRatio), 0),
75-
top: Math.max(Math.floor(topToolbarHeight * pixelRatio), 0)
76-
};
16+
return new Safari15Utils(nativeLocators);
7717
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
'use strict';
2+
3+
const CommonUtils = require('../common');
4+
5+
const {withExisting, withNativeCtx, withTestCtxMemo} = require('../decorators');
6+
const {TOP_TOOLBAR_SIZE} = require('../../test-context');
7+
8+
module.exports = class Safari15Utils extends CommonUtils {
9+
async getTopToolbarHeight(browser) {
10+
const {VIEW_PORT} = this._nativeLocators;
11+
const action = {fn: browser.getLocation, args: VIEW_PORT, default: {x: 0, y: 0}};
12+
const existingWrapper = {fn: withExisting, args: action};
13+
const inNativeCtxWrapper = {fn: withNativeCtx, args: existingWrapper};
14+
15+
return (await withTestCtxMemo.call(browser, inNativeCtxWrapper, TOP_TOOLBAR_SIZE)).y;
16+
}
17+
};

lib/commands/deviceClickBack.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
'use strict';
22

33
const {runInNativeContext} = require('../command-helpers/context-switcher');
4-
const {DEVICE_BACK} = require('../native-locators');
54

6-
module.exports = (browser) => {
5+
module.exports = (browser, {nativeLocators}) => {
76
browser.addCommand('deviceClickBack', async () => {
7+
const {DEVICE_BACK} = nativeLocators;
88
const action = {fn: browser.click, args: [DEVICE_BACK, {unwrap: true}]};
99

1010
await runInNativeContext(browser, action);

lib/commands/dragAndDrop.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
'use strict';
22

3-
const {getElemCenterLocation} = require('../command-helpers/element-utils');
43
const {WAIT_BETWEEN_ACTIONS_IN_MS} = require('../constants');
54

6-
module.exports = (browser) => {
5+
module.exports = (browser, {elementUtils}) => {
76
browser.addCommand('dragAndDrop', async (srcSelector, destSelector) => {
8-
const {x: srcX, y: srcY} = await getElemCenterLocation(browser, srcSelector);
9-
const {x: destX, y: destY} = await getElemCenterLocation(browser, destSelector);
7+
const {x: srcX, y: srcY} = await elementUtils.getElemCenterLocation(browser, srcSelector);
8+
const {x: destX, y: destY} = await elementUtils.getElemCenterLocation(browser, destSelector);
109

1110
await browser.touchAction([
1211
{action: 'tap', x: srcX, y: srcY},

lib/commands/screenshot.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,17 @@
33
const {PNG} = require('pngjs');
44
const concat = require('concat-stream');
55
const streamifier = require('streamifier');
6-
const {calcWebViewCoords, getPixelRatio} = require('../command-helpers/element-utils');
76
const {runInNativeContext} = require('../command-helpers/context-switcher');
87
const {isWdioLatest} = require('../utils');
98

10-
module.exports = (browser) => {
9+
module.exports = (browser, {elementUtils}) => {
1110
const commandName = isWdioLatest(browser) ? 'takeScreenshot' : 'screenshot';
1211
const baseScreenshotFn = browser[commandName];
1312

1413
browser.addCommand(commandName, async () => {
1514
const {width: bodyWidth} = await browser.getElementSize('body');
16-
const pixelRatio = await getPixelRatio(browser);
17-
const cropCoords = await runInNativeContext(browser, {fn: calcWebViewCoords, args: [browser, {bodyWidth, pixelRatio}]});
18-
15+
const pixelRatio = await elementUtils.getPixelRatio(browser);
16+
const cropCoords = await runInNativeContext(browser, {fn: elementUtils.calcWebViewCoords.bind(elementUtils), args: [browser, {bodyWidth, pixelRatio}]});
1917
const screenshotResult = await baseScreenshotFn.call(browser);
2018
const base64 = isWdioLatest(browser) ? screenshotResult : screenshotResult.value;
2119

lib/commands/swipe.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22

33
const _ = require('lodash');
44
const {resetTestContextValues, TOP_TOOLBAR_SIZE, BOTTOM_TOOLBAR_LOCATION} = require('../command-helpers/test-context');
5-
const {getElemCenterLocation} = require('../command-helpers/element-utils');
65
const {WAIT_BETWEEN_ACTIONS_IN_MS} = require('../constants');
76

8-
module.exports = (browser) => {
7+
module.exports = (browser, {elementUtils}) => {
98
browser.addCommand('swipe', async (selector, xOffset = 0, yOffset = 0, speed = WAIT_BETWEEN_ACTIONS_IN_MS) => {
109
if (typeof selector === 'number') {
1110
throw new TypeError(
@@ -20,7 +19,7 @@ module.exports = (browser) => {
2019
);
2120
}
2221

23-
const {x, y} = await getElemCenterLocation(browser, selector);
22+
const {x, y} = await elementUtils.getElemCenterLocation(browser, selector);
2423

2524
await browser.touchAction([
2625
{action: 'press', x, y},

lib/commands/touch.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
'use strict';
22

3-
const {getElemCenterLocation} = require('../command-helpers/element-utils');
4-
5-
module.exports = (browser) => {
3+
module.exports = (browser, {elementUtils}) => {
64
browser.addCommand('touch', async (selector) => {
7-
const {x, y} = await getElemCenterLocation(browser, selector);
5+
const {x, y} = await elementUtils.getElemCenterLocation(browser, selector);
86

97
await browser.touchAction([
108
{action: 'tap', x, y}

0 commit comments

Comments
 (0)