@applitools/driver
Advanced tools
Comparing version 1.1.0 to 1.1.1
@@ -7,7 +7,7 @@ { | ||
"version": "file:../dry-run.tgz", | ||
"integrity": "sha512-u+leMyDOpfDemMXOEueO0V5KC3o9LULKXjfGutDhvtUwx9b0dRUQ8pO32hdoVybZTRFKD24+1yrs6EyDuzLoXQ==", | ||
"integrity": "sha512-AvnuMezSG970vwPR9njia77mVTPF8JuGBFJaUrPUuNwDSpAlJKoCts1ZIwE4rpl2zh8aCEPdFdOl8Bu76bTlGQ==", | ||
"requires": { | ||
"@applitools/snippets": "2.1.4", | ||
"@applitools/types": "1.0.6", | ||
"@applitools/utils": "1.2.1" | ||
"@applitools/utils": "1.2.2" | ||
} | ||
@@ -26,7 +26,7 @@ }, | ||
"@applitools/utils": { | ||
"version": "1.2.1", | ||
"resolved": "https://registry.npmjs.org/@applitools/utils/-/utils-1.2.1.tgz", | ||
"integrity": "sha512-lIHYqgirhkyL+xAc9+FwidAvcI7apB/6Y7uyVimHdTRjjIwAqoazymwYiFZiia+q81F/smPLvMw2RUwU6wi13w==" | ||
"version": "1.2.2", | ||
"resolved": "https://registry.npmjs.org/@applitools/utils/-/utils-1.2.2.tgz", | ||
"integrity": "sha512-SyHY41J+hkZR9gma/M8gjbJXLXeLoVS5DQVYd/RinzWAq62Yvg9eA97+8oHDl8s+6ELK6wMcs4yajjqCPdpF0A==" | ||
} | ||
} | ||
} |
@@ -6,2 +6,7 @@ # Change Log | ||
## 1.1.1 - 2021/8/7 | ||
- improve context and element location calculations | ||
- updated to @applitools/utils@1.2.2 (from 1.2.1) | ||
## 1.1.0 - 2021/8/4 | ||
@@ -8,0 +13,0 @@ |
@@ -35,4 +35,9 @@ "use strict"; | ||
this._logger = options.logger; | ||
if ((_c = (_b = (_a = this._spec).isContext) === null || _b === void 0 ? void 0 : _b.call(_a, options.context)) !== null && _c !== void 0 ? _c : this._spec.isDriver(options.context)) { | ||
this._target = options.context; | ||
if (options.context) { | ||
if ((_c = (_b = (_a = this._spec).isContext) === null || _b === void 0 ? void 0 : _b.call(_a, options.context)) !== null && _c !== void 0 ? _c : this._spec.isDriver(options.context)) { | ||
this._target = options.context; | ||
} | ||
else { | ||
throw new TypeError('Context constructor called with argument of unknown type of context!'); | ||
} | ||
} | ||
@@ -160,7 +165,6 @@ if (this.isReference(options.reference)) { | ||
if (this.parent.isMain) | ||
await this.parent.preserveRegions(); | ||
await this.preserveRegions(); | ||
await this.parent.preserveContextRegions(); | ||
await this.preserveContextRegions(); | ||
this._target = await this._spec.childContext(this.parent.target, this._element.target); | ||
// TODO replace | ||
await this.driver.updateCurrentContext(this); | ||
this.driver.updateCurrentContext(this); | ||
return this; | ||
@@ -344,2 +348,9 @@ } | ||
} | ||
async getScrollingRegion() { | ||
if (this.isCurrent) { | ||
const scrollingElement = await this.getScrollingElement(); | ||
this._state.scrollingRegion = await scrollingElement.getClientRegion(); | ||
} | ||
return this._state.scrollingRegion; | ||
} | ||
async getContentSize() { | ||
@@ -364,6 +375,5 @@ return this.execute(snippets.getDocumentSize); | ||
var _a, _b; | ||
let location = { x: 0, y: 0 }; | ||
if (this.isMain) { | ||
return utils.geometry.offsetNegative(location, await this.getInnerOffset()); | ||
} | ||
let location = utils.geometry.offsetNegative({ x: 0, y: 0 }, await this.getInnerOffset()); | ||
if (this.isMain) | ||
return location; | ||
let currentContext = this; | ||
@@ -387,4 +397,6 @@ while (currentContext) { | ||
const contextRegion = await currentContext.getClientRegion(); | ||
// const contextScrollingRegion = await currentContext.getScrollingRegion() | ||
const parentContextInnerOffset = (_b = (await ((_a = currentContext.parent) === null || _a === void 0 ? void 0 : _a.getInnerOffset()))) !== null && _b !== void 0 ? _b : { x: 0, y: 0 }; | ||
region = utils.geometry.intersect(contextRegion, utils.geometry.offset(region, contextRegion)); | ||
// region = utils.geometry.intersect(contextScrollingRegion, region) | ||
region = utils.geometry.offsetNegative(region, parentContextInnerOffset); | ||
@@ -398,7 +410,10 @@ currentContext = currentContext.parent; | ||
} | ||
async preserveRegions() { | ||
async preserveContextRegions() { | ||
this._state.region = await this.getRegion(); | ||
this._state.clientRegion = await this.getClientRegion(); | ||
} | ||
async preserveScrollingRegion() { | ||
this._state.scrollingRegion = await this.getScrollingRegion(); | ||
} | ||
} | ||
exports.Context = Context; |
@@ -293,8 +293,2 @@ "use strict"; | ||
async getRegionInViewport(context, region) { | ||
region = { | ||
x: Math.round(region.x), | ||
y: Math.round(region.y), | ||
width: region.width, | ||
height: region.height, | ||
}; | ||
await context.focus(); | ||
@@ -301,0 +295,0 @@ return context.getRegionInViewport(region); |
@@ -124,2 +124,3 @@ "use strict"; | ||
const size = await this.withRefresh(async () => { | ||
var _a; | ||
if (this.driver.isWeb) { | ||
@@ -132,11 +133,10 @@ this._logger.log('Extracting content size of web element with selector', this.selector); | ||
try { | ||
let size; | ||
if (this.driver.isAndroid) { | ||
const className = await this._spec.getElementAttribute(this.driver.target, this.target, 'className'); | ||
const className = await this.getAttribute('className'); | ||
if ([ | ||
'android.widget.ListView', | ||
'android.widget.GridView', | ||
'android.support.v7.widget.RecyclerView', | ||
'androidx.recyclerview.widget.RecyclerView', | ||
// 'androidx.recyclerview.widget.RecyclerView', | ||
'androidx.viewpager2.widget.ViewPager2', | ||
'android.widget.ListView', | ||
'android.widget.GridView', | ||
].includes(className)) { | ||
@@ -152,3 +152,3 @@ this._logger.log('Trying to extract content size using android helper library'); | ||
const info = await this._spec.getElementText(this.driver.target, helperElement.target); | ||
size = utils.geometry.scale({ width: elementRegion.width, height: Number(info) }, 1 / this.driver.pixelRatio); | ||
this._state.contentSize = utils.geometry.scale({ width: elementRegion.width, height: Number(info) }, 1 / this.driver.pixelRatio); | ||
} | ||
@@ -161,3 +161,3 @@ else { | ||
else if (this.driver.isIOS) { | ||
const type = await this._spec.getElementAttribute(this.driver.target, this.target, 'type'); | ||
const type = await this.getAttribute('type'); | ||
if (type === 'XCUIElementTypeScrollView') { | ||
@@ -170,3 +170,3 @@ const elementRegion = await this._spec.getElementRegion(this.driver.target, this.target); | ||
const childElementRegion = await this._spec.getElementRegion(this.driver.target, childElement.target); | ||
size = { | ||
this._state.contentSize = { | ||
width: elementRegion.width, | ||
@@ -193,3 +193,3 @@ height: childElementRegion.y + childElementRegion.height - elementRegion.y, | ||
const [_, width, height] = info.match(/\{(\d+),\s?(\d+)\}/); | ||
size = { width: Number(width), height: Number(height) }; | ||
this._state.contentSize = { width: Number(width), height: Number(height) }; | ||
} | ||
@@ -202,10 +202,10 @@ } | ||
} | ||
if (!size) { | ||
const data = JSON.parse(await this._spec.getElementAttribute(this.driver.target, this.target, 'contentSize')); | ||
if (!this._state.contentSize) { | ||
const data = JSON.parse(await this.getAttribute('contentSize')); | ||
this._logger.log('Extracted native content size attribute', data); | ||
size = this.driver.isIOS | ||
this._state.contentSize = this.driver.isIOS | ||
? { width: data.width, height: data.scrollableOffset } | ||
: utils.geometry.scale({ width: data.width, height: data.height + data.scrollableOffset }, 1 / this.driver.pixelRatio); | ||
this._touchPadding = (_a = data.touchPadding) !== null && _a !== void 0 ? _a : this._touchPadding; | ||
} | ||
this._state.contentSize = size; | ||
if (this.driver.isAndroid) { | ||
@@ -238,7 +238,7 @@ this._logger.log('Stabilizing android scroll offset'); | ||
else if (this.driver.isAndroid) { | ||
const data = JSON.parse(await this._spec.getElementAttribute(this.driver.target, this.target, 'scrollable')); | ||
const data = JSON.parse(await this.getAttribute('scrollable')); | ||
return Boolean(data) || false; | ||
} | ||
else if (this.driver.isIOS) { | ||
const type = await this._spec.getElementAttribute(this.driver.target, this.target, 'type'); | ||
const type = await this.getAttribute('type'); | ||
return ['XCUIElementTypeScrollView', 'XCUIElementTypeTable', 'XCUIElementTypeCollectionView'].includes(type); | ||
@@ -262,2 +262,29 @@ } | ||
} | ||
async getTouchPadding() { | ||
if (this._touchPadding == null) { | ||
if (this.driver.isWeb) | ||
this._touchPadding = 0; | ||
else if (this.driver.isIOS) | ||
this._touchPadding = 14; | ||
else if (this.driver.isAndroid) { | ||
const { touchPadding } = JSON.parse(await this.getAttribute('contentSize')); | ||
this._touchPadding = touchPadding !== null && touchPadding !== void 0 ? touchPadding : 0; | ||
} | ||
} | ||
return this._touchPadding; | ||
} | ||
async getAttribute(name) { | ||
if (this.driver.isWeb) { | ||
const properties = await this.context.execute(snippets.getElementProperties, [this, [name]]); | ||
return properties[name]; | ||
} | ||
else { | ||
return this._spec.getElementAttribute(this.driver.target, this.target, name); | ||
} | ||
} | ||
async setAttribute(name, value) { | ||
if (this.driver.isWeb) { | ||
await this.context.execute(snippets.setElementAttributes, [this, { [name]: value }]); | ||
} | ||
} | ||
async scrollTo(offset) { | ||
@@ -311,3 +338,3 @@ return this.withRefresh(async () => { | ||
const yDirection = remainingOffset.y > 0 ? 'down' : 'up'; | ||
let yRemaining = Math.abs(remainingOffset.y) + (this.driver.isIOS ? 28 : 48); // ??? | ||
let yRemaining = Math.abs(remainingOffset.y) + (await this.getTouchPadding()) * 2; | ||
while (yRemaining > 0) { | ||
@@ -367,3 +394,3 @@ const yBottom = scrollableRegion.y + Math.min(yRemaining + yPadding, scrollableRegion.height - yPadding); | ||
return; | ||
// TODO create one js snippet | ||
// TODO create single js snippet | ||
const scrollOffset = await this.getScrollOffset(); | ||
@@ -374,4 +401,7 @@ const transforms = await this.context.execute(snippets.getElementStyleProperties, [ | ||
]); | ||
this._state = { scrollOffset, transforms }; | ||
return this._state; | ||
if (!utils.types.has(this._state, ['scrollOffset', 'transforms'])) { | ||
this._state.scrollOffset = scrollOffset; | ||
this._state.transforms = transforms; | ||
} | ||
return { scrollOffset, transforms }; | ||
} | ||
@@ -381,4 +411,2 @@ async restoreState(state = this._state) { | ||
return; | ||
if (!state) | ||
return; | ||
if (state.scrollOffset) | ||
@@ -388,2 +416,6 @@ await this.scrollTo(state.scrollOffset); | ||
await this.context.execute(snippets.setElementStyleProperties, [this, state.transforms]); | ||
if (state === this._state) { | ||
this._state.scrollOffset = null; | ||
this._state.transforms = null; | ||
} | ||
} | ||
@@ -390,0 +422,0 @@ async hideScrollbars() { |
{ | ||
"name": "@applitools/driver", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"description": "Applitools universal framework wrapper", | ||
@@ -49,3 +49,3 @@ "keywords": [ | ||
"@applitools/types": "1.0.6", | ||
"@applitools/utils": "1.2.1" | ||
"@applitools/utils": "1.2.2" | ||
}, | ||
@@ -52,0 +52,0 @@ "devDependencies": { |
@@ -5,2 +5,3 @@ import type * as types from '@applitools/types' | ||
import {Element} from './element' | ||
const snippets = require('@applitools/snippets') | ||
@@ -26,2 +27,3 @@ | ||
clientRegion?: types.Region | ||
scrollingRegion?: types.Region | ||
innerOffset?: types.Location | ||
@@ -59,4 +61,8 @@ } | ||
if (this._spec.isContext?.(options.context) ?? this._spec.isDriver(options.context)) { | ||
this._target = options.context | ||
if (options.context) { | ||
if (this._spec.isContext?.(options.context) ?? this._spec.isDriver(options.context)) { | ||
this._target = options.context | ||
} else { | ||
throw new TypeError('Context constructor called with argument of unknown type of context!') | ||
} | ||
} | ||
@@ -198,9 +204,9 @@ | ||
if (this.parent.isMain) await this.parent.preserveRegions() | ||
await this.preserveRegions() | ||
if (this.parent.isMain) await this.parent.preserveContextRegions() | ||
await this.preserveContextRegions() | ||
this._target = await this._spec.childContext(this.parent.target, this._element.target) | ||
// TODO replace | ||
await this.driver.updateCurrentContext(this) | ||
this.driver.updateCurrentContext(this) | ||
return this | ||
@@ -393,2 +399,10 @@ } | ||
async getScrollingRegion(): Promise<types.Region> { | ||
if (this.isCurrent) { | ||
const scrollingElement = await this.getScrollingElement() | ||
this._state.scrollingRegion = await scrollingElement.getClientRegion() | ||
} | ||
return this._state.scrollingRegion | ||
} | ||
async getContentSize(): Promise<types.Size> { | ||
@@ -415,7 +429,6 @@ return this.execute(snippets.getDocumentSize) | ||
async getLocationInViewport(): Promise<types.Location> { | ||
let location = {x: 0, y: 0} | ||
if (this.isMain) { | ||
return utils.geometry.offsetNegative(location, await this.getInnerOffset()) | ||
} | ||
let location = utils.geometry.offsetNegative({x: 0, y: 0}, await this.getInnerOffset()) | ||
if (this.isMain) return location | ||
let currentContext = this as Context<TDriver, TContext, TElement, TSelector> | ||
@@ -443,5 +456,7 @@ while (currentContext) { | ||
const contextRegion = await currentContext.getClientRegion() | ||
// const contextScrollingRegion = await currentContext.getScrollingRegion() | ||
const parentContextInnerOffset = (await currentContext.parent?.getInnerOffset()) ?? {x: 0, y: 0} | ||
region = utils.geometry.intersect(contextRegion, utils.geometry.offset(region, contextRegion)) | ||
// region = utils.geometry.intersect(contextScrollingRegion, region) | ||
region = utils.geometry.offsetNegative(region, parentContextInnerOffset) | ||
@@ -458,6 +473,10 @@ | ||
private async preserveRegions() { | ||
private async preserveContextRegions() { | ||
this._state.region = await this.getRegion() | ||
this._state.clientRegion = await this.getClientRegion() | ||
} | ||
private async preserveScrollingRegion() { | ||
this._state.scrollingRegion = await this.getScrollingRegion() | ||
} | ||
} |
@@ -6,2 +6,3 @@ import type * as types from '@applitools/types' | ||
import {parseUserAgent} from './user-agent' | ||
const snippets = require('@applitools/snippets') | ||
@@ -310,10 +311,3 @@ | ||
): Promise<types.Region> { | ||
region = { | ||
x: Math.round(region.x), | ||
y: Math.round(region.y), | ||
width: region.width, | ||
height: region.height, | ||
} | ||
await context.focus() | ||
return context.getRegionInViewport(region) | ||
@@ -320,0 +314,0 @@ } |
import type * as types from '@applitools/types' | ||
import type {Context} from './context' | ||
import * as utils from '@applitools/utils' | ||
const snippets = require('@applitools/snippets') | ||
@@ -20,2 +21,3 @@ | ||
private _originalOverflow: any | ||
private _touchPadding: number | ||
private _logger: any | ||
@@ -138,12 +140,11 @@ | ||
try { | ||
let size | ||
if (this.driver.isAndroid) { | ||
const className = await this._spec.getElementAttribute(this.driver.target, this.target, 'className') | ||
const className = await this.getAttribute('className') | ||
if ( | ||
[ | ||
'android.widget.ListView', | ||
'android.widget.GridView', | ||
'android.support.v7.widget.RecyclerView', | ||
'androidx.recyclerview.widget.RecyclerView', | ||
// 'androidx.recyclerview.widget.RecyclerView', | ||
'androidx.viewpager2.widget.ViewPager2', | ||
'android.widget.ListView', | ||
'android.widget.GridView', | ||
].includes(className) | ||
@@ -160,3 +161,3 @@ ) { | ||
const info = await this._spec.getElementText(this.driver.target, helperElement.target) | ||
size = utils.geometry.scale( | ||
this._state.contentSize = utils.geometry.scale( | ||
{width: elementRegion.width, height: Number(info)}, | ||
@@ -170,3 +171,3 @@ 1 / this.driver.pixelRatio, | ||
} else if (this.driver.isIOS) { | ||
const type = await this._spec.getElementAttribute(this.driver.target, this.target, 'type') | ||
const type = await this.getAttribute('type') | ||
if (type === 'XCUIElementTypeScrollView') { | ||
@@ -179,3 +180,3 @@ const elementRegion = await this._spec.getElementRegion(this.driver.target, this.target) | ||
const childElementRegion = await this._spec.getElementRegion(this.driver.target, childElement.target) | ||
size = { | ||
this._state.contentSize = { | ||
width: elementRegion.width, | ||
@@ -201,3 +202,3 @@ height: childElementRegion.y + childElementRegion.height - elementRegion.y, | ||
const [_, width, height] = info.match(/\{(\d+),\s?(\d+)\}/) | ||
size = {width: Number(width), height: Number(height)} | ||
this._state.contentSize = {width: Number(width), height: Number(height)} | ||
} | ||
@@ -210,8 +211,6 @@ } else { | ||
if (!size) { | ||
const data = JSON.parse( | ||
await this._spec.getElementAttribute(this.driver.target, this.target, 'contentSize'), | ||
) | ||
if (!this._state.contentSize) { | ||
const data = JSON.parse(await this.getAttribute('contentSize')) | ||
this._logger.log('Extracted native content size attribute', data) | ||
size = this.driver.isIOS | ||
this._state.contentSize = this.driver.isIOS | ||
? {width: data.width, height: data.scrollableOffset} | ||
@@ -222,6 +221,5 @@ : utils.geometry.scale( | ||
) | ||
this._touchPadding = data.touchPadding ?? this._touchPadding | ||
} | ||
this._state.contentSize = size | ||
if (this.driver.isAndroid) { | ||
@@ -256,6 +254,6 @@ this._logger.log('Stabilizing android scroll offset') | ||
} else if (this.driver.isAndroid) { | ||
const data = JSON.parse(await this._spec.getElementAttribute(this.driver.target, this.target, 'scrollable')) | ||
const data = JSON.parse(await this.getAttribute('scrollable')) | ||
return Boolean(data) || false | ||
} else if (this.driver.isIOS) { | ||
const type = await this._spec.getElementAttribute(this.driver.target, this.target, 'type') | ||
const type = await this.getAttribute('type') | ||
return ['XCUIElementTypeScrollView', 'XCUIElementTypeTable', 'XCUIElementTypeCollectionView'].includes(type) | ||
@@ -280,2 +278,29 @@ } | ||
async getTouchPadding(): Promise<number> { | ||
if (this._touchPadding == null) { | ||
if (this.driver.isWeb) this._touchPadding = 0 | ||
else if (this.driver.isIOS) this._touchPadding = 14 | ||
else if (this.driver.isAndroid) { | ||
const {touchPadding} = JSON.parse(await this.getAttribute('contentSize')) | ||
this._touchPadding = touchPadding ?? 0 | ||
} | ||
} | ||
return this._touchPadding | ||
} | ||
async getAttribute(name: string): Promise<string> { | ||
if (this.driver.isWeb) { | ||
const properties = await this.context.execute(snippets.getElementProperties, [this, [name]]) | ||
return properties[name] | ||
} else { | ||
return this._spec.getElementAttribute(this.driver.target, this.target, name) | ||
} | ||
} | ||
async setAttribute(name: string, value: string): Promise<void> { | ||
if (this.driver.isWeb) { | ||
await this.context.execute(snippets.setElementAttributes, [this, {[name]: value}]) | ||
} | ||
} | ||
async scrollTo(offset: types.Location): Promise<types.Location> { | ||
@@ -336,3 +361,3 @@ return this.withRefresh(async () => { | ||
const yDirection = remainingOffset.y > 0 ? 'down' : 'up' | ||
let yRemaining = Math.abs(remainingOffset.y) + (this.driver.isIOS ? 28 : 48) // ??? | ||
let yRemaining = Math.abs(remainingOffset.y) + (await this.getTouchPadding()) * 2 | ||
while (yRemaining > 0) { | ||
@@ -400,3 +425,3 @@ const yBottom = scrollableRegion.y + Math.min(yRemaining + yPadding, scrollableRegion.height - yPadding) | ||
if (this.driver.isNative) return | ||
// TODO create one js snippet | ||
// TODO create single js snippet | ||
const scrollOffset = await this.getScrollOffset() | ||
@@ -407,4 +432,7 @@ const transforms = await this.context.execute(snippets.getElementStyleProperties, [ | ||
]) | ||
this._state = {scrollOffset, transforms} | ||
return this._state | ||
if (!utils.types.has(this._state, ['scrollOffset', 'transforms'])) { | ||
this._state.scrollOffset = scrollOffset | ||
this._state.transforms = transforms | ||
} | ||
return {scrollOffset, transforms} | ||
} | ||
@@ -414,5 +442,8 @@ | ||
if (this.driver.isNative) return | ||
if (!state) return | ||
if (state.scrollOffset) await this.scrollTo(state.scrollOffset) | ||
if (state.transforms) await this.context.execute(snippets.setElementStyleProperties, [this, state.transforms]) | ||
if (state === this._state) { | ||
this._state.scrollOffset = null | ||
this._state.transforms = null | ||
} | ||
} | ||
@@ -419,0 +450,0 @@ |
@@ -126,3 +126,3 @@ import assert from 'assert' | ||
const childContext11 = await childContext1.context('frame1-1') | ||
await childContext11.init() | ||
await childContext11.focus() | ||
@@ -129,0 +129,0 @@ const locationContext11 = await childContext11.getLocationInViewport() |
@@ -433,3 +433,2 @@ import assert from 'assert' | ||
it('returns device name', () => { | ||
console.log(driver) | ||
assert.strictEqual(driver.deviceName, 'MobilePhone') | ||
@@ -436,0 +435,0 @@ }) |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
1
222672
22
4006
+ Added@applitools/utils@1.2.2(transitive)
- Removed@applitools/utils@1.2.1(transitive)
Updated@applitools/utils@1.2.2