@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.
@@ -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 = (_b = options.debugLogger) !== null && _b !== void 0 ? _b : logUtils_1.logInternal;
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
- makeGetRequest(path) {
91
- return this.retryWrappedRequest(`makeGetRequest('${path}')`, () => this.getRequest(path));
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: (_b = (_a = this.retryConfig) === null || _a === void 0 ? void 0 : _a.retryCount) !== null && _b !== void 0 ? _b : DEFAULT_RETRIES,
165
- minTimeout: (_d = (_c = this.retryConfig) === null || _c === void 0 ? void 0 : _c.minRetryIntervalMillis) !== null && _d !== void 0 ? _d : DEFAULT_MIN_RETRY_INTERVAL_MILLISECONDS,
166
- maxTimeout: (_f = (_e = this.retryConfig) === null || _e === void 0 ? void 0 : _e.maxRetryIntervalMillis) !== null && _f !== void 0 ? _f : DEFAULT_MAX_RETRY_INTERVAL_MILLISECONDS,
167
- maxRetryTime: (_h = (_g = this.retryConfig) === null || _g === void 0 ? void 0 : _g.maxRetryTimeMillis) !== null && _h !== void 0 ? _h : DEFAULT_MAX_TOTAL_RETRY_TIME_MILLISECONDS,
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
- const axiosError = error;
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;
@@ -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 logUtils_1 = require("../util/logUtils");
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 getRunnerTypeFromFeatureFlag(organizationId) {
691
- var _a, _b;
692
- if (organizationId === undefined) {
693
- organizationId = (_a = (await this.getSelf()).preferences) === null || _a === void 0 ? void 0 : _a.default_workspace_id;
694
- }
695
- if (organizationId !== undefined) {
696
- try {
697
- const workspace = await this.getWorkspace(organizationId);
698
- const account = await this.getAccount(workspace.account_id);
699
- return ((_b = account.effective_features) === null || _b === void 0 ? void 0 : _b.includes(PLAYWRIGHT_FEATURE_FLAG)) ? runnerType_1.RunnerType.Playwright
700
- : runnerType_1.RunnerType.Puppeteer;
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 runnerType = await (await mablApiClientFactory_1.MablApiClientFactory.createApiClient()).getRunnerTypeFromFeatureFlag(test.organization_id);
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())));