@mablhq/mabl-cli 1.12.24 → 1.13.17

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.
Files changed (107) hide show
  1. package/api/basicApiClient.js +63 -26
  2. package/api/mablApiClient.js +9 -9
  3. package/api/mablApiClientFactory.js +1 -0
  4. package/auth/AuthClient.js +1 -4
  5. package/browserLauncher/browserLauncherFactory.js +7 -3
  6. package/browserLauncher/playwrightBrowserLauncher/playwrightBrowser.js +6 -2
  7. package/browserLauncher/playwrightBrowserLauncher/playwrightBrowserLauncher.js +1 -0
  8. package/browserLauncher/playwrightBrowserLauncher/playwrightDom.js +60 -20
  9. package/browserLauncher/playwrightBrowserLauncher/playwrightFrame.js +24 -17
  10. package/browserLauncher/playwrightBrowserLauncher/playwrightHttpResponse.js +3 -0
  11. package/browserLauncher/playwrightBrowserLauncher/playwrightPage.js +72 -68
  12. package/browserLauncher/playwrightBrowserLauncher/wrappers.js +1 -1
  13. package/browserLauncher/puppeteerBrowserLauncher/puppeteerBrowser.js +7 -3
  14. package/browserLauncher/puppeteerBrowserLauncher/puppeteerElementHandle.js +13 -7
  15. package/browserLauncher/puppeteerBrowserLauncher/puppeteerFrame.js +7 -7
  16. package/browserLauncher/puppeteerBrowserLauncher/puppeteerHttpRequest.js +1 -1
  17. package/browserLauncher/puppeteerBrowserLauncher/puppeteerHttpResponse.js +4 -1
  18. package/browserLauncher/puppeteerBrowserLauncher/puppeteerJsHandle.js +3 -3
  19. package/browserLauncher/puppeteerBrowserLauncher/puppeteerPage.js +23 -16
  20. package/browserLauncher/puppeteerBrowserLauncher/wrappers.js +1 -1
  21. package/browserLauncher/types.js +6 -1
  22. package/cli.js +6 -4
  23. package/commands/applications/applications_cmds/list.js +1 -1
  24. package/commands/branches/branches_cmds/create.js +1 -1
  25. package/commands/branches/branches_cmds/list.js +1 -1
  26. package/commands/branches/branches_cmds/merge.js +1 -1
  27. package/commands/commandUtil/awaitCompletion.js +2 -2
  28. package/commands/commandUtil/codeInsights.js +6 -6
  29. package/commands/commandUtil/fileUtil.js +1 -1
  30. package/commands/commandUtil/util.js +12 -12
  31. package/commands/config/config_cmds/list.js +1 -1
  32. package/commands/constants.js +1 -1
  33. package/commands/credentials/credentials_cmds/list.js +1 -1
  34. package/commands/deploy/deploy_cmds/create.js +2 -2
  35. package/commands/deploy/deploy_cmds/executionResultPresenter.js +7 -7
  36. package/commands/deploy/deploy_cmds/list.js +1 -1
  37. package/commands/environments/environments_cmds/create.js +3 -3
  38. package/commands/environments/environments_cmds/list.js +1 -1
  39. package/commands/environments/environments_cmds/urls_cmds/add.js +1 -1
  40. package/commands/flows/flows_cmds/list.js +1 -1
  41. package/commands/plans/plans_cmds/list.js +1 -1
  42. package/commands/test-runs/test-runs_cmds/export.js +1 -1
  43. package/commands/tests/executionUtil.js +1 -1
  44. package/commands/tests/testsUtil.js +16 -20
  45. package/commands/tests/tests_cmds/edit.js +1 -1
  46. package/commands/tests/tests_cmds/export.js +1 -1
  47. package/commands/tests/tests_cmds/import.js +13 -13
  48. package/commands/tests/tests_cmds/list.js +2 -2
  49. package/commands/tests/tests_cmds/run-alpha.js +1 -1
  50. package/commands/tests/tests_cmds/run-cloud.js +7 -7
  51. package/commands/tests/tests_cmds/run-legacy.js +2 -2
  52. package/commands/tests/tests_cmds/run.js +25 -7
  53. package/commands/workspaces/workspace_cmds/copy.js +1 -1
  54. package/commands/workspaces/workspace_cmds/list.js +1 -1
  55. package/configGenerators/flowConfigGenerator.js +3 -3
  56. package/configGenerators/selIdeGenerator.js +1 -1
  57. package/configGenerators/testConfigGenerator.js +7 -8
  58. package/core/execution/ApiTestUtils.js +2 -2
  59. package/core/trainer/openUtils.js +47 -0
  60. package/core/trainer/trainingSessions.js +36 -61
  61. package/env/defaultEnv.js +2 -1
  62. package/env/dev.js +2 -1
  63. package/env/env.js +3 -1
  64. package/env/local.js +2 -1
  65. package/env/prod.js +2 -1
  66. package/execution/index.js +1 -1
  67. package/execution/index.js.LICENSE.txt +12 -0
  68. package/index.d.ts +7 -0
  69. package/mablscript/MablStep.js +11 -7
  70. package/mablscript/actions/ConditionAction.js +2 -4
  71. package/mablscript/actions/FindAction.js +4 -4
  72. package/mablscript/importer.js +16 -14
  73. package/mablscript/steps/AccessibilityCheck.js +88 -0
  74. package/mablscript/steps/AssertStep.js +6 -5
  75. package/mablscript/steps/CreateVariableStep.js +2 -3
  76. package/mablscript/steps/DownloadStep.js +1 -2
  77. package/mablscript/steps/EnterTextStep.js +2 -1
  78. package/mablscript/steps/IfConditionStep.js +3 -3
  79. package/mablscript/steps/SendHttpRequestStep.js +11 -3
  80. package/mablscript/steps/SendKeyStep.js +2 -2
  81. package/mablscript/steps/SetFilesStep.js +1 -1
  82. package/mablscript/steps/SwitchContextStep.js +2 -1
  83. package/mablscript/types/AccessibilityCheckStepDescriptor.js +2 -0
  84. package/mablscript/types/AccessibilityCheckTypes.js +9 -0
  85. package/mablscript/types/VariableDataType.js +1 -8
  86. package/mablscript/types/VariableNamespace.js +1 -1
  87. package/mablscriptFind/index.js +1 -1
  88. package/package.json +8 -6
  89. package/popupDismissal/index.js +36 -30
  90. package/providers/authenticationProvider.js +2 -3
  91. package/providers/cliConfigProvider.js +1 -1
  92. package/providers/exportRequestProvider.js +1 -1
  93. package/providers/logging/loggingProvider.js +2 -2
  94. package/providers/scmContextProvider.js +1 -1
  95. package/reporters/mochAwesome/mochAwesomeReporter.js +10 -6
  96. package/reporters/reporter.js +1 -1
  97. package/resources/mablFind.js +1 -1
  98. package/resources/popupDismissal.js +1 -1
  99. package/util/RichPromise.js +2 -2
  100. package/util/actionabilityUtil.js +59 -9
  101. package/util/asyncUtil.js +45 -0
  102. package/util/downloadUtil.js +1 -1
  103. package/util/logUtils.js +22 -3
  104. package/util/markdownUtil.js +3 -3
  105. package/util/pureUtil.js +6 -6
  106. package/util/resourceUtil.js +18 -1
  107. package/core/trainer/trainerBrowserUtil.js +0 -33
@@ -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 m})),n.d(e,"detectAndDismissPopupCandidates",(function(){return h})),n.d(e,"elementsInFrontCount",(function(){return g}));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){let e=[t];return Array.from(t.children).forEach(t=>{e=e.concat(u(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 s(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 l(t,e,n){const o=void 0!==e?e:f(t).x,r=void 0!==n?n:f(t).y,i=document.elementsFromPoint(o,r),u=i.findIndex(e=>e===t);return u?i.slice(0,u):[]}function d(t){return new Promise(e=>setTimeout(e,t))}function f(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 m(t){const e=i(function(t){const e=t=>void 0===t||"html"===t.tagName.toLowerCase();let n=t;for(;!e(n);){const e=window.getComputedStyle(t).zIndex;if(e&&"auto"!==e)return e;n=(null==n?void 0:n.parentElement)?n.parentElement:void 0}return 0}(t[t.length-1])),n=Array.from(e).map(([t,e])=>({zIndex:t,elements:e.flatMap(u).reverse()}));return n.sort((t,e)=>e.zIndex-t.zIndex),n}async function h(t){const e=f(t);try{let n=l(t,e.x,e.y);const o=n.length;if(0===o)return{zIndex:0,elementsInFront:0,dismissedStatus:!1,domCovering:[],actionableElements:[]};const r=async function(n,r){for(const i of n)if(s(i,r),await d(750),l(t,e.x,e.y).length<o)return!0;return!1};let i=m(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 t.dismissedStatus=!0,t}n=l(t,e.x,e.y),i=m(n);const a=c(i),f=a.length?a[0]:{zIndex:0,elementsInFront:0,dismissedStatus:!1,domCovering:[],actionableElements:[]};return f.elementsInFront=n.length,f.dismissedStatus=!1,f}catch(t){return{zIndex:0,elementsInFront:0,dismissedStatus:!1,domCovering:[],actionableElements:[],errorInDetection:t.toString()}}}function g(t){return l(t).length}}]);
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}}]);
@@ -12,8 +12,8 @@ class RichPromise {
12
12
  });
13
13
  if (chained) {
14
14
  chained
15
- .then(result => this.resolve(result))
16
- .catch(reason => this.reject(reason));
15
+ .then((result) => this.resolve(result))
16
+ .catch((reason) => this.reject(reason));
17
17
  }
18
18
  }
19
19
  isPending() {
@@ -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,19 +29,51 @@ 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, ['Element not at point', 'Element not clickable at point'], executionContext);
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 && error === NO_CLICKABLE_POINT_ERROR) {
42
- throw new Error('Unable to find a clickable point for the element');
70
+ if (failIfClickablePointWasNotFound &&
71
+ error.message === NO_CLICKABLE_POINT_ERROR) {
72
+ throw new Error(NO_CLICKABLE_POINT_ERROR);
43
73
  }
44
- logUtils_1.logWebUIAndCliOutput(`Found element may not be actionable`, loggingProvider_1.LogLevel.Warn, executionContext, { executionPhase: messaging_1.ExecutionPhase.DURING_ACTION });
74
+ logUtils_1.logWebUIAndCliOutput(`Found element may not be actionable`, loggingProvider_1.LogLevel.Warn, executionContext, {
75
+ executionPhase: messaging_1.ExecutionPhase.DURING_ACTION,
76
+ });
45
77
  logUtils_1.logInternal(`Found element might not be actionable at the expected point (x: ${(_b = (_a = actionabilityResult === null || actionabilityResult === void 0 ? void 0 : actionabilityResult.clickablePoint) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 'Not found'}, y: ${(_d = (_c = actionabilityResult === null || actionabilityResult === void 0 ? void 0 : actionabilityResult.clickablePoint) === null || _c === void 0 ? void 0 : _c.y) !== null && _d !== void 0 ? _d : 'Not found'}), performing action anyway`);
46
78
  }
47
79
  }
@@ -67,7 +99,14 @@ async function checkActionabilityAt(elementHandle, executionContext, recheckOnFa
67
99
  if (result !== 'done') {
68
100
  if (typeof result === 'object' && 'actionabilityDescription' in result) {
69
101
  logUtils_1.logInternal(`${result.actionabilityDescription} intercepts pointer events. Trying to auto-dismiss popups.`);
70
- await attemptPopupDismissal(elementHandle);
102
+ const hasPopup = await isElementWithPopup(elementHandle);
103
+ if (hasPopup) {
104
+ return {
105
+ result: 'done',
106
+ clickablePoint: point,
107
+ };
108
+ }
109
+ await attemptPopupDismissal(elementHandle, executionContext);
71
110
  if (recheckOnFail) {
72
111
  return checkActionabilityAt(elementHandle, executionContext, false);
73
112
  }
@@ -78,13 +117,16 @@ async function checkActionabilityAt(elementHandle, executionContext, recheckOnFa
78
117
  return { result, clickablePoint: point };
79
118
  }
80
119
  exports.checkActionabilityAt = checkActionabilityAt;
81
- async function attemptPopupDismissal(element) {
120
+ async function attemptPopupDismissal(element, executionContext) {
82
121
  const frame = await element.frame();
83
122
  if (frame === undefined) {
84
123
  return false;
85
124
  }
86
125
  await maybeAddPopupLogic(element);
87
- 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
+ }
88
130
  if (!dismissedStatus) {
89
131
  if (elementsInFront) {
90
132
  logUtils_1.logInternal('Failed to auto dismiss and there are still elements in front. Sending escape key to body.');
@@ -92,7 +134,7 @@ async function attemptPopupDismissal(element) {
92
134
  if (bodyElement) {
93
135
  await bodyElement.press('Escape');
94
136
  }
95
- const elementsInFront = await element.evaluate(element => window.popupDismissal.elementsInFrontCount(element));
137
+ const elementsInFront = await element.evaluate((element) => window.popupDismissal.elementsInFrontCount(element));
96
138
  if (elementsInFront) {
97
139
  logUtils_1.logInternal('The popup did not dismiss using the escape key.');
98
140
  return false;
@@ -103,8 +145,12 @@ async function attemptPopupDismissal(element) {
103
145
  return false;
104
146
  }
105
147
  }
148
+ logUtils_1.logWebUIAndCliOutput(`A popup was detected and dismissed`, loggingProvider_1.LogLevel.Info, executionContext, {
149
+ executionPhase: messaging_1.ExecutionPhase.DURING_ACTION,
150
+ });
106
151
  return true;
107
152
  }
153
+ exports.attemptPopupDismissal = attemptPopupDismissal;
108
154
  async function maybeAddPopupLogic(element) {
109
155
  const hasPopupDismissalLogic = await isPopupDismissalInTarget(element);
110
156
  if (!hasPopupDismissalLogic) {
@@ -130,3 +176,7 @@ function isActionabilityLogicInTarget(element) {
130
176
  function isPopupDismissalInTarget(element) {
131
177
  return element.evaluate(() => !!window.popupDismissal);
132
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
+ };
@@ -54,7 +54,7 @@ async function getLatestFile(downloadDirectory, filePathSuffix) {
54
54
  const filesInDownloadDir = await readDirectoryAsync(downloadDirectory);
55
55
  let latestFileTime = 0;
56
56
  let latestFilePath;
57
- filesInDownloadDir.forEach(fileName => {
57
+ filesInDownloadDir.forEach((fileName) => {
58
58
  const fullPath = `${downloadDirectory}/${fileName}`;
59
59
  try {
60
60
  const stats = fs.statSync(path.normalize(fullPath));
package/util/logUtils.js CHANGED
@@ -1,10 +1,15 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.logWebUIAndCliOutput = exports.findResultSeverityToLogLevel = exports.logCliOutput = exports.logInternal = void 0;
6
+ exports.formatTimestamp = exports.valueToString = exports.logWebUIAndCliOutput = exports.findResultSeverityToLogLevel = exports.logCliOutput = exports.logInternal = void 0;
4
7
  const mablscriptFind_1 = require("../mablscriptFind");
5
8
  const loggingProvider_1 = require("../providers/logging/loggingProvider");
6
- function logInternal(logLine) {
7
- loggingProvider_1.logger.debug(logLine);
9
+ const moment_1 = __importDefault(require("moment"));
10
+ const constants_1 = require("../commands/constants");
11
+ function logInternal(logLine, ...meta) {
12
+ loggingProvider_1.logger.debug(logLine, meta);
8
13
  }
9
14
  exports.logInternal = logInternal;
10
15
  function logCliOutput(logLevel, logLine) {
@@ -55,3 +60,17 @@ function logWebUIAndCliOutput(logLine, logLevel, executionContext, metadata) {
55
60
  }
56
61
  }
57
62
  exports.logWebUIAndCliOutput = logWebUIAndCliOutput;
63
+ function valueToString(value) {
64
+ if (typeof value !== 'object') {
65
+ return '' + value;
66
+ }
67
+ return JSON.stringify(value);
68
+ }
69
+ exports.valueToString = valueToString;
70
+ function formatTimestamp(timeAsNumber) {
71
+ if (!timeAsNumber) {
72
+ return '';
73
+ }
74
+ return moment_1.default.utc(timeAsNumber).format(constants_1.ListTimeFormat);
75
+ }
76
+ exports.formatTimestamp = formatTimestamp;
@@ -19,7 +19,7 @@ function formatResultsAsGithubMarkdown(results) {
19
19
  const tableRows = [];
20
20
  tableRows.push(['Plan', 'Test', 'Browser', 'Status', 'Run Time']);
21
21
  const finalExecutions = (_a = results === null || results === void 0 ? void 0 : results.executions) !== null && _a !== void 0 ? _a : [];
22
- finalExecutions.forEach(summary => {
22
+ finalExecutions.forEach((summary) => {
23
23
  var _a, _b, _c, _d, _e, _f, _g;
24
24
  const retryPrefix = ((_a = summary === null || summary === void 0 ? void 0 : summary.plan_execution) === null || _a === void 0 ? void 0 : _a.is_retry) ? '[Retry] ' : '';
25
25
  const planName = retryPrefix + ((_c = (_b = summary.plan) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : '<plan name unavailable>');
@@ -29,7 +29,7 @@ function formatResultsAsGithubMarkdown(results) {
29
29
  maybeCapitalize(humanizedPlanRunStatus === null || humanizedPlanRunStatus === void 0 ? void 0 : humanizedPlanRunStatus.toString());
30
30
  const planHref = (_e = summary.plan) === null || _e === void 0 ? void 0 : _e.app_href;
31
31
  const journeyMap = new Map();
32
- (_f = summary.journeys) === null || _f === void 0 ? void 0 : _f.forEach(journeySummary => journeyMap.set(journeySummary.id, journeySummary));
32
+ (_f = summary.journeys) === null || _f === void 0 ? void 0 : _f.forEach((journeySummary) => journeyMap.set(journeySummary.id, journeySummary));
33
33
  tableRows.push([
34
34
  `[${planName}](${planHref})`,
35
35
  '---',
@@ -37,7 +37,7 @@ function formatResultsAsGithubMarkdown(results) {
37
37
  planRunStatus,
38
38
  summaryToElapsedTime(summary),
39
39
  ]);
40
- (_g = summary.journey_executions) === null || _g === void 0 ? void 0 : _g.forEach(journeyRun => {
40
+ (_g = summary.journey_executions) === null || _g === void 0 ? void 0 : _g.forEach((journeyRun) => {
41
41
  const humanizedJourneyRunStatus = humanizeMablStatus(journeyRun.status);
42
42
  const journeyStatus = humanizedMablStatusToGithubIcon(humanizedJourneyRunStatus) +
43
43
  ' ' +
package/util/pureUtil.js CHANGED
@@ -32,8 +32,8 @@ function getCliPackage() {
32
32
  return cliPackage;
33
33
  }
34
34
  const packagePath = possibleCliPackagePaths
35
- .map(relativePath => path.resolve(__dirname, relativePath))
36
- .find(path => fs.existsSync(path));
35
+ .map((relativePath) => path.resolve(__dirname, relativePath))
36
+ .find((path) => fs.existsSync(path));
37
37
  if (!packagePath) {
38
38
  throw new Error('Cannot find package.json');
39
39
  }
@@ -82,10 +82,10 @@ exports.getCliName = getCliName;
82
82
  function extractKeyCountsFromArgs(argv) {
83
83
  const ignoreKeys = ['$0', '_'];
84
84
  const keysUsed = Object.keys(argv)
85
- .filter(key => !ignoreKeys.includes(key))
86
- .filter(key => !/[A-Z]/.test(key));
85
+ .filter((key) => !ignoreKeys.includes(key))
86
+ .filter((key) => !/[A-Z]/.test(key));
87
87
  const keyValueCountMap = {};
88
- keysUsed.forEach(key => {
88
+ keysUsed.forEach((key) => {
89
89
  const value = argv[key];
90
90
  let count;
91
91
  if (value === undefined || value === null) {
@@ -118,7 +118,7 @@ function extractKeyCountsFromArgs(argv) {
118
118
  }
119
119
  exports.extractKeyCountsFromArgs = extractKeyCountsFromArgs;
120
120
  function getCaseInsensitiveProperty(obj, key) {
121
- const keyInObject = Object.keys(obj).find(k => k.toLowerCase() === key.toLowerCase());
121
+ const keyInObject = Object.keys(obj).find((k) => k.toLowerCase() === key.toLowerCase());
122
122
  if (keyInObject !== undefined) {
123
123
  return obj[keyInObject];
124
124
  }
@@ -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.findDirectory = exports.findResource = void 0;
22
+ exports.findNodeModulesDirectory = exports.findDirectory = exports.findResource = void 0;
23
23
  const path = __importStar(require("path"));
24
24
  const fs = __importStar(require("fs"));
25
25
  function findResource(pathInResource) {
@@ -40,3 +40,20 @@ function findDirectory(pathFromBase) {
40
40
  return packedPath;
41
41
  }
42
42
  exports.findDirectory = findDirectory;
43
+ function findNodeModulesDirectory() {
44
+ const unpackedPath = path.normalize(path.resolve(`${__dirname}/../../../node_modules`));
45
+ if (fs.existsSync(unpackedPath)) {
46
+ return unpackedPath;
47
+ }
48
+ const packedAsMabltronDependency = path.normalize(path.resolve(`${__dirname}/../../mabl-cli-internal/node_modules/`));
49
+ if (fs.existsSync(packedAsMabltronDependency)) {
50
+ return packedAsMabltronDependency;
51
+ }
52
+ const packedAsExecutionEngineDependency = path.normalize(path.resolve(`${__dirname}/../../mabl-cli-internal-unpacked/node_modules/`));
53
+ if (fs.existsSync(packedAsExecutionEngineDependency)) {
54
+ return packedAsExecutionEngineDependency;
55
+ }
56
+ const packedPath = path.normalize(path.resolve(`${__dirname}/../../node_modules`));
57
+ return packedPath;
58
+ }
59
+ exports.findNodeModulesDirectory = findNodeModulesDirectory;
@@ -1,33 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.addClosedAllWindowsEventWatch = exports.addManualCloseEventWatch = void 0;
4
- const messaging_1 = require("../messaging/messaging");
5
- const testsUtil_1 = require("../../commands/tests/testsUtil");
6
- const browserLauncher_1 = require("../../browserLauncher/browserLauncher");
7
- function addManualCloseEventWatch(trainingBrowser, closeAction) {
8
- trainingBrowser.on(browserLauncher_1.BrowserEvent.Disconnected, async () => {
9
- await testsUtil_1.sleep(1000);
10
- if (closeAction) {
11
- closeAction();
12
- }
13
- trainingBrowser
14
- .close()
15
- .catch(error => messaging_1.mablEventEmitter.log('Error shutting down browser on manual close' + error));
16
- });
17
- }
18
- exports.addManualCloseEventWatch = addManualCloseEventWatch;
19
- function addClosedAllWindowsEventWatch(trainingBrowser, closeAction) {
20
- trainingBrowser.on(browserLauncher_1.BrowserEvent.PageDestroyed, async () => {
21
- const pages = await trainingBrowser.pages();
22
- if (pages.length === 0) {
23
- await testsUtil_1.sleep(1000);
24
- if (closeAction) {
25
- closeAction();
26
- }
27
- trainingBrowser
28
- .close()
29
- .catch(error => messaging_1.mablEventEmitter.log('Error shutting down browser on manual close' + error));
30
- }
31
- });
32
- }
33
- exports.addClosedAllWindowsEventWatch = addClosedAllWindowsEventWatch;