@mablhq/mabl-cli 2.34.10 → 2.37.7

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.
@@ -116,7 +116,10 @@ class MablStep extends MablAction_1.MablAction {
116
116
  disabled: this.isDisabled(),
117
117
  mablscript: this.toMablscript(),
118
118
  };
119
- return (0, fast_json_stable_stringify_1.default)(lineDiffProperties);
119
+ return this.stringify(lineDiffProperties);
120
+ }
121
+ stringify(value) {
122
+ return (0, fast_json_stable_stringify_1.default)(value);
120
123
  }
121
124
  static cloneAndRemoveUndefinedEntriesFromObject(obj) {
122
125
  const clone = {};
@@ -47,6 +47,14 @@ class MablStepV2 extends MablStep_1.MablStep {
47
47
  this.stepDescription() ||
48
48
  this.getStepName());
49
49
  }
50
+ toLineDiffFormat() {
51
+ const lineDiffProperties = {
52
+ annotation: this.annotation,
53
+ disabled: this.isDisabled(),
54
+ descriptor: this.toStepDescriptor(),
55
+ };
56
+ return this.stringify(lineDiffProperties);
57
+ }
50
58
  }
51
59
  exports.MablStepV2 = MablStepV2;
52
60
  MablStepV2.mablScriptStepNames = [];
@@ -42,9 +42,17 @@ function convertOperationValue(op) {
42
42
  return DiffOperation.EQUAL;
43
43
  }
44
44
  }
45
+ function parseFlowIntoStepList(flow) {
46
+ if (flow.flow_type === mablApi_1.Flow.FlowTypeEnum.Mobile) {
47
+ return (0, importer_1.interpretStepsFromObjectsInFlow)(flow, true);
48
+ }
49
+ return (0, importer_1.parseMablScriptIntoSteps)(flow);
50
+ }
45
51
  function convertFlowToStepList(flow, flowConfig) {
46
- if (!flow.reusable && flow.flow_type === mablApi_1.Flow.FlowTypeEnum.Mablscript) {
47
- return (0, importer_1.parseMablScriptIntoSteps)(flow);
52
+ if (!flow.reusable &&
53
+ (flow.flow_type === mablApi_1.Flow.FlowTypeEnum.Mablscript ||
54
+ flow.flow_type === mablApi_1.Flow.FlowTypeEnum.Mobile)) {
55
+ return parseFlowIntoStepList(flow);
48
56
  }
49
57
  const evaluateFlowStep = new EvaluateFlowStep_1.EvaluateFlowStep(EvaluateFlowStep_1.EvaluateFlowStep.mablScriptStepNames[0], [{ invariant_id: flow === null || flow === void 0 ? void 0 : flow.invariant_id }, flowConfig], []);
50
58
  if (flow.description) {
@@ -53,7 +61,7 @@ function convertFlowToStepList(flow, flowConfig) {
53
61
  return [evaluateFlowStep];
54
62
  }
55
63
  exports.convertFlowToStepList = convertFlowToStepList;
56
- function convertStepListToFlow(steps) {
64
+ function convertStepListToFlow(steps, flowType = mablApi_1.Flow.FlowTypeEnum.Mablscript) {
57
65
  if (steps.length > 1 && steps.some((step) => (0, EvaluateFlowStep_1.isEvaluateFlowStep)(step))) {
58
66
  throw new Error('EvaluateFlow step(s) cannot be combined with other steps in a flow');
59
67
  }
@@ -76,20 +84,30 @@ function convertStepListToFlow(steps) {
76
84
  return annotations;
77
85
  }, {});
78
86
  const flow = {
79
- script: addTrailingNewline((0, importer_1.mablscriptTheLoadedSteps)(steps)),
80
- script_description: steps
81
- .map((step) => { var _a; return (_a = step.getDescription()) !== null && _a !== void 0 ? _a : ''; })
82
- .join('\n'),
87
+ json_steps: flowType === mablApi_1.Flow.FlowTypeEnum.Mobile
88
+ ? { steps: steps.map((step) => step.getFormattedStep(true)) }
89
+ : undefined,
90
+ script: flowType === mablApi_1.Flow.FlowTypeEnum.Mablscript
91
+ ? addTrailingNewline((0, importer_1.mablscriptTheLoadedSteps)(steps))
92
+ : undefined,
93
+ script_description: steps.map(getStepDescription).join('\n'),
83
94
  step_annotations: stepAnnotations,
84
95
  };
85
96
  return { flow };
86
97
  }
87
98
  exports.convertStepListToFlow = convertStepListToFlow;
99
+ function getStepDescription(step) {
100
+ var _a;
101
+ if (step.getStepVersion() === 2) {
102
+ return step.stepDescription();
103
+ }
104
+ return (_a = step.getDescription()) !== null && _a !== void 0 ? _a : '';
105
+ }
88
106
  function flattenTestFlowsIntoSteps(flows, flowConfigs) {
89
107
  return flows.flatMap((flow, index) => convertFlowToStepList(flow, flowConfigs === null || flowConfigs === void 0 ? void 0 : flowConfigs[index]));
90
108
  }
91
109
  exports.flattenTestFlowsIntoSteps = flattenTestFlowsIntoSteps;
92
- function constructTestFlowsFromSteps(steps) {
110
+ function constructTestFlowsFromSteps(steps, flowType = mablApi_1.Flow.FlowTypeEnum.Mablscript) {
93
111
  const flowSteps = [];
94
112
  let chunk = [];
95
113
  for (const step of steps) {
@@ -115,7 +133,7 @@ function constructTestFlowsFromSteps(steps) {
115
133
  flowConfigs: {},
116
134
  };
117
135
  flowSteps.reduce((output, chunk, index) => {
118
- const { flow, flowConfig } = convertStepListToFlow(chunk);
136
+ const { flow, flowConfig } = convertStepListToFlow(chunk, flowType);
119
137
  output.flows.push(flow);
120
138
  if (flowConfig) {
121
139
  const key = Number(index).toString();
@@ -174,9 +192,9 @@ function diffTests(test1Flows, test1FlowConfig, test2Flows, test2FlowConfig) {
174
192
  exports.diffTests = diffTests;
175
193
  function diffFlows(flow1, flow2) {
176
194
  var _a, _b;
177
- const flow1Steps = (0, importer_1.parseMablScriptIntoSteps)(flow1);
195
+ const flow1Steps = parseFlowIntoStepList(flow1);
178
196
  const formattedFlow1Steps = addTrailingNewline(flow1Steps.map((step) => step.toLineDiffFormat()).join('\n'));
179
- const flow2Steps = (0, importer_1.parseMablScriptIntoSteps)(flow2);
197
+ const flow2Steps = parseFlowIntoStepList(flow2);
180
198
  const formattedFlow2Steps = addTrailingNewline(flow2Steps.map((step) => step.toLineDiffFormat()).join('\n'));
181
199
  const flattenedDiffs = lineModeDiff(formattedFlow1Steps, formattedFlow2Steps);
182
200
  const stepDiffs = convertDiffingFormatIntoDiffingSteps(flattenedDiffs, flow1Steps, flow2Steps);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getSnippetIdsFromFlows = exports.getSnippetIdsFromMablscriptFlow = exports.getSnippetIdsFromJsonFlow = exports.parseMablScriptIntoV2Step = exports.extractOutputVariables = exports.extractInputVariables = exports.parseMablScriptIntoSteps = exports.mablscriptTheLoadedSteps = exports.interpretStepsFromObjects = exports.interpretStepsFromObjectsInFlow = exports.loadYamlSteps = exports.yamlifyTheLoadedSteps = exports.loadMablScriptIntoSteps = exports.parseMablScript = void 0;
3
+ exports.getSnippetIdsFromFlows = exports.getSnippetIdsFromApiFlow = exports.getSnippetIdsFromMablscriptFlow = exports.getSnippetIdsFromJsonFlow = exports.parseMablScriptIntoV2Step = exports.extractOutputVariables = exports.extractInputVariables = exports.parseMablScriptIntoSteps = exports.mablscriptTheLoadedSteps = exports.interpretStepsFromObjects = exports.interpretStepsFromObjectsInFlow = exports.loadYamlSteps = exports.yamlifyTheLoadedSteps = exports.loadMablScriptIntoSteps = exports.parseMablScript = void 0;
4
4
  const esprima_1 = require("esprima");
5
5
  const estraverse_1 = require("estraverse");
6
6
  const AssertStep_1 = require("./steps/AssertStep");
@@ -49,6 +49,7 @@ const JavaScriptAction_1 = require("./actions/JavaScriptAction");
49
49
  const ClickAndHoldStep_1 = require("./steps/ClickAndHoldStep");
50
50
  const ReleaseStep_1 = require("./steps/ReleaseStep");
51
51
  const CountAction_1 = require("./actions/CountAction");
52
+ const mablApi_1 = require("../mablApi");
52
53
  const AccessibilityCheck_1 = require("./steps/AccessibilityCheck");
53
54
  const EvaluateFlowStep_1 = require("./steps/EvaluateFlowStep");
54
55
  const RightClickStep_1 = require("./steps/RightClickStep");
@@ -544,9 +545,24 @@ function getSnippetIdsFromMablscriptFlow(flow) {
544
545
  return snippetIds;
545
546
  }
546
547
  exports.getSnippetIdsFromMablscriptFlow = getSnippetIdsFromMablscriptFlow;
547
- function getSnippetIdsFromFlows(flows, isMobileTest) {
548
- return uniqueArray(flows.flatMap((flow) => isMobileTest
549
- ? getSnippetIdsFromJsonFlow(flow)
550
- : getSnippetIdsFromMablscriptFlow(flow)));
548
+ function getSnippetIdsFromApiFlow(flow) {
549
+ var _a, _b;
550
+ return (_b = (_a = flow.snippet_references) === null || _a === void 0 ? void 0 : _a.map((reference) => reference.id)) !== null && _b !== void 0 ? _b : [];
551
+ }
552
+ exports.getSnippetIdsFromApiFlow = getSnippetIdsFromApiFlow;
553
+ function getSnippetIdsFromFlow(flow, testType) {
554
+ switch (testType) {
555
+ case mablApi_1.TestTypeEnum.Api:
556
+ return getSnippetIdsFromApiFlow(flow);
557
+ case mablApi_1.TestTypeEnum.Mobile:
558
+ return getSnippetIdsFromJsonFlow(flow);
559
+ case mablApi_1.TestTypeEnum.Browser:
560
+ return getSnippetIdsFromMablscriptFlow(flow);
561
+ default:
562
+ return [];
563
+ }
564
+ }
565
+ function getSnippetIdsFromFlows(flows, testType) {
566
+ return uniqueArray(flows.flatMap((flow) => getSnippetIdsFromFlow(flow, testType)));
551
567
  }
552
568
  exports.getSnippetIdsFromFlows = getSnippetIdsFromFlows;
@@ -34,10 +34,16 @@ function humanizeScrollInformation(stepDescriptor) {
34
34
  return humanizeCoordinateScroll(coordinates, 'of the screen');
35
35
  }
36
36
  case ScrollStepDescriptor_1.ScrollType.ScrollToElement: {
37
- const { find, maxScrollAttempts, scrollDirection, targetElementDescriptor, } = stepDescriptor;
38
- const containerElementDescription = (0, stepUtil_1.getElementDescriptionFromMobileFindDescriptor)(find);
37
+ const { coordinates, find, maxScrollAttempts, scrollDirection, targetElementDescriptor, } = stepDescriptor;
38
+ let scrollText = `Scroll ${scrollDirection} a maximum of ${maxScrollAttempts} times`;
39
+ if (coordinates) {
40
+ scrollText = humanizeCoordinateScroll(coordinates, `a maximum of ${maxScrollAttempts} times`);
41
+ }
42
+ const containerElementDescription = find
43
+ ? (0, stepUtil_1.getElementDescriptionFromMobileFindDescriptor)(find)
44
+ : 'screen';
39
45
  const targetElementDescription = (0, stepUtil_1.getElementDescriptionFromMobileFindDescriptor)(targetElementDescriptor);
40
- return `Scroll ${scrollDirection} a maximum of ${maxScrollAttempts} times within the ${containerElementDescription} until the ${targetElementDescription} is visible`;
46
+ return `${scrollText} within the ${containerElementDescription} until the ${targetElementDescription} is visible`;
41
47
  }
42
48
  case ScrollStepDescriptor_1.ScrollType.ScrollWithinElement: {
43
49
  const { coordinates, find } = stepDescriptor;
@@ -9,6 +9,7 @@ describe('Scroll steps parse correctly', () => {
9
9
  it('Parses a ScrollDeviceScreen step', () => {
10
10
  const windowSize = { width: 1440, height: 2392 };
11
11
  const scrollStepDescriptor = {
12
+ description: 'Scroll down 94.06% of the screen',
12
13
  id: 'scrolliePolieOlie',
13
14
  coordinates: {
14
15
  from: {
@@ -159,6 +160,7 @@ describe('Scroll steps parse correctly', () => {
159
160
  };
160
161
  it('Parses a ScrollToElement step', () => {
161
162
  const scrollStepDescriptor = {
163
+ description: 'Scroll right a maximum of 6 times within the "Name field" element until the "Email field" element is visible',
162
164
  id: 'scrollMe',
163
165
  actionCode: 'scroll',
164
166
  find,
@@ -176,7 +178,58 @@ describe('Scroll steps parse correctly', () => {
176
178
  const scrollStep = new ScrollStep_1.ScrollStep(scrollStepDescriptor);
177
179
  expect(scrollStep.stepId()).toEqual(scrollStepDescriptor.id);
178
180
  });
179
- it('Humanizes a ScrollToElement step', () => {
181
+ it('Humanizes ScrollToElement step with container element', () => {
182
+ const scrollStepDescriptor = {
183
+ id: 'scrollMe',
184
+ actionCode: 'scroll',
185
+ coordinates: {
186
+ from: {
187
+ xPercent: 0.109212,
188
+ yPercent: 0.241223,
189
+ },
190
+ to: {
191
+ xPercent: 0.145543,
192
+ yPercent: 0.865454,
193
+ },
194
+ },
195
+ find,
196
+ maxScrollAttempts: 6,
197
+ scrollDirection: ScrollStepDescriptor_1.ScrollDirection.Up,
198
+ scrollType: ScrollStepDescriptor_1.ScrollType.ScrollToElement,
199
+ targetElementDescriptor: innerFindTarget,
200
+ };
201
+ const stepYaml = {
202
+ Scroll: scrollStepDescriptor,
203
+ };
204
+ const step = (0, StepTestsUtil_1.loadRawStepIntoMablStep)(stepYaml);
205
+ expect(step.stepDescription()).toEqual(`Scroll up 62.42% a maximum of 6 times within the "Name field" element until the "Email field" element is visible`);
206
+ });
207
+ it('Humanizes ScrollToElement step without container element', () => {
208
+ const scrollStepDescriptor = {
209
+ id: 'scrollMe',
210
+ actionCode: 'scroll',
211
+ coordinates: {
212
+ from: {
213
+ xPercent: 0.109212,
214
+ yPercent: 0.241223,
215
+ },
216
+ to: {
217
+ xPercent: 0.145543,
218
+ yPercent: 0.865454,
219
+ },
220
+ },
221
+ maxScrollAttempts: 6,
222
+ scrollDirection: ScrollStepDescriptor_1.ScrollDirection.Up,
223
+ scrollType: ScrollStepDescriptor_1.ScrollType.ScrollToElement,
224
+ targetElementDescriptor: innerFindTarget,
225
+ };
226
+ const stepYaml = {
227
+ Scroll: scrollStepDescriptor,
228
+ };
229
+ const step = (0, StepTestsUtil_1.loadRawStepIntoMablStep)(stepYaml);
230
+ expect(step.stepDescription()).toEqual(`Scroll up 62.42% a maximum of 6 times within the screen until the "Email field" element is visible`);
231
+ });
232
+ it('Humanizes a legacy ScrollToElement step', () => {
180
233
  const scrollStepDescriptor = {
181
234
  id: 'scrollMe',
182
235
  actionCode: 'scroll',
@@ -207,6 +260,7 @@ describe('Scroll steps parse correctly', () => {
207
260
  };
208
261
  it('Parses a ScrollWithinElement step', () => {
209
262
  const scrollStepDescriptor = {
263
+ description: 'Scroll right 80% within the "Name field" element',
210
264
  id: 'scrollMe',
211
265
  actionCode: 'scroll',
212
266
  coordinates: {
@@ -18,8 +18,7 @@ class AccessibilityCheckStep extends MablStep_1.MablStep {
18
18
  if (this.actions.length) {
19
19
  this.findAction = ActionsUtils_1.ActionsUtils.validateSingleFindAction(this.actions);
20
20
  }
21
- this.checkConfig =
22
- this.getActionArgs()[0];
21
+ this.checkConfig = this.getActionArgs()[0];
23
22
  }
24
23
  canContinueOnFailure() {
25
24
  return true;
@@ -28,7 +27,6 @@ class AccessibilityCheckStep extends MablStep_1.MablStep {
28
27
  return AccessibilityCheckStep.yamlMablScriptNames[0];
29
28
  }
30
29
  toStepDescriptor() {
31
- var _a, _b, _c, _d;
32
30
  if (this.findAction) {
33
31
  const find = this.findAction.toDescriptor();
34
32
  switch (find.findType) {
@@ -47,11 +45,8 @@ class AccessibilityCheckStep extends MablStep_1.MablStep {
47
45
  }
48
46
  }
49
47
  return {
50
- tags: (_a = this.checkConfig) === null || _a === void 0 ? void 0 : _a.tags,
51
- rules: (_b = this.checkConfig) === null || _b === void 0 ? void 0 : _b.rules,
52
- disabledRules: (_c = this.checkConfig) === null || _c === void 0 ? void 0 : _c.disabledRules,
53
- failOn: (_d = this.checkConfig) === null || _d === void 0 ? void 0 : _d.failOn,
54
48
  actionCode: this.actionCode,
49
+ ...this.checkConfig,
55
50
  };
56
51
  }
57
52
  getFormattedStep(_fullLocatorsOn) {
@@ -266,6 +266,17 @@ class AssertStep extends MablStep_1.MablStep {
266
266
  }
267
267
  return `${this.primaryAction.toMablscript()}.${this.conditionAction.toMablscript()}${assertAction}`;
268
268
  }
269
+ toLineDiffFormat() {
270
+ if (this.primaryAction instanceof MobileFindAction_1.MobileFindAction) {
271
+ const lineDiffProperties = {
272
+ annotation: this.annotation,
273
+ disabled: this.isDisabled(),
274
+ descriptor: this.toStepDescriptor(),
275
+ };
276
+ return this.stringify(lineDiffProperties);
277
+ }
278
+ return super.toLineDiffFormat();
279
+ }
269
280
  getInputVariables() {
270
281
  var _a, _b, _c, _d;
271
282
  return (0, MablAction_1.distinctStrings)([
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isScrollToElementStepDescriptor = exports.ScrollType = exports.ScrollDirection = void 0;
3
+ exports.isScrollDeviceStepDescriptor = exports.isScrollWithinElementStepDescriptor = exports.isScrollToElementStepDescriptor = exports.ScrollType = exports.ScrollDirection = void 0;
4
4
  var ScrollDirection;
5
5
  (function (ScrollDirection) {
6
6
  ScrollDirection["Down"] = "down";
@@ -20,3 +20,13 @@ function isScrollToElementStepDescriptor(step) {
20
20
  !!step.targetElementDescriptor);
21
21
  }
22
22
  exports.isScrollToElementStepDescriptor = isScrollToElementStepDescriptor;
23
+ function isScrollWithinElementStepDescriptor(step) {
24
+ return (step.scrollType === ScrollType.ScrollWithinElement &&
25
+ !!step.scrollDirection &&
26
+ !!step.find);
27
+ }
28
+ exports.isScrollWithinElementStepDescriptor = isScrollWithinElementStepDescriptor;
29
+ function isScrollDeviceStepDescriptor(step) {
30
+ return (step.scrollType === ScrollType.ScrollDeviceScreen && !!step.scrollDirection);
31
+ }
32
+ exports.isScrollDeviceStepDescriptor = isScrollDeviceStepDescriptor;