@mablhq/mabl-cli 1.58.28 → 1.59.6
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/mablApiClient.js +6 -3
- package/browserEngines/chromiumBrowserEngine.js +0 -1
- package/browserLauncher/playwrightBrowserLauncher/playwrightDom.js +1 -1
- package/browserTestMonitoring/cloudMonitoringPerformanceMetrics.js +28 -56
- package/browserTestMonitoring/distributions.js +1 -6
- package/browserTestMonitoring/metricsRecorder.js +47 -30
- package/commands/flows/flows_cmds/export.js +3 -3
- package/commands/tests/testsUtil.js +4 -2
- package/commands/tests/tests_cmds/run-cloud.js +21 -3
- package/commands/tests/tests_cmds/run.js +0 -2
- package/core/trainer/trainingSessions.js +17 -1
- package/execution/index.js +1 -1
- package/mablApi/index.js +1 -1
- package/package.json +3 -3
package/api/mablApiClient.js
CHANGED
|
@@ -678,16 +678,16 @@ class MablApiClient extends basicApiClient_1.BasicApiClient {
|
|
|
678
678
|
throw toApiError(`Failed to retrieve tests for plan`, error);
|
|
679
679
|
}
|
|
680
680
|
}
|
|
681
|
-
async postPlanRun(organizationId, testId, branchName, browserTypes, appUrl, apiUrl, deploymentId, credentialsId, deploymentIds, basicAuthCredentialsId) {
|
|
681
|
+
async postPlanRun(organizationId, testId, branchName, browserTypes, appUrl, apiUrl, deploymentId, credentialsId, deploymentIds, basicAuthCredentialsId, localizationOptions) {
|
|
682
682
|
try {
|
|
683
|
-
const requestBody = this.buildAdHocPlanRunRequestBody(organizationId, testId, browserTypes, branchName, appUrl, apiUrl, deploymentId, credentialsId, deploymentIds, basicAuthCredentialsId);
|
|
683
|
+
const requestBody = this.buildAdHocPlanRunRequestBody(organizationId, testId, browserTypes, branchName, appUrl, apiUrl, deploymentId, credentialsId, deploymentIds, basicAuthCredentialsId, localizationOptions);
|
|
684
684
|
return await this.makePostRequest(`${this.baseApiUrl}/planRuns/`, requestBody);
|
|
685
685
|
}
|
|
686
686
|
catch (error) {
|
|
687
687
|
throw toApiError(`Failed to create planRun`, error);
|
|
688
688
|
}
|
|
689
689
|
}
|
|
690
|
-
buildAdHocPlanRunRequestBody(organizationId, testId, browserTypes, branchName, appUrl, apiUrl, deploymentId, credentialsId, deploymentIds, basicAuthCredentialsId) {
|
|
690
|
+
buildAdHocPlanRunRequestBody(organizationId, testId, browserTypes, branchName, appUrl, apiUrl, deploymentId, credentialsId, deploymentIds, basicAuthCredentialsId, localizationOptions) {
|
|
691
691
|
const requestBody = {
|
|
692
692
|
ad_hoc_run_info: {
|
|
693
693
|
is_ad_hoc_run: true,
|
|
@@ -717,6 +717,9 @@ class MablApiClient extends basicApiClient_1.BasicApiClient {
|
|
|
717
717
|
planOverrides.http_auth_credentials_id = basicAuthCredentialsId;
|
|
718
718
|
planOverrides.http_auth_credentials_required = true;
|
|
719
719
|
}
|
|
720
|
+
if (localizationOptions) {
|
|
721
|
+
planOverrides.localization_options = [localizationOptions];
|
|
722
|
+
}
|
|
720
723
|
if (testId) {
|
|
721
724
|
planOverrides.journeys = [{ journey_id: testId }];
|
|
722
725
|
planOverrides.execution_stages = [
|
|
@@ -108,7 +108,6 @@ class ChromiumBrowserEngine {
|
|
|
108
108
|
launchArgs.push('--use-fake-device-for-media-stream');
|
|
109
109
|
launchArgs.push(`--use-file-for-fake-audio-capture=${fakeMicrophoneMediaPath}`);
|
|
110
110
|
launchArgs.push(`--use-file-for-fake-video-capture=${fakeWebcamMediaPath}`);
|
|
111
|
-
launchArgs.push('--disable-notifications');
|
|
112
111
|
if (ignoreCertificateErrors) {
|
|
113
112
|
launchArgs.push('--ignore-certificate-errors');
|
|
114
113
|
}
|
|
@@ -59,7 +59,7 @@ class PlaywrightJsHandle {
|
|
|
59
59
|
isContextDestroyed() {
|
|
60
60
|
var _a, _b;
|
|
61
61
|
const elementImpl = playwright._toImpl(this.handle);
|
|
62
|
-
return !!((_b = (_a = elementImpl._context) === null || _a === void 0 ? void 0 : _a.
|
|
62
|
+
return !!((_b = (_a = elementImpl._context) === null || _a === void 0 ? void 0 : _a._contextDestroyedScope) === null || _b === void 0 ? void 0 : _b.isClosed());
|
|
63
63
|
}
|
|
64
64
|
static unwrapProperties(arg, addSecondaryWorldFlag = false) {
|
|
65
65
|
if (arg === undefined) {
|
|
@@ -69,6 +69,11 @@ class CloudMonitoringPerformanceMetrics {
|
|
|
69
69
|
...this.generateCommonInstrumentNames('test'),
|
|
70
70
|
executionTime: this.generateInstrumentName('test', 'execution', 'time'),
|
|
71
71
|
runnerCount: this.generateCountInstrumentName('test', 'runner'),
|
|
72
|
+
firstContentfulPaintFailCount: this.generateCWVFailCountInstrumentName('test', 'firstContentfulPaint'),
|
|
73
|
+
largestContentfulPaintFailCount: this.generateCWVFailCountInstrumentName('test', 'largestContentfulPaint'),
|
|
74
|
+
cumulativeLayoutShiftFailCount: this.generateCWVFailCountInstrumentName('test', 'cumulativeLayoutShift'),
|
|
75
|
+
timeToFirstByteFailCount: this.generateCWVFailCountInstrumentName('test', 'timeToFirstByte'),
|
|
76
|
+
domContentLoadedFailCount: this.generateCWVFailCountInstrumentName('test', 'domContentLoaded'),
|
|
72
77
|
};
|
|
73
78
|
}
|
|
74
79
|
initializeOpenTelemetry() {
|
|
@@ -105,26 +110,6 @@ class CloudMonitoringPerformanceMetrics {
|
|
|
105
110
|
aggregation: new sdk_metrics_1.ExplicitBucketHistogramAggregation(distributions_1.DCLBucketBoundaries, true),
|
|
106
111
|
instrumentName: this.stepMetricsInstrumentNames.domContentLoaded,
|
|
107
112
|
}),
|
|
108
|
-
firstContentfulPaintCategory: new sdk_metrics_1.View({
|
|
109
|
-
aggregation: new sdk_metrics_1.ExplicitBucketHistogramAggregation(distributions_1.FCPCategoryBucketBoundaries, false),
|
|
110
|
-
instrumentName: this.stepMetricsInstrumentNames.firstContentfulPaintCategory,
|
|
111
|
-
}),
|
|
112
|
-
largestContentfulPaintCategory: new sdk_metrics_1.View({
|
|
113
|
-
aggregation: new sdk_metrics_1.ExplicitBucketHistogramAggregation(distributions_1.LCPCategoryBucketBoundaries, false),
|
|
114
|
-
instrumentName: this.stepMetricsInstrumentNames.largestContentfulPaintCategory,
|
|
115
|
-
}),
|
|
116
|
-
cumulativeLayoutShiftCategory: new sdk_metrics_1.View({
|
|
117
|
-
aggregation: new sdk_metrics_1.ExplicitBucketHistogramAggregation(distributions_1.CLSCategoryBucketBoundaries, false),
|
|
118
|
-
instrumentName: this.stepMetricsInstrumentNames.cumulativeLayoutShiftCategory,
|
|
119
|
-
}),
|
|
120
|
-
timeToFirstByteCategory: new sdk_metrics_1.View({
|
|
121
|
-
aggregation: new sdk_metrics_1.ExplicitBucketHistogramAggregation(distributions_1.TTFBCategoryBucketBoundaries, false),
|
|
122
|
-
instrumentName: this.stepMetricsInstrumentNames.timeToFirstByteCategory,
|
|
123
|
-
}),
|
|
124
|
-
domContentLoadedCategory: new sdk_metrics_1.View({
|
|
125
|
-
aggregation: new sdk_metrics_1.ExplicitBucketHistogramAggregation(distributions_1.DCLCategoryBucketBoundaries, false),
|
|
126
|
-
instrumentName: this.stepMetricsInstrumentNames.domContentLoadedCategory,
|
|
127
|
-
}),
|
|
128
113
|
};
|
|
129
114
|
const TestMetricsViews = {
|
|
130
115
|
executionCount: new sdk_metrics_1.View({
|
|
@@ -147,25 +132,25 @@ class CloudMonitoringPerformanceMetrics {
|
|
|
147
132
|
aggregation: new sdk_metrics_1.LastValueAggregation(),
|
|
148
133
|
instrumentName: this.testMetricsInstrumentNames.runnerCount,
|
|
149
134
|
}),
|
|
150
|
-
|
|
151
|
-
aggregation: new sdk_metrics_1.
|
|
152
|
-
instrumentName: this.
|
|
135
|
+
firstContentfulPaintFailCount: new sdk_metrics_1.View({
|
|
136
|
+
aggregation: new sdk_metrics_1.SumAggregation(),
|
|
137
|
+
instrumentName: this.testMetricsInstrumentNames.firstContentfulPaintFailCount,
|
|
153
138
|
}),
|
|
154
|
-
|
|
155
|
-
aggregation: new sdk_metrics_1.
|
|
156
|
-
instrumentName: this.
|
|
139
|
+
largestContentfulPaintFailCount: new sdk_metrics_1.View({
|
|
140
|
+
aggregation: new sdk_metrics_1.SumAggregation(),
|
|
141
|
+
instrumentName: this.testMetricsInstrumentNames.largestContentfulPaintFailCount,
|
|
157
142
|
}),
|
|
158
|
-
|
|
159
|
-
aggregation: new sdk_metrics_1.
|
|
160
|
-
instrumentName: this.
|
|
143
|
+
cumulativeLayoutShiftFailCount: new sdk_metrics_1.View({
|
|
144
|
+
aggregation: new sdk_metrics_1.SumAggregation(),
|
|
145
|
+
instrumentName: this.testMetricsInstrumentNames.cumulativeLayoutShiftFailCount,
|
|
161
146
|
}),
|
|
162
|
-
|
|
163
|
-
aggregation: new sdk_metrics_1.
|
|
164
|
-
instrumentName: this.
|
|
147
|
+
timeToFirstByteFailCount: new sdk_metrics_1.View({
|
|
148
|
+
aggregation: new sdk_metrics_1.SumAggregation(),
|
|
149
|
+
instrumentName: this.testMetricsInstrumentNames.timeToFirstByteFailCount,
|
|
165
150
|
}),
|
|
166
|
-
|
|
167
|
-
aggregation: new sdk_metrics_1.
|
|
168
|
-
instrumentName: this.
|
|
151
|
+
domContentLoadedFailCount: new sdk_metrics_1.View({
|
|
152
|
+
aggregation: new sdk_metrics_1.SumAggregation(),
|
|
153
|
+
instrumentName: this.testMetricsInstrumentNames.domContentLoadedFailCount,
|
|
169
154
|
}),
|
|
170
155
|
};
|
|
171
156
|
const meterProvider = new sdk_metrics_1.MeterProvider({
|
|
@@ -200,11 +185,6 @@ class CloudMonitoringPerformanceMetrics {
|
|
|
200
185
|
cumulativeLayoutShift: this.initializeStepTimeHistogram('cumulativeLayoutShift'),
|
|
201
186
|
timeToFirstByte: this.initializeStepTimeHistogram('timeToFirstByte'),
|
|
202
187
|
domContentLoaded: this.initializeStepTimeHistogram('domContentLoaded'),
|
|
203
|
-
firstContentfulPaintCategory: this.initializeStepTimeHistogram('firstContentfulPaintCategory'),
|
|
204
|
-
largestContentfulPaintCategory: this.initializeStepTimeHistogram('largestContentfulPaintCategory'),
|
|
205
|
-
cumulativeLayoutShiftCategory: this.initializeStepTimeHistogram('cumulativeLayoutShiftCategory'),
|
|
206
|
-
timeToFirstByteCategory: this.initializeStepTimeHistogram('timeToFirstByteCategory'),
|
|
207
|
-
domContentLoadedCategory: this.initializeStepTimeHistogram('domContentLoadedCategory'),
|
|
208
188
|
};
|
|
209
189
|
}
|
|
210
190
|
initializeTestMetrics() {
|
|
@@ -214,11 +194,11 @@ class CloudMonitoringPerformanceMetrics {
|
|
|
214
194
|
failCount: this.initializeTestCount('failCount'),
|
|
215
195
|
passCount: this.initializeTestCount('passCount'),
|
|
216
196
|
runnerCount: this.initializeTestCount('runnerCount'),
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
197
|
+
firstContentfulPaintFailCount: this.initializeTestCount('firstContentfulPaintFailCount'),
|
|
198
|
+
largestContentfulPaintFailCount: this.initializeTestCount('largestContentfulPaintFailCount'),
|
|
199
|
+
cumulativeLayoutShiftFailCount: this.initializeTestCount('cumulativeLayoutShiftFailCount'),
|
|
200
|
+
timeToFirstByteFailCount: this.initializeTestCount('timeToFirstByteFailCount'),
|
|
201
|
+
domContentLoadedFailCount: this.initializeTestCount('domContentLoadedFailCount'),
|
|
222
202
|
};
|
|
223
203
|
}
|
|
224
204
|
initializeStepCount(instrumentName) {
|
|
@@ -240,10 +220,7 @@ class CloudMonitoringPerformanceMetrics {
|
|
|
240
220
|
}
|
|
241
221
|
initializeTimeHistogram(instrumentName) {
|
|
242
222
|
const histogram = this.meter.createHistogram(instrumentName, {
|
|
243
|
-
unit: instrumentName ===
|
|
244
|
-
this.stepMetricsInstrumentNames.cumulativeLayoutShift ||
|
|
245
|
-
instrumentName ===
|
|
246
|
-
this.stepMetricsInstrumentNames.cumulativeLayoutShiftCategory
|
|
223
|
+
unit: instrumentName === this.stepMetricsInstrumentNames.cumulativeLayoutShift
|
|
247
224
|
? undefined
|
|
248
225
|
: 'ms',
|
|
249
226
|
});
|
|
@@ -254,11 +231,6 @@ class CloudMonitoringPerformanceMetrics {
|
|
|
254
231
|
executionCount: this.generateCountInstrumentName(granularity, 'execution'),
|
|
255
232
|
failCount: this.generateResultInstrumentName(granularity, 'fail'),
|
|
256
233
|
passCount: this.generateResultInstrumentName(granularity, 'pass'),
|
|
257
|
-
firstContentfulPaintCategory: this.generateCWVCategoryInstrumentName(granularity, 'firstContentfulPaint'),
|
|
258
|
-
largestContentfulPaintCategory: this.generateCWVCategoryInstrumentName(granularity, 'largestContentfulPaint'),
|
|
259
|
-
cumulativeLayoutShiftCategory: this.generateCWVCategoryInstrumentName(granularity, 'cumulativeLayoutShift'),
|
|
260
|
-
timeToFirstByteCategory: this.generateCWVCategoryInstrumentName(granularity, 'timeToFirstByte'),
|
|
261
|
-
domContentLoadedCategory: this.generateCWVCategoryInstrumentName(granularity, 'domContentLoaded'),
|
|
262
234
|
};
|
|
263
235
|
}
|
|
264
236
|
generateCountInstrumentName(granularity, type) {
|
|
@@ -267,8 +239,8 @@ class CloudMonitoringPerformanceMetrics {
|
|
|
267
239
|
generateResultInstrumentName(granularity, type) {
|
|
268
240
|
return this.generateInstrumentName(granularity, 'result', type);
|
|
269
241
|
}
|
|
270
|
-
|
|
271
|
-
return this.generateInstrumentName(granularity, type, '
|
|
242
|
+
generateCWVFailCountInstrumentName(granularity, type) {
|
|
243
|
+
return this.generateInstrumentName(granularity, type, 'failCount');
|
|
272
244
|
}
|
|
273
245
|
generateInstrumentName(granularity, ...path) {
|
|
274
246
|
return `${METRIC_NAME_PREFIX}/${granularity}/${path.join('/')}`;
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateBucketBoundaries = exports.
|
|
3
|
+
exports.generateBucketBoundaries = exports.DCLBucketBoundaries = exports.TTFBBucketBoundaries = exports.CLSBucketBoundaries = exports.LCPBucketBoundaries = exports.FCPBucketBoundaries = exports.ElapsedExecutionTimeBucketBoundaries = void 0;
|
|
4
4
|
exports.ElapsedExecutionTimeBucketBoundaries = generateBucketBoundaries({ limit: 60000, width: 1000 }, { limit: 300000, width: 5000 }, { limit: 3600000, width: 60000 });
|
|
5
5
|
exports.FCPBucketBoundaries = generateBucketBoundaries({ limit: 1800, width: 25 }, { limit: 3000, width: 50 }, { limit: 6000, width: 100 }, { limit: 30000, width: 500 }, { limit: 50000, width: 1000 });
|
|
6
|
-
exports.FCPCategoryBucketBoundaries = [1800.01, 3000.01];
|
|
7
6
|
exports.LCPBucketBoundaries = generateBucketBoundaries({ limit: 1500, width: 25 }, { limit: 2500, width: 50 }, { limit: 4000, width: 75 }, { limit: 8000, width: 250 }, { limit: 30000, width: 500 }, { limit: 60000, width: 1000 });
|
|
8
|
-
exports.LCPCategoryBucketBoundaries = [2500.01, 4000.01];
|
|
9
7
|
exports.CLSBucketBoundaries = generateBucketBoundaries({ limit: 0.1, width: 0.001 }, { limit: 0.25, width: 0.0025 }, { limit: 0.5, width: 0.01 }, { limit: 1, width: 0.05 });
|
|
10
|
-
exports.CLSCategoryBucketBoundaries = [0.1001, 0.2501];
|
|
11
8
|
exports.TTFBBucketBoundaries = generateBucketBoundaries({ limit: 1000, width: 25 }, { limit: 2000, width: 50 }, { limit: 5000, width: 75 }, { limit: 10000, width: 250 }, { limit: 30000, width: 500 }, { limit: 60000, width: 1000 });
|
|
12
|
-
exports.TTFBCategoryBucketBoundaries = [800.01, 1800.01];
|
|
13
9
|
exports.DCLBucketBoundaries = generateBucketBoundaries({ limit: 1000, width: 25 }, { limit: 2000, width: 50 }, { limit: 5000, width: 75 }, { limit: 10000, width: 250 }, { limit: 30000, width: 500 }, { limit: 60000, width: 1000 });
|
|
14
|
-
exports.DCLCategoryBucketBoundaries = [1000.01, 2000.01];
|
|
15
10
|
function generateBucketBoundaries(...rules) {
|
|
16
11
|
if (!rules.length) {
|
|
17
12
|
throw new Error('At least one rule must be specified');
|
|
@@ -4,16 +4,17 @@ exports.MetricsRecorder = void 0;
|
|
|
4
4
|
const cloudMonitoringPerformanceMetrics_1 = require("./cloudMonitoringPerformanceMetrics");
|
|
5
5
|
const Executor_1 = require("../execution/Executor");
|
|
6
6
|
const TestResult_1 = require("../core/execution/TestResult");
|
|
7
|
+
const pureUtil_1 = require("../util/pureUtil");
|
|
7
8
|
class MetricsRecorder {
|
|
8
|
-
constructor(projectId, testMetricLabels, metricsFactory = (projectId, runnerId) => new cloudMonitoringPerformanceMetrics_1.CloudMonitoringPerformanceMetrics(projectId, runnerId)) {
|
|
9
|
+
constructor(projectId, testMetricLabels, metricsFactory = (projectId, runnerId) => new cloudMonitoringPerformanceMetrics_1.CloudMonitoringPerformanceMetrics(projectId, runnerId), cwvFailureCriteria) {
|
|
9
10
|
this.testMetricLabels = testMetricLabels;
|
|
11
|
+
this.cwvFailureCriteria = cwvFailureCriteria;
|
|
10
12
|
this.metrics = metricsFactory(projectId, testMetricLabels.runner_id);
|
|
11
13
|
}
|
|
12
14
|
async stop() {
|
|
13
15
|
await this.metrics.shutdown();
|
|
14
16
|
}
|
|
15
|
-
recordTestMetricsForResult(testResult,
|
|
16
|
-
var _a, _b, _c, _d, _e;
|
|
17
|
+
recordTestMetricsForResult(testResult, navigationInfo) {
|
|
17
18
|
const testElapsedTimeMillis = testResult.endTime - testResult.startTime;
|
|
18
19
|
const testPassed = testResult.status === TestResult_1.TestResultStatus.passed;
|
|
19
20
|
this.recordTestMetrics({
|
|
@@ -22,13 +23,44 @@ class MetricsRecorder {
|
|
|
22
23
|
failCount: testPassed ? 0 : 1,
|
|
23
24
|
passCount: testPassed ? 1 : 0,
|
|
24
25
|
runnerCount: 1,
|
|
25
|
-
|
|
26
|
-
largestContentfulPaintCategory: (_b = metric.find((metric) => metric.name === 'LCP')) === null || _b === void 0 ? void 0 : _b.value,
|
|
27
|
-
cumulativeLayoutShiftCategory: (_c = metric.find((metric) => metric.name === 'CLS')) === null || _c === void 0 ? void 0 : _c.value,
|
|
28
|
-
timeToFirstByteCategory: (_d = metric.find((metric) => metric.name === 'TTFB')) === null || _d === void 0 ? void 0 : _d.value,
|
|
29
|
-
domContentLoadedCategory: (_e = metric.find((metric) => metric.name === 'domContentLoadedEventEnd')) === null || _e === void 0 ? void 0 : _e.value,
|
|
26
|
+
...this.getCWVFailCounts(navigationInfo),
|
|
30
27
|
});
|
|
31
28
|
}
|
|
29
|
+
getCWVFailCounts(navigationInfo) {
|
|
30
|
+
var _a;
|
|
31
|
+
if (!this.cwvFailureCriteria) {
|
|
32
|
+
return {};
|
|
33
|
+
}
|
|
34
|
+
const { relevantStepIds, metricConfiguration } = this.cwvFailureCriteria;
|
|
35
|
+
const relevantNavigationInfo = (_a = relevantStepIds === null || relevantStepIds === void 0 ? void 0 : relevantStepIds.map((stepId) => navigationInfo.get(stepId)).filter(pureUtil_1.isDefined)) !== null && _a !== void 0 ? _a : Array.from(navigationInfo.values());
|
|
36
|
+
const relevantMetric = relevantNavigationInfo.flatMap((navigationInfo) => navigationInfo.metric);
|
|
37
|
+
return metricConfiguration
|
|
38
|
+
.map((configuration) => {
|
|
39
|
+
const { name, threshold } = configuration;
|
|
40
|
+
const hasTestFailed = relevantMetric
|
|
41
|
+
.filter((metric) => metric.name === name)
|
|
42
|
+
.some((metric) => metric.value > threshold);
|
|
43
|
+
return {
|
|
44
|
+
[this.metricNameToTestMeasurementName(name)]: hasTestFailed ? 1 : 0,
|
|
45
|
+
};
|
|
46
|
+
})
|
|
47
|
+
.reduce((measurements, measurement) => Object.assign(measurements, measurement), {});
|
|
48
|
+
}
|
|
49
|
+
metricNameToTestMeasurementName(name) {
|
|
50
|
+
switch (name) {
|
|
51
|
+
case 'FCP':
|
|
52
|
+
return 'firstContentfulPaintFailCount';
|
|
53
|
+
case 'LCP':
|
|
54
|
+
return 'largestContentfulPaintFailCount';
|
|
55
|
+
case 'CLS':
|
|
56
|
+
return 'cumulativeLayoutShiftFailCount';
|
|
57
|
+
case 'TTFB':
|
|
58
|
+
return 'timeToFirstByteFailCount';
|
|
59
|
+
default:
|
|
60
|
+
case 'domContentLoadedEventEnd':
|
|
61
|
+
return 'domContentLoadedFailCount';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
32
64
|
recordStepMetricsForResult(result) {
|
|
33
65
|
const labels = {
|
|
34
66
|
...this.testMetricLabels,
|
|
@@ -45,36 +77,21 @@ class MetricsRecorder {
|
|
|
45
77
|
...this.testMetricLabels,
|
|
46
78
|
step_id: stepId,
|
|
47
79
|
};
|
|
48
|
-
this.recordStepMetrics(labels, this.
|
|
80
|
+
this.recordStepMetrics(labels, this.transformCWVStepMetricToStepMeasurement(metric));
|
|
49
81
|
}
|
|
50
|
-
|
|
82
|
+
transformCWVStepMetricToStepMeasurement(metric) {
|
|
51
83
|
const { name, value } = metric;
|
|
52
84
|
switch (name) {
|
|
53
85
|
case 'FCP':
|
|
54
|
-
return {
|
|
55
|
-
firstContentfulPaint: value,
|
|
56
|
-
firstContentfulPaintCategory: value,
|
|
57
|
-
};
|
|
86
|
+
return { firstContentfulPaint: value };
|
|
58
87
|
case 'LCP':
|
|
59
|
-
return {
|
|
60
|
-
largestContentfulPaint: value,
|
|
61
|
-
largestContentfulPaintCategory: value,
|
|
62
|
-
};
|
|
88
|
+
return { largestContentfulPaint: value };
|
|
63
89
|
case 'CLS':
|
|
64
|
-
return {
|
|
65
|
-
cumulativeLayoutShift: value,
|
|
66
|
-
cumulativeLayoutShiftCategory: value,
|
|
67
|
-
};
|
|
90
|
+
return { cumulativeLayoutShift: value };
|
|
68
91
|
case 'TTFB':
|
|
69
|
-
return {
|
|
70
|
-
timeToFirstByte: value,
|
|
71
|
-
timeToFirstByteCategory: value,
|
|
72
|
-
};
|
|
92
|
+
return { timeToFirstByte: value };
|
|
73
93
|
case 'domContentLoadedEventEnd':
|
|
74
|
-
return {
|
|
75
|
-
domContentLoaded: value,
|
|
76
|
-
domContentLoadedCategory: value,
|
|
77
|
-
};
|
|
94
|
+
return { domContentLoaded: value };
|
|
78
95
|
default:
|
|
79
96
|
return {};
|
|
80
97
|
}
|
|
@@ -4,7 +4,7 @@ const mablApiClientFactory_1 = require("../../../api/mablApiClientFactory");
|
|
|
4
4
|
const util_1 = require("../../commandUtil/util");
|
|
5
5
|
const js_yaml_1 = require("js-yaml");
|
|
6
6
|
const constants_1 = require("../../constants");
|
|
7
|
-
const
|
|
7
|
+
const execution_1 = require("../../../execution");
|
|
8
8
|
const fileUtil_1 = require("../../commandUtil/fileUtil");
|
|
9
9
|
const os = require('os');
|
|
10
10
|
const JSON_REPLACER = null;
|
|
@@ -55,7 +55,7 @@ async function pullFlow(parsed) {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
function dumpYamlOrJsonToFile(type, flow, detailLevel) {
|
|
58
|
-
const flowConfig = new
|
|
58
|
+
const flowConfig = new execution_1.FlowConfig(flow, false);
|
|
59
59
|
const configGenerated = detailLevel === constants_1.DetailLevelFormats.Full
|
|
60
60
|
? flowConfig.generateConfigFile()
|
|
61
61
|
: flowConfig.generateSimpleFormat();
|
|
@@ -72,7 +72,7 @@ function dumpYamlOrJsonToFile(type, flow, detailLevel) {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
function dumpToCsv(flow) {
|
|
75
|
-
const flowConfig = new
|
|
75
|
+
const flowConfig = new execution_1.FlowConfig(flow, false);
|
|
76
76
|
const output = flowConfig.generateSimpleCsv();
|
|
77
77
|
(0, fileUtil_1.writeExportedEntityToFile)(output.join(os.EOL), 'csv', flow.id);
|
|
78
78
|
}
|
|
@@ -29,21 +29,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
29
29
|
exports.parseBrowserType = exports.toBasicHttpAuthenticationCredentials = exports.logTestInfoIfPresent = exports.milliSecondsToSeconds = exports.calculateTotalTimeSeconds = exports.extractTestRunConfig = exports.pullDownTestRunConfig = exports.validateRunCommandWithLabels = exports.validateRunEditCommand = exports.cleanupTestResources = exports.sleep = exports.editTheTest = exports.runTheTest = exports.prepareTrainerForSplitPlayback = exports.cleanUpInitialPages = exports.getExtensionBackgroundPageWithCliTool = exports.createBrowserForExecutionEngine = exports.createBrowser = exports.getFinalUrl = void 0;
|
|
30
30
|
const cli_table3_1 = __importDefault(require("cli-table3"));
|
|
31
31
|
const fs = __importStar(require("fs-extra"));
|
|
32
|
-
const mablApi_1 = require("../../mablApi");
|
|
33
32
|
const os = __importStar(require("os"));
|
|
34
33
|
const path = __importStar(require("path"));
|
|
35
34
|
const browserLauncher_1 = require("../../browserLauncher/browserLauncher");
|
|
36
35
|
const trainingSessionActions_1 = require("../../core/messaging/actions/trainingSessionActions");
|
|
37
36
|
const logLineMessaging_1 = require("../../core/messaging/logLineMessaging");
|
|
38
37
|
const messaging_1 = require("../../core/messaging/messaging");
|
|
38
|
+
const mablApi_1 = require("../../mablApi");
|
|
39
39
|
const cliConfigProvider_1 = require("../../providers/cliConfigProvider");
|
|
40
40
|
const loggingProvider_1 = require("../../providers/logging/loggingProvider");
|
|
41
41
|
const fileUploadUtil_1 = require("../../util/fileUploadUtil");
|
|
42
42
|
const logUtils_1 = require("../../util/logUtils");
|
|
43
43
|
const browserTypes_1 = require("../browserTypes");
|
|
44
44
|
const constants_1 = require("../constants");
|
|
45
|
-
const trainerUtil_1 = require("./tests_cmds/trainerUtil");
|
|
46
45
|
const utils_1 = require("../datatables/utils");
|
|
46
|
+
const trainerUtil_1 = require("./tests_cmds/trainerUtil");
|
|
47
47
|
const chalk = require('chalk');
|
|
48
48
|
let RUNNING_TEST = false;
|
|
49
49
|
function getFinalUrl(test, parsedUrl) {
|
|
@@ -414,6 +414,7 @@ async function pullDownTestRunConfig(testRunId, apiClient) {
|
|
|
414
414
|
environmentId: (_k = (_j = journeyRun.journey_parameters) === null || _j === void 0 ? void 0 : _j.deployment) === null || _k === void 0 ? void 0 : _k.environment_id,
|
|
415
415
|
filterHttpRequests: false,
|
|
416
416
|
importedVariables: (_l = journeyRun.journey_parameters) === null || _l === void 0 ? void 0 : _l.imported_variables,
|
|
417
|
+
localizationOptions: journeyRun.localization_options,
|
|
417
418
|
pageLoadWait: (_m = journeyRun.journey_parameters) === null || _m === void 0 ? void 0 : _m.page_load_wait,
|
|
418
419
|
runId: journeyRun.id,
|
|
419
420
|
testId: (_o = journeyRun.journey) === null || _o === void 0 ? void 0 : _o.invariant_id,
|
|
@@ -443,6 +444,7 @@ async function extractTestRunConfig(executionMessage, apiClient) {
|
|
|
443
444
|
environmentId: (_o = (_m = journeyRun === null || journeyRun === void 0 ? void 0 : journeyRun.journey_parameters) === null || _m === void 0 ? void 0 : _m.deployment) === null || _o === void 0 ? void 0 : _o.environment_id,
|
|
444
445
|
filterHttpRequests: true,
|
|
445
446
|
importedVariables: (_p = journeyRun.journey_parameters) === null || _p === void 0 ? void 0 : _p.imported_variables,
|
|
447
|
+
localizationOptions: journeyRun.localization_options,
|
|
446
448
|
pageLoadWait: (_q = journeyRun.journey_parameters) === null || _q === void 0 ? void 0 : _q.page_load_wait,
|
|
447
449
|
runId: journeyRun.id,
|
|
448
450
|
runnerType: maybeRunnerType,
|
|
@@ -119,6 +119,16 @@ exports.builder = (yargs) => {
|
|
|
119
119
|
describe: 'Credentials ID to run the test with',
|
|
120
120
|
nargs: 1,
|
|
121
121
|
type: 'string',
|
|
122
|
+
})
|
|
123
|
+
.option(constants_1.CommandArgLocale, {
|
|
124
|
+
describe: 'Locale to run the test in, e.g. en-US',
|
|
125
|
+
nargs: 1,
|
|
126
|
+
type: 'string',
|
|
127
|
+
})
|
|
128
|
+
.option(constants_1.CommandArgTimezoneID, {
|
|
129
|
+
describe: 'Identifier of the timezone to run the test in, e.g. America/Buenos_Aires',
|
|
130
|
+
nargs: 1,
|
|
131
|
+
type: 'string',
|
|
122
132
|
})
|
|
123
133
|
.option(constants_1.CommandArgPrompt, {
|
|
124
134
|
describe: 'Prompt to confirm execution selections',
|
|
@@ -150,6 +160,14 @@ async function runInCloud(parsed) {
|
|
|
150
160
|
const applicationId = parsed[constants_1.CommandArgApplicationId];
|
|
151
161
|
const environmentId = parsed[constants_1.CommandArgEnvironmentId];
|
|
152
162
|
const basicAuthCredentialsId = parsed[constants_1.CommandArgBasicAuthCredentials];
|
|
163
|
+
const parsedLocale = parsed[constants_1.CommandArgLocale];
|
|
164
|
+
const parsedTimezone = parsed[constants_1.CommandArgTimezoneID];
|
|
165
|
+
const localizationOptions = parsedLocale || parsedTimezone
|
|
166
|
+
? {
|
|
167
|
+
locale: parsedLocale,
|
|
168
|
+
timezone_identifier: parsedTimezone,
|
|
169
|
+
}
|
|
170
|
+
: undefined;
|
|
153
171
|
let tests = [];
|
|
154
172
|
if (maybeTestId) {
|
|
155
173
|
const journey = await apiClient.getJourney(maybeTestId, branchName);
|
|
@@ -180,7 +198,7 @@ async function runInCloud(parsed) {
|
|
|
180
198
|
loggingProvider_1.logger.info(chalk.white('---'));
|
|
181
199
|
const resultUrls = [];
|
|
182
200
|
for (const test of tests) {
|
|
183
|
-
const testRuns = await executeRunCloudTest(test, browsers, branchName, apiClient, maybeDeploymentId, maybeUrlApp, maybeUrlApi, credentialsId, applicationId, environmentId, basicAuthCredentialsId);
|
|
201
|
+
const testRuns = await executeRunCloudTest(test, browsers, branchName, apiClient, maybeDeploymentId, maybeUrlApp, maybeUrlApi, credentialsId, applicationId, environmentId, basicAuthCredentialsId, localizationOptions);
|
|
184
202
|
testRuns.forEach((testRun) => resultUrls.push(`${env_1.BASE_APP_URL}/workspaces/${testRun.organization_id}/test/journey-runs/${testRun.id}`));
|
|
185
203
|
loggingProvider_1.logger.info(chalk.white('---'));
|
|
186
204
|
}
|
|
@@ -199,7 +217,7 @@ async function runInCloud(parsed) {
|
|
|
199
217
|
}
|
|
200
218
|
return outputUrl;
|
|
201
219
|
}
|
|
202
|
-
async function executeRunCloudTest(test, browsers, branchName, apiClient, maybeDeploymentId, appUrl, apiUrl, credentialsId, applicationId, environmentId, basicAuthCredentialsId) {
|
|
220
|
+
async function executeRunCloudTest(test, browsers, branchName, apiClient, maybeDeploymentId, appUrl, apiUrl, credentialsId, applicationId, environmentId, basicAuthCredentialsId, localizationOptions) {
|
|
203
221
|
var _a;
|
|
204
222
|
const effectiveAppUrl = appUrl !== null && appUrl !== void 0 ? appUrl : (test.test_type === undefined || test.test_type === mablApi_1.TestTypeEnum.Browser
|
|
205
223
|
? test === null || test === void 0 ? void 0 : test.url
|
|
@@ -234,7 +252,7 @@ async function executeRunCloudTest(test, browsers, branchName, apiClient, maybeD
|
|
|
234
252
|
}
|
|
235
253
|
deploymentIds = foundDeployments.map((deployment) => deployment.id);
|
|
236
254
|
}
|
|
237
|
-
const planRun = await apiClient.postPlanRun(workspaceId, testId, branchName, browsers, effectiveAppUrl, effectiveApiUrl, maybeDeploymentId, credentialsId, deploymentIds, basicAuthCredentialsId);
|
|
255
|
+
const planRun = await apiClient.postPlanRun(workspaceId, testId, branchName, browsers, effectiveAppUrl, effectiveApiUrl, maybeDeploymentId, credentialsId, deploymentIds, basicAuthCredentialsId, localizationOptions);
|
|
238
256
|
const testRunsQueryResult = await apiClient.getTestRunsForPlan(planRun.id);
|
|
239
257
|
return (_a = testRunsQueryResult.test_script_executions) !== null && _a !== void 0 ? _a : [];
|
|
240
258
|
}
|
|
@@ -77,13 +77,11 @@ exports.builder = (yargs) => {
|
|
|
77
77
|
describe: 'Locale to run the test in, e.g. en-US',
|
|
78
78
|
nargs: 1,
|
|
79
79
|
type: 'string',
|
|
80
|
-
hidden: true,
|
|
81
80
|
})
|
|
82
81
|
.option(constants_1.CommandArgTimezoneID, {
|
|
83
82
|
describe: 'Identifier of the timezone to run the test in, e.g. America/Buenos_Aires',
|
|
84
83
|
nargs: 1,
|
|
85
84
|
type: 'string',
|
|
86
|
-
hidden: true,
|
|
87
85
|
})
|
|
88
86
|
.option('width', {
|
|
89
87
|
describe: 'Set the browser width in pixels',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.editTest = exports.trainNewTest = exports.ElectronProtocolUrl = exports.SENDER = exports.DEFAULT_WIDTH = exports.DEFAULT_HEIGHT = void 0;
|
|
3
|
+
exports.editTest = exports.getInitialFlows = exports.trainNewTest = exports.ElectronProtocolUrl = exports.SENDER = exports.DEFAULT_WIDTH = exports.DEFAULT_HEIGHT = void 0;
|
|
4
4
|
const branches_1 = require("../../commands/commandUtil/branches");
|
|
5
5
|
const testsUtil_1 = require("../../commands/tests/testsUtil");
|
|
6
6
|
const mablApi_1 = require("../../mablApi");
|
|
@@ -44,6 +44,7 @@ async function trainNewTest(trainingSessionOptions) {
|
|
|
44
44
|
await apiClient.getApplication(applicationId);
|
|
45
45
|
}
|
|
46
46
|
const account = await apiClient.getAccountByWorkspaceId(workspaceId);
|
|
47
|
+
const flows = await getInitialFlows(apiClient, autoLogin, workspaceId);
|
|
47
48
|
(0, testsUtil_1.logTestInfoIfPresent)(`Creating test in desktop app: `, testName);
|
|
48
49
|
(0, testsUtil_1.logTestInfoIfPresent)(`Add auto login flow: `, autoLogin);
|
|
49
50
|
(0, testsUtil_1.logTestInfoIfPresent)(`URL: `, url);
|
|
@@ -61,6 +62,7 @@ async function trainNewTest(trainingSessionOptions) {
|
|
|
61
62
|
accountId: account.id,
|
|
62
63
|
branchName,
|
|
63
64
|
dataTables: dataTableIds,
|
|
65
|
+
flows,
|
|
64
66
|
height: height !== null && height !== void 0 ? height : exports.DEFAULT_HEIGHT,
|
|
65
67
|
sender: exports.SENDER,
|
|
66
68
|
width: width !== null && width !== void 0 ? width : exports.DEFAULT_WIDTH,
|
|
@@ -68,6 +70,20 @@ async function trainNewTest(trainingSessionOptions) {
|
|
|
68
70
|
await (0, openUtils_1.openUrlInDesktopApp)(ElectronProtocolUrl.TRAIN_NEW_TEST, scriptConfig);
|
|
69
71
|
}
|
|
70
72
|
exports.trainNewTest = trainNewTest;
|
|
73
|
+
async function getInitialFlows(apiClient, autoLogin, workspaceId) {
|
|
74
|
+
const initialFlows = [];
|
|
75
|
+
if (autoLogin) {
|
|
76
|
+
const loginFlows = await apiClient.getFlows({
|
|
77
|
+
flow_type: 'login',
|
|
78
|
+
organization_id: workspaceId,
|
|
79
|
+
});
|
|
80
|
+
if (loginFlows === null || loginFlows === void 0 ? void 0 : loginFlows[0]) {
|
|
81
|
+
initialFlows.push(loginFlows[0].id);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return initialFlows;
|
|
85
|
+
}
|
|
86
|
+
exports.getInitialFlows = getInitialFlows;
|
|
71
87
|
async function editTest(trainingSessionOptions) {
|
|
72
88
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
73
89
|
const apiClient = await (0, util_1.getApiClientFromOptions)(trainingSessionOptions, true);
|