@testim/testim-cli 3.230.0 → 3.233.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/cli.js +6 -0
- package/commons/featureFlags.js +1 -1
- package/commons/httpRequest.js +4 -3
- package/commons/testimCloudflare.js +73 -0
- package/commons/testimServicesApi.js +34 -0
- package/commons/testimTunnel.js +18 -2
- package/npm-shrinkwrap.json +394 -322
- package/package.json +1 -1
- package/player/WebDriverHttpRequest.js +1 -1
- package/player/stepActions/scripts/scroll.js +12 -2
- package/player/stepActions/scrollStepAction.js +1 -1
- package/player/stepActions/stepActionRegistrar.js +0 -4
- package/player/utils/eyeSdkService.js +21 -2
- package/runOptions.js +21 -0
- package/runner.js +1 -1
- package/runners/TestPlanRunner.js +8 -5
- package/services/gridService.js +1 -1
- package/services/lambdatestService.js +2 -1
- package/player/stepActions/salesforceAutoLoginStepAction.js +0 -39
package/cli.js
CHANGED
|
@@ -94,6 +94,12 @@ function main() {
|
|
|
94
94
|
return undefined;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
if (options.tunnelOnlyMode) {
|
|
98
|
+
await testRunner.init(options);
|
|
99
|
+
await require('./commons/testimTunnel').serveTunneling(options);
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
|
|
97
103
|
if (agentMode.shouldStartAgentMode(options)) {
|
|
98
104
|
return agentMode.runAgentMode(options);
|
|
99
105
|
}
|
package/commons/featureFlags.js
CHANGED
|
@@ -53,10 +53,10 @@ class FeatureFlagsService {
|
|
|
53
53
|
useSameBrowserForMultiTests: new LabFeatureFlag('labs'),
|
|
54
54
|
highSpeedMode: new LabFeatureFlag(),
|
|
55
55
|
usePortedHtml5DragDrop: new Rox.Flag(),
|
|
56
|
-
applitoolsNewIntegration: new Rox.Flag(),
|
|
57
56
|
testNamesToBeforeSuiteHook: new Rox.Flag(),
|
|
58
57
|
addCustomCapabilities: new Rox.Variant('{}'),
|
|
59
58
|
enableWorkerThreadsCliCodeExecution: new Rox.Flag(true),
|
|
59
|
+
LTNetworkCapabilities: new Rox.Flag(),
|
|
60
60
|
};
|
|
61
61
|
Rox.register('default', this.flags);
|
|
62
62
|
}
|
package/commons/httpRequest.js
CHANGED
|
@@ -37,8 +37,8 @@ const logErrorAndRethrow = (logMsg, data) => err => {
|
|
|
37
37
|
throw err;
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
function deleteMethod(url, headers, timeout) {
|
|
41
|
-
return deleteFullRes(url, headers, timeout)
|
|
40
|
+
function deleteMethod(url, body, headers, timeout) {
|
|
41
|
+
return deleteFullRes(url, body, headers, timeout)
|
|
42
42
|
.then(res => {
|
|
43
43
|
if (res.type === 'text/plain') {
|
|
44
44
|
return res.text;
|
|
@@ -48,9 +48,10 @@ function deleteMethod(url, headers, timeout) {
|
|
|
48
48
|
.catch(logErrorAndRethrow('failed to delete request', { url }));
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
function deleteFullRes(url, headers = {}, timeout = DEFAULT_REQUEST_TIMEOUT) {
|
|
51
|
+
function deleteFullRes(url, body = {}, headers = {}, timeout = DEFAULT_REQUEST_TIMEOUT) {
|
|
52
52
|
const request = superagent
|
|
53
53
|
.delete(url)
|
|
54
|
+
.send(body)
|
|
54
55
|
.timeout(timeout)
|
|
55
56
|
.set(headers);
|
|
56
57
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const os = require('os');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { spawn } = require('child_process');
|
|
6
|
+
const fse = require('fs-extra');
|
|
7
|
+
const { downloadAndSave, unzipFile } = require('../utils');
|
|
8
|
+
const servicesApi = require('./testimServicesApi.js');
|
|
9
|
+
|
|
10
|
+
const TUNNEL_BINARY_ORIGIN = 'https://github.com/cloudflare/cloudflared/releases/download/2022.4.1/';
|
|
11
|
+
const TUNNEL_BINARY_PATHNAME = {
|
|
12
|
+
win32ia32: { path: 'cloudflared-windows-386.exe' },
|
|
13
|
+
win32x64: { path: 'cloudflared-windows-amd64.exe' },
|
|
14
|
+
darwinx64: { path: 'cloudflared-darwin-amd64.tgz', extract: true },
|
|
15
|
+
linuxia32: { path: 'cloudflared-linux-386' },
|
|
16
|
+
linuxx64: { path: 'cloudflared-linux-amd64' },
|
|
17
|
+
};
|
|
18
|
+
const TUNNEL_BINARY_DIRECTORY = `${os.tmpdir()}/cloudflared`;
|
|
19
|
+
const TUNNEL_BINARY_LOCATION = `${TUNNEL_BINARY_DIRECTORY}/cloudflared`;
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
let tunnelId = null;
|
|
23
|
+
let tunnelProcess = null;
|
|
24
|
+
|
|
25
|
+
async function prepareTunnel() {
|
|
26
|
+
const isBinaryExist = await fse.pathExists(TUNNEL_BINARY_LOCATION);
|
|
27
|
+
if (isBinaryExist) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const downloadUrl = TUNNEL_BINARY_PATHNAME[os.platform() + os.arch()];
|
|
32
|
+
if (!downloadUrl) {
|
|
33
|
+
throw new Error(`tunnel on ${os.platform() + os.arch()} platform is not supported.`);
|
|
34
|
+
}
|
|
35
|
+
const destination = downloadUrl.extract ? path.extname(downloadUrl.path) : downloadUrl.path;
|
|
36
|
+
await downloadAndSave(`${TUNNEL_BINARY_ORIGIN}/${downloadUrl.path}`, destination);
|
|
37
|
+
if (downloadUrl.extract) {
|
|
38
|
+
await unzipFile(destination, TUNNEL_BINARY_DIRECTORY);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const connectTunnel = async (options) => {
|
|
43
|
+
const [result] = await Promise.all([
|
|
44
|
+
servicesApi.getCloudflareTunnel(options.company.companyId, options.tunnelRoutes),
|
|
45
|
+
prepareTunnel(),
|
|
46
|
+
]);
|
|
47
|
+
tunnelId = result._id;
|
|
48
|
+
tunnelProcess = spawn('./cloudflared', ['tunnel', '--no-autoupdate', 'run', '--force', '--token', result.token], { cwd: TUNNEL_BINARY_DIRECTORY, stdio: 'inherit' });
|
|
49
|
+
await servicesApi.forceUpdateCloudflareTunnelRoutes(options.company.companyId, tunnelId);
|
|
50
|
+
await fse.writeFileSync(options.tunnelRoutesOutput, JSON.stringify(result.routesMapping, null, 2));
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const disconnectTunnel = async (options) => {
|
|
54
|
+
if (tunnelId) {
|
|
55
|
+
await servicesApi.deleteCloudflareTunnel(options.company.companyId, tunnelId);
|
|
56
|
+
}
|
|
57
|
+
if (tunnelProcess) {
|
|
58
|
+
await new Promise((resolve, reject) => {
|
|
59
|
+
tunnelProcess.on('close', (code) => {
|
|
60
|
+
if (code) {
|
|
61
|
+
reject();
|
|
62
|
+
}
|
|
63
|
+
resolve();
|
|
64
|
+
});
|
|
65
|
+
tunnelProcess.kill();
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
module.exports = {
|
|
71
|
+
connectTunnel,
|
|
72
|
+
disconnectTunnel,
|
|
73
|
+
};
|
|
@@ -55,6 +55,11 @@ function putAuth(url, body) {
|
|
|
55
55
|
.then(headers => httpRequest.put(`${config.SERVICES_HOST}${url || ''}`, body, headers));
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
function deleteAuth(url, body) {
|
|
59
|
+
return getTokenHeader()
|
|
60
|
+
.then(headers => httpRequest.delete(`${config.SERVICES_HOST}${url || ''}`, body, headers));
|
|
61
|
+
}
|
|
62
|
+
|
|
58
63
|
function getWithAuth(url, query, options, timeout) {
|
|
59
64
|
return getTokenHeader()
|
|
60
65
|
.then(headers => httpRequest.get(`${config.SERVICES_HOST}${url || ''}`, query, headers, timeout, options));
|
|
@@ -444,6 +449,32 @@ function getApplitoolsIntegrationData(projectId) {
|
|
|
444
449
|
}
|
|
445
450
|
}
|
|
446
451
|
|
|
452
|
+
|
|
453
|
+
function getCloudflareTunnel(companyId, routes) {
|
|
454
|
+
try {
|
|
455
|
+
return putAuth('/tunnel', { companyId, routes });
|
|
456
|
+
} catch (err) {
|
|
457
|
+
logger.warn('could\'nt get tunnel.', { err });
|
|
458
|
+
return {};
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
function forceUpdateCloudflareTunnelRoutes(companyId, tunnelId) {
|
|
462
|
+
try {
|
|
463
|
+
return postAuth({ url: `/tunnel/${tunnelId}`, body: { companyId } });
|
|
464
|
+
} catch (err) {
|
|
465
|
+
logger.warn('could\'nt get tunnel.', { err });
|
|
466
|
+
return {};
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
function deleteCloudflareTunnel(companyId, tunnelId) {
|
|
470
|
+
try {
|
|
471
|
+
return deleteAuth(`/tunnel/${tunnelId}`, { companyId });
|
|
472
|
+
} catch (err) {
|
|
473
|
+
logger.warn('could\'nt get tunnel.', { err });
|
|
474
|
+
return {};
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
447
478
|
module.exports = {
|
|
448
479
|
getS3Artifact,
|
|
449
480
|
getTestPlan,
|
|
@@ -476,4 +507,7 @@ module.exports = {
|
|
|
476
507
|
loadTest,
|
|
477
508
|
isTestResultCompleted,
|
|
478
509
|
getApplitoolsIntegrationData,
|
|
510
|
+
getCloudflareTunnel,
|
|
511
|
+
forceUpdateCloudflareTunnelRoutes,
|
|
512
|
+
deleteCloudflareTunnel,
|
|
479
513
|
};
|
package/commons/testimTunnel.js
CHANGED
|
@@ -3,22 +3,29 @@
|
|
|
3
3
|
const ora = require('ora');
|
|
4
4
|
|
|
5
5
|
const LambdatestService = require('../services/lambdatestService');
|
|
6
|
+
const { registerExitHook } = require('../processHandler');
|
|
7
|
+
const testimCustomToken = require('./testimCustomToken');
|
|
6
8
|
const { gridTypes } = require('./constants');
|
|
7
9
|
const testimNgrok = require('./testimNgrok');
|
|
10
|
+
const testimCloudflare = require('./testimCloudflare');
|
|
8
11
|
const logger = require('./logger').getLogger('tunnel');
|
|
9
12
|
|
|
10
|
-
const shouldUseLambdatestTunnel = options => [gridTypes.LAMBDATEST, gridTypes.HYBRID].includes(options.gridData.type) && options.gridData.tunnel !== 'ngrok';
|
|
13
|
+
const shouldUseLambdatestTunnel = options => [gridTypes.LAMBDATEST, gridTypes.HYBRID].includes(options.gridData && options.gridData.type) && options.gridData.tunnel !== 'ngrok';
|
|
11
14
|
|
|
12
|
-
const connect = async (options
|
|
15
|
+
const connect = async (options) => {
|
|
13
16
|
if (!options.tunnel) {
|
|
14
17
|
return;
|
|
15
18
|
}
|
|
16
19
|
|
|
20
|
+
const authData = testimCustomToken.getTokenV3UserData();
|
|
17
21
|
let spinner;
|
|
18
22
|
try {
|
|
19
23
|
if (shouldUseLambdatestTunnel(options)) {
|
|
20
24
|
spinner = ora('Starting testim lambdatest tunnel...').start();
|
|
21
25
|
await LambdatestService.connectTunnel(options);
|
|
26
|
+
} else if (options.tunnelRoutes) {
|
|
27
|
+
spinner = ora('Starting testim cloudflare tunnel...').start();
|
|
28
|
+
await testimCloudflare.connectTunnel(options);
|
|
22
29
|
} else {
|
|
23
30
|
spinner = ora('Starting testim ngrok tunnel...').start();
|
|
24
31
|
await testimNgrok.connectTunnel(options, authData);
|
|
@@ -40,6 +47,8 @@ const disconnect = async (options) => {
|
|
|
40
47
|
try {
|
|
41
48
|
if (shouldUseLambdatestTunnel(options)) {
|
|
42
49
|
await LambdatestService.disconnectTunnel(options);
|
|
50
|
+
} else if (options.tunnelRoutes) {
|
|
51
|
+
await testimCloudflare.disconnectTunnel(options);
|
|
43
52
|
} else {
|
|
44
53
|
await testimNgrok.disconnectTunnel(options);
|
|
45
54
|
}
|
|
@@ -50,7 +59,14 @@ const disconnect = async (options) => {
|
|
|
50
59
|
}
|
|
51
60
|
};
|
|
52
61
|
|
|
62
|
+
const serveTunneling = async (options) => {
|
|
63
|
+
await connect(options);
|
|
64
|
+
registerExitHook(() => disconnect(options));
|
|
65
|
+
return await new Promise(() => { /* avoid exiting process */ });
|
|
66
|
+
};
|
|
67
|
+
|
|
53
68
|
module.exports = {
|
|
54
69
|
connect,
|
|
55
70
|
disconnect,
|
|
71
|
+
serveTunneling,
|
|
56
72
|
};
|