@applitools/driver
Advanced tools
Comparing version 1.11.2 to 1.11.3
@@ -107,2 +107,66 @@ "use strict"; | ||
} | ||
async _findElements(selector, options = {}) { | ||
await this.focus(); | ||
const { parent, all, wait } = options; | ||
const transformedSelector = specUtils.transformSelector(this._spec, selector, this.driver); | ||
let elements = []; | ||
if (wait) { | ||
if (this._spec.waitForSelector) { | ||
const element = await this._spec.waitForSelector(this.target, specUtils.transformSelector(this._spec, selector, this.driver), parent, wait); | ||
if (element) | ||
elements = [element]; | ||
} | ||
else { | ||
let waiting = true; | ||
const timeout = setTimeout(() => (waiting = false), wait.timeout); | ||
while (waiting) { | ||
const element = await this._spec.findElement(this.target, specUtils.transformSelector(this._spec, selector, this.driver), parent); | ||
if (element) { | ||
clearTimeout(timeout); | ||
elements = [element]; | ||
} | ||
await utils.general.sleep(wait.interval); | ||
} | ||
} | ||
} | ||
else if (all) { | ||
elements = await this._spec.findElements(this.target, transformedSelector, parent); | ||
} | ||
else { | ||
const element = await this._spec.findElement(this.target, transformedSelector, parent); | ||
if (element) | ||
elements = [element]; | ||
} | ||
if (specUtils.isCommonSelector(this._spec, selector)) { | ||
if (elements.length > 0) { | ||
if (selector.child) { | ||
elements = await elements.reduce((result, element) => { | ||
return result.then(async (result) => { | ||
return result.concat(await this._findElements(selector.child, { parent: element, all, wait })); | ||
}); | ||
}, Promise.resolve([])); | ||
} | ||
else if (selector.shadow) { | ||
elements = await elements.reduce((result, element) => { | ||
return result.then(async (result) => { | ||
const root = await this._spec.executeScript(this.target, snippets.getShadowRoot, [element]); | ||
return result.concat(root ? await this._findElements(selector.shadow, { parent: root, all, wait }) : []); | ||
}); | ||
}, Promise.resolve([])); | ||
} | ||
else if (selector.frame) { | ||
elements = await elements.reduce((result, element) => { | ||
return result.then(async (result) => { | ||
const context = await this.context(element); | ||
return result.concat(await context._findElements(selector.frame, { all, wait })); | ||
}); | ||
}, Promise.resolve([])); | ||
} | ||
} | ||
if (elements.length === 0 && selector.fallback) { | ||
elements = await this._findElements(selector.fallback, parent); | ||
} | ||
} | ||
return elements; | ||
} | ||
async init() { | ||
@@ -205,37 +269,2 @@ if (this.isInitialized) | ||
} | ||
async root(selector) { | ||
var _a; | ||
await this.focus(); | ||
const { contextSelectors, elementSelector } = specUtils.splitSelector(this._spec, selector); | ||
let context = this; | ||
for (const contextSelector of contextSelectors) { | ||
try { | ||
context = await context.context(contextSelector); | ||
await context.focus(); | ||
} | ||
catch { | ||
return null; | ||
} | ||
} | ||
if ((_a = this.driver.features) === null || _a === void 0 ? void 0 : _a.shadowSelector) | ||
return { context, selector: elementSelector }; | ||
let root = null; | ||
let element = null; | ||
let currentSelector = elementSelector; | ||
while (specUtils.isCommonSelector(this._spec, currentSelector) && | ||
specUtils.isSelector(this._spec, currentSelector.shadow)) { | ||
element = await this._spec.findElement(this.target, specUtils.transformSelector(this._spec, currentSelector, this.driver), root); | ||
if (!element) | ||
return null; | ||
root = await this._spec.executeScript(this.target, snippets.getShadowRoot, [element]); | ||
if (!root) | ||
return null; | ||
currentSelector = currentSelector.shadow; | ||
} | ||
return { | ||
context, | ||
shadow: element && new element_1.Element({ spec: this._spec, context, element, logger: this._logger }), | ||
selector: currentSelector, | ||
}; | ||
} | ||
async element(elementOrSelector) { | ||
@@ -245,19 +274,13 @@ if (this._spec.isElement(elementOrSelector)) { | ||
} | ||
else if (specUtils.isSelector(this._spec, elementOrSelector)) { | ||
if (this.isRef) { | ||
return new element_1.Element({ spec: this._spec, context: this, selector: elementOrSelector, logger: this._logger }); | ||
} | ||
this._logger.log('Finding element by selector: ', elementOrSelector); | ||
const root = await this.root(elementOrSelector); | ||
if (!root) | ||
return null; | ||
const element = await this._spec.findElement(root.context.target, specUtils.transformSelector(this._spec, root.selector, this.driver), root.shadow && (await root.shadow.getShadowRoot())); | ||
// TODO root.selector is not a full selector from context root to an element, but selector inside a shadow | ||
return element | ||
? new element_1.Element({ spec: this._spec, context: root.context, element, selector: root.selector, logger: this._logger }) | ||
: null; | ||
} | ||
else { | ||
else if (!specUtils.isSelector(this._spec, elementOrSelector)) { | ||
throw new TypeError('Cannot find element using argument of unknown type!'); | ||
} | ||
if (this.isRef) { | ||
return new element_1.Element({ spec: this._spec, context: this, selector: elementOrSelector, logger: this._logger }); | ||
} | ||
this._logger.log('Finding element by selector: ', elementOrSelector); | ||
const [element] = await this._findElements(elementOrSelector, { all: false }); | ||
return element | ||
? new element_1.Element({ spec: this._spec, context: this, element, selector: elementOrSelector, logger: this._logger }) | ||
: null; | ||
} | ||
@@ -270,13 +293,9 @@ async elements(selectorOrElement) { | ||
this._logger.log('Finding elements by selector: ', selectorOrElement); | ||
const root = await this.root(selectorOrElement); | ||
if (!root) | ||
return []; | ||
const elements = await this._spec.findElements(root.context.target, specUtils.transformSelector(this._spec, root.selector, this.driver), root.shadow && (await root.shadow.getShadowRoot())); | ||
const elements = await this._findElements(selectorOrElement, { all: true }); | ||
return elements.map((element, index) => { | ||
// TODO root.selector is not a full selector from context root to an element, but selector inside a shadow | ||
return new element_1.Element({ | ||
spec: this._spec, | ||
context: root.context, | ||
context: this, | ||
element, | ||
selector: root.selector, | ||
selector: selectorOrElement, | ||
index, | ||
@@ -295,30 +314,6 @@ logger: this._logger, | ||
async waitFor(selector, options) { | ||
var _a, _b; | ||
const root = await this.root(selector); | ||
if (!root) | ||
return null; | ||
options = { state: 'exist', timeout: 10000, interval: 500, ...options }; | ||
if (this._spec.waitForSelector) { | ||
const element = await this._spec.waitForSelector(root.context.target, specUtils.transformSelector(this._spec, root.selector, this.driver), (_a = root.shadow) === null || _a === void 0 ? void 0 : _a.target, options); | ||
return element | ||
? new element_1.Element({ spec: this._spec, context: root.context, element, selector: root.selector, logger: this._logger }) | ||
: null; | ||
} | ||
let waiting = true; | ||
const timeout = setTimeout(() => (waiting = false), options.timeout); | ||
while (waiting) { | ||
const element = await this._spec.findElement(root.context.target, specUtils.transformSelector(this._spec, root.selector, this.driver), (_b = root.shadow) === null || _b === void 0 ? void 0 : _b.target); | ||
if (element) { | ||
clearTimeout(timeout); | ||
return new element_1.Element({ | ||
spec: this._spec, | ||
context: root.context, | ||
element, | ||
selector: root.selector, | ||
logger: this._logger, | ||
}); | ||
} | ||
await utils.general.sleep(options.interval); | ||
} | ||
return null; | ||
const [element] = await this._findElements(selector, { | ||
wait: { state: 'exist', timeout: 10000, interval: 500, ...options }, | ||
}); | ||
return element ? new element_1.Element({ spec: this._spec, context: this, element, selector, logger: this._logger }) : null; | ||
} | ||
@@ -325,0 +320,0 @@ async execute(script, arg) { |
@@ -37,3 +37,3 @@ "use strict"; | ||
utils.types.has(selector, 'selector') && | ||
Object.keys(selector).every(key => ['selector', 'type', 'frame', 'shadow'].includes(key)) && | ||
Object.keys(selector).every(key => ['selector', 'type', 'frame', 'shadow', 'child', 'fallback'].includes(key)) && | ||
(utils.types.isString(selector.selector) || spec.isSelector(selector.selector))); | ||
@@ -71,3 +71,7 @@ } | ||
activeSelector.type = targetSelector.type; | ||
if (targetSelector.shadow) { | ||
if (targetSelector.child) { | ||
activeSelector = activeSelector.child = {}; | ||
targetSelector = targetSelector.child; | ||
} | ||
else if (targetSelector.shadow) { | ||
activeSelector = activeSelector.shadow = {}; | ||
@@ -74,0 +78,0 @@ targetSelector = targetSelector.shadow; |
{ | ||
"name": "@applitools/driver", | ||
"version": "1.11.2", | ||
"version": "1.11.3", | ||
"description": "Applitools universal framework wrapper", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -50,2 +50,3 @@ import type { Location, Size, Region } from '@applitools/utils'; | ||
get isRef(): boolean; | ||
private _findElements; | ||
init(): Promise<this>; | ||
@@ -55,7 +56,2 @@ focus(): Promise<this>; | ||
context(reference: ContextPlain<TDriver, TContext, TElement, TSelector>): Promise<Context<TDriver, TContext, TElement, TSelector>>; | ||
root(selector: Selector<TSelector>): Promise<{ | ||
context: Context<TDriver, TContext, TElement, TSelector>; | ||
shadow?: Element<TDriver, TContext, TElement, TSelector>; | ||
selector: Selector<TSelector>; | ||
}>; | ||
element(elementOrSelector: TElement | Selector<TSelector>): Promise<Element<TDriver, TContext, TElement, TSelector>>; | ||
@@ -62,0 +58,0 @@ elements(selectorOrElement: Selector<TSelector> | TElement): Promise<Element<TDriver, TContext, TElement, TSelector>[]>; |
export declare type Selector<TSelector = never> = TSelector | string | { | ||
selector: TSelector | string; | ||
type?: string; | ||
child?: Selector<TSelector>; | ||
shadow?: Selector<TSelector>; | ||
frame?: Selector<TSelector>; | ||
fallback?: Selector<TSelector>; | ||
}; | ||
export declare type CommonSelector = Selector; |
import { type SpecDriver } from './spec-driver'; | ||
import { type Selector } from './selector'; | ||
declare type CommonSelector<TSelector = never> = { | ||
selector: TSelector | string; | ||
type?: string; | ||
shadow?: CommonSelector<TSelector> | TSelector | string; | ||
frame?: CommonSelector<TSelector> | TSelector | string; | ||
}; | ||
declare type CommonSelector<TSelector = never> = Exclude<Selector<TSelector>, TSelector | string>; | ||
export declare function isSimpleCommonSelector(selector: any): selector is CommonSelector; | ||
@@ -10,0 +5,0 @@ export declare function isCommonSelector<TSelector>(spec: Pick<SpecDriver<unknown, unknown, unknown, TSelector>, 'isSelector'>, selector: any): selector is CommonSelector<TSelector>; |
230692
3747