@mablhq/mabl-cli 1.13.28 → 1.16.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/basicApiClient.js +52 -28
- package/api/featureSet.js +27 -0
- package/api/mablApiClient.js +22 -21
- package/browserLauncher/pageEvent.js +1 -0
- package/browserLauncher/playwrightBrowserLauncher/playwrightBrowserLauncher.js +2 -0
- package/browserLauncher/playwrightBrowserLauncher/playwrightDom.js +12 -0
- package/browserLauncher/playwrightBrowserLauncher/playwrightPage.js +6 -0
- package/browserLauncher/puppeteerBrowserLauncher/puppeteerElementHandle.js +12 -0
- package/browserLauncher/puppeteerBrowserLauncher/puppeteerPage.js +6 -0
- package/commands/tests/executionUtil.js +6 -1
- package/commands/tests/testsUtil.js +10 -4
- package/domUtil/index.js +1 -1
- package/execution/index.js +1 -1
- package/mablApi/index.js +1 -1
- package/mablscript/MablStep.js +3 -0
- package/mablscript/actions/FindAction.js +9 -6
- package/mablscript/steps/AccessibilityCheck.js +14 -2
- package/mablscriptFind/index.js +1 -1
- package/package.json +2 -1
- package/resources/mablFind.js +1 -1
- package/resources/pdf-viewer/embeddedPdfDetection.js +2 -1
- package/util/resourceUtil.js +39 -13
- package/api/entities/JourneyRunScheduledMessage.js +0 -2
package/api/basicApiClient.js
CHANGED
|
@@ -37,6 +37,14 @@ const DEFAULT_MAX_TOTAL_RETRY_TIME_MILLISECONDS = DEFAULT_RETRYABLE_REQUEST_TIME
|
|
|
37
37
|
const DEFAULT_NONRETRYABLE_REQUEST_TIMEOUT_MILLISECONDS = DEFAULT_MAX_TOTAL_RETRY_TIME_MILLISECONDS;
|
|
38
38
|
const DEFAULT_MIN_RETRY_INTERVAL_MILLISECONDS = 1000;
|
|
39
39
|
const DEFAULT_MAX_RETRY_INTERVAL_MILLISECONDS = 10000;
|
|
40
|
+
const RETRYABLE_NODEJS_ERRORS = [
|
|
41
|
+
'EAI_AGAIN',
|
|
42
|
+
'ECONNRESET',
|
|
43
|
+
'ENOTFOUND',
|
|
44
|
+
'ENETUNREACH',
|
|
45
|
+
'ETIMEOUT',
|
|
46
|
+
'ECONNABORTED',
|
|
47
|
+
];
|
|
40
48
|
var AuthType;
|
|
41
49
|
(function (AuthType) {
|
|
42
50
|
AuthType[AuthType["Bearer"] = 0] = "Bearer";
|
|
@@ -44,12 +52,12 @@ var AuthType;
|
|
|
44
52
|
})(AuthType = exports.AuthType || (exports.AuthType = {}));
|
|
45
53
|
class BasicApiClient {
|
|
46
54
|
constructor(options) {
|
|
47
|
-
var _a, _b;
|
|
55
|
+
var _a, _b, _c, _d;
|
|
48
56
|
const config = httpUtil_1.axiosProxyConfig({
|
|
49
57
|
sslVerify: options.sslVerify,
|
|
50
58
|
proxyHost: options.proxyUrl,
|
|
51
59
|
});
|
|
52
|
-
config.timeout = (_a = options.requestTimeoutMillis) !== null && _a !== void 0 ? _a : DEFAULT_RETRYABLE_REQUEST_TIMEOUT_MILLISECONDS;
|
|
60
|
+
config.timeout = (_c = (_a = options.requestTimeoutMillis) !== null && _a !== void 0 ? _a : (_b = options.retryConfig) === null || _b === void 0 ? void 0 : _b.requestTimeoutMillis) !== null && _c !== void 0 ? _c : DEFAULT_RETRYABLE_REQUEST_TIMEOUT_MILLISECONDS;
|
|
53
61
|
switch (options.authType) {
|
|
54
62
|
case AuthType.ApiKey:
|
|
55
63
|
config.auth = {
|
|
@@ -77,7 +85,7 @@ class BasicApiClient {
|
|
|
77
85
|
this.httpRequestConfig = config;
|
|
78
86
|
this.httpClient = axios_1.default.create(config);
|
|
79
87
|
this.retryConfig = options.retryConfig;
|
|
80
|
-
this.debugLogger = (
|
|
88
|
+
this.debugLogger = (_d = options.debugLogger) !== null && _d !== void 0 ? _d : logUtils_1.logInternal;
|
|
81
89
|
}
|
|
82
90
|
getNonRetryableRequestConfig(override) {
|
|
83
91
|
const overrideWithTimeout = { ...(override !== null && override !== void 0 ? override : {}) };
|
|
@@ -87,20 +95,26 @@ class BasicApiClient {
|
|
|
87
95
|
}
|
|
88
96
|
return { ...this.httpRequestConfig, ...overrideWithTimeout };
|
|
89
97
|
}
|
|
90
|
-
|
|
91
|
-
|
|
98
|
+
getRetryableRequestConfig(retryConfig) {
|
|
99
|
+
var _a;
|
|
100
|
+
return this.getNonRetryableRequestConfig({
|
|
101
|
+
timeout: (_a = retryConfig === null || retryConfig === void 0 ? void 0 : retryConfig.requestTimeoutMillis) !== null && _a !== void 0 ? _a : this.httpRequestConfig.timeout,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
makeGetRequest(path, retryConfig) {
|
|
105
|
+
return this.retryWrappedRequest(`makeGetRequest('${path}')`, () => this.getRequest(path, this.getRetryableRequestConfig(retryConfig)), retryConfig);
|
|
92
106
|
}
|
|
93
|
-
async getRequest(path) {
|
|
94
|
-
const response = await this.debugRequest('GET', path, () => this.httpClient.get(path));
|
|
107
|
+
async getRequest(path, config) {
|
|
108
|
+
const response = await this.debugRequest('GET', path, () => this.httpClient.get(path, config));
|
|
95
109
|
BasicApiClient.checkResponseStatusCode(response);
|
|
96
110
|
return response.data;
|
|
97
111
|
}
|
|
98
|
-
makeGetRequestWithETag(path) {
|
|
99
|
-
return this.retryWrappedRequest(`makeGetRequestWithETag('${path}')`, () => this.getRequestWithETag(path));
|
|
112
|
+
makeGetRequestWithETag(path, retryConfig) {
|
|
113
|
+
return this.retryWrappedRequest(`makeGetRequestWithETag('${path}')`, () => this.getRequestWithETag(path, this.getRetryableRequestConfig(retryConfig)), retryConfig);
|
|
100
114
|
}
|
|
101
|
-
async getRequestWithETag(path) {
|
|
115
|
+
async getRequestWithETag(path, config) {
|
|
102
116
|
var _a;
|
|
103
|
-
const response = await this.debugRequest('GET', path, () => this.httpClient.get(path));
|
|
117
|
+
const response = await this.debugRequest('GET', path, () => this.httpClient.get(path, config));
|
|
104
118
|
BasicApiClient.checkResponseStatusCode(response);
|
|
105
119
|
const headers = response.headers;
|
|
106
120
|
const result = response.data;
|
|
@@ -120,11 +134,11 @@ class BasicApiClient {
|
|
|
120
134
|
BasicApiClient.checkResponseStatusCode(response);
|
|
121
135
|
return response.data;
|
|
122
136
|
}
|
|
123
|
-
makeDeleteRequest(path) {
|
|
124
|
-
return this.retryWrappedRequest(`makeDeleteRequest('${path}')`, () => this.deleteRequest(path));
|
|
137
|
+
makeDeleteRequest(path, retryConfig) {
|
|
138
|
+
return this.retryWrappedRequest(`makeDeleteRequest('${path}')`, () => this.deleteRequest(path, this.getRetryableRequestConfig(retryConfig)), retryConfig);
|
|
125
139
|
}
|
|
126
|
-
async deleteRequest(path) {
|
|
127
|
-
const response = await this.debugRequest('DELETE', path, () => this.deleteRequest(path));
|
|
140
|
+
async deleteRequest(path, config) {
|
|
141
|
+
const response = await this.debugRequest('DELETE', path, () => this.deleteRequest(path, config));
|
|
128
142
|
BasicApiClient.checkResponseStatusCode(response);
|
|
129
143
|
return response.data;
|
|
130
144
|
}
|
|
@@ -158,38 +172,48 @@ class BasicApiClient {
|
|
|
158
172
|
throw new ApiError_1.ApiError(`[${statusCode} - ${response.statusText}]`, statusCode);
|
|
159
173
|
}
|
|
160
174
|
}
|
|
161
|
-
retryWrappedRequest(description, requestFunc) {
|
|
162
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
175
|
+
retryWrappedRequest(description, requestFunc, retryConfigOverride) {
|
|
176
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
163
177
|
const retryOptions = {
|
|
164
|
-
retries: (
|
|
165
|
-
minTimeout: (_d = (
|
|
166
|
-
maxTimeout: (
|
|
167
|
-
maxRetryTime: (
|
|
178
|
+
retries: (_c = (_a = retryConfigOverride === null || retryConfigOverride === void 0 ? void 0 : retryConfigOverride.retryCount) !== null && _a !== void 0 ? _a : (_b = this.retryConfig) === null || _b === void 0 ? void 0 : _b.retryCount) !== null && _c !== void 0 ? _c : DEFAULT_RETRIES,
|
|
179
|
+
minTimeout: (_f = (_d = retryConfigOverride === null || retryConfigOverride === void 0 ? void 0 : retryConfigOverride.minRetryIntervalMillis) !== null && _d !== void 0 ? _d : (_e = this.retryConfig) === null || _e === void 0 ? void 0 : _e.minRetryIntervalMillis) !== null && _f !== void 0 ? _f : DEFAULT_MIN_RETRY_INTERVAL_MILLISECONDS,
|
|
180
|
+
maxTimeout: (_j = (_g = retryConfigOverride === null || retryConfigOverride === void 0 ? void 0 : retryConfigOverride.maxRetryIntervalMillis) !== null && _g !== void 0 ? _g : (_h = this.retryConfig) === null || _h === void 0 ? void 0 : _h.maxRetryIntervalMillis) !== null && _j !== void 0 ? _j : DEFAULT_MAX_RETRY_INTERVAL_MILLISECONDS,
|
|
181
|
+
maxRetryTime: (_m = (_k = retryConfigOverride === null || retryConfigOverride === void 0 ? void 0 : retryConfigOverride.maxRetryTimeMillis) !== null && _k !== void 0 ? _k : (_l = this.retryConfig) === null || _l === void 0 ? void 0 : _l.maxRetryTimeMillis) !== null && _m !== void 0 ? _m : DEFAULT_MAX_TOTAL_RETRY_TIME_MILLISECONDS,
|
|
168
182
|
onRetry: (error) => {
|
|
169
183
|
this.debugLogger(`Retrying failed API request "${description}"`, error);
|
|
170
184
|
},
|
|
171
185
|
forever: false,
|
|
172
186
|
};
|
|
173
187
|
return asyncUtil_1.promiseWithTimeout(async_retry_1.default(async (bail) => {
|
|
174
|
-
var _a, _b;
|
|
175
188
|
try {
|
|
176
189
|
return await requestFunc();
|
|
177
190
|
}
|
|
178
191
|
catch (error) {
|
|
179
|
-
|
|
180
|
-
const statusCode = (_a = axiosError.code) !== null && _a !== void 0 ? _a : (_b = axiosError.response) === null || _b === void 0 ? void 0 : _b.status;
|
|
181
|
-
if (statusCode === 429 ||
|
|
182
|
-
statusCode === 502 ||
|
|
183
|
-
statusCode === 503 ||
|
|
184
|
-
statusCode === 504) {
|
|
192
|
+
if (axios_1.default.isAxiosError(error) && BasicApiClient.isRetryable(error)) {
|
|
185
193
|
throw error;
|
|
186
194
|
}
|
|
187
195
|
else {
|
|
196
|
+
let code;
|
|
197
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
198
|
+
code = error.code;
|
|
199
|
+
}
|
|
200
|
+
this.debugLogger(`Non-retryable error on API client: ${code} ${description} ${error}`);
|
|
188
201
|
bail(error);
|
|
189
202
|
return {};
|
|
190
203
|
}
|
|
191
204
|
}
|
|
192
205
|
}, retryOptions), retryOptions.maxRetryTime + retryOptions.maxTimeout, 'Retryable API request');
|
|
193
206
|
}
|
|
207
|
+
static isRetryable(axiosError) {
|
|
208
|
+
if (axiosError.response) {
|
|
209
|
+
const statusCode = axiosError.response.status;
|
|
210
|
+
return (statusCode === 429 ||
|
|
211
|
+
statusCode === 502 ||
|
|
212
|
+
statusCode === 503 ||
|
|
213
|
+
statusCode === 504);
|
|
214
|
+
}
|
|
215
|
+
return (axiosError.code !== undefined &&
|
|
216
|
+
RETRYABLE_NODEJS_ERRORS.includes(axiosError.code));
|
|
217
|
+
}
|
|
194
218
|
}
|
|
195
219
|
exports.BasicApiClient = BasicApiClient;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FeatureSet = exports.FindImplementationVersion = void 0;
|
|
4
|
+
const runnerType_1 = require("../browserLauncher/runnerType");
|
|
5
|
+
const PLAYWRIGHT_FEATURE_FLAG = 'nodejs_execution_engine_playwright';
|
|
6
|
+
const SMARTER_WAIT_FEATURE_FLAG = 'smarter_wait';
|
|
7
|
+
var FindImplementationVersion;
|
|
8
|
+
(function (FindImplementationVersion) {
|
|
9
|
+
FindImplementationVersion[FindImplementationVersion["V1"] = 0] = "V1";
|
|
10
|
+
FindImplementationVersion[FindImplementationVersion["SmartFind"] = 1] = "SmartFind";
|
|
11
|
+
})(FindImplementationVersion = exports.FindImplementationVersion || (exports.FindImplementationVersion = {}));
|
|
12
|
+
class FeatureSet {
|
|
13
|
+
constructor(featureFlags) {
|
|
14
|
+
this.featureFlags = featureFlags;
|
|
15
|
+
}
|
|
16
|
+
getRunnerType() {
|
|
17
|
+
return this.featureFlags.has(PLAYWRIGHT_FEATURE_FLAG)
|
|
18
|
+
? runnerType_1.RunnerType.Playwright
|
|
19
|
+
: runnerType_1.RunnerType.Puppeteer;
|
|
20
|
+
}
|
|
21
|
+
getFindImplementationVersion() {
|
|
22
|
+
return this.featureFlags.has(SMARTER_WAIT_FEATURE_FLAG)
|
|
23
|
+
? FindImplementationVersion.SmartFind
|
|
24
|
+
: FindImplementationVersion.V1;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.FeatureSet = FeatureSet;
|
package/api/mablApiClient.js
CHANGED
|
@@ -26,9 +26,7 @@ const mablApi_1 = require("../mablApi");
|
|
|
26
26
|
const cliConfigProvider_1 = require("../providers/cliConfigProvider");
|
|
27
27
|
const basicApiClient_1 = require("./basicApiClient");
|
|
28
28
|
const queryString = __importStar(require("query-string"));
|
|
29
|
-
const
|
|
30
|
-
const runnerType_1 = require("../browserLauncher/runnerType");
|
|
31
|
-
const PLAYWRIGHT_FEATURE_FLAG = 'nodejs_execution_engine_playwright';
|
|
29
|
+
const featureSet_1 = require("./featureSet");
|
|
32
30
|
class MablApiClient extends basicApiClient_1.BasicApiClient {
|
|
33
31
|
constructor(options) {
|
|
34
32
|
super(options);
|
|
@@ -229,7 +227,7 @@ class MablApiClient extends basicApiClient_1.BasicApiClient {
|
|
|
229
227
|
}
|
|
230
228
|
async getDeploymentResults(deploymentEventId) {
|
|
231
229
|
try {
|
|
232
|
-
return await this.makeGetRequest(`${env_1.BASE_API_URL}/execution/result/event/${deploymentEventId}
|
|
230
|
+
return await this.makeGetRequest(`${env_1.BASE_API_URL}/execution/result/event/${deploymentEventId}`, { requestTimeoutMillis: 600000, maxRetryTimeMillis: 900000 });
|
|
233
231
|
}
|
|
234
232
|
catch (error) {
|
|
235
233
|
throw toApiError(`Failed to get deployment results`, error);
|
|
@@ -237,12 +235,20 @@ class MablApiClient extends basicApiClient_1.BasicApiClient {
|
|
|
237
235
|
}
|
|
238
236
|
async getTestFindSummaries(testId, environmentId) {
|
|
239
237
|
try {
|
|
240
|
-
return await this.makeGetRequest(`${env_1.BASE_API_URL}/findSummary?journey_id=${testId}&environment_id=${environmentId}`);
|
|
238
|
+
return await this.makeGetRequest(`${env_1.BASE_API_URL}/findSummary?journey_id=${testId}&environment_id=${environmentId}`).then((result) => { var _a; return (_a = result.findsummaries) !== null && _a !== void 0 ? _a : []; });
|
|
241
239
|
}
|
|
242
240
|
catch (error) {
|
|
243
241
|
throw toApiError(`Failed to get test find summaries results`, error);
|
|
244
242
|
}
|
|
245
243
|
}
|
|
244
|
+
async getTestFindModels(testId, environmentId) {
|
|
245
|
+
try {
|
|
246
|
+
return await this.makeGetRequest(`${env_1.BASE_API_URL}/findModel/test/${testId}?environment_id=${environmentId}`).then((result) => { var _a; return (_a = result.findModels) !== null && _a !== void 0 ? _a : []; });
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
throw toApiError(`Failed to get test find model results`, error);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
246
252
|
async getTestOverrides(testId, environmentId, selectorOverrideLimit = 10) {
|
|
247
253
|
try {
|
|
248
254
|
return await this.makeGetRequest(`${env_1.BASE_API_URL}/tests/testScripts/${testId}/overrides?environment_id=${environmentId}&selector_override_limit=${selectorOverrideLimit}`).then((result) => { var _a; return (_a = result.overrides) !== null && _a !== void 0 ? _a : []; });
|
|
@@ -687,23 +693,18 @@ class MablApiClient extends basicApiClient_1.BasicApiClient {
|
|
|
687
693
|
timeout: 3600000,
|
|
688
694
|
});
|
|
689
695
|
}
|
|
690
|
-
async
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
}
|
|
702
|
-
catch (ex) {
|
|
703
|
-
logUtils_1.logInternal(`Unable to get the playwright feature flag (${ex})`);
|
|
704
|
-
}
|
|
696
|
+
async getEffectiveFeaturesByWorkspaceId(workspaceId) {
|
|
697
|
+
try {
|
|
698
|
+
const workspace = await this.getWorkspace(workspaceId);
|
|
699
|
+
const account = await this.getAccount(workspace.account_id);
|
|
700
|
+
const features = account.effective_features
|
|
701
|
+
? new Set(account.effective_features)
|
|
702
|
+
: new Set();
|
|
703
|
+
return new featureSet_1.FeatureSet(features);
|
|
704
|
+
}
|
|
705
|
+
catch (error) {
|
|
706
|
+
throw toApiError(`Failed to get feature flags for workspace ${workspaceId}`, error);
|
|
705
707
|
}
|
|
706
|
-
return runnerType_1.RunnerType.Puppeteer;
|
|
707
708
|
}
|
|
708
709
|
}
|
|
709
710
|
exports.MablApiClient = MablApiClient;
|
|
@@ -13,4 +13,5 @@ var PageEvent;
|
|
|
13
13
|
PageEvent["Response"] = "response";
|
|
14
14
|
PageEvent["TracingBufferUsage"] = "tracingbufferusage";
|
|
15
15
|
PageEvent["TracingComplete"] = "tracingcomplete";
|
|
16
|
+
PageEvent["TracingDataCollected"] = "TracingDataCollected";
|
|
16
17
|
})(PageEvent = exports.PageEvent || (exports.PageEvent = {}));
|
|
@@ -7,6 +7,7 @@ exports.PlaywrightBrowserLauncher = void 0;
|
|
|
7
7
|
const test_1 = require("@playwright/test");
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const playwrightBrowser_1 = require("./playwrightBrowser");
|
|
10
|
+
const BROWSER_LAUNCH_TIMEOUT_MS = 60000;
|
|
10
11
|
class PlaywrightBrowserLauncher {
|
|
11
12
|
async connect(options, currentDownloadPath) {
|
|
12
13
|
const browser = await test_1.chromium.connect(options.browserWSEndpoint);
|
|
@@ -35,6 +36,7 @@ class PlaywrightBrowserLauncher {
|
|
|
35
36
|
isMobile: (_a = options.defaultDeviceDescriptor) === null || _a === void 0 ? void 0 : _a.isMobile,
|
|
36
37
|
deviceScaleFactor: (_b = options.defaultDeviceDescriptor) === null || _b === void 0 ? void 0 : _b.deviceScaleFactor,
|
|
37
38
|
hasTouch: (_c = options.defaultDeviceDescriptor) === null || _c === void 0 ? void 0 : _c.hasTouch,
|
|
39
|
+
timeout: BROWSER_LAUNCH_TIMEOUT_MS,
|
|
38
40
|
});
|
|
39
41
|
return new playwrightBrowser_1.PlaywrightBrowser(defaultContext, path_1.default.join(options.downloadPath, 'final'), '');
|
|
40
42
|
}
|
|
@@ -26,6 +26,7 @@ const utils_1 = require("../utils");
|
|
|
26
26
|
const logUtils_1 = require("../../util/logUtils");
|
|
27
27
|
const elementHandle_1 = require("../elementHandle");
|
|
28
28
|
const testsUtil_1 = require("../../commands/tests/testsUtil");
|
|
29
|
+
const pureUtil_1 = require("../../util/pureUtil");
|
|
29
30
|
exports.NAVIGATION_ERROR_MESSAGE = 'waiting for scheduled navigations to finish';
|
|
30
31
|
class PlaywrightJsHandle {
|
|
31
32
|
constructor(handle, page) {
|
|
@@ -267,5 +268,16 @@ class PlaywrightElementHandle extends PlaywrightJsHandle {
|
|
|
267
268
|
var _a;
|
|
268
269
|
return ((_a = this.cdpSession) !== null && _a !== void 0 ? _a : this.page.getCdpSession()).send(method, paramArgs);
|
|
269
270
|
}
|
|
271
|
+
getTagName() {
|
|
272
|
+
return this.element.evaluate((el) => el.tagName.toLowerCase());
|
|
273
|
+
}
|
|
274
|
+
async getAttribute(attributeName) {
|
|
275
|
+
const result = await this.element.evaluate((el, attributeName) => el.getAttribute(attributeName), attributeName);
|
|
276
|
+
return pureUtil_1.isNullish(result) ? undefined : result;
|
|
277
|
+
}
|
|
278
|
+
async getInnerText() {
|
|
279
|
+
const result = await this.element.evaluate((el) => el.innerText);
|
|
280
|
+
return pureUtil_1.isNullish(result) ? undefined : result;
|
|
281
|
+
}
|
|
270
282
|
}
|
|
271
283
|
exports.PlaywrightElementHandle = PlaywrightElementHandle;
|
|
@@ -130,6 +130,12 @@ class PlaywrightPage extends events_1.default {
|
|
|
130
130
|
this.emit(browserLauncher_1.PageEvent.TracingBufferUsage, tracing);
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
|
+
if (event === browserLauncher_1.PageEvent.TracingDataCollected &&
|
|
134
|
+
!this.listenerCount(event)) {
|
|
135
|
+
this.getCdpSession().on('Tracing.dataCollected', (data) => {
|
|
136
|
+
this.emit(browserLauncher_1.PageEvent.TracingDataCollected, data);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
133
139
|
if (event === browserLauncher_1.PageEvent.TracingComplete && !this.listenerCount(event)) {
|
|
134
140
|
this.getCdpSession().on('Tracing.tracingComplete', (tracingComplete) => {
|
|
135
141
|
this.emit(browserLauncher_1.PageEvent.TracingComplete, tracingComplete);
|
|
@@ -5,6 +5,7 @@ const puppeteerJsHandle_1 = require("./puppeteerJsHandle");
|
|
|
5
5
|
const utils_1 = require("../utils");
|
|
6
6
|
const testsUtil_1 = require("../../commands/tests/testsUtil");
|
|
7
7
|
const elementHandle_1 = require("../elementHandle");
|
|
8
|
+
const pureUtil_1 = require("../../util/pureUtil");
|
|
8
9
|
const msBetweenClicks = 100;
|
|
9
10
|
class PuppeteerElementHandle extends puppeteerJsHandle_1.PuppeteerJsHandle {
|
|
10
11
|
constructor(element, parentPage) {
|
|
@@ -123,5 +124,16 @@ class PuppeteerElementHandle extends puppeteerJsHandle_1.PuppeteerJsHandle {
|
|
|
123
124
|
getValue() {
|
|
124
125
|
return this.element.evaluate((el) => el.value);
|
|
125
126
|
}
|
|
127
|
+
async getInnerText() {
|
|
128
|
+
const result = await this.element.evaluate((el) => el.innerText);
|
|
129
|
+
return pureUtil_1.isNullish(result) ? undefined : result;
|
|
130
|
+
}
|
|
131
|
+
getTagName() {
|
|
132
|
+
return this.element.evaluate((el) => el.tagName.toLowerCase());
|
|
133
|
+
}
|
|
134
|
+
async getAttribute(attributeName) {
|
|
135
|
+
const result = await this.element.evaluate((el, attributeName) => el.getAttribute(attributeName), attributeName);
|
|
136
|
+
return pureUtil_1.isNullish(result) ? undefined : result;
|
|
137
|
+
}
|
|
126
138
|
}
|
|
127
139
|
exports.PuppeteerElementHandle = PuppeteerElementHandle;
|
|
@@ -245,6 +245,12 @@ class PuppeteerPage extends events_1.default {
|
|
|
245
245
|
this.emit(browserLauncher_1.PageEvent.TracingComplete, tracingComplete);
|
|
246
246
|
});
|
|
247
247
|
}
|
|
248
|
+
if (event === browserLauncher_1.PageEvent.TracingDataCollected &&
|
|
249
|
+
!this.listenerCount(event)) {
|
|
250
|
+
this.getCdpClient().on('Tracing.dataCollected', (data) => {
|
|
251
|
+
this.emit(browserLauncher_1.PageEvent.TracingComplete, data);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
248
254
|
}
|
|
249
255
|
evaluateHandleInSecondaryWorld(code, ...args) {
|
|
250
256
|
return this.mainFrame().evaluateHandleInSecondaryWorld(code, ...args);
|
|
@@ -15,7 +15,12 @@ async function runTheTestInNewWindow(test, flows, branchName, url, credentialsId
|
|
|
15
15
|
const authConfig = await new authenticationProvider_1.AuthenticationProvider().getAuthConfigWithAutoRenew();
|
|
16
16
|
const browserPreferences = testsUtil_1.generateChromiumPreferencesFile();
|
|
17
17
|
const browserPreferencesDirectory = await testsUtil_1.prepareChromePreferencesDirectory(browserPreferences);
|
|
18
|
-
const
|
|
18
|
+
const apiClient = await mablApiClientFactory_1.MablApiClientFactory.createApiClient();
|
|
19
|
+
if (!test.organization_id) {
|
|
20
|
+
throw new Error('The test workspace ID is required, but it is not set.');
|
|
21
|
+
}
|
|
22
|
+
const featureFlags = await apiClient.getEffectiveFeaturesByWorkspaceId(test.organization_id);
|
|
23
|
+
const runnerType = featureFlags.getRunnerType();
|
|
19
24
|
const trainingBrowser = await testsUtil_1.createBrowserWithAuthedExtension(authConfig.accessToken, width || exports.DEFAULT_BROWSER_WIDTH, height || exports.DEFAULT_BROWSER_HEIGHT, browserPreferencesDirectory, {
|
|
20
25
|
runnerType,
|
|
21
26
|
});
|
|
@@ -22,7 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
22
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.toBasicHttpAuthenticationCredentials = exports.generateChromiumPreferencesFile = exports.logTestInfoIfPresent = exports.calculateTotalTimeSeconds = exports.extractTestRunConfig = exports.pullDownTestRunConfig = exports.validateRunCommandWithLabels = exports.validateRunEditCommand = exports.downloadUploadFile = exports.sleep = exports.editTheTest = exports.runTheTest = exports.prepareTrainerForSplitPlayback = exports.createTrainingSession = exports.cleanUpInitialPages = exports.getExtensionBackgroundPageWithCliTool = exports.setUpAuthTokenForExtension = exports.createBrowserForExecutionEngine = exports.addExecutionEngineLaunchArgs = exports.createBrowser = exports.prepareChromePreferencesDirectory = exports.createBrowserWithAuthedExtension = exports.findChrome = exports.searchForChrome = exports.getFinalUrl = exports.getTempChromePrefDirectory = void 0;
|
|
25
|
+
exports.toBasicHttpAuthenticationCredentials = exports.generateChromiumPreferencesFile = exports.logTestInfoIfPresent = exports.milliSecondsToSeconds = exports.calculateTotalTimeSeconds = exports.extractTestRunConfig = exports.pullDownTestRunConfig = exports.validateRunCommandWithLabels = exports.validateRunEditCommand = exports.downloadUploadFile = exports.sleep = exports.editTheTest = exports.runTheTest = exports.prepareTrainerForSplitPlayback = exports.createTrainingSession = exports.cleanUpInitialPages = exports.getExtensionBackgroundPageWithCliTool = exports.setUpAuthTokenForExtension = exports.createBrowserForExecutionEngine = exports.addExecutionEngineLaunchArgs = exports.createBrowser = exports.prepareChromePreferencesDirectory = exports.createBrowserWithAuthedExtension = exports.findChrome = exports.searchForChrome = exports.getFinalUrl = exports.getTempChromePrefDirectory = void 0;
|
|
26
26
|
const os = __importStar(require("os"));
|
|
27
27
|
const trainerUtil_1 = require("./tests_cmds/trainer_cmds/trainerUtil");
|
|
28
28
|
const fs = __importStar(require("fs-extra"));
|
|
@@ -158,6 +158,8 @@ async function launchBrowserInstance(chromePath, launchArgs, userDataDir, headle
|
|
|
158
158
|
messaging_1.mablEventEmitter.log(error.message);
|
|
159
159
|
});
|
|
160
160
|
}
|
|
161
|
+
messaging_1.mablEventEmitter.log('Browser launch failed', Date.now(), logLineMessaging_1.LogLineColor.red);
|
|
162
|
+
messaging_1.mablEventEmitter.log(error.message);
|
|
161
163
|
}
|
|
162
164
|
return browser;
|
|
163
165
|
}
|
|
@@ -197,7 +199,7 @@ function removeTempBrowserPreferencesDirectory(tempDirPath) {
|
|
|
197
199
|
}
|
|
198
200
|
}
|
|
199
201
|
async function createBrowser(browserWidth, browserHeight, headless, containerTesting, tempBrowserPreferencesDirectory, options) {
|
|
200
|
-
const { credentials, browserPath, disableIsolation, extraHttpHeaders, ignoreCertificateErrors, emulationConfig, enableExtensions, runnerType, loggerFunc, } = options || {};
|
|
202
|
+
const { credentials, browserPath, disableIsolation, extraHttpHeaders, ignoreCertificateErrors, emulationConfig, enableExtensions, runnerType, loggerFunc, resourcesDirectoryOverride, } = options || {};
|
|
201
203
|
const chromePath = browserPath !== null && browserPath !== void 0 ? browserPath : findChrome();
|
|
202
204
|
if (!chromePath.length) {
|
|
203
205
|
messaging_1.mablEventEmitter.log(chalk.yellow('Could not find a local install of Chrome to use, please ensure you have it installed and try again'));
|
|
@@ -213,8 +215,8 @@ async function createBrowser(browserWidth, browserHeight, headless, containerTes
|
|
|
213
215
|
}
|
|
214
216
|
disableFeaturesFlags.push('site-per-process');
|
|
215
217
|
launchArgs.push(`--disable-features=${disableFeaturesFlags.join(',')}`);
|
|
216
|
-
const fakeMicrophoneMedia = resourceUtil_1.findResource('media/mabl_test_audio.wav');
|
|
217
|
-
const fakeWebcamMedia = resourceUtil_1.findResource('media/mabl_test_pattern.y4m');
|
|
218
|
+
const fakeMicrophoneMedia = resourceUtil_1.findResource('media/mabl_test_audio.wav', resourcesDirectoryOverride);
|
|
219
|
+
const fakeWebcamMedia = resourceUtil_1.findResource('media/mabl_test_pattern.y4m', resourcesDirectoryOverride);
|
|
218
220
|
const defaultDeviceDescriptor = addLaunchArgs(launchArgs, browserWidth, browserHeight, fakeMicrophoneMedia, fakeWebcamMedia, ignoreCertificateErrors, emulationConfig);
|
|
219
221
|
let ignoreDefaultArgs;
|
|
220
222
|
if (enableExtensions) {
|
|
@@ -648,6 +650,10 @@ function calculateTotalTimeSeconds(startTimeMillis, endTimeMillis) {
|
|
|
648
650
|
return (endTimeMillis - startTimeMillis) / 1000;
|
|
649
651
|
}
|
|
650
652
|
exports.calculateTotalTimeSeconds = calculateTotalTimeSeconds;
|
|
653
|
+
function milliSecondsToSeconds(timeMs) {
|
|
654
|
+
return Math.round((timeMs !== null && timeMs !== void 0 ? timeMs : 0) / 100) / 10;
|
|
655
|
+
}
|
|
656
|
+
exports.milliSecondsToSeconds = milliSecondsToSeconds;
|
|
651
657
|
function logTestInfoIfPresent(description, infoArg) {
|
|
652
658
|
if (infoArg !== undefined) {
|
|
653
659
|
messaging_1.mablEventEmitter.log(chalk.cyan(description, chalk.magenta(infoArg.toString())));
|