@testim/testim-cli 3.243.0 → 3.246.0
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/chromiumInstaller.js +92 -0
- package/cli.js +89 -87
- package/cliAgentMode.js +39 -114
- package/commons/chromedriverWrapper.js +4 -3
- package/commons/featureFlags.js +1 -0
- package/commons/getSessionPlayerRequire.js +2 -1
- package/commons/httpRequestCounters.test.js +9 -9
- package/commons/npmWrapper.js +3 -3
- package/commons/npmWrapper.test.js +1 -1
- package/commons/prepareRunner.js +2 -0
- package/commons/socket/baseSocketServiceSocketIO.js +2 -2
- package/commons/testimAnalytics.js +8 -3
- package/commons/testimServicesApi.js +45 -39
- package/errors.js +2 -1
- package/npm-shrinkwrap.json +595 -494
- package/package.json +2 -2
- package/player/WebDriverHttpRequest.js +45 -37
- package/player/chromeLauncherTestPlayer.js +2 -2
- package/player/services/playbackTimeoutCalculator.js +5 -1
- package/player/stepActions/RefreshStepAction.js +2 -4
- package/player/stepActions/inputFileStepAction.js +6 -2
- package/player/stepActions/scripts/doClick.js +3 -1
- package/player/stepActions/scripts/html5dragAction.js +3 -1
- package/player/stepActions/scripts/html5dragActionV2.js +3 -1
- package/player/stepActions/scripts/runCode.js +23 -6
- package/player/stepActions/scripts/scroll.js +1 -6
- package/player/stepActions/scripts/setText.js +4 -1
- package/player/stepActions/sfdcStepAction.js +27 -0
- package/player/stepActions/stepActionRegistrar.js +12 -0
- package/player/utils/screenshotUtils.js +2 -2
- package/player/utils/windowUtils.js +3 -3
- package/player/webdriver.js +51 -52
- package/runOptions.js +3 -1
- package/runner.js +44 -41
- package/services/lambdatestService.js +2 -2
- package/services/lambdatestService.test.js +2 -1
- package/testRunHandler.js +7 -3
- package/testRunStatus.js +2 -1
- package/utils.js +56 -21
- package/utils.test.js +27 -1
- package/workers/BaseWorker.js +9 -7
- package/workers/BaseWorker.test.js +11 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testim/testim-cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.246.0",
|
|
4
4
|
"description": "Command line interface for running Testing on your CI",
|
|
5
5
|
"author": "Oren Rubin",
|
|
6
6
|
"contributors": [{
|
|
@@ -57,7 +57,6 @@
|
|
|
57
57
|
"appium-dom-utils": "1.0.6",
|
|
58
58
|
"archiver": "5.3.0",
|
|
59
59
|
"bluebird": "3.7.2",
|
|
60
|
-
"bluebird-retry": "0.11.0",
|
|
61
60
|
"body-parser": "1.19.1",
|
|
62
61
|
"chalk": "4.1.2",
|
|
63
62
|
"chrome-launcher": "0.15.0",
|
|
@@ -87,6 +86,7 @@
|
|
|
87
86
|
"npm": "8.3.0",
|
|
88
87
|
"object-hash": "3.0.0",
|
|
89
88
|
"ora": "5.4.1",
|
|
89
|
+
"p-retry": "4.6.2",
|
|
90
90
|
"pako": "1.0.11",
|
|
91
91
|
"portfinder": "1.0.28",
|
|
92
92
|
"promise-queue": "2.2.5",
|
|
@@ -4,8 +4,8 @@ const _ = require('lodash');
|
|
|
4
4
|
const httpRequest = require('../commons/httpRequest');
|
|
5
5
|
const utils = require('../utils');
|
|
6
6
|
const SeleniumProtocolError = require('./SeleniumProtocolError');
|
|
7
|
-
const {SELENIUM_STATUS_CODES} = require('./constants');
|
|
8
|
-
const logger = require('
|
|
7
|
+
const { SELENIUM_STATUS_CODES } = require('./constants');
|
|
8
|
+
const logger = require('../commons/logger').getLogger('WebDriverHttpRequest');
|
|
9
9
|
|
|
10
10
|
function isSuccessfulResponse(body, statusCode) {
|
|
11
11
|
/**
|
|
@@ -56,37 +56,37 @@ class WebDriverHttpRequest {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
handleFailedStatus(requestId, response, err = {}) {
|
|
59
|
-
const {body, statusCode, headers, text} = response;
|
|
59
|
+
const { body, statusCode, headers, text } = response;
|
|
60
60
|
const resBody = _.isEmpty(body) && text ? text : body;
|
|
61
61
|
/**
|
|
62
62
|
* in Appium you find sometimes more exact error messages in origValue
|
|
63
63
|
*/
|
|
64
64
|
if (resBody && resBody.value && typeof resBody.value.origValue === 'string' && typeof resBody.value.message === 'string') {
|
|
65
|
-
resBody.value.message +=
|
|
65
|
+
resBody.value.message += ` ${resBody.value.origValue}`;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
if (resBody && typeof resBody === 'string') {
|
|
69
|
-
throw new SeleniumProtocolError(resBody, {requestId});
|
|
69
|
+
throw new SeleniumProtocolError(resBody, { requestId });
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
if (resBody && resBody.value) {
|
|
73
73
|
const errorCode = SELENIUM_STATUS_CODES[resBody.status] || (resBody.value && SELENIUM_STATUS_CODES[resBody.value.error]) || SELENIUM_STATUS_CODES[-1];
|
|
74
|
-
|
|
74
|
+
const error = {
|
|
75
75
|
type: errorCode ? errorCode.id : 'unknown',
|
|
76
76
|
message: errorCode ? errorCode.message : 'unknown',
|
|
77
|
-
orgStatusMessage: resBody.value ? resBody.value.message : ''
|
|
77
|
+
orgStatusMessage: resBody.value ? resBody.value.message : '',
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
-
throw new SeleniumProtocolError(error, {requestId});
|
|
80
|
+
throw new SeleniumProtocolError(error, { requestId });
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
// IEServer webdriver bug where the error is put into the Allow header
|
|
84
84
|
// https://github.com/SeleniumHQ/selenium/issues/6828
|
|
85
85
|
if (statusCode === 405) {
|
|
86
86
|
const allowHeader = headers && headers.allow;
|
|
87
|
-
const
|
|
88
|
-
if (
|
|
89
|
-
throw
|
|
87
|
+
const _err = new SeleniumProtocolError(allowHeader, { requestId });
|
|
88
|
+
if (_err.message.match(/Command not found/)) {
|
|
89
|
+
throw _err;
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -94,12 +94,12 @@ class WebDriverHttpRequest {
|
|
|
94
94
|
status: -1,
|
|
95
95
|
type: err.code || 'ECONNREFUSED',
|
|
96
96
|
orgStatusMessage: err.rawResponse || err.message,
|
|
97
|
-
message: err.rawResponse || "Couldn't connect to selenium server"
|
|
98
|
-
}, {requestId});
|
|
97
|
+
message: err.rawResponse || "Couldn't connect to selenium server",
|
|
98
|
+
}, { requestId });
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
processHttpOnSuccess(response, requestId) {
|
|
102
|
-
const {body, statusCode} = response;
|
|
102
|
+
const { body, statusCode } = response;
|
|
103
103
|
if (isSuccessfulResponse(body, statusCode)) {
|
|
104
104
|
return body;
|
|
105
105
|
}
|
|
@@ -108,44 +108,49 @@ class WebDriverHttpRequest {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
processHttpOnError(err, requestId) {
|
|
111
|
-
const response = err && err.response || {};
|
|
111
|
+
const response = (err && err.response) || {};
|
|
112
112
|
return this.handleFailedStatus(requestId, response, err);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
httpPostRequest(path, body = {}) {
|
|
116
116
|
const requestId = utils.guid();
|
|
117
|
-
if (path ===
|
|
118
|
-
logger.info(
|
|
117
|
+
if (path === '/session') {
|
|
118
|
+
logger.info('POST REQUEST', { requestId, path, testResultId: this.testResultId });
|
|
119
119
|
} else {
|
|
120
|
-
logger.info(
|
|
120
|
+
logger.info('POST REQUEST', { requestId, path, body, testResultId: this.testResultId });
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
return httpRequest.postFullRes(`${this.gridUrl}${path}`, body, this.headers, this.connectionRetryTimeout)
|
|
124
|
-
.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
124
|
+
.then(response => {
|
|
125
|
+
logger.info('POST RESPONSE', {
|
|
126
|
+
requestId,
|
|
127
|
+
path,
|
|
128
|
+
res: JSON.stringify(response.body),
|
|
129
|
+
testResultId: this.testResultId,
|
|
130
|
+
});
|
|
131
|
+
return response;
|
|
132
|
+
})
|
|
130
133
|
.catch(err => this.processHttpOnError(err, requestId))
|
|
131
134
|
.then((response) => this.processHttpOnSuccess(response, requestId));
|
|
132
135
|
}
|
|
133
136
|
|
|
134
137
|
httpGetRequest(path) {
|
|
135
138
|
const requestId = utils.guid();
|
|
136
|
-
logger.info(
|
|
139
|
+
logger.info('GET REQUEST', { requestId, path, testResultId: this.testResultId });
|
|
137
140
|
const query = {};
|
|
138
141
|
return httpRequest.getFullRes(`${this.gridUrl}${path}`, query, this.headers, this.connectionRetryTimeout)
|
|
139
|
-
.
|
|
140
|
-
if (_.endsWith(path,
|
|
141
|
-
|
|
142
|
+
.then(response => {
|
|
143
|
+
if (_.endsWith(path, '/screenshot')) {
|
|
144
|
+
logger.info('GET RESPONSE', { requestId, path, testResultId: this.testResultId });
|
|
145
|
+
return response;
|
|
142
146
|
}
|
|
143
|
-
logger.info(
|
|
147
|
+
logger.info('GET RESPONSE', {
|
|
144
148
|
requestId,
|
|
145
149
|
path,
|
|
146
150
|
res: JSON.stringify(response.body),
|
|
147
|
-
testResultId: this.testResultId
|
|
151
|
+
testResultId: this.testResultId,
|
|
148
152
|
});
|
|
153
|
+
return response;
|
|
149
154
|
})
|
|
150
155
|
.catch(err => this.processHttpOnError(err, requestId))
|
|
151
156
|
.then((response) => this.processHttpOnSuccess(response, requestId));
|
|
@@ -153,14 +158,17 @@ class WebDriverHttpRequest {
|
|
|
153
158
|
|
|
154
159
|
httpDeleteRequest(path) {
|
|
155
160
|
const requestId = utils.guid();
|
|
156
|
-
logger.info(
|
|
161
|
+
logger.info('DELETE REQUEST', { requestId, path, testResultId: this.testResultId });
|
|
157
162
|
return httpRequest.deleteFullRes(`${this.gridUrl}${path}`, undefined, this.headers, this.connectionRetryTimeout)
|
|
158
|
-
.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
163
|
+
.then(response => {
|
|
164
|
+
logger.info('DELETE RESPONSE', {
|
|
165
|
+
requestId,
|
|
166
|
+
path,
|
|
167
|
+
res: JSON.stringify(response.body),
|
|
168
|
+
testResultId: this.testResultId,
|
|
169
|
+
});
|
|
170
|
+
return response;
|
|
171
|
+
})
|
|
164
172
|
.catch(err => this.processHttpOnError(err, requestId))
|
|
165
173
|
.then((response) => this.processHttpOnSuccess(response, requestId));
|
|
166
174
|
}
|
|
@@ -23,8 +23,8 @@ class LauncherDriver {
|
|
|
23
23
|
this.chrome.process.once('exit', () => { this._isAlive = false; });
|
|
24
24
|
this.chrome.process.once('close', () => { this._isAlive = false; });
|
|
25
25
|
this._isAlive = true;
|
|
26
|
-
const
|
|
27
|
-
await this.cdpTestRunner.initSession(
|
|
26
|
+
const webSocketDebuggerUrl = await utils.getCdpAddressForHost(`localhost:${this.chrome.port}`);
|
|
27
|
+
await this.cdpTestRunner.initSession(webSocketDebuggerUrl);
|
|
28
28
|
|
|
29
29
|
registerExitHook(() => this.chrome.kill());
|
|
30
30
|
}
|
|
@@ -4,6 +4,7 @@ const _ = require('lodash');
|
|
|
4
4
|
|
|
5
5
|
const COMMUNICATION_BUFFER_TIME = 1000;
|
|
6
6
|
const UI_VERIFICATION_STEPS = ['simple-ui-verification', 'wait-for-simple-ui-verification'];
|
|
7
|
+
const FULL_TIMEOUT_STEP_TYPES = [...UI_VERIFICATION_STEPS, 'custom-validation', 'sfdc-step-login'];
|
|
7
8
|
|
|
8
9
|
class PlaybackTimeoutCalculator {
|
|
9
10
|
constructor(isDebuggerConnected) {
|
|
@@ -41,7 +42,7 @@ class PlaybackTimeoutCalculator {
|
|
|
41
42
|
};
|
|
42
43
|
stepPlayback.setStartTimestamp();
|
|
43
44
|
const totalStepTime = this.getTotalStepRunTime(stepPlayback);
|
|
44
|
-
const currentRetryTimes =
|
|
45
|
+
const currentRetryTimes = FULL_TIMEOUT_STEP_TYPES.includes(stepPlayback.stepType) ? [totalStepTime] : getRetryTimeoutSuggestions(totalStepTime);
|
|
45
46
|
this.resetStepVariables(totalStepTime, currentRetryTimes);
|
|
46
47
|
stepPlayback.context.data.maxTotalStepTime = totalStepTime;
|
|
47
48
|
}
|
|
@@ -61,6 +62,9 @@ class PlaybackTimeoutCalculator {
|
|
|
61
62
|
if (UI_VERIFICATION_STEPS.includes(stepPlayback.stepType)) {
|
|
62
63
|
fallbackTimeout = stepPlayback.context.config.applitoolsStepTimeout || HALF_HOUR_IN_MS;
|
|
63
64
|
}
|
|
65
|
+
if (stepPlayback.step.type.startsWith('sfdc-')) {
|
|
66
|
+
fallbackTimeout = stepPlayback.step.defaultTimeout;
|
|
67
|
+
}
|
|
64
68
|
return (stepPlayback.step.useStepTimeout && stepPlayback.step.stepTimeout) ? stepPlayback.step.stepTimeout : fallbackTimeout;
|
|
65
69
|
}
|
|
66
70
|
getTotalStepTimeLeftToPlay(stepPlayback, totalStepTime = this.totalStepTime) {
|
|
@@ -6,10 +6,8 @@ require('bluebird');
|
|
|
6
6
|
class RefreshStepAction extends StepAction {
|
|
7
7
|
execute() {
|
|
8
8
|
return this.driver.reloadTab()
|
|
9
|
-
.
|
|
10
|
-
.catch(error => {
|
|
11
|
-
return { success: false, reason: error.message };
|
|
12
|
-
});
|
|
9
|
+
.then(() => ({ success: true }))
|
|
10
|
+
.catch(error => ({ success: false, reason: error.message }));
|
|
13
11
|
}
|
|
14
12
|
}
|
|
15
13
|
|
|
@@ -86,18 +86,22 @@ class InputFileStepAction extends StepAction {
|
|
|
86
86
|
const target = this.context.data[this.step.targetId || 'targetId'];
|
|
87
87
|
const overrideAzureStorageUrl = featureFlagService.flags.overrideAzureStorageUrl.isEnabled();
|
|
88
88
|
const useJsInputCodeInSafari = featureFlagService.flags.useJsInputCodeInSafari.isEnabled();
|
|
89
|
+
const useJsInputCodeInFirefox = featureFlagService.flags.useJsInputCodeInFirefox.isEnabled();
|
|
89
90
|
const downloadToBase64 = featureFlagService.flags.downloadToBase64.isEnabled();
|
|
90
91
|
|
|
91
92
|
let fileUrls = await utils.addTokenToFileUrl(this.context.project.id, this.step.fileUrls, this.stepActionUtils.testimServicesApi, overrideAzureStorageUrl, logger);
|
|
92
93
|
|
|
94
|
+
|
|
95
|
+
const isSafariJsInputCode = this.driver.isSafari() && (useJsInputCodeInSafari || fileUrls.length > 1);
|
|
96
|
+
const isFirefoxJsInputCode = this.driver.isFirefox() && (useJsInputCodeInFirefox || fileUrls.length > 1);
|
|
97
|
+
|
|
93
98
|
if (downloadToBase64) {
|
|
94
99
|
fileUrls = await Promise.all(fileUrls.map(async ({ name, url }) => {
|
|
95
100
|
const res = await download(url);
|
|
96
101
|
return { name, url: `data:${res.type};base64,${Buffer.from(res.body).toString('base64')}` };
|
|
97
102
|
}));
|
|
98
103
|
}
|
|
99
|
-
|
|
100
|
-
if (this.driver.isSafari() && (useJsInputCodeInSafari || fileUrls.length > 1)) {
|
|
104
|
+
if (isSafariJsInputCode || isFirefoxJsInputCode) {
|
|
101
105
|
await this.driver.executeJSWithArray(`
|
|
102
106
|
const getLocatedElement = ${codeSnippets.getLocatedElementCode};
|
|
103
107
|
const downloadAndUploadFile = ${downloadAndUpload()};
|
|
@@ -3,23 +3,40 @@
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
5
|
const runCode = function (eventData, preCompiledCode) {
|
|
6
|
+
typeof Object.tstassign !== 'function' && (Object.tstassign = function (n, t) {
|
|
7
|
+
'use strict';
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
if (n == null) throw new TypeError('Cannot convert undefined or null to object'); for (var r = Object(n), e = 1; e < arguments.length; e++) { var o = arguments[e]; if (o != null) for (var a in o)Object.prototype.hasOwnProperty.call(o, a) && (r[a] = o[a]); } return r;
|
|
10
|
+
});
|
|
11
|
+
Object.assign = typeof Object.assign !== 'function' ? Object.tstassign : Object.assign;
|
|
9
12
|
|
|
10
13
|
function appendToStorage(name, data) {
|
|
11
14
|
const sessionItem = 'data-testim-' + name;
|
|
15
|
+
|
|
16
|
+
const nativeFuncErrMsg = 'Native sessionStorage is not available';
|
|
17
|
+
function isNativeFunction(fn) {
|
|
18
|
+
if (!fn || !fn.toString) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return fn.toString().indexOf('[native code]') > -1;
|
|
22
|
+
}
|
|
12
23
|
try {
|
|
24
|
+
if (![window.sessionStorage.setItem, window.sessionStorage.getItem].every(isNativeFunction)) {
|
|
25
|
+
throw new Error(nativeFuncErrMsg);
|
|
26
|
+
}
|
|
13
27
|
const oldData = JSON.parse(window.sessionStorage.getItem(sessionItem) || '{}');
|
|
14
28
|
const newData = Object.tstassign({}, oldData, data);
|
|
15
29
|
window.sessionStorage.setItem(sessionItem, JSON.stringify(newData));
|
|
16
30
|
} catch (err) {
|
|
17
|
-
// any
|
|
31
|
+
// any variation QuotaExceededError from browsers
|
|
18
32
|
const isQuotaExceededError = err.message.toLowerCase().indexOf('quota') > -1;
|
|
33
|
+
const isNativeFunctionError = err.message === nativeFuncErrMsg;
|
|
34
|
+
|
|
19
35
|
if (err.message.indexOf('sessionStorage') > -1 || // Chrome + Firefox
|
|
20
36
|
err.message.indexOf('The operation is insecure') > -1 || // Safari
|
|
21
37
|
err.message.indexOf('SecurityError') > -1 || // Edge
|
|
22
|
-
isQuotaExceededError
|
|
38
|
+
isQuotaExceededError ||
|
|
39
|
+
isNativeFunctionError
|
|
23
40
|
) {
|
|
24
41
|
var storage = document.head.querySelector('#testim-storage-backup');
|
|
25
42
|
if (!storage) {
|
|
@@ -30,13 +47,13 @@ const runCode = function (eventData, preCompiledCode) {
|
|
|
30
47
|
const oldData = JSON.parse(storage.getAttribute(sessionItem) || '{}');
|
|
31
48
|
const newData = Object.tstassign({}, oldData, data);
|
|
32
49
|
storage.setAttribute(sessionItem, JSON.stringify(newData));
|
|
33
|
-
if (isQuotaExceededError) {
|
|
50
|
+
if (isQuotaExceededError || isNativeFunctionError) {
|
|
34
51
|
try {
|
|
35
52
|
window.sessionStorage.removeItem(sessionItem);
|
|
36
53
|
} catch (e) {
|
|
37
54
|
// Prevents future retries from looking in sessionStorage with old data
|
|
38
55
|
}
|
|
39
|
-
window.TSTA.useFallbackStorage = true;
|
|
56
|
+
(window.TSTA = window.TSTA || {}).useFallbackStorage = true;
|
|
40
57
|
}
|
|
41
58
|
return;
|
|
42
59
|
}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
/* eslint-disable no-var */
|
|
3
|
-
/* eslint-disable no-redeclare */
|
|
4
|
-
/* eslint-disable object-shorthand */
|
|
5
|
-
/* eslint-disable one-var */
|
|
6
|
-
/* eslint-disable operator-linebreak */
|
|
1
|
+
/* globals getLocatedElement, elementScrollTo */
|
|
7
2
|
|
|
8
3
|
'use strict';
|
|
9
4
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const StepAction = require('./stepAction');
|
|
2
|
+
const { sfdc } = require('../../commons/getSessionPlayerRequire');
|
|
3
|
+
|
|
4
|
+
class SfdcStepAction extends StepAction {
|
|
5
|
+
async performAction() {
|
|
6
|
+
const page = sfdc.sfdcNewSePage(this.driver);
|
|
7
|
+
try {
|
|
8
|
+
const actions = this.context.sfdcTestActions;
|
|
9
|
+
if (actions === undefined) {
|
|
10
|
+
throw new Error('No test actions were compiled');
|
|
11
|
+
}
|
|
12
|
+
await sfdc.sfdcExecute(page, actions);
|
|
13
|
+
return { success: true };
|
|
14
|
+
} catch (err) {
|
|
15
|
+
return {
|
|
16
|
+
success: false,
|
|
17
|
+
reason: err.reason || err.message,
|
|
18
|
+
exception: err,
|
|
19
|
+
shouldRetry: false, // TODO - check this. Our (bFormat) steps are probably not retryable?
|
|
20
|
+
};
|
|
21
|
+
} finally {
|
|
22
|
+
page.releaseObjects();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = SfdcStepAction;
|
|
@@ -27,6 +27,7 @@ const CliJsStepAction = require('./cliJsStepAction');
|
|
|
27
27
|
const CliConditionStepAction = require('./cliConditionStepAction');
|
|
28
28
|
const NodePackageStepAction = require('./nodePackageStepAction');
|
|
29
29
|
const ExtensionOnlyStepAction = require('./extensionOnlyStepAction');
|
|
30
|
+
const SfdcStepAction = require('./sfdcStepAction');
|
|
30
31
|
|
|
31
32
|
function register(stepActionByType, stepActionFactory) {
|
|
32
33
|
Object.keys(stepActionByType).forEach(type => {
|
|
@@ -82,6 +83,17 @@ module.exports = function (driver, stepActionFactory, runMode) {
|
|
|
82
83
|
'email-code-step': JsCodeStepAction,
|
|
83
84
|
'cli-email-code-step': CliJsStepAction,
|
|
84
85
|
'tdk-hybrid': TdkHybridStepAction,
|
|
86
|
+
|
|
87
|
+
'sfdc-step-login': SfdcStepAction,
|
|
88
|
+
'sfdc-step-logout': SfdcStepAction,
|
|
89
|
+
'sfdc-step-sobjectcreate': SfdcStepAction,
|
|
90
|
+
'sfdc-step-sobjectdelete': SfdcStepAction,
|
|
91
|
+
'sfdc-step-findrecord': SfdcStepAction,
|
|
92
|
+
'sfdc-step-quickaction': SfdcStepAction,
|
|
93
|
+
'sfdc-step-edit': SfdcStepAction,
|
|
94
|
+
'sfdc-step-sobjectvalidate': SfdcStepAction,
|
|
95
|
+
'sfdc-step-launchapp': SfdcStepAction,
|
|
96
|
+
'sfdc-step-closeconsoletabs': SfdcStepAction,
|
|
85
97
|
};
|
|
86
98
|
|
|
87
99
|
register(STEP_ACTION_MAPPING, stepActionFactory);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const Promise = require('bluebird');
|
|
4
|
-
const
|
|
4
|
+
const pRetry = require('p-retry');
|
|
5
5
|
|
|
6
6
|
class ScreenshotUtils {
|
|
7
7
|
constructor(tabId, driver, options = { takeScreenshots: true }) {
|
|
@@ -29,7 +29,7 @@ class ScreenshotUtils {
|
|
|
29
29
|
const SCREENSHOT_RETRY_DELAY = 2000;
|
|
30
30
|
const devicePixelRatioPromise = this.currentDevicePixelRatio ? Promise.resolve(this.currentDevicePixelRatio) : this.getDevicePixelRatio();
|
|
31
31
|
const getScreenshot = () => Promise.all([devicePixelRatioPromise, this.driver.takeScreenshot()]);
|
|
32
|
-
return
|
|
32
|
+
return pRetry(getScreenshot, { retries: MAX_RETRY_COUNT, minTimeout: SCREENSHOT_RETRY_DELAY })
|
|
33
33
|
.then(([devicePixelRatio, image]) => {
|
|
34
34
|
const base64 = image ? image.value : '';
|
|
35
35
|
const dataUrl = `data:image/png;base64,${this.base64AddPadding(base64.replace(/[\r\n]/g, ''))}`;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const Promise = require('bluebird');
|
|
4
|
-
const
|
|
4
|
+
const pRetry = require('p-retry');
|
|
5
5
|
const { PageNotAvailableError } = require('../../errors');
|
|
6
6
|
const logger = require('../../commons/logger').getLogger('window-utils');
|
|
7
7
|
|
|
@@ -152,12 +152,12 @@ WindowUtils.prototype.quit = function () {
|
|
|
152
152
|
};
|
|
153
153
|
|
|
154
154
|
WindowUtils.prototype.getOsAndBrowser = function () {
|
|
155
|
-
return
|
|
155
|
+
return pRetry(() => this.driver.getBrowserAndOS(), { retries: 3 })
|
|
156
156
|
.then(osAndBrowser => ({ uaBrowserName: osAndBrowser.browser, uaOs: osAndBrowser.os, userAgent: osAndBrowser.userAgent, browserVersion: osAndBrowser.browserVersion }));
|
|
157
157
|
};
|
|
158
158
|
|
|
159
159
|
WindowUtils.prototype.getUserAgentInfo = function () {
|
|
160
|
-
return
|
|
160
|
+
return pRetry(() => this.driver.getUserAgentInfo(), { retries: 3 });
|
|
161
161
|
};
|
|
162
162
|
|
|
163
163
|
module.exports = WindowUtils;
|