@mablhq/mabl-cli 1.12.33 → 1.13.19
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/api/basicApiClient.js +63 -26
- package/api/mablApiClientFactory.js +1 -0
- package/browserLauncher/browserLauncherFactory.js +7 -3
- package/browserLauncher/playwrightBrowserLauncher/playwrightBrowser.js +4 -0
- package/browserLauncher/playwrightBrowserLauncher/playwrightBrowserLauncher.js +1 -0
- package/browserLauncher/playwrightBrowserLauncher/playwrightDom.js +38 -12
- package/browserLauncher/playwrightBrowserLauncher/playwrightFrame.js +10 -0
- package/browserLauncher/playwrightBrowserLauncher/playwrightHttpResponse.js +3 -0
- package/browserLauncher/playwrightBrowserLauncher/playwrightPage.js +61 -57
- package/browserLauncher/puppeteerBrowserLauncher/puppeteerBrowser.js +4 -0
- package/browserLauncher/puppeteerBrowserLauncher/puppeteerElementHandle.js +7 -1
- package/browserLauncher/puppeteerBrowserLauncher/puppeteerHttpResponse.js +3 -0
- package/browserLauncher/types.js +6 -1
- package/commands/tests/testsUtil.js +6 -3
- package/commands/tests/tests_cmds/run-cloud.js +1 -1
- package/commands/tests/tests_cmds/run.js +20 -2
- package/execution/index.js +1 -1
- package/execution/index.js.LICENSE.txt +12 -0
- package/index.d.ts +7 -0
- package/mablscript/steps/SendHttpRequestStep.js +9 -1
- package/package.json +3 -2
- package/popupDismissal/index.js +29 -23
- package/resources/popupDismissal.js +1 -1
- package/util/actionabilityUtil.js +55 -7
- package/util/asyncUtil.js +45 -0
- package/util/logUtils.js +2 -2
- package/util/resourceUtil.js +4 -0
|
@@ -162,6 +162,18 @@ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
162
162
|
PERFORMANCE OF THIS SOFTWARE.
|
|
163
163
|
***************************************************************************** */
|
|
164
164
|
|
|
165
|
+
/*! axe v4.3.3
|
|
166
|
+
* Copyright (c) 2021 Deque Systems, Inc.
|
|
167
|
+
*
|
|
168
|
+
* Your use of this Source Code Form is subject to the terms of the Mozilla Public
|
|
169
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
170
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
171
|
+
*
|
|
172
|
+
* This entire copyright notice must appear in every copy of this file you
|
|
173
|
+
* distribute or in any file that contains substantial portions of this source
|
|
174
|
+
* code.
|
|
175
|
+
*/
|
|
176
|
+
|
|
165
177
|
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
166
178
|
|
|
167
179
|
/**
|
package/index.d.ts
CHANGED
|
@@ -26,6 +26,9 @@ declare module '@mablhq/mabl-cli' {
|
|
|
26
26
|
Playwright = 'playwright',
|
|
27
27
|
Puppeteer = 'puppeteer',
|
|
28
28
|
}
|
|
29
|
+
export interface HttpHeadersType {
|
|
30
|
+
[key: string]: string;
|
|
31
|
+
}
|
|
29
32
|
export interface TestRunConfig {
|
|
30
33
|
authToken?: string;
|
|
31
34
|
basicAuthCredentialsId?: string;
|
|
@@ -33,6 +36,10 @@ declare module '@mablhq/mabl-cli' {
|
|
|
33
36
|
branchChangesOnly?: boolean;
|
|
34
37
|
credentialsId?: string;
|
|
35
38
|
environmentId?: string;
|
|
39
|
+
/**
|
|
40
|
+
* An object containing additional HTTP headers to be sent with every request.
|
|
41
|
+
*/
|
|
42
|
+
extraHttpHeaders?: HttpHeadersType;
|
|
36
43
|
filterHttpRequests: boolean;
|
|
37
44
|
fromPlanId?: string;
|
|
38
45
|
headless?: boolean;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.HttpResponseAssertion = exports.SendHttpRequestStep = void 0;
|
|
3
|
+
exports.VariableSource = exports.HttpResponseAssertion = exports.SendHttpRequestStep = void 0;
|
|
4
4
|
const MablStep_1 = require("../MablStep");
|
|
5
5
|
const AssertStep_1 = require("./AssertStep");
|
|
6
6
|
const ConditionDescriptor_1 = require("../types/ConditionDescriptor");
|
|
@@ -55,3 +55,11 @@ var HttpResponseAssertion;
|
|
|
55
55
|
}
|
|
56
56
|
HttpResponseAssertion.toComparisonDescriptor = toComparisonDescriptor;
|
|
57
57
|
})(HttpResponseAssertion = exports.HttpResponseAssertion || (exports.HttpResponseAssertion = {}));
|
|
58
|
+
var VariableSource;
|
|
59
|
+
(function (VariableSource) {
|
|
60
|
+
VariableSource["Body"] = "body";
|
|
61
|
+
VariableSource["Header"] = "header";
|
|
62
|
+
VariableSource["Json"] = "json";
|
|
63
|
+
VariableSource["Response"] = "response";
|
|
64
|
+
VariableSource["Status"] = "status";
|
|
65
|
+
})(VariableSource = exports.VariableSource || (exports.VariableSource = {}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mablhq/mabl-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.19",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
5
5
|
"description": "The official mabl command line interface tool",
|
|
6
6
|
"main": "index.js",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"postinstall": "node ./util/postInstallMessage.js"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@playwright/test": "1.
|
|
28
|
+
"@playwright/test": "1.17.1",
|
|
29
|
+
"playwright-core": "1.17.1",
|
|
29
30
|
"@types/fs-extra": "^8.1.0",
|
|
30
31
|
"@types/serve-handler": "^6.1.0",
|
|
31
32
|
"@types/tmp": "^0.2.0",
|
package/popupDismissal/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.elementsInFrontCount = exports.detectAndDismissPopupCandidates = exports.getAllElementsAbove = exports.elementsByHigherZIndex = void 0;
|
|
3
|
+
exports.elementsInFrontCount = exports.detectAndDismissPopupCandidates = exports.getAllElementsAbove = exports.elementsAtCoordinate = exports.elementsByHigherZIndex = void 0;
|
|
4
4
|
const DISMISSAL_WAIT_TIME_MS = 750;
|
|
5
5
|
const ZINDEX_AUTO = 'auto';
|
|
6
6
|
const MINIMUM_POPUP_DISPLAY_COVERAGE_PX = 0.95;
|
|
@@ -40,9 +40,9 @@ function getEffectiveZIndex(element) {
|
|
|
40
40
|
const isRootElement = (element) => element === undefined || element.tagName.toLowerCase() === 'html';
|
|
41
41
|
let current = element;
|
|
42
42
|
while (!isRootElement(current)) {
|
|
43
|
-
const zIndex = window.getComputedStyle(
|
|
43
|
+
const zIndex = window.getComputedStyle(current).zIndex;
|
|
44
44
|
if (zIndex && zIndex !== ZINDEX_AUTO) {
|
|
45
|
-
return zIndex;
|
|
45
|
+
return parseInt(zIndex, 10);
|
|
46
46
|
}
|
|
47
47
|
current = (current === null || current === void 0 ? void 0 : current.parentElement) ? current.parentElement : undefined;
|
|
48
48
|
}
|
|
@@ -135,13 +135,14 @@ function fireClickEvent(targetElement, leftEdgeClick) {
|
|
|
135
135
|
});
|
|
136
136
|
targetElement.dispatchEvent(mouseEvent);
|
|
137
137
|
}
|
|
138
|
-
function
|
|
138
|
+
function elementsAtCoordinate(element, pointX, pointY) {
|
|
139
139
|
const x = pointX !== undefined ? pointX : getBoundingClientRectWithXY(element).x;
|
|
140
140
|
const y = pointY !== undefined ? pointY : getBoundingClientRectWithXY(element).y;
|
|
141
141
|
const elementsAtPoint = document.elementsFromPoint(x, y);
|
|
142
142
|
const targetIndex = elementsAtPoint.findIndex((iterElement) => iterElement === element);
|
|
143
143
|
return targetIndex ? elementsAtPoint.slice(0, targetIndex) : [];
|
|
144
144
|
}
|
|
145
|
+
exports.elementsAtCoordinate = elementsAtCoordinate;
|
|
145
146
|
function sleep(time) {
|
|
146
147
|
return new Promise((resolve) => setTimeout(resolve, time));
|
|
147
148
|
}
|
|
@@ -158,8 +159,15 @@ function getBoundingClientRectWithXY(element) {
|
|
|
158
159
|
width: Math.floor(rect.right) - Math.ceil(rect.left),
|
|
159
160
|
};
|
|
160
161
|
}
|
|
161
|
-
function getAllElementsAbove(elements) {
|
|
162
|
-
|
|
162
|
+
function getAllElementsAbove(targetElement, elements) {
|
|
163
|
+
if (elements.length === 0) {
|
|
164
|
+
return [];
|
|
165
|
+
}
|
|
166
|
+
const targetZindex = getEffectiveZIndex(targetElement);
|
|
167
|
+
const zIndexAboveTarget = Math.min(...elements === null || elements === void 0 ? void 0 : elements.map((el) => getEffectiveZIndex(el)));
|
|
168
|
+
if (zIndexAboveTarget <= targetZindex) {
|
|
169
|
+
return [];
|
|
170
|
+
}
|
|
163
171
|
const higherElementsByZIndex = elementsByHigherZIndex(zIndexAboveTarget);
|
|
164
172
|
const allElementsByZIndex = Array.from(higherElementsByZIndex).map(([item, higherElements]) => {
|
|
165
173
|
const allElements = higherElements
|
|
@@ -174,29 +182,25 @@ exports.getAllElementsAbove = getAllElementsAbove;
|
|
|
174
182
|
async function detectAndDismissPopupCandidates(element) {
|
|
175
183
|
const elementBoundingBox = getBoundingClientRectWithXY(element);
|
|
176
184
|
try {
|
|
177
|
-
let higherElements =
|
|
185
|
+
let higherElements = elementsAtCoordinate(element, elementBoundingBox.x, elementBoundingBox.y);
|
|
178
186
|
const elementsInFrontCount = higherElements.length;
|
|
179
187
|
if (elementsInFrontCount === 0) {
|
|
180
188
|
return {
|
|
181
|
-
zIndex: 0,
|
|
182
189
|
elementsInFront: 0,
|
|
183
190
|
dismissedStatus: false,
|
|
184
|
-
domCovering: [],
|
|
185
|
-
actionableElements: [],
|
|
186
191
|
};
|
|
187
192
|
}
|
|
188
193
|
const clickCandidates = async function (candidates, leftEdgeClick) {
|
|
189
194
|
for (const candidate of candidates) {
|
|
190
195
|
fireClickEvent(candidate, leftEdgeClick);
|
|
191
196
|
await sleep(DISMISSAL_WAIT_TIME_MS);
|
|
192
|
-
if (
|
|
193
|
-
.length < elementsInFrontCount) {
|
|
197
|
+
if (elementsAtCoordinate(element, elementBoundingBox.x, elementBoundingBox.y).length < elementsInFrontCount) {
|
|
194
198
|
return true;
|
|
195
199
|
}
|
|
196
200
|
}
|
|
197
201
|
return false;
|
|
198
202
|
};
|
|
199
|
-
let allElements = getAllElementsAbove(higherElements);
|
|
203
|
+
let allElements = getAllElementsAbove(element, higherElements);
|
|
200
204
|
const candidatesByZIndex = developCloseCandidates(allElements);
|
|
201
205
|
for (const candidate of candidatesByZIndex) {
|
|
202
206
|
let matched = await clickCandidates(candidate.domCovering, true);
|
|
@@ -204,12 +208,14 @@ async function detectAndDismissPopupCandidates(element) {
|
|
|
204
208
|
matched = await clickCandidates(candidate.actionableElements, false);
|
|
205
209
|
}
|
|
206
210
|
if (matched) {
|
|
207
|
-
|
|
208
|
-
|
|
211
|
+
return {
|
|
212
|
+
dismissedStatus: true,
|
|
213
|
+
elementsInFront: 0,
|
|
214
|
+
};
|
|
209
215
|
}
|
|
210
216
|
}
|
|
211
|
-
higherElements =
|
|
212
|
-
allElements = getAllElementsAbove(higherElements);
|
|
217
|
+
higherElements = elementsAtCoordinate(element, elementBoundingBox.x, elementBoundingBox.y);
|
|
218
|
+
allElements = getAllElementsAbove(element, higherElements);
|
|
213
219
|
const candidates = developCloseCandidates(allElements);
|
|
214
220
|
const result = candidates.length
|
|
215
221
|
? candidates[0]
|
|
@@ -222,21 +228,21 @@ async function detectAndDismissPopupCandidates(element) {
|
|
|
222
228
|
};
|
|
223
229
|
result.elementsInFront = higherElements.length;
|
|
224
230
|
result.dismissedStatus = false;
|
|
225
|
-
return
|
|
231
|
+
return {
|
|
232
|
+
dismissedStatus: result.dismissedStatus,
|
|
233
|
+
elementsInFront: result.elementsInFront,
|
|
234
|
+
};
|
|
226
235
|
}
|
|
227
236
|
catch (error) {
|
|
228
237
|
return {
|
|
229
|
-
zIndex: 0,
|
|
230
238
|
elementsInFront: 0,
|
|
231
239
|
dismissedStatus: false,
|
|
232
|
-
|
|
233
|
-
actionableElements: [],
|
|
234
|
-
errorInDetection: error.toString(),
|
|
240
|
+
error: error.toString(),
|
|
235
241
|
};
|
|
236
242
|
}
|
|
237
243
|
}
|
|
238
244
|
exports.detectAndDismissPopupCandidates = detectAndDismissPopupCandidates;
|
|
239
245
|
function elementsInFrontCount(element) {
|
|
240
|
-
return
|
|
246
|
+
return elementsAtCoordinate(element).length;
|
|
241
247
|
}
|
|
242
248
|
exports.elementsInFrontCount = elementsInFrontCount;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
window.popupDismissal=function(t){var e={};function n(o){if(e[o])return e[o].exports;var r=e[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(o,r,function(e){return t[e]}.bind(null,r));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=0)}([function(t,e,n){"use strict";n.r(e),n.d(e,"elementsByHigherZIndex",(function(){return i})),n.d(e,"getAllElementsAbove",(function(){return
|
|
1
|
+
window.popupDismissal=function(t){var e={};function n(o){if(e[o])return e[o].exports;var r=e[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(o,r,function(e){return t[e]}.bind(null,r));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=0)}([function(t,e,n){"use strict";n.r(e),n.d(e,"elementsByHigherZIndex",(function(){return i})),n.d(e,"elementsAtCoordinate",(function(){return d})),n.d(e,"getAllElementsAbove",(function(){return h})),n.d(e,"detectAndDismissPopupCandidates",(function(){return g})),n.d(e,"elementsInFrontCount",(function(){return p}));const o=["close","dismiss","exit","not at this time","no thanks","no, thanks","i, agree","i agree"],r=[{attributeName:"className",matchFunction:a},{attributeName:"name",matchFunction:a},{attributeName:"id",matchFunction:a},{attributeName:"href",matchFunction:a},{attributeName:"innerText",matchFunction:function(t,e){const n=new RegExp(`\\b${e}\\b`);return!!t.toLowerCase().match(n)}}];function i(t){return Array.from(document.querySelectorAll("body *")).reduce((e,n)=>{const o=parseFloat(window.getComputedStyle(n).zIndex);return!Number.isNaN(o)&&o>=t&&(e.has(o)?e.get(o).push(n):e.set(o,[n])),e},new Map)}function u(t){const e=t=>void 0===t||"html"===t.tagName.toLowerCase();let n=t;for(;!e(n);){const t=window.getComputedStyle(n).zIndex;if(t&&"auto"!==t)return parseInt(t,10);n=(null==n?void 0:n.parentElement)?n.parentElement:void 0}return 0}function s(t){let e=[t];return Array.from(t.children).forEach(t=>{e=e.concat(s(t))}),e}function a(t,e){return t.toLowerCase().includes(e)}function c(t){const e=[];return t.forEach(t=>{const n=[],i=[];t.elements.forEach(t=>{var e,u;(null===(e=t)||void 0===e?void 0:e.offsetParent)&&(["BUTTON","A","DIV"].includes(null===(u=t.tagName)||void 0===u?void 0:u.toUpperCase())&&function(t){let e=0;return r.forEach(n=>{o.forEach(o=>{t.getAttribute(n.attributeName)&&n.matchFunction(t.getAttribute(n.attributeName),o)&&(e+=1)})}),e}(t)&&!i.includes(t)?i.push(t):function(t){if(t.getBoundingClientRect){const e=t.getBoundingClientRect(),n=e.width/window.innerWidth,o=e.height/window.innerHeight;return n>.95&&o>.95}return!1}(t)&&n.push(t))}),e.push({zIndex:t.zIndex,actionableElements:i,domCovering:n,dismissedStatus:!1,elementsInFront:0})}),e}function l(t,e){const n=t.getBoundingClientRect(),o=n.height/2,r=e?1:n.width/2,i=new MouseEvent("click",{bubbles:!0,cancelable:!0,view:window,detail:0,screenX:n.left+r,screenY:n.top+o,clientX:t.clientLeft+r,clientY:t.clientTop+o,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:void 0});t.dispatchEvent(i)}function d(t,e,n){const o=void 0!==e?e:m(t).x,r=void 0!==n?n:m(t).y,i=document.elementsFromPoint(o,r),u=i.findIndex(e=>e===t);return u?i.slice(0,u):[]}function f(t){return new Promise(e=>setTimeout(e,t))}function m(t){const e=t.getBoundingClientRect();return{x:Math.floor(e.x),y:Math.floor(e.y),top:Math.floor(e.top),bottom:Math.ceil(e.bottom),left:Math.floor(e.left),right:Math.ceil(e.right),height:Math.floor(e.bottom)-Math.ceil(e.top),width:Math.floor(e.right)-Math.ceil(e.left)}}function h(t,e){if(0===e.length)return[];const n=u(t),o=Math.min(...null==e?void 0:e.map(t=>u(t)));if(o<=n)return[];const r=i(o),a=Array.from(r).map(([t,e])=>({zIndex:t,elements:e.flatMap(s).reverse()}));return a.sort((t,e)=>e.zIndex-t.zIndex),a}async function g(t){const e=m(t);try{let n=d(t,e.x,e.y);const o=n.length;if(0===o)return{elementsInFront:0,dismissedStatus:!1};const r=async function(n,r){for(const i of n)if(l(i,r),await f(750),d(t,e.x,e.y).length<o)return!0;return!1};let i=h(t,n);const u=c(i);for(const t of u){let e=await r(t.domCovering,!0);if(e||(e=await r(t.actionableElements,!1)),e)return{dismissedStatus:!0,elementsInFront:0}}n=d(t,e.x,e.y),i=h(t,n);const s=c(i),a=s.length?s[0]:{zIndex:0,elementsInFront:0,dismissedStatus:!1,domCovering:[],actionableElements:[]};return a.elementsInFront=n.length,a.dismissedStatus=!1,{dismissedStatus:a.dismissedStatus,elementsInFront:a.elementsInFront}}catch(t){return{elementsInFront:0,dismissedStatus:!1,error:t.toString()}}}function p(t){return d(t).length}}]);
|
|
@@ -19,7 +19,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.maybeAddPopupLogic = exports.checkActionabilityAt = exports.checkActionabilityAtWithRetries = void 0;
|
|
22
|
+
exports.maybeAddPopupLogic = exports.attemptPopupDismissal = exports.checkActionabilityAt = exports.checkActionabilityAtWithRetries = exports.checkPopupDismissalOnAction = void 0;
|
|
23
23
|
const fs = __importStar(require("fs"));
|
|
24
24
|
const resourceUtil_1 = require("./resourceUtil");
|
|
25
25
|
const messaging_1 = require("../core/messaging/messaging");
|
|
@@ -29,17 +29,47 @@ const loggingProvider_1 = require("../providers/logging/loggingProvider");
|
|
|
29
29
|
const ACTIONABILITY_CHECK_SCRIPT_LOCATION = resourceUtil_1.findResource('actionabilityCheck.js');
|
|
30
30
|
const EMBEDDED_POPUP_SCRIPT_LOCATION = resourceUtil_1.findResource('popupDismissal.js');
|
|
31
31
|
const NO_CLICKABLE_POINT_ERROR = 'Unable to find a clickable point for the element';
|
|
32
|
+
const POPUP_ERROR_MESSAGE_HINT = 'intercepts pointer events';
|
|
32
33
|
let embeddedPopupScript;
|
|
33
34
|
let embeddedActionabilityLogic;
|
|
35
|
+
async function checkPopupDismissalOnAction(elementHandle, action, executionContext, recheckOnFail = true) {
|
|
36
|
+
try {
|
|
37
|
+
await action();
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (error.message.includes(POPUP_ERROR_MESSAGE_HINT)) {
|
|
41
|
+
const hasPopup = await isElementWithPopup(elementHandle);
|
|
42
|
+
if (hasPopup) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const dismissalResult = await attemptPopupDismissal(elementHandle, executionContext);
|
|
46
|
+
if (recheckOnFail) {
|
|
47
|
+
return checkPopupDismissalOnAction(elementHandle, action, executionContext, false);
|
|
48
|
+
}
|
|
49
|
+
if (!dismissalResult) {
|
|
50
|
+
logUtils_1.logWebUIAndCliOutput(`Found element may not be actionable`, loggingProvider_1.LogLevel.Warn, executionContext, {
|
|
51
|
+
executionPhase: messaging_1.ExecutionPhase.DURING_ACTION,
|
|
52
|
+
});
|
|
53
|
+
logUtils_1.logInternal(`Found element might not be actionable. ${error.toString()}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.checkPopupDismissalOnAction = checkPopupDismissalOnAction;
|
|
34
59
|
async function checkActionabilityAtWithRetries(elementHandle, executionContext, failIfClickablePointWasNotFound = true) {
|
|
35
60
|
var _a, _b, _c, _d;
|
|
36
61
|
let actionabilityResult;
|
|
37
62
|
try {
|
|
38
|
-
actionabilityResult = await ExecutorUtils_1.runWithRetries(() => checkActionabilityAt(elementHandle, executionContext), 10, [
|
|
63
|
+
actionabilityResult = await ExecutorUtils_1.runWithRetries(() => checkActionabilityAt(elementHandle, executionContext), 10, [
|
|
64
|
+
'Element not at point',
|
|
65
|
+
'Element not clickable at point',
|
|
66
|
+
NO_CLICKABLE_POINT_ERROR,
|
|
67
|
+
], executionContext);
|
|
39
68
|
}
|
|
40
69
|
catch (error) {
|
|
41
|
-
if (failIfClickablePointWasNotFound &&
|
|
42
|
-
|
|
70
|
+
if (failIfClickablePointWasNotFound &&
|
|
71
|
+
error.message === NO_CLICKABLE_POINT_ERROR) {
|
|
72
|
+
throw new Error(NO_CLICKABLE_POINT_ERROR);
|
|
43
73
|
}
|
|
44
74
|
logUtils_1.logWebUIAndCliOutput(`Found element may not be actionable`, loggingProvider_1.LogLevel.Warn, executionContext, {
|
|
45
75
|
executionPhase: messaging_1.ExecutionPhase.DURING_ACTION,
|
|
@@ -69,7 +99,14 @@ async function checkActionabilityAt(elementHandle, executionContext, recheckOnFa
|
|
|
69
99
|
if (result !== 'done') {
|
|
70
100
|
if (typeof result === 'object' && 'actionabilityDescription' in result) {
|
|
71
101
|
logUtils_1.logInternal(`${result.actionabilityDescription} intercepts pointer events. Trying to auto-dismiss popups.`);
|
|
72
|
-
await
|
|
102
|
+
const hasPopup = await isElementWithPopup(elementHandle);
|
|
103
|
+
if (hasPopup) {
|
|
104
|
+
return {
|
|
105
|
+
result: 'done',
|
|
106
|
+
clickablePoint: point,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
await attemptPopupDismissal(elementHandle, executionContext);
|
|
73
110
|
if (recheckOnFail) {
|
|
74
111
|
return checkActionabilityAt(elementHandle, executionContext, false);
|
|
75
112
|
}
|
|
@@ -80,13 +117,16 @@ async function checkActionabilityAt(elementHandle, executionContext, recheckOnFa
|
|
|
80
117
|
return { result, clickablePoint: point };
|
|
81
118
|
}
|
|
82
119
|
exports.checkActionabilityAt = checkActionabilityAt;
|
|
83
|
-
async function attemptPopupDismissal(element) {
|
|
120
|
+
async function attemptPopupDismissal(element, executionContext) {
|
|
84
121
|
const frame = await element.frame();
|
|
85
122
|
if (frame === undefined) {
|
|
86
123
|
return false;
|
|
87
124
|
}
|
|
88
125
|
await maybeAddPopupLogic(element);
|
|
89
|
-
const { dismissedStatus, elementsInFront } = await element.evaluate((element) => window.popupDismissal.detectAndDismissPopupCandidates(element));
|
|
126
|
+
const { dismissedStatus, elementsInFront, error } = await element.evaluate((element) => window.popupDismissal.detectAndDismissPopupCandidates(element));
|
|
127
|
+
if (error) {
|
|
128
|
+
logUtils_1.logInternal(`Error while trying to dismiss popups: ${error}`);
|
|
129
|
+
}
|
|
90
130
|
if (!dismissedStatus) {
|
|
91
131
|
if (elementsInFront) {
|
|
92
132
|
logUtils_1.logInternal('Failed to auto dismiss and there are still elements in front. Sending escape key to body.');
|
|
@@ -105,8 +145,12 @@ async function attemptPopupDismissal(element) {
|
|
|
105
145
|
return false;
|
|
106
146
|
}
|
|
107
147
|
}
|
|
148
|
+
logUtils_1.logWebUIAndCliOutput(`A popup was detected and dismissed`, loggingProvider_1.LogLevel.Info, executionContext, {
|
|
149
|
+
executionPhase: messaging_1.ExecutionPhase.DURING_ACTION,
|
|
150
|
+
});
|
|
108
151
|
return true;
|
|
109
152
|
}
|
|
153
|
+
exports.attemptPopupDismissal = attemptPopupDismissal;
|
|
110
154
|
async function maybeAddPopupLogic(element) {
|
|
111
155
|
const hasPopupDismissalLogic = await isPopupDismissalInTarget(element);
|
|
112
156
|
if (!hasPopupDismissalLogic) {
|
|
@@ -132,3 +176,7 @@ function isActionabilityLogicInTarget(element) {
|
|
|
132
176
|
function isPopupDismissalInTarget(element) {
|
|
133
177
|
return element.evaluate(() => !!window.popupDismissal);
|
|
134
178
|
}
|
|
179
|
+
function isElementWithPopup(element) {
|
|
180
|
+
return element.evaluate((element) => element.getAttribute('aria-expanded') === 'true' &&
|
|
181
|
+
element.getAttribute('aria-haspopup') === 'true');
|
|
182
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TimeoutError = exports.promiseWithTimeout = void 0;
|
|
4
|
+
const loggingProvider_1 = require("../providers/logging/loggingProvider");
|
|
5
|
+
async function promiseWithTimeout(promise, timeoutMillis, description) {
|
|
6
|
+
const startTimeMillis = new Date().getTime();
|
|
7
|
+
const { timer, cancelTimer } = startTimer(timeoutMillis, description);
|
|
8
|
+
try {
|
|
9
|
+
const result = await Promise.race([timer, promise]);
|
|
10
|
+
if (loggingProvider_1.logger.isDebugEnabled()) {
|
|
11
|
+
loggingProvider_1.logger.debug(`"${description}" completed in ${new Date().getTime() - startTimeMillis}ms`);
|
|
12
|
+
}
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
if (error instanceof TimeoutError) {
|
|
17
|
+
loggingProvider_1.logger.warn(error.message);
|
|
18
|
+
}
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
cancelTimer();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.promiseWithTimeout = promiseWithTimeout;
|
|
26
|
+
class TimeoutError extends Error {
|
|
27
|
+
constructor(timeoutMillis, description) {
|
|
28
|
+
super(`[mabl promise timeout] "${description}" timed out after ${timeoutMillis}ms`);
|
|
29
|
+
this.timeoutMillis = timeoutMillis;
|
|
30
|
+
this.description = description;
|
|
31
|
+
Object.setPrototypeOf(this, TimeoutError.prototype);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.TimeoutError = TimeoutError;
|
|
35
|
+
const startTimer = (timeoutMillis, description) => {
|
|
36
|
+
let timeout;
|
|
37
|
+
const promise = new Promise((_resolve, reject) => {
|
|
38
|
+
timeout = global.setTimeout(() => reject(new TimeoutError(timeoutMillis, description)), timeoutMillis);
|
|
39
|
+
timeout.unref();
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
timer: promise,
|
|
43
|
+
cancelTimer: () => global.clearTimeout(timeout),
|
|
44
|
+
};
|
|
45
|
+
};
|
package/util/logUtils.js
CHANGED
|
@@ -8,8 +8,8 @@ const mablscriptFind_1 = require("../mablscriptFind");
|
|
|
8
8
|
const loggingProvider_1 = require("../providers/logging/loggingProvider");
|
|
9
9
|
const moment_1 = __importDefault(require("moment"));
|
|
10
10
|
const constants_1 = require("../commands/constants");
|
|
11
|
-
function logInternal(logLine) {
|
|
12
|
-
loggingProvider_1.logger.debug(logLine);
|
|
11
|
+
function logInternal(logLine, ...meta) {
|
|
12
|
+
loggingProvider_1.logger.debug(logLine, meta);
|
|
13
13
|
}
|
|
14
14
|
exports.logInternal = logInternal;
|
|
15
15
|
function logCliOutput(logLevel, logLine) {
|
package/util/resourceUtil.js
CHANGED
|
@@ -49,6 +49,10 @@ function findNodeModulesDirectory() {
|
|
|
49
49
|
if (fs.existsSync(packedAsMabltronDependency)) {
|
|
50
50
|
return packedAsMabltronDependency;
|
|
51
51
|
}
|
|
52
|
+
const packedAsExecutionEngineDependency = path.normalize(path.resolve(`${__dirname}/../../mabl-cli-internal-unpacked/node_modules/`));
|
|
53
|
+
if (fs.existsSync(packedAsExecutionEngineDependency)) {
|
|
54
|
+
return packedAsExecutionEngineDependency;
|
|
55
|
+
}
|
|
52
56
|
const packedPath = path.normalize(path.resolve(`${__dirname}/../../node_modules`));
|
|
53
57
|
return packedPath;
|
|
54
58
|
}
|