@mablhq/mabl-cli 1.13.14 → 1.13.21
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 +53 -16
- package/api/mablApiClient.js +1 -1
- package/browserLauncher/playwrightBrowserLauncher/playwrightFrame.js +10 -0
- package/execution/index.js +1 -1
- package/package.json +3 -3
- package/popupDismissal/index.js +20 -13
- package/resources/popupDismissal.js +1 -1
- package/util/actionabilityUtil.js +29 -8
- package/util/logUtils.js +2 -2
package/api/basicApiClient.js
CHANGED
|
@@ -28,9 +28,13 @@ const httpUtil_1 = require("../util/httpUtil");
|
|
|
28
28
|
const axios_1 = __importDefault(require("axios"));
|
|
29
29
|
const os = __importStar(require("os"));
|
|
30
30
|
const async_retry_1 = __importDefault(require("async-retry"));
|
|
31
|
+
const logUtils_1 = require("../util/logUtils");
|
|
31
32
|
const asyncUtil_1 = require("../util/asyncUtil");
|
|
32
33
|
const MABL_ENTITY_VERSION_HEADER = 'x-mabl-entity-version';
|
|
33
|
-
const
|
|
34
|
+
const DEFAULT_RETRYABLE_REQUEST_TIMEOUT_MILLISECONDS = 60000;
|
|
35
|
+
const DEFAULT_NONRETRYABLE_REQUEST_TIMEOUT_MILLISECONDS = 600000;
|
|
36
|
+
const DEFAULT_RETRIES = 5;
|
|
37
|
+
const DEFAULT_MAX_TOTAL_RETRY_TIME_MILLISECONDS = DEFAULT_RETRYABLE_REQUEST_TIMEOUT_MILLISECONDS * DEFAULT_RETRIES;
|
|
34
38
|
const DEFAULT_MIN_RETRY_TIMEOUT_MILLISECONDS = 100;
|
|
35
39
|
const DEFAULT_MAX_RETRY_TIMEOUT_MILLISECONDS = 1000;
|
|
36
40
|
var AuthType;
|
|
@@ -40,10 +44,12 @@ var AuthType;
|
|
|
40
44
|
})(AuthType = exports.AuthType || (exports.AuthType = {}));
|
|
41
45
|
class BasicApiClient {
|
|
42
46
|
constructor(options) {
|
|
47
|
+
var _a, _b;
|
|
43
48
|
const config = httpUtil_1.axiosProxyConfig({
|
|
44
49
|
sslVerify: options.sslVerify,
|
|
45
50
|
proxyHost: options.proxyUrl,
|
|
46
51
|
});
|
|
52
|
+
config.timeout = (_a = options.requestTimeoutMillis) !== null && _a !== void 0 ? _a : DEFAULT_RETRYABLE_REQUEST_TIMEOUT_MILLISECONDS;
|
|
47
53
|
switch (options.authType) {
|
|
48
54
|
case AuthType.ApiKey:
|
|
49
55
|
config.auth = {
|
|
@@ -68,23 +74,33 @@ class BasicApiClient {
|
|
|
68
74
|
if (options.userAgentOverride) {
|
|
69
75
|
config.headers[httpUtil_1.USER_AGENT_HEADER] = options.userAgentOverride;
|
|
70
76
|
}
|
|
77
|
+
this.httpRequestConfig = config;
|
|
71
78
|
this.httpClient = axios_1.default.create(config);
|
|
72
79
|
this.retryConfig = options.retryConfig;
|
|
80
|
+
this.debugLogger = (_b = options.debugLogger) !== null && _b !== void 0 ? _b : logUtils_1.logInternal;
|
|
73
81
|
}
|
|
74
|
-
|
|
75
|
-
|
|
82
|
+
getNonRetryableRequestConfig(override) {
|
|
83
|
+
const overrideWithTimeout = { ...(override !== null && override !== void 0 ? override : {}) };
|
|
84
|
+
if (!overrideWithTimeout.timeout) {
|
|
85
|
+
overrideWithTimeout.timeout =
|
|
86
|
+
DEFAULT_NONRETRYABLE_REQUEST_TIMEOUT_MILLISECONDS;
|
|
87
|
+
}
|
|
88
|
+
return { ...this.httpRequestConfig, ...overrideWithTimeout };
|
|
89
|
+
}
|
|
90
|
+
makeGetRequest(path) {
|
|
91
|
+
return this.retryWrappedRequest(`makeGetRequest('${path}')`, () => this.getRequest(path));
|
|
76
92
|
}
|
|
77
93
|
async getRequest(path) {
|
|
78
|
-
const response = await this.httpClient.get(path);
|
|
94
|
+
const response = await this.debugRequest('GET', path, () => this.httpClient.get(path));
|
|
79
95
|
BasicApiClient.checkResponseStatusCode(response);
|
|
80
96
|
return response.data;
|
|
81
97
|
}
|
|
82
|
-
|
|
83
|
-
return this.retryWrappedRequest(
|
|
98
|
+
makeGetRequestWithETag(path) {
|
|
99
|
+
return this.retryWrappedRequest(`makeGetRequestWithETag('${path}')`, () => this.getRequestWithETag(path));
|
|
84
100
|
}
|
|
85
101
|
async getRequestWithETag(path) {
|
|
86
102
|
var _a;
|
|
87
|
-
const response = await this.httpClient.get(path);
|
|
103
|
+
const response = await this.debugRequest('GET', path, () => this.httpClient.get(path));
|
|
88
104
|
BasicApiClient.checkResponseStatusCode(response);
|
|
89
105
|
const headers = response.headers;
|
|
90
106
|
const result = response.data;
|
|
@@ -95,42 +111,63 @@ class BasicApiClient {
|
|
|
95
111
|
return { ...result, entity_version: versionHeader };
|
|
96
112
|
}
|
|
97
113
|
async makePostRequest(path, requestBody, requestConfig) {
|
|
98
|
-
const response = await this.httpClient.post(path, requestBody, requestConfig);
|
|
114
|
+
const response = await this.debugRequest('POST', path, () => this.httpClient.post(path, requestBody, this.getNonRetryableRequestConfig(requestConfig)));
|
|
99
115
|
BasicApiClient.checkResponseStatusCode(response);
|
|
100
116
|
return response.data;
|
|
101
117
|
}
|
|
102
118
|
async makePutRequest(path, requestBody) {
|
|
103
|
-
const response = await this.httpClient.put(path, requestBody);
|
|
119
|
+
const response = await this.debugRequest('PUT', path, () => this.httpClient.put(path, requestBody, this.getNonRetryableRequestConfig()));
|
|
104
120
|
BasicApiClient.checkResponseStatusCode(response);
|
|
105
121
|
return response.data;
|
|
106
122
|
}
|
|
107
|
-
|
|
108
|
-
return this.retryWrappedRequest(
|
|
123
|
+
makeDeleteRequest(path) {
|
|
124
|
+
return this.retryWrappedRequest(`makeDeleteRequest('${path}')`, () => this.deleteRequest(path));
|
|
109
125
|
}
|
|
110
126
|
async deleteRequest(path) {
|
|
111
|
-
const response = await this.
|
|
127
|
+
const response = await this.debugRequest('DELETE', path, () => this.deleteRequest(path));
|
|
112
128
|
BasicApiClient.checkResponseStatusCode(response);
|
|
113
129
|
return response.data;
|
|
114
130
|
}
|
|
115
131
|
async makePatchRequest(path, requestBody, ifMatch) {
|
|
116
132
|
const extraConfig = ifMatch ? { headers: { 'If-Match': ifMatch } } : {};
|
|
117
|
-
const response = await this.httpClient.patch(path, requestBody, extraConfig);
|
|
133
|
+
const response = await this.debugRequest('PATCH', path, () => this.httpClient.patch(path, requestBody, extraConfig));
|
|
118
134
|
BasicApiClient.checkResponseStatusCode(response);
|
|
119
135
|
return response.data;
|
|
120
136
|
}
|
|
137
|
+
async debugRequest(method, path, request) {
|
|
138
|
+
const startTimeMillis = Date.now();
|
|
139
|
+
let responseCode;
|
|
140
|
+
let error;
|
|
141
|
+
try {
|
|
142
|
+
this.debugLogger(`API Client: Sending ${method} ${path}`);
|
|
143
|
+
const response = await request();
|
|
144
|
+
responseCode = response.status;
|
|
145
|
+
return response;
|
|
146
|
+
}
|
|
147
|
+
catch (e) {
|
|
148
|
+
error = e;
|
|
149
|
+
throw e;
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
this.debugLogger(`API Client: ${method} ${path} ${error ? 'failed' : 'completed'} in ${Date.now() - startTimeMillis}ms with ${responseCode !== null && responseCode !== void 0 ? responseCode : error}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
121
155
|
static checkResponseStatusCode(response) {
|
|
122
156
|
const statusCode = response.status;
|
|
123
157
|
if (!statusCode || statusCode >= 400) {
|
|
124
158
|
throw new ApiError_1.ApiError(`[${statusCode} - ${response.statusText}]`, statusCode);
|
|
125
159
|
}
|
|
126
160
|
}
|
|
127
|
-
retryWrappedRequest(requestFunc) {
|
|
161
|
+
retryWrappedRequest(description, requestFunc) {
|
|
128
162
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
129
163
|
const retryOptions = {
|
|
130
|
-
retries: (_b = (_a = this.retryConfig) === null || _a === void 0 ? void 0 : _a.retryCount) !== null && _b !== void 0 ? _b :
|
|
164
|
+
retries: (_b = (_a = this.retryConfig) === null || _a === void 0 ? void 0 : _a.retryCount) !== null && _b !== void 0 ? _b : DEFAULT_RETRIES,
|
|
131
165
|
minTimeout: (_d = (_c = this.retryConfig) === null || _c === void 0 ? void 0 : _c.minTimeoutMillis) !== null && _d !== void 0 ? _d : DEFAULT_MIN_RETRY_TIMEOUT_MILLISECONDS,
|
|
132
166
|
maxTimeout: (_f = (_e = this.retryConfig) === null || _e === void 0 ? void 0 : _e.maxTimeoutMillis) !== null && _f !== void 0 ? _f : DEFAULT_MAX_RETRY_TIMEOUT_MILLISECONDS,
|
|
133
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,
|
|
168
|
+
onRetry: (error) => {
|
|
169
|
+
this.debugLogger(`Retrying failed API request "${description}"`, error);
|
|
170
|
+
},
|
|
134
171
|
forever: false,
|
|
135
172
|
};
|
|
136
173
|
return asyncUtil_1.promiseWithTimeout(async_retry_1.default(async (bail) => {
|
|
@@ -152,7 +189,7 @@ class BasicApiClient {
|
|
|
152
189
|
return {};
|
|
153
190
|
}
|
|
154
191
|
}
|
|
155
|
-
}, retryOptions),
|
|
192
|
+
}, retryOptions), retryOptions.maxRetryTime + retryOptions.maxTimeout, 'Retryable API request');
|
|
156
193
|
}
|
|
157
194
|
}
|
|
158
195
|
exports.BasicApiClient = BasicApiClient;
|
package/api/mablApiClient.js
CHANGED
|
@@ -127,7 +127,7 @@ class MablApiClient extends basicApiClient_1.BasicApiClient {
|
|
|
127
127
|
}
|
|
128
128
|
async createDeployment(deployment) {
|
|
129
129
|
try {
|
|
130
|
-
return await this.makePostRequest(`${env_1.BASE_API_URL}/deployments`, deployment);
|
|
130
|
+
return await this.makePostRequest(`${env_1.BASE_API_URL}/deployments`, deployment, { timeout: 0 });
|
|
131
131
|
}
|
|
132
132
|
catch (error) {
|
|
133
133
|
throw toApiError(`Failed to create deployment`, error);
|
|
@@ -22,6 +22,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
22
22
|
exports.PlaywrightFrame = void 0;
|
|
23
23
|
const browserLauncher_1 = require("../browserLauncher");
|
|
24
24
|
const playwright = __importStar(require("@playwright/test"));
|
|
25
|
+
const types_1 = require("../types");
|
|
25
26
|
const utils_1 = require("../utils");
|
|
26
27
|
const playwrightHttpResponse_1 = require("./playwrightHttpResponse");
|
|
27
28
|
const playwrightDom_1 = require("./playwrightDom");
|
|
@@ -117,7 +118,16 @@ class PlaywrightFrame extends browserLauncher_1.Frame {
|
|
|
117
118
|
}
|
|
118
119
|
async goto(url, options) {
|
|
119
120
|
try {
|
|
121
|
+
const waitForNetworkIdle = (options === null || options === void 0 ? void 0 : options.waitUntil) === types_1.LifecycleEvent.NetworkIdle;
|
|
122
|
+
if (options && waitForNetworkIdle) {
|
|
123
|
+
options.waitUntil = types_1.LifecycleEvent.Load;
|
|
124
|
+
}
|
|
120
125
|
const response = await this.frame.goto(url, options);
|
|
126
|
+
if (waitForNetworkIdle) {
|
|
127
|
+
await this.frame.waitForLoadState('networkidle', {
|
|
128
|
+
timeout: types_1.DefaultTimeouts.quickActionTimeoutMs,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
121
131
|
return utils_1.mapIfNotNull(response, (response) => new playwrightHttpResponse_1.PlaywrightHttpResponse(this.parentPage, response));
|
|
122
132
|
}
|
|
123
133
|
catch (e) {
|