@mablhq/mabl-cli 1.43.7 → 1.43.10
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/execution/index.js +1 -1
- package/package.json +2 -1
- package/util/clickUtil.js +53 -0
- package/util/javaScriptStepMigration.js +114 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mablhq/mabl-cli",
|
|
3
|
-
"version": "1.43.
|
|
3
|
+
"version": "1.43.10",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
5
5
|
"description": "The official mabl command line interface tool",
|
|
6
6
|
"main": "index.js",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"decompress-zip": "0.2.2",
|
|
43
43
|
"encodeurl": "1.0.2",
|
|
44
44
|
"env-paths": "2.2.0",
|
|
45
|
+
"escodegen": "2.0.0",
|
|
45
46
|
"esprima": "4.0.1",
|
|
46
47
|
"estraverse": "4.3.0",
|
|
47
48
|
"fast-json-stable-stringify": "2.1.0",
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clickOnElement = exports.ClickType = void 0;
|
|
4
|
+
const messaging_1 = require("../core/messaging/messaging");
|
|
5
|
+
const loggingProvider_1 = require("../providers/logging/loggingProvider");
|
|
6
|
+
const actionabilityUtil_1 = require("./actionabilityUtil");
|
|
7
|
+
const logUtils_1 = require("./logUtils");
|
|
8
|
+
var ClickType;
|
|
9
|
+
(function (ClickType) {
|
|
10
|
+
ClickType[ClickType["LeftClick"] = 0] = "LeftClick";
|
|
11
|
+
ClickType[ClickType["DoubleClick"] = 1] = "DoubleClick";
|
|
12
|
+
})(ClickType = exports.ClickType || (exports.ClickType = {}));
|
|
13
|
+
async function clickOnElement(elementHandle, executionContext, clickType) {
|
|
14
|
+
const trialClickOptions = {
|
|
15
|
+
trial: true,
|
|
16
|
+
minimizeScrollIntoView: executionContext.browserConfig.minimizeScrollIntoView,
|
|
17
|
+
};
|
|
18
|
+
const elementHandleTrialClickAction = clickType === ClickType.LeftClick
|
|
19
|
+
? () => elementHandle.click(trialClickOptions)
|
|
20
|
+
: () => elementHandle.doubleClick(trialClickOptions);
|
|
21
|
+
const noOverlappingElement = await (0, actionabilityUtil_1.checkPopupDismissalOnAction)(elementHandle, elementHandleTrialClickAction, executionContext);
|
|
22
|
+
const elementBoundingBox = await elementHandle.boundingBox();
|
|
23
|
+
const elementHasSurfaceArea = elementBoundingBox
|
|
24
|
+
? elementBoundingBox.height > 0 && elementBoundingBox.width > 0
|
|
25
|
+
: false;
|
|
26
|
+
if (!noOverlappingElement || !elementHasSurfaceArea) {
|
|
27
|
+
const jsClickReasons = [
|
|
28
|
+
!noOverlappingElement && "there is a popup we couldn't dismiss",
|
|
29
|
+
!elementHasSurfaceArea && 'the element is not visible',
|
|
30
|
+
]
|
|
31
|
+
.filter((reason) => reason !== false)
|
|
32
|
+
.join(' and ');
|
|
33
|
+
const clickText = clickType === ClickType.LeftClick ? 'click' : 'double click';
|
|
34
|
+
(0, logUtils_1.logWebUIAndCliOutput)(`Attempting ${clickText} with javascript because ${jsClickReasons}`, loggingProvider_1.LogLevel.Warn, executionContext, {
|
|
35
|
+
executionPhase: messaging_1.ExecutionPhase.DURING_ACTION,
|
|
36
|
+
});
|
|
37
|
+
if (noOverlappingElement) {
|
|
38
|
+
await (0, actionabilityUtil_1.maybeAddPopupLogic)(elementHandle);
|
|
39
|
+
}
|
|
40
|
+
const jsClickEventFirer = clickType === ClickType.LeftClick
|
|
41
|
+
? (element) => window.popupDismissal.fireClickEvent(element)
|
|
42
|
+
: (element) => window.popupDismissal.fireDoubleClickEvent(element);
|
|
43
|
+
return elementHandle.evaluate(jsClickEventFirer);
|
|
44
|
+
}
|
|
45
|
+
const finalClickOptions = {
|
|
46
|
+
timeout: 0,
|
|
47
|
+
minimizeScrollIntoView: executionContext.browserConfig.minimizeScrollIntoView,
|
|
48
|
+
};
|
|
49
|
+
return clickType === ClickType.LeftClick
|
|
50
|
+
? elementHandle.click(finalClickOptions)
|
|
51
|
+
: elementHandle.doubleClick(finalClickOptions);
|
|
52
|
+
}
|
|
53
|
+
exports.clickOnElement = clickOnElement;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.normalizeScript = exports.hasVariableReferences = exports.attemptReusableSnippetParameterization = exports.attemptMigrationToParameterizedStep = void 0;
|
|
27
|
+
const typescript_api_client_nodejs_1 = require("@mablhq/typescript-api-client-nodejs");
|
|
28
|
+
const encodingUtil_1 = require("./encodingUtil");
|
|
29
|
+
const esprima = __importStar(require("esprima"));
|
|
30
|
+
const escodegen = __importStar(require("escodegen"));
|
|
31
|
+
const loggingProvider_1 = require("../providers/logging/loggingProvider");
|
|
32
|
+
function attemptMigrationToParameterizedStep(descriptor) {
|
|
33
|
+
let hasVariables;
|
|
34
|
+
let migrationDisabled;
|
|
35
|
+
try {
|
|
36
|
+
const decodedJS = (0, encodingUtil_1.b64DecodeUnicodeInNode)(descriptor.encodedJS);
|
|
37
|
+
migrationDisabled = isMigrationDisabled(decodedJS);
|
|
38
|
+
hasVariables = hasVariableReferences(decodedJS);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
loggingProvider_1.logger.warn(`Failed to determine if the inline snippet uses variables: ${error}`);
|
|
42
|
+
return descriptor;
|
|
43
|
+
}
|
|
44
|
+
if (migrationDisabled) {
|
|
45
|
+
return descriptor;
|
|
46
|
+
}
|
|
47
|
+
if (hasVariables) {
|
|
48
|
+
return descriptor;
|
|
49
|
+
}
|
|
50
|
+
loggingProvider_1.logger.info('Converting legacy inline JavaScript step to parameterized step.');
|
|
51
|
+
return migrateInlineDescriptor(descriptor);
|
|
52
|
+
}
|
|
53
|
+
exports.attemptMigrationToParameterizedStep = attemptMigrationToParameterizedStep;
|
|
54
|
+
function migrateInlineDescriptor(descriptor) {
|
|
55
|
+
return {
|
|
56
|
+
inlineSnippet: {
|
|
57
|
+
body: descriptor.encodedJS,
|
|
58
|
+
description: '',
|
|
59
|
+
name: 'Unnamed snippet',
|
|
60
|
+
parameters: [],
|
|
61
|
+
snippet_type: typescript_api_client_nodejs_1.Snippet.SnippetTypeEnum.Javascript,
|
|
62
|
+
},
|
|
63
|
+
parameterOverrides: [],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function attemptReusableSnippetParameterization(snippet) {
|
|
67
|
+
if (Array.isArray(snippet.parameters)) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (!snippet.body) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
let hasVariables;
|
|
74
|
+
let migrationDisabled;
|
|
75
|
+
try {
|
|
76
|
+
const decodedJS = (0, encodingUtil_1.b64DecodeUnicodeInNode)(snippet.body);
|
|
77
|
+
migrationDisabled = isMigrationDisabled(decodedJS);
|
|
78
|
+
hasVariables = hasVariableReferences(decodedJS);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
loggingProvider_1.logger.warn(`Failed to determine if the reusable snippet uses variables: ${error}`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (migrationDisabled) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (hasVariables) {
|
|
88
|
+
loggingProvider_1.logger.info(`Skipping snippet parameter conversion due to variable usage. Snippet ID: ${snippet.id}`);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
loggingProvider_1.logger.info(`Migrating legacy snippet to parameterized snippet. Snippet ID: ${snippet.id}`);
|
|
92
|
+
snippet.parameters = [];
|
|
93
|
+
}
|
|
94
|
+
exports.attemptReusableSnippetParameterization = attemptReusableSnippetParameterization;
|
|
95
|
+
function isMigrationDisabled(decodedScript) {
|
|
96
|
+
return decodedScript.indexOf('@mabl-disable-parameterization') >= 0;
|
|
97
|
+
}
|
|
98
|
+
function hasVariableReferences(decodedScript) {
|
|
99
|
+
const normalizedCode = normalizeScript(decodedScript);
|
|
100
|
+
const hasSignature = normalizedCode.indexOf('function mablJavaScriptStep(mablInputs') >= 0;
|
|
101
|
+
if (!hasSignature) {
|
|
102
|
+
throw new Error('Did not find expected mabl JavaScript function signature.');
|
|
103
|
+
}
|
|
104
|
+
const rex = /mablInputs/gi;
|
|
105
|
+
const match = normalizedCode.match(rex);
|
|
106
|
+
const matchCount = match ? match.length : 0;
|
|
107
|
+
return matchCount > 1;
|
|
108
|
+
}
|
|
109
|
+
exports.hasVariableReferences = hasVariableReferences;
|
|
110
|
+
function normalizeScript(decodedScript) {
|
|
111
|
+
const tree = esprima.parseScript(decodedScript, { tolerant: true });
|
|
112
|
+
return escodegen.generate(tree);
|
|
113
|
+
}
|
|
114
|
+
exports.normalizeScript = normalizeScript;
|