@applitools/driver 1.4.17-beta.2 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/context.js CHANGED
@@ -1,493 +1,499 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
- }) : (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- o[k2] = m[k];
8
- }));
9
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
- Object.defineProperty(o, "default", { enumerable: true, value: v });
11
- }) : function(o, v) {
12
- o["default"] = v;
13
- });
14
- var __importStar = (this && this.__importStar) || function (mod) {
15
- if (mod && mod.__esModule) return mod;
16
- var result = {};
17
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
- __setModuleDefault(result, mod);
19
- return result;
20
- };
21
- Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.Context = void 0;
23
- const utils = __importStar(require("@applitools/utils"));
24
- const specUtils = __importStar(require("./spec-utils"));
25
- const element_1 = require("./element");
26
- const snippets = require('@applitools/snippets');
27
- class Context {
28
- constructor(options) {
29
- var _a, _b, _c;
30
- this._state = {};
31
- if (options.context instanceof Context)
32
- return options.context;
33
- this._spec = options.spec;
34
- if (options.logger)
35
- this._logger = options.logger;
36
- if (options.context) {
37
- 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)) {
38
- this._target = options.context;
39
- }
40
- else {
41
- throw new TypeError('Context constructor called with argument of unknown type of context!');
42
- }
43
- }
44
- if (this._isReference(options.reference)) {
45
- if (options.reference instanceof Context)
46
- return options.reference;
47
- if (!options.parent) {
48
- throw new TypeError('Cannot construct child context without reference to the parent');
49
- }
50
- this._reference = options.reference;
51
- this._parent = options.parent;
52
- this._scrollingElement = options.scrollingElement;
53
- this._driver = options.driver || this._parent.driver;
54
- }
55
- else if (!options.reference) {
56
- this._element = null;
57
- this._parent = null;
58
- this._scrollingElement = options.scrollingElement;
59
- this._driver = options.driver;
60
- }
61
- else {
62
- throw new TypeError('Context constructor called with argument of unknown type!');
63
- }
64
- }
65
- _isReference(reference) {
66
- return (reference instanceof Context ||
67
- utils.types.isInteger(reference) ||
68
- utils.types.isString(reference) ||
69
- reference instanceof element_1.Element ||
70
- this._spec.isElement(reference) ||
71
- specUtils.isSelector(this._spec, reference));
72
- }
73
- get target() {
74
- return this._target;
75
- }
76
- get driver() {
77
- return this._driver;
78
- }
79
- get parent() {
80
- var _a;
81
- return (_a = this._parent) !== null && _a !== void 0 ? _a : null;
82
- }
83
- get main() {
84
- var _a, _b;
85
- return (_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.main) !== null && _b !== void 0 ? _b : this;
86
- }
87
- get path() {
88
- var _a, _b;
89
- return [...((_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : []), this];
90
- }
91
- get isMain() {
92
- return this.main === this;
93
- }
94
- get isCurrent() {
95
- return this.driver.currentContext === this;
96
- }
97
- get isInitialized() {
98
- return Boolean(this._element) || this.isMain;
99
- }
100
- get isRef() {
101
- return !this._target;
102
- }
103
- async init() {
104
- if (this.isInitialized)
105
- return this;
106
- if (!this._reference)
107
- throw new TypeError('Cannot initialize context without a reference to the context element');
108
- await this.parent.focus();
109
- this._logger.log('Context initialization');
110
- if (utils.types.isInteger(this._reference)) {
111
- this._logger.log('Getting context element using index:', this._reference);
112
- const elements = await this.parent.elements('frame, iframe');
113
- if (this._reference > elements.length) {
114
- throw new TypeError(`Context element with index ${this._reference} is not found`);
115
- }
116
- this._element = elements[this._reference];
117
- }
118
- else if (utils.types.isString(this._reference) || specUtils.isSelector(this._spec, this._reference)) {
119
- if (utils.types.isString(this._reference)) {
120
- this._logger.log('Getting context element by name or id', this._reference);
121
- this._element = await this.parent
122
- .element(`iframe[name="${this._reference}"], iframe#${this._reference}`)
123
- .catch(() => null);
124
- }
125
- if (!this._element && specUtils.isSelector(this._spec, this._reference)) {
126
- this._logger.log('Getting context element by selector', this._reference);
127
- this._element = await this.parent.element(this._reference);
128
- }
129
- if (!this._element) {
130
- throw new TypeError(`Context element with name, id, or selector ${JSON.stringify(this._reference)}' is not found`);
131
- }
132
- }
133
- else if (this._spec.isElement(this._reference) || this._reference instanceof element_1.Element) {
134
- this._logger.log('Initialize context from reference element', this._reference);
135
- this._element = new element_1.Element({
136
- spec: this._spec,
137
- context: this.parent,
138
- element: this._reference,
139
- logger: this._logger,
140
- });
141
- }
142
- else {
143
- throw new TypeError('Reference type does not supported');
144
- }
145
- this._reference = null;
146
- return this;
147
- }
148
- async focus() {
149
- if (this.isCurrent) {
150
- return this;
151
- }
152
- else if (this.isMain) {
153
- await this.driver.switchToMainContext();
154
- return this;
155
- }
156
- if (this.isRef) {
157
- await this.init();
158
- }
159
- if (!this.parent.isCurrent) {
160
- await this.driver.switchTo(this);
161
- return this;
162
- }
163
- await this.parent.preserveInnerOffset();
164
- if (this.parent.isMain)
165
- await this.parent.preserveContextRegions();
166
- await this.preserveContextRegions();
167
- this._target = await this._spec.childContext(this.parent.target, this._element.target);
168
- this.driver.updateCurrentContext(this);
169
- return this;
170
- }
171
- async equals(context) {
172
- if (context === this || (this.isMain && context === null))
173
- return true;
174
- if (!this._element)
175
- return false;
176
- return this._element.equals(context instanceof Context ? await context.getContextElement() : context);
177
- }
178
- async context(reference) {
179
- if (reference instanceof Context) {
180
- if (reference.parent !== this && !(await this.equals(reference.parent))) {
181
- throw Error('Cannot attach a child context because it has a different parent');
182
- }
183
- return reference;
184
- }
185
- else if (this._isReference(reference)) {
186
- return new Context({ spec: this._spec, parent: this, driver: this.driver, reference, logger: this._logger });
187
- }
188
- else if (utils.types.has(reference, 'reference')) {
189
- const parent = reference.parent ? await this.context(reference.parent) : this;
190
- return new Context({
191
- spec: this._spec,
192
- parent,
193
- driver: this.driver,
194
- reference: reference.reference,
195
- scrollingElement: reference === null || reference === void 0 ? void 0 : reference.scrollingElement,
196
- logger: this._logger,
197
- });
198
- }
199
- }
200
- async root(selector) {
201
- var _a;
202
- await this.focus();
203
- const { contextSelectors, elementSelector } = specUtils.splitSelector(this._spec, selector);
204
- let context = this;
205
- for (const contextSelector of contextSelectors) {
206
- try {
207
- context = await context.context(contextSelector);
208
- await context.focus();
209
- }
210
- catch (_b) {
211
- return null;
212
- }
213
- }
214
- if ((_a = this.driver.features) === null || _a === void 0 ? void 0 : _a.shadowSelector)
215
- return { context, selector: elementSelector };
216
- let root = null;
217
- let currentSelector = elementSelector;
218
- while (specUtils.isCommonSelector(this._spec, currentSelector) &&
219
- specUtils.isSelector(this._spec, currentSelector.shadow)) {
220
- const element = await this._spec.findElement(this.target, specUtils.transformSelector(this._spec, currentSelector, this.driver), root);
221
- if (!element)
222
- return null;
223
- root = await this._spec.executeScript(this.target, snippets.getShadowRoot, [element]);
224
- if (!root)
225
- return null;
226
- currentSelector = currentSelector.shadow;
227
- }
228
- return {
229
- context,
230
- shadow: root ? new element_1.Element({ spec: this._spec, context, element: root, logger: this._logger }) : null,
231
- selector: currentSelector,
232
- };
233
- }
234
- async element(elementOrSelector) {
235
- var _a;
236
- if (this._spec.isElement(elementOrSelector)) {
237
- return new element_1.Element({ spec: this._spec, context: this, element: elementOrSelector, logger: this._logger });
238
- }
239
- else if (specUtils.isSelector(this._spec, elementOrSelector)) {
240
- if (this.isRef) {
241
- return new element_1.Element({ spec: this._spec, context: this, selector: elementOrSelector, logger: this._logger });
242
- }
243
- const root = await this.root(elementOrSelector);
244
- if (!root)
245
- return null;
246
- const element = await this._spec.findElement(root.context.target, specUtils.transformSelector(this._spec, root.selector, this.driver), (_a = root.shadow) === null || _a === void 0 ? void 0 : _a.target);
247
- // TODO root.selector is not a full selector from context root to an element, but selector inside a shadow
248
- return element
249
- ? new element_1.Element({ spec: this._spec, context: root.context, element, selector: root.selector, logger: this._logger })
250
- : null;
251
- }
252
- else {
253
- throw new TypeError('Cannot find element using argument of unknown type!');
254
- }
255
- }
256
- async elements(elementOrSelector) {
257
- var _a;
258
- if (this._spec.isElement(elementOrSelector)) {
259
- return [new element_1.Element({ spec: this._spec, context: this, element: elementOrSelector, logger: this._logger })];
260
- }
261
- else if (specUtils.isSelector(this._spec, elementOrSelector)) {
262
- if (this.isRef) {
263
- return [new element_1.Element({ spec: this._spec, context: this, selector: elementOrSelector, logger: this._logger })];
264
- }
265
- const root = await this.root(elementOrSelector);
266
- if (!root)
267
- return [];
268
- const elements = await this._spec.findElements(root.context.target, specUtils.transformSelector(this._spec, root.selector, this.driver), (_a = root.shadow) === null || _a === void 0 ? void 0 : _a.target);
269
- return elements.map((element, index) => {
270
- // TODO root.selector is not a full selector from context root to an element, but selector inside a shadow
271
- return new element_1.Element({
272
- spec: this._spec,
273
- context: root.context,
274
- element,
275
- selector: root.selector,
276
- index,
277
- logger: this._logger,
278
- });
279
- });
280
- }
281
- else {
282
- throw new TypeError('Cannot find elements using argument of unknown type!');
283
- }
284
- }
285
- async waitFor(selector, options) {
286
- var _a, _b;
287
- const root = await this.root(selector);
288
- if (!root)
289
- return null;
290
- options = Object.assign({ state: 'exist', timeout: 10000, interval: 500 }, options);
291
- if (this._spec.waitForSelector) {
292
- 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);
293
- return element
294
- ? new element_1.Element({ spec: this._spec, context: root.context, element, selector: root.selector, logger: this._logger })
295
- : null;
296
- }
297
- let waiting = true;
298
- const timeout = setTimeout(() => (waiting = false), options.timeout);
299
- while (waiting) {
300
- 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);
301
- if (element) {
302
- clearTimeout(timeout);
303
- return new element_1.Element({
304
- spec: this._spec,
305
- context: root.context,
306
- element,
307
- selector: root.selector,
308
- logger: this._logger,
309
- });
310
- }
311
- await utils.general.sleep(options.interval);
312
- }
313
- return null;
314
- }
315
- async execute(script, arg) {
316
- await this.focus();
317
- try {
318
- return await this._spec.executeScript(this.target, script, serialize.call(this, arg));
319
- }
320
- catch (err) {
321
- this._logger.warn('Error during script execution with argument', arg);
322
- this._logger.error(err);
323
- throw err;
324
- }
325
- function serialize(value) {
326
- var _a, _b;
327
- if (this._spec.isElement(value) || value instanceof element_1.Element) {
328
- return value instanceof element_1.Element ? value.toJSON() : value;
329
- }
330
- else if (utils.types.isArray(value)) {
331
- return value.map(value => serialize.call(this, value));
332
- }
333
- else if (utils.types.isObject(value)) {
334
- return Object.entries((_b = (_a = value.toJSON) === null || _a === void 0 ? void 0 : _a.call(value)) !== null && _b !== void 0 ? _b : value).reduce((serialized, [key, value]) => {
335
- return Object.assign(serialized, { [key]: serialize.call(this, value) });
336
- }, {});
337
- }
338
- else {
339
- return value;
340
- }
341
- }
342
- }
343
- async getContextElement() {
344
- if (this.isMain)
345
- return null;
346
- await this.init();
347
- return this._element;
348
- }
349
- async getScrollingElement() {
350
- if (!(this._scrollingElement instanceof element_1.Element)) {
351
- await this.focus();
352
- if (this._scrollingElement) {
353
- this._scrollingElement = await this.element(this._scrollingElement);
354
- }
355
- else {
356
- this._scrollingElement = await this.element(this.driver.isWeb ? { type: 'css', selector: 'html' } : { type: 'xpath', selector: '//*[@scrollable="true"]' });
357
- }
358
- }
359
- return this._scrollingElement;
360
- }
361
- async setScrollingElement(scrollingElement) {
362
- if (scrollingElement === undefined)
363
- return;
364
- else if (scrollingElement === null)
365
- this._scrollingElement = null;
366
- else {
367
- this._scrollingElement =
368
- scrollingElement instanceof element_1.Element ? scrollingElement : await this.element(scrollingElement);
369
- }
370
- }
371
- async blurElement(element) {
372
- try {
373
- return await this.execute(snippets.blurElement, [element]);
374
- }
375
- catch (err) {
376
- this._logger.warn('Cannot blur element', element);
377
- this._logger.error(err);
378
- return null;
379
- }
380
- }
381
- async focusElement(element) {
382
- try {
383
- return await this.execute(snippets.focusElement, [element]);
384
- }
385
- catch (err) {
386
- this._logger.warn('Cannot focus element', element);
387
- this._logger.error(err);
388
- return null;
389
- }
390
- }
391
- async getRegion() {
392
- var _a;
393
- if (this.isMain && this.isCurrent) {
394
- const viewportRegion = utils.geometry.region({ x: 0, y: 0 }, await this.driver.getViewportSize());
395
- this._state.region = this._scrollingElement
396
- ? utils.geometry.region({ x: 0, y: 0 }, utils.geometry.intersect(viewportRegion, await this._scrollingElement.getRegion()))
397
- : viewportRegion;
398
- }
399
- else if ((_a = this.parent) === null || _a === void 0 ? void 0 : _a.isCurrent) {
400
- await this.init();
401
- this._state.region = await this._element.getRegion();
402
- }
403
- return this._state.region;
404
- }
405
- async getClientRegion() {
406
- var _a;
407
- if (this.isMain && this.isCurrent) {
408
- const viewportRegion = utils.geometry.region({ x: 0, y: 0 }, await this.driver.getViewportSize());
409
- this._state.clientRegion = this._scrollingElement
410
- ? utils.geometry.region({ x: 0, y: 0 }, utils.geometry.intersect(viewportRegion, await this._scrollingElement.getClientRegion()))
411
- : viewportRegion;
412
- }
413
- else if ((_a = this.parent) === null || _a === void 0 ? void 0 : _a.isCurrent) {
414
- await this.init();
415
- this._state.clientRegion = await this._element.getClientRegion();
416
- }
417
- return this._state.clientRegion;
418
- }
419
- async getScrollingRegion() {
420
- if (this.isCurrent) {
421
- const scrollingElement = await this.getScrollingElement();
422
- this._state.scrollingRegion = await scrollingElement.getClientRegion();
423
- }
424
- return this._state.scrollingRegion;
425
- }
426
- async getContentSize() {
427
- return this.execute(snippets.getDocumentSize);
428
- }
429
- async getInnerOffset() {
430
- if (this.isCurrent) {
431
- const scrollingElement = await this.getScrollingElement();
432
- this._state.innerOffset = scrollingElement ? await scrollingElement.getInnerOffset() : { x: 0, y: 0 };
433
- }
434
- return this._state.innerOffset;
435
- }
436
- async getLocationInMainContext() {
437
- return this.path.reduce((location, context) => {
438
- return location.then(async (location) => {
439
- return utils.geometry.offset(location, utils.geometry.location(await context.getClientRegion()));
440
- });
441
- }, Promise.resolve({ x: 0, y: 0 }));
442
- }
443
- async getLocationInViewport() {
444
- var _a, _b;
445
- let location = utils.geometry.offsetNegative({ x: 0, y: 0 }, await this.getInnerOffset());
446
- if (this.isMain)
447
- return location;
448
- let currentContext = this;
449
- while (currentContext) {
450
- const contextLocation = utils.geometry.location(await currentContext.getClientRegion());
451
- const parentContextInnerOffset = (_b = (await ((_a = currentContext.parent) === null || _a === void 0 ? void 0 : _a.getInnerOffset()))) !== null && _b !== void 0 ? _b : { x: 0, y: 0 };
452
- location = utils.geometry.offsetNegative(utils.geometry.offset(location, contextLocation), parentContextInnerOffset);
453
- currentContext = currentContext.parent;
454
- }
455
- return location;
456
- }
457
- async getRegionInViewport(region) {
458
- var _a, _b;
459
- let currentContext = this;
460
- if (region)
461
- region = utils.geometry.offsetNegative(region, await currentContext.getInnerOffset());
462
- else
463
- region = { x: 0, y: 0, width: Infinity, height: Infinity };
464
- while (currentContext) {
465
- const contextRegion = await currentContext.getClientRegion();
466
- // const contextScrollingRegion = await currentContext.getScrollingRegion()
467
- const parentContextInnerOffset = (_b = (await ((_a = currentContext.parent) === null || _a === void 0 ? void 0 : _a.getInnerOffset()))) !== null && _b !== void 0 ? _b : { x: 0, y: 0 };
468
- region = utils.geometry.intersect(contextRegion, utils.geometry.offset(region, contextRegion));
469
- // region = utils.geometry.intersect(contextScrollingRegion, region)
470
- region = utils.geometry.offsetNegative(region, parentContextInnerOffset);
471
- currentContext = currentContext.parent;
472
- }
473
- return region;
474
- }
475
- async getCookies() {
476
- var _a, _b, _c;
477
- if (this.driver.isNative)
478
- return [];
479
- await this.focus();
480
- return (_c = (_b = (_a = this._spec).getCookies) === null || _b === void 0 ? void 0 : _b.call(_a, this.target, true)) !== null && _c !== void 0 ? _c : [];
481
- }
482
- async preserveInnerOffset() {
483
- this._state.innerOffset = await this.getInnerOffset();
484
- }
485
- async preserveContextRegions() {
486
- this._state.region = await this.getRegion();
487
- this._state.clientRegion = await this.getClientRegion();
488
- }
489
- async preserveScrollingRegion() {
490
- this._state.scrollingRegion = await this.getScrollingRegion();
491
- }
492
- }
493
- exports.Context = Context;
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.Context = void 0;
23
+ const utils = __importStar(require("@applitools/utils"));
24
+ const specUtils = __importStar(require("./spec-utils"));
25
+ const element_1 = require("./element");
26
+ const snippets = require('@applitools/snippets');
27
+ class Context {
28
+ constructor(options) {
29
+ var _a, _b, _c;
30
+ this._state = {};
31
+ if (options.context instanceof Context)
32
+ return options.context;
33
+ this._spec = options.spec;
34
+ if (options.logger)
35
+ this._logger = options.logger;
36
+ if (options.context) {
37
+ 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)) {
38
+ this._target = options.context;
39
+ }
40
+ else {
41
+ throw new TypeError('Context constructor called with argument of unknown type of context!');
42
+ }
43
+ }
44
+ if (this._isReference(options.reference)) {
45
+ if (options.reference instanceof Context)
46
+ return options.reference;
47
+ if (!options.parent) {
48
+ throw new TypeError('Cannot construct child context without reference to the parent');
49
+ }
50
+ this._reference = options.reference;
51
+ this._parent = options.parent;
52
+ this._scrollingElement = options.scrollingElement;
53
+ this._driver = options.driver || this._parent.driver;
54
+ }
55
+ else if (!options.reference) {
56
+ this._element = null;
57
+ this._parent = null;
58
+ this._scrollingElement = options.scrollingElement;
59
+ this._driver = options.driver;
60
+ }
61
+ else {
62
+ throw new TypeError('Context constructor called with argument of unknown type!');
63
+ }
64
+ }
65
+ _isReference(reference) {
66
+ return (reference instanceof Context ||
67
+ utils.types.isInteger(reference) ||
68
+ utils.types.isString(reference) ||
69
+ reference instanceof element_1.Element ||
70
+ this._spec.isElement(reference) ||
71
+ specUtils.isSelector(this._spec, reference));
72
+ }
73
+ get target() {
74
+ return this._target;
75
+ }
76
+ get driver() {
77
+ return this._driver;
78
+ }
79
+ get parent() {
80
+ var _a;
81
+ return (_a = this._parent) !== null && _a !== void 0 ? _a : null;
82
+ }
83
+ get main() {
84
+ var _a, _b;
85
+ return (_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.main) !== null && _b !== void 0 ? _b : this;
86
+ }
87
+ get path() {
88
+ var _a, _b;
89
+ return [...((_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : []), this];
90
+ }
91
+ get isMain() {
92
+ return this.main === this;
93
+ }
94
+ get isCurrent() {
95
+ return this.driver.currentContext === this;
96
+ }
97
+ get isInitialized() {
98
+ return Boolean(this._element) || this.isMain;
99
+ }
100
+ get isRef() {
101
+ return !this._target;
102
+ }
103
+ async init() {
104
+ if (this.isInitialized)
105
+ return this;
106
+ if (!this._reference)
107
+ throw new TypeError('Cannot initialize context without a reference to the context element');
108
+ await this.parent.focus();
109
+ this._logger.log('Context initialization');
110
+ if (utils.types.isInteger(this._reference)) {
111
+ this._logger.log('Getting context element using index:', this._reference);
112
+ const elements = await this.parent.elements('frame, iframe');
113
+ if (this._reference > elements.length) {
114
+ throw new TypeError(`Context element with index ${this._reference} is not found`);
115
+ }
116
+ this._element = elements[this._reference];
117
+ }
118
+ else if (utils.types.isString(this._reference) || specUtils.isSelector(this._spec, this._reference)) {
119
+ if (utils.types.isString(this._reference)) {
120
+ this._logger.log('Getting context element by name or id', this._reference);
121
+ this._element = await this.parent
122
+ .element(`iframe[name="${this._reference}"], iframe#${this._reference}`)
123
+ .catch(() => null);
124
+ }
125
+ if (!this._element && specUtils.isSelector(this._spec, this._reference)) {
126
+ this._logger.log('Getting context element by selector', this._reference);
127
+ this._element = await this.parent.element(this._reference);
128
+ }
129
+ if (!this._element) {
130
+ throw new TypeError(`Context element with name, id, or selector ${JSON.stringify(this._reference)}' is not found`);
131
+ }
132
+ }
133
+ else if (this._spec.isElement(this._reference) || this._reference instanceof element_1.Element) {
134
+ this._logger.log('Initialize context from reference element', this._reference);
135
+ this._element = new element_1.Element({
136
+ spec: this._spec,
137
+ context: this.parent,
138
+ element: this._reference,
139
+ logger: this._logger,
140
+ });
141
+ }
142
+ else {
143
+ throw new TypeError('Reference type does not supported');
144
+ }
145
+ this._reference = null;
146
+ return this;
147
+ }
148
+ async focus() {
149
+ if (this.isCurrent) {
150
+ return this;
151
+ }
152
+ else if (this.isMain) {
153
+ await this.driver.switchToMainContext();
154
+ return this;
155
+ }
156
+ if (this.isRef) {
157
+ await this.init();
158
+ }
159
+ if (!this.parent.isCurrent) {
160
+ await this.driver.switchTo(this);
161
+ return this;
162
+ }
163
+ await this.parent.preserveInnerOffset();
164
+ if (this.parent.isMain)
165
+ await this.parent.preserveContextRegions();
166
+ await this.preserveContextRegions();
167
+ this._target = await this._spec.childContext(this.parent.target, this._element.target);
168
+ this.driver.updateCurrentContext(this);
169
+ return this;
170
+ }
171
+ async equals(context) {
172
+ if (context === this || (this.isMain && context === null))
173
+ return true;
174
+ if (!this._element)
175
+ return false;
176
+ return this._element.equals(context instanceof Context ? await context.getContextElement() : context);
177
+ }
178
+ async context(reference) {
179
+ if (reference instanceof Context) {
180
+ if (reference.parent !== this && !(await this.equals(reference.parent))) {
181
+ throw Error('Cannot attach a child context because it has a different parent');
182
+ }
183
+ return reference;
184
+ }
185
+ else if (this._isReference(reference)) {
186
+ return new Context({ spec: this._spec, parent: this, driver: this.driver, reference, logger: this._logger });
187
+ }
188
+ else if (utils.types.has(reference, 'reference')) {
189
+ const parent = reference.parent ? await this.context(reference.parent) : this;
190
+ return new Context({
191
+ spec: this._spec,
192
+ parent,
193
+ driver: this.driver,
194
+ reference: reference.reference,
195
+ scrollingElement: reference === null || reference === void 0 ? void 0 : reference.scrollingElement,
196
+ logger: this._logger,
197
+ });
198
+ }
199
+ }
200
+ async root(selector) {
201
+ var _a;
202
+ await this.focus();
203
+ const { contextSelectors, elementSelector } = specUtils.splitSelector(this._spec, selector);
204
+ let context = this;
205
+ for (const contextSelector of contextSelectors) {
206
+ try {
207
+ context = await context.context(contextSelector);
208
+ await context.focus();
209
+ }
210
+ catch (_b) {
211
+ return null;
212
+ }
213
+ }
214
+ if ((_a = this.driver.features) === null || _a === void 0 ? void 0 : _a.shadowSelector)
215
+ return { context, selector: elementSelector };
216
+ let root = null;
217
+ let currentSelector = elementSelector;
218
+ while (specUtils.isCommonSelector(this._spec, currentSelector) &&
219
+ specUtils.isSelector(this._spec, currentSelector.shadow)) {
220
+ const element = await this._spec.findElement(this.target, specUtils.transformSelector(this._spec, currentSelector, this.driver), root);
221
+ if (!element)
222
+ return null;
223
+ root = await this._spec.executeScript(this.target, snippets.getShadowRoot, [element]);
224
+ if (!root)
225
+ return null;
226
+ currentSelector = currentSelector.shadow;
227
+ }
228
+ return {
229
+ context,
230
+ shadow: root ? new element_1.Element({ spec: this._spec, context, element: root, logger: this._logger }) : null,
231
+ selector: currentSelector,
232
+ };
233
+ }
234
+ async element(elementOrSelector) {
235
+ var _a;
236
+ if (this._spec.isElement(elementOrSelector)) {
237
+ return new element_1.Element({ spec: this._spec, context: this, element: elementOrSelector, logger: this._logger });
238
+ }
239
+ else if (specUtils.isSelector(this._spec, elementOrSelector)) {
240
+ if (this.isRef) {
241
+ return new element_1.Element({ spec: this._spec, context: this, selector: elementOrSelector, logger: this._logger });
242
+ }
243
+ const root = await this.root(elementOrSelector);
244
+ if (!root)
245
+ return null;
246
+ const element = await this._spec.findElement(root.context.target, specUtils.transformSelector(this._spec, root.selector, this.driver), (_a = root.shadow) === null || _a === void 0 ? void 0 : _a.target);
247
+ // TODO root.selector is not a full selector from context root to an element, but selector inside a shadow
248
+ return element
249
+ ? new element_1.Element({ spec: this._spec, context: root.context, element, selector: root.selector, logger: this._logger })
250
+ : null;
251
+ }
252
+ else {
253
+ throw new TypeError('Cannot find element using argument of unknown type!');
254
+ }
255
+ }
256
+ async elements(elementOrSelector) {
257
+ var _a;
258
+ if (this._spec.isElement(elementOrSelector)) {
259
+ return [new element_1.Element({ spec: this._spec, context: this, element: elementOrSelector, logger: this._logger })];
260
+ }
261
+ else if (specUtils.isSelector(this._spec, elementOrSelector)) {
262
+ if (this.isRef) {
263
+ return [new element_1.Element({ spec: this._spec, context: this, selector: elementOrSelector, logger: this._logger })];
264
+ }
265
+ const root = await this.root(elementOrSelector);
266
+ if (!root)
267
+ return [];
268
+ const elements = await this._spec.findElements(root.context.target, specUtils.transformSelector(this._spec, root.selector, this.driver), (_a = root.shadow) === null || _a === void 0 ? void 0 : _a.target);
269
+ return elements.map((element, index) => {
270
+ // TODO root.selector is not a full selector from context root to an element, but selector inside a shadow
271
+ return new element_1.Element({
272
+ spec: this._spec,
273
+ context: root.context,
274
+ element,
275
+ selector: root.selector,
276
+ index,
277
+ logger: this._logger,
278
+ });
279
+ });
280
+ }
281
+ else {
282
+ throw new TypeError('Cannot find elements using argument of unknown type!');
283
+ }
284
+ }
285
+ async waitFor(selector, options) {
286
+ var _a, _b;
287
+ const root = await this.root(selector);
288
+ if (!root)
289
+ return null;
290
+ options = Object.assign({ state: 'exist', timeout: 10000, interval: 500 }, options);
291
+ if (this._spec.waitForSelector) {
292
+ 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);
293
+ return element
294
+ ? new element_1.Element({ spec: this._spec, context: root.context, element, selector: root.selector, logger: this._logger })
295
+ : null;
296
+ }
297
+ let waiting = true;
298
+ const timeout = setTimeout(() => (waiting = false), options.timeout);
299
+ while (waiting) {
300
+ 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);
301
+ if (element) {
302
+ clearTimeout(timeout);
303
+ return new element_1.Element({
304
+ spec: this._spec,
305
+ context: root.context,
306
+ element,
307
+ selector: root.selector,
308
+ logger: this._logger,
309
+ });
310
+ }
311
+ await utils.general.sleep(options.interval);
312
+ }
313
+ return null;
314
+ }
315
+ async execute(script, arg) {
316
+ await this.focus();
317
+ try {
318
+ return await this._spec.executeScript(this.target, script, serialize.call(this, arg));
319
+ }
320
+ catch (err) {
321
+ this._logger.warn('Error during script execution with argument', arg);
322
+ this._logger.error(err);
323
+ throw err;
324
+ }
325
+ function serialize(value) {
326
+ var _a, _b;
327
+ if (this._spec.isElement(value) || value instanceof element_1.Element) {
328
+ return value instanceof element_1.Element ? value.toJSON() : value;
329
+ }
330
+ else if (utils.types.isArray(value)) {
331
+ return value.map(value => serialize.call(this, value));
332
+ }
333
+ else if (utils.types.isObject(value)) {
334
+ return Object.entries((_b = (_a = value.toJSON) === null || _a === void 0 ? void 0 : _a.call(value)) !== null && _b !== void 0 ? _b : value).reduce((serialized, [key, value]) => {
335
+ return Object.assign(serialized, { [key]: serialize.call(this, value) });
336
+ }, {});
337
+ }
338
+ else {
339
+ return value;
340
+ }
341
+ }
342
+ }
343
+ async getContextElement() {
344
+ if (this.isMain)
345
+ return null;
346
+ await this.init();
347
+ return this._element;
348
+ }
349
+ async getScrollingElement() {
350
+ if (!(this._scrollingElement instanceof element_1.Element)) {
351
+ await this.focus();
352
+ if (this._scrollingElement) {
353
+ this._scrollingElement = await this.element(this._scrollingElement);
354
+ }
355
+ else if (this.driver.isWeb) {
356
+ const isIOS = this.driver.isIOS;
357
+ const selector = isIOS ? 'html' : await this.execute(snippets.getDocumentScrollingElement);
358
+ this._logger.log(`default SRE is ${selector}${isIOS ? ' (because Safari on iOS)' : ''}`);
359
+ this._scrollingElement = await this.element({ type: 'css', selector });
360
+ }
361
+ else {
362
+ this._scrollingElement = await this.element({ type: 'xpath', selector: '//*[@scrollable="true"]' });
363
+ }
364
+ }
365
+ return this._scrollingElement;
366
+ }
367
+ async setScrollingElement(scrollingElement) {
368
+ if (scrollingElement === undefined)
369
+ return;
370
+ else if (scrollingElement === null)
371
+ this._scrollingElement = null;
372
+ else {
373
+ this._scrollingElement =
374
+ scrollingElement instanceof element_1.Element ? scrollingElement : await this.element(scrollingElement);
375
+ }
376
+ }
377
+ async blurElement(element) {
378
+ try {
379
+ return await this.execute(snippets.blurElement, [element]);
380
+ }
381
+ catch (err) {
382
+ this._logger.warn('Cannot blur element', element);
383
+ this._logger.error(err);
384
+ return null;
385
+ }
386
+ }
387
+ async focusElement(element) {
388
+ try {
389
+ return await this.execute(snippets.focusElement, [element]);
390
+ }
391
+ catch (err) {
392
+ this._logger.warn('Cannot focus element', element);
393
+ this._logger.error(err);
394
+ return null;
395
+ }
396
+ }
397
+ async getRegion() {
398
+ var _a;
399
+ if (this.isMain && this.isCurrent) {
400
+ const viewportRegion = utils.geometry.region({ x: 0, y: 0 }, await this.driver.getViewportSize());
401
+ this._state.region = this._scrollingElement
402
+ ? utils.geometry.region({ x: 0, y: 0 }, utils.geometry.intersect(viewportRegion, await this._scrollingElement.getRegion()))
403
+ : viewportRegion;
404
+ }
405
+ else if ((_a = this.parent) === null || _a === void 0 ? void 0 : _a.isCurrent) {
406
+ await this.init();
407
+ this._state.region = await this._element.getRegion();
408
+ }
409
+ return this._state.region;
410
+ }
411
+ async getClientRegion() {
412
+ var _a;
413
+ if (this.isMain && this.isCurrent) {
414
+ const viewportRegion = utils.geometry.region({ x: 0, y: 0 }, await this.driver.getViewportSize());
415
+ this._state.clientRegion = this._scrollingElement
416
+ ? utils.geometry.region({ x: 0, y: 0 }, utils.geometry.intersect(viewportRegion, await this._scrollingElement.getClientRegion()))
417
+ : viewportRegion;
418
+ }
419
+ else if ((_a = this.parent) === null || _a === void 0 ? void 0 : _a.isCurrent) {
420
+ await this.init();
421
+ this._state.clientRegion = await this._element.getClientRegion();
422
+ }
423
+ return this._state.clientRegion;
424
+ }
425
+ async getScrollingRegion() {
426
+ if (this.isCurrent) {
427
+ const scrollingElement = await this.getScrollingElement();
428
+ this._state.scrollingRegion = await scrollingElement.getClientRegion();
429
+ }
430
+ return this._state.scrollingRegion;
431
+ }
432
+ async getContentSize() {
433
+ return this.execute(snippets.getDocumentSize);
434
+ }
435
+ async getInnerOffset() {
436
+ if (this.isCurrent) {
437
+ const scrollingElement = await this.getScrollingElement();
438
+ this._state.innerOffset = scrollingElement ? await scrollingElement.getInnerOffset() : { x: 0, y: 0 };
439
+ }
440
+ return this._state.innerOffset;
441
+ }
442
+ async getLocationInMainContext() {
443
+ return this.path.reduce((location, context) => {
444
+ return location.then(async (location) => {
445
+ return utils.geometry.offset(location, utils.geometry.location(await context.getClientRegion()));
446
+ });
447
+ }, Promise.resolve({ x: 0, y: 0 }));
448
+ }
449
+ async getLocationInViewport() {
450
+ var _a, _b;
451
+ let location = utils.geometry.offsetNegative({ x: 0, y: 0 }, await this.getInnerOffset());
452
+ if (this.isMain)
453
+ return location;
454
+ let currentContext = this;
455
+ while (currentContext) {
456
+ const contextLocation = utils.geometry.location(await currentContext.getClientRegion());
457
+ const parentContextInnerOffset = (_b = (await ((_a = currentContext.parent) === null || _a === void 0 ? void 0 : _a.getInnerOffset()))) !== null && _b !== void 0 ? _b : { x: 0, y: 0 };
458
+ location = utils.geometry.offsetNegative(utils.geometry.offset(location, contextLocation), parentContextInnerOffset);
459
+ currentContext = currentContext.parent;
460
+ }
461
+ return location;
462
+ }
463
+ async getRegionInViewport(region) {
464
+ var _a, _b;
465
+ let currentContext = this;
466
+ if (region)
467
+ region = utils.geometry.offsetNegative(region, await currentContext.getInnerOffset());
468
+ else
469
+ region = { x: 0, y: 0, width: Infinity, height: Infinity };
470
+ while (currentContext) {
471
+ const contextRegion = await currentContext.getClientRegion();
472
+ // const contextScrollingRegion = await currentContext.getScrollingRegion()
473
+ const parentContextInnerOffset = (_b = (await ((_a = currentContext.parent) === null || _a === void 0 ? void 0 : _a.getInnerOffset()))) !== null && _b !== void 0 ? _b : { x: 0, y: 0 };
474
+ region = utils.geometry.intersect(contextRegion, utils.geometry.offset(region, contextRegion));
475
+ // region = utils.geometry.intersect(contextScrollingRegion, region)
476
+ region = utils.geometry.offsetNegative(region, parentContextInnerOffset);
477
+ currentContext = currentContext.parent;
478
+ }
479
+ return region;
480
+ }
481
+ async getCookies() {
482
+ var _a, _b, _c;
483
+ if (this.driver.isNative)
484
+ return [];
485
+ await this.focus();
486
+ return (_c = (_b = (_a = this._spec).getCookies) === null || _b === void 0 ? void 0 : _b.call(_a, this.target, true)) !== null && _c !== void 0 ? _c : [];
487
+ }
488
+ async preserveInnerOffset() {
489
+ this._state.innerOffset = await this.getInnerOffset();
490
+ }
491
+ async preserveContextRegions() {
492
+ this._state.region = await this.getRegion();
493
+ this._state.clientRegion = await this.getClientRegion();
494
+ }
495
+ async preserveScrollingRegion() {
496
+ this._state.scrollingRegion = await this.getScrollingRegion();
497
+ }
498
+ }
499
+ exports.Context = Context;