@testim/testim-cli 3.289.0 → 3.290.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 +22390 -122
- package/cli.js.map +1 -0
- package/npm-shrinkwrap.json +1951 -203
- package/package.json +9 -5
- package/OverrideTestDataBuilder.js +0 -117
- package/agent/routers/cliJsCode/index.js +0 -13
- package/agent/routers/cliJsCode/router.js +0 -63
- package/agent/routers/cliJsCode/service.js +0 -705
- package/agent/routers/codim/router.js +0 -69
- package/agent/routers/codim/router.test.js +0 -60
- package/agent/routers/codim/service.js +0 -193
- package/agent/routers/general/index.js +0 -36
- package/agent/routers/hybrid/registerRoutes.js +0 -81
- package/agent/routers/index.js +0 -56
- package/agent/routers/playground/router.js +0 -77
- package/agent/routers/playground/service.js +0 -96
- package/agent/routers/standalone-browser/registerRoutes.js +0 -47
- package/agent/server.js +0 -150
- package/cdpTestRunner.js +0 -86
- package/chromiumInstaller.js +0 -91
- package/cli/isCiRun.js +0 -10
- package/cli/onExit.js +0 -65
- package/cli/writeStackTrace.js +0 -27
- package/cliAgentMode.js +0 -384
- package/codim/codim-cli.js +0 -91
- package/codim/codim-npm-package/index.ts +0 -427
- package/codim/codim-npm-package/package-lock.json +0 -14
- package/codim/codim-npm-package/package.json +0 -14
- package/codim/hybrid-utils.js +0 -28
- package/codim/measure-perf.js +0 -41
- package/codim/template.js/.idea/workspace.xml +0 -57
- package/codim/template.js/.vscode/launch.json +0 -53
- package/codim/template.ts/.idea/workspace.xml +0 -57
- package/codim/template.ts/.vscode/launch.json +0 -55
- package/commons/AbortError.js +0 -12
- package/commons/SeleniumPerfStats.js +0 -58
- package/commons/chrome-launcher.js +0 -15
- package/commons/chromedriverWrapper.js +0 -70
- package/commons/config.js +0 -39
- package/commons/constants.js +0 -67
- package/commons/detectDebugger.js +0 -19
- package/commons/featureAvailabilityService.js +0 -26
- package/commons/featureFlags.js +0 -132
- package/commons/getSessionPlayerRequire.js +0 -28
- package/commons/httpRequest.js +0 -261
- package/commons/httpRequestCounters.js +0 -98
- package/commons/httpRequestCounters.test.js +0 -38
- package/commons/initializeUserWithAuth.js +0 -55
- package/commons/lazyRequire.js +0 -105
- package/commons/logUtils.js +0 -15
- package/commons/logUtils.test.js +0 -21
- package/commons/logger.js +0 -178
- package/commons/mockNetworkRuleFileSchema.json +0 -140
- package/commons/npmWrapper.js +0 -174
- package/commons/npmWrapper.test.js +0 -374
- package/commons/performance-logger.js +0 -71
- package/commons/preloadTests.js +0 -29
- package/commons/prepareRunner.js +0 -85
- package/commons/prepareRunner.test.js +0 -144
- package/commons/prepareRunnerAndTestimStartUtils.js +0 -198
- package/commons/prepareRunnerAndTestimStartUtils.test.js +0 -73
- package/commons/requireWithFallback.js +0 -25
- package/commons/runnerFileCache.js +0 -204
- package/commons/socket/baseSocketServiceSocketIO.js +0 -197
- package/commons/socket/realDataService.js +0 -59
- package/commons/socket/realDataServiceSocketIO.js +0 -33
- package/commons/socket/remoteStepService.js +0 -55
- package/commons/socket/remoteStepServiceSocketIO.js +0 -61
- package/commons/socket/socketService.js +0 -175
- package/commons/socket/testResultService.js +0 -62
- package/commons/socket/testResultServiceSocketIO.js +0 -64
- package/commons/testimAnalytics.js +0 -40
- package/commons/testimCloudflare.js +0 -83
- package/commons/testimCloudflare.test.js +0 -185
- package/commons/testimCustomToken.js +0 -124
- package/commons/testimDesiredCapabilitiesBuilder.js +0 -647
- package/commons/testimNgrok.js +0 -90
- package/commons/testimNgrok.test.js +0 -140
- package/commons/testimServicesApi.js +0 -631
- package/commons/testimTunnel.js +0 -73
- package/commons/testimTunnel.test.js +0 -172
- package/commons/xhr2.js +0 -897
- package/coverage/SummaryToObjectReport.js +0 -19
- package/coverage/jsCoverage.js +0 -252
- package/credentialsManager.js +0 -142
- package/errors.js +0 -161
- package/executionQueue.js +0 -37
- package/fixLocalBuild.js +0 -24
- package/inputFileUtils.js +0 -103
- package/lib/coralogix-winston.transport.js +0 -99
- package/player/SeleniumProtocolError.js +0 -100
- package/player/WebDriverHttpRequest.js +0 -177
- package/player/WebdriverioWebDriverApi.js +0 -671
- package/player/appiumTestPlayer.js +0 -90
- package/player/chromeLauncherTestPlayer.js +0 -67
- package/player/constants.js +0 -332
- package/player/extensionTestPlayer.js +0 -32
- package/player/findElementStrategy.js +0 -154
- package/player/scripts/isElementDisplayed.js +0 -252
- package/player/seleniumTestPlayer.js +0 -140
- package/player/services/frameLocator.js +0 -170
- package/player/services/mobileFrameLocatorMock.js +0 -32
- package/player/services/playbackTimeoutCalculator.js +0 -175
- package/player/services/portSelector.js +0 -19
- package/player/services/tabService.js +0 -551
- package/player/services/tabServiceMock.js +0 -167
- package/player/services/windowCreationListener.js +0 -8
- package/player/stepActions/RefreshStepAction.js +0 -16
- package/player/stepActions/apiStepAction.js +0 -89
- package/player/stepActions/baseCliJsStepAction.js +0 -51
- package/player/stepActions/baseJsStepAction.js +0 -277
- package/player/stepActions/cliConditionStepAction.js +0 -11
- package/player/stepActions/cliJsStepAction.js +0 -11
- package/player/stepActions/dropFileStepAction.js +0 -34
- package/player/stepActions/evaluateExpressionStepAction.js +0 -52
- package/player/stepActions/extensionOnlyStepAction.js +0 -12
- package/player/stepActions/extractTextStepAction.js +0 -19
- package/player/stepActions/hoverStepAction.js +0 -55
- package/player/stepActions/inputFileStepAction.js +0 -199
- package/player/stepActions/jsCodeStepAction.js +0 -11
- package/player/stepActions/jsConditionStepAction.js +0 -11
- package/player/stepActions/locateStepAction.js +0 -159
- package/player/stepActions/mouseStepAction.js +0 -370
- package/player/stepActions/navigationStepAction.js +0 -29
- package/player/stepActions/nodePackageStepAction.js +0 -47
- package/player/stepActions/pixelValidationStepAction.js +0 -39
- package/player/stepActions/scripts/dispatchEvents.js +0 -282
- package/player/stepActions/scripts/doClick.js +0 -221
- package/player/stepActions/scripts/doDragPath.js +0 -225
- package/player/stepActions/scripts/doubleClick.js +0 -119
- package/player/stepActions/scripts/dropEvent.js +0 -63
- package/player/stepActions/scripts/focusElement.js +0 -46
- package/player/stepActions/scripts/html5dragAction.js +0 -56
- package/player/stepActions/scripts/html5dragActionV2.js +0 -312
- package/player/stepActions/scripts/runCode.js +0 -147
- package/player/stepActions/scripts/scroll.js +0 -90
- package/player/stepActions/scripts/selectOption.js +0 -51
- package/player/stepActions/scripts/setText.js +0 -415
- package/player/stepActions/scripts/wheel.js +0 -61
- package/player/stepActions/scrollStepAction.js +0 -96
- package/player/stepActions/selectOptionStepAction.js +0 -49
- package/player/stepActions/sfdcRecordedStepAction.js +0 -24
- package/player/stepActions/sfdcStepAction.js +0 -28
- package/player/stepActions/sleepStepAction.js +0 -12
- package/player/stepActions/specialKeyStepAction.js +0 -52
- package/player/stepActions/stepAction.js +0 -73
- package/player/stepActions/stepActionRegistrar.js +0 -111
- package/player/stepActions/submitStepAction.js +0 -12
- package/player/stepActions/tdkHybridStepAction.js +0 -18
- package/player/stepActions/textStepAction.js +0 -110
- package/player/stepActions/textValidationStepAction.js +0 -64
- package/player/stepActions/wheelStepAction.js +0 -41
- package/player/utils/cookieUtils.js +0 -39
- package/player/utils/eyeSdkService.js +0 -250
- package/player/utils/imageCaptureUtils.js +0 -267
- package/player/utils/screenshotUtils.js +0 -68
- package/player/utils/stepActionUtils.js +0 -90
- package/player/utils/windowUtils.js +0 -195
- package/player/webDriverUtils.js +0 -40
- package/player/webDriverUtils.test.js +0 -116
- package/player/webdriver.js +0 -976
- package/polyfills/Array.prototype.at.js +0 -13
- package/polyfills/index.js +0 -13
- package/processHandler.js +0 -79
- package/processHandler.test.js +0 -55
- package/reports/chromeReporter.js +0 -17
- package/reports/consoleReporter.js +0 -190
- package/reports/debugReporter.js +0 -82
- package/reports/jsonReporter.js +0 -55
- package/reports/junitReporter.js +0 -183
- package/reports/reporter.js +0 -166
- package/reports/reporterUtils.js +0 -54
- package/reports/teamCityReporter.js +0 -73
- package/runOptions.d.ts +0 -305
- package/runOptions.js +0 -1288
- package/runOptionsAgentFlow.js +0 -87
- package/runOptionsUtils.js +0 -60
- package/runner.js +0 -355
- package/runners/ParallelWorkerManager.js +0 -284
- package/runners/TestPlanRunner.js +0 -419
- package/runners/buildCodeTests.js +0 -159
- package/runners/runnerUtils.js +0 -81
- package/services/analyticsService.js +0 -96
- package/services/branchService.js +0 -29
- package/services/gridService.js +0 -357
- package/services/gridService.test.js +0 -357
- package/services/labFeaturesService.js +0 -64
- package/services/lambdatestService.js +0 -227
- package/services/lambdatestService.test.js +0 -353
- package/services/localRCASaver.js +0 -124
- package/stepPlayers/cliJsStepPlayback.js +0 -40
- package/stepPlayers/hybridStepPlayback.js +0 -140
- package/stepPlayers/nodePackageStepPlayback.js +0 -28
- package/stepPlayers/playwrightHybridStepPlayback.js +0 -61
- package/stepPlayers/puppeteerHybridStepPlayback.js +0 -76
- package/stepPlayers/remoteStepPlayback.js +0 -80
- package/stepPlayers/seleniumHybridStepPlayback.js +0 -84
- package/stepPlayers/tdkHybridStepPlayback.js +0 -112
- package/testRunHandler.js +0 -603
- package/testRunStatus.js +0 -567
- package/testimNpmDriver.js +0 -52
- package/utils/argsUtils.js +0 -91
- package/utils/argsUtils.test.js +0 -32
- package/utils/fsUtils.js +0 -174
- package/utils/index.js +0 -197
- package/utils/promiseUtils.js +0 -85
- package/utils/stringUtils.js +0 -98
- package/utils/stringUtils.test.js +0 -22
- package/utils/timeUtils.js +0 -25
- package/utils/utils.test.js +0 -27
- package/workers/BaseWorker.js +0 -498
- package/workers/BaseWorker.test.js +0 -186
- package/workers/WorkerAppium.js +0 -180
- package/workers/WorkerExtension.js +0 -192
- package/workers/WorkerExtensionSingleBrowser.js +0 -77
- package/workers/WorkerSelenium.js +0 -253
- package/workers/workerUtils.js +0 -20
package/utils/argsUtils.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
const { sessionType, testStatus: testStatusConst } = require('../commons/constants');
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @typedef {import('../runOptions').Options} Options
|
|
10
|
-
* @typedef {import('../runOptions').InitModeOptions} InitModeOptions
|
|
11
|
-
* @typedef {import('../runOptions').LoginModeOptions} LoginModeOptions
|
|
12
|
-
* @typedef {import('../runOptions').TunnelOptions} TunnelOptions
|
|
13
|
-
* @typedef {import('../runOptions').NgrokTunnelOptions} NgrokTunnelOptions
|
|
14
|
-
* @typedef {import('../runOptions').TunnelDaemonOptions} TunnelDaemonOptions
|
|
15
|
-
* @typedef {import('../runOptions').RunnerOptions} RunnerOptions
|
|
16
|
-
* @typedef {import('../runOptions').InstallLazyDepsOptions} InstallLazyDepsOptions
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
/** @param {RunnerOptions} options */
|
|
20
|
-
function getSessionType(options) {
|
|
21
|
-
return options.files.length > 0 ? sessionType.CODEFUL : sessionType.CODELESS;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @param {RunnerOptions} options
|
|
26
|
-
* @param {{ runConfig: { browserValue: string } }[]} testList
|
|
27
|
-
*/
|
|
28
|
-
function getUniqBrowsers(options, testList) {
|
|
29
|
-
if ((options.testConfigNames?.length || options.testConfigIds?.length || options.testPlan.length || options.testPlanIds.length) && !options.browser) {
|
|
30
|
-
return [...new Set(testList.map(t => t.runConfig.browserValue))];
|
|
31
|
-
}
|
|
32
|
-
return [options.browser?.toLowerCase()];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** @param {RunnerOptions} options */
|
|
36
|
-
const hasTestPlanFlag = (options) => Boolean(options.testPlan?.length || options.testPlanIds?.length);
|
|
37
|
-
|
|
38
|
-
/** @param {RunnerOptions} options */
|
|
39
|
-
const isRemoteRun = (options) => options.resultId && options.source === 'remote-run';
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* @param {{ testStatus?: string }} test
|
|
43
|
-
* @param {RunnerOptions} options
|
|
44
|
-
*/
|
|
45
|
-
const isQuarantineAndNotRemoteRun = (test, options) => test.testStatus === testStatusConst.QUARANTINE && !isRemoteRun(options) && !options.runQuarantinedTests;
|
|
46
|
-
|
|
47
|
-
function getArgsOnRemoteRunFailure() {
|
|
48
|
-
const { argv: args } = process;
|
|
49
|
-
if (!args.includes('--remoteRunId')) {
|
|
50
|
-
return undefined;
|
|
51
|
-
}
|
|
52
|
-
return {
|
|
53
|
-
remoteRunId: args[args.indexOf('--remoteRunId') + 1],
|
|
54
|
-
projectId: args[args.indexOf('--project') + 1],
|
|
55
|
-
token: args[args.indexOf('--token') + 1],
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
/** @type {(options: Options) => options is InitModeOptions} options */
|
|
61
|
-
// @ts-ignore should be `as any` etc
|
|
62
|
-
const isInitCodimMode = (options) => Boolean(options.initCodimMode);
|
|
63
|
-
|
|
64
|
-
/** @type {(options: Options) => options is LoginModeOptions} options */
|
|
65
|
-
// @ts-ignore should be `as any` etc
|
|
66
|
-
const isLoginMode = (options) => Boolean(options.loginMode);
|
|
67
|
-
|
|
68
|
-
/** @type {(options: Options) => options is TunnelOptions} options */
|
|
69
|
-
// @ts-ignore should be `as any` etc
|
|
70
|
-
const isTunnelOnlyMode = (options) => Boolean(options.tunnelOnlyMode);
|
|
71
|
-
|
|
72
|
-
/** @type {(options: Options) => options is RunnerOptions & { createPrefechedData: true; }} options */
|
|
73
|
-
// @ts-ignore should be `as any` etc
|
|
74
|
-
const isCreatePrefetchedDataMode = (options) => Boolean(options.createPrefechedData);
|
|
75
|
-
/** @type {(options: Options) => options is InstallLazyDepsOptions} options */
|
|
76
|
-
// @ts-ignore should be `as any` etc
|
|
77
|
-
const isInstallLazyDepsMode = (options) => Boolean(options.installLazyDepsMode);
|
|
78
|
-
|
|
79
|
-
module.exports = {
|
|
80
|
-
getSessionType,
|
|
81
|
-
getUniqBrowsers,
|
|
82
|
-
hasTestPlanFlag,
|
|
83
|
-
isRemoteRun,
|
|
84
|
-
isQuarantineAndNotRemoteRun,
|
|
85
|
-
getArgsOnRemoteRunFailure,
|
|
86
|
-
isInitCodimMode,
|
|
87
|
-
isLoginMode,
|
|
88
|
-
isTunnelOnlyMode,
|
|
89
|
-
isCreatePrefetchedDataMode,
|
|
90
|
-
isInstallLazyDepsMode,
|
|
91
|
-
};
|
package/utils/argsUtils.test.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
const chai = require('chai'); // eslint-disable-line import/no-extraneous-dependencies
|
|
2
|
-
const argsUtils = require('./argsUtils');
|
|
3
|
-
|
|
4
|
-
const expect = chai.expect;
|
|
5
|
-
|
|
6
|
-
describe('argsUtils', () => {
|
|
7
|
-
describe('getArgsOnRemoteRunFailure', () => {
|
|
8
|
-
let originalArgv;
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
originalArgv = process.argv;
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
afterEach(() => {
|
|
15
|
-
process.argv = originalArgv;
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('should return undefined if no remote run is current', () => {
|
|
19
|
-
process.argv = ['node', 'file.js', '--token', 'token', '--project', 'project-id'];
|
|
20
|
-
expect(argsUtils.getArgsOnRemoteRunFailure()).to.be.undefined;
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('should return details if remote run is current', () => {
|
|
24
|
-
process.argv = ['node', 'file.js', '--token', 'token', '--project', 'project-id', '--remoteRunId', 'remote-run-id'];
|
|
25
|
-
expect(argsUtils.getArgsOnRemoteRunFailure()).to.eql({
|
|
26
|
-
remoteRunId: 'remote-run-id',
|
|
27
|
-
projectId: 'project-id',
|
|
28
|
-
token: 'token',
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
});
|
package/utils/fsUtils.js
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
const path = require('path');
|
|
6
|
-
const pRetry = require('p-retry');
|
|
7
|
-
const decompress = require('decompress');
|
|
8
|
-
const stringUtils = require('./stringUtils');
|
|
9
|
-
const httpRequest = require('../commons/httpRequest');
|
|
10
|
-
const { promises: fsPromises, createReadStream, createWriteStream, statSync } = require('fs');
|
|
11
|
-
|
|
12
|
-
const DOWNLOAD_RETRY = 3;
|
|
13
|
-
|
|
14
|
-
function getCliLocation() {
|
|
15
|
-
let cliLocation;
|
|
16
|
-
if (!require.main) { // we're in a REPL
|
|
17
|
-
return process.cwd(); // fall back on the current working directory
|
|
18
|
-
}
|
|
19
|
-
if (require.main.filename.includes('/src') || require.main.filename.includes('\\src') || process.env.IS_UNIT_TEST) {
|
|
20
|
-
cliLocation = path.resolve(__dirname, '../../');
|
|
21
|
-
} else {
|
|
22
|
-
cliLocation = path.resolve(__dirname, '../');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return cliLocation;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* @param {string} url
|
|
30
|
-
*/
|
|
31
|
-
const download = async (url) => pRetry(() => httpRequest.download(url), { retries: DOWNLOAD_RETRY });
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* @param {string} url
|
|
35
|
-
* @param {import('fs').PathLike} saveToLocation
|
|
36
|
-
*/
|
|
37
|
-
const downloadAndSave = async (url, saveToLocation) => {
|
|
38
|
-
const res = await download(url);
|
|
39
|
-
return fsPromises.writeFile(saveToLocation, res.body);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @param {import('fs').PathLike} readFile
|
|
44
|
-
* @param {import('fs').PathLike} destFile
|
|
45
|
-
* @return {Promise<void>}
|
|
46
|
-
*/
|
|
47
|
-
const copy = async (readFile, destFile) => new Promise((resolve, reject) => {
|
|
48
|
-
try {
|
|
49
|
-
// TODO: can this use fsPromises.copyFile?
|
|
50
|
-
const file = createWriteStream(destFile);
|
|
51
|
-
createReadStream(readFile).pipe(file);
|
|
52
|
-
file.on('finish', () => {
|
|
53
|
-
file.close(() => resolve());
|
|
54
|
-
});
|
|
55
|
-
} catch (err) {
|
|
56
|
-
reject(err);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* @param {string} location
|
|
62
|
-
* @param {string=} fileName
|
|
63
|
-
*/
|
|
64
|
-
function getSourcePath(location, fileName) {
|
|
65
|
-
if (stringUtils.isURL(location)) {
|
|
66
|
-
return fileName || path.join(process.cwd(), location.replace(/^.*[\\\/]/, ''));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return fileName || path.basename(location);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* @param {string} location
|
|
74
|
-
* @param {string} fileName
|
|
75
|
-
*/
|
|
76
|
-
const getSource = async (location, fileName) => {
|
|
77
|
-
const destFile = getSourcePath(location, fileName);
|
|
78
|
-
if (stringUtils.isURL(location)) {
|
|
79
|
-
return downloadAndSave(location, destFile);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return copy(location, destFile);
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* @param {string} location
|
|
87
|
-
*/
|
|
88
|
-
const getSourceAsBuffer = async (location) => {
|
|
89
|
-
if (stringUtils.isURL(location)) {
|
|
90
|
-
return download(location);
|
|
91
|
-
}
|
|
92
|
-
return fsPromises.readFile(location);
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* @param {string} srcZipFile
|
|
97
|
-
* @param {string} destZipPath
|
|
98
|
-
*/
|
|
99
|
-
const unzipFile = async (srcZipFile, destZipPath) => await decompress(srcZipFile, destZipPath);
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* @param {import('fs').PathLike} fileLocation
|
|
103
|
-
*/
|
|
104
|
-
const getLocalFileSizeInMB = (fileLocation) => {
|
|
105
|
-
const stats = statSync(fileLocation);
|
|
106
|
-
const fileSizeInBytes = stats.size;
|
|
107
|
-
return fileSizeInBytes / 1000000;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
function getRunnerVersion() {
|
|
112
|
-
try {
|
|
113
|
-
/** @type {import('../../package.json')} */
|
|
114
|
-
const pack = require(`${__dirname}/../package.json`); // eslint-disable-line import/no-dynamic-require
|
|
115
|
-
return pack.version;
|
|
116
|
-
} catch (err) {
|
|
117
|
-
return '';
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function getEnginesVersion() {
|
|
122
|
-
try {
|
|
123
|
-
/** @type {import('../../package.json')} */
|
|
124
|
-
const pack = require(`${__dirname}/../package.json`); // eslint-disable-line import/no-dynamic-require
|
|
125
|
-
return pack.engines.node;
|
|
126
|
-
} catch (err) {
|
|
127
|
-
return '';
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
async function getEnginesVersionAsync() {
|
|
132
|
-
try {
|
|
133
|
-
/** @type {import('../../package.json')} */
|
|
134
|
-
const pack = JSON.parse(await fsPromises.readFile(`${__dirname}/../package.json`, 'utf8'));
|
|
135
|
-
return pack.engines.node;
|
|
136
|
-
} catch (err) {
|
|
137
|
-
return '';
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* @param {string} src Source directory to copy its contents
|
|
143
|
-
* @param {string} dest Target directory to copy to
|
|
144
|
-
* @param {boolean} [createParentDirs=true] Whether to create parent directories
|
|
145
|
-
*/
|
|
146
|
-
async function copyDir(src, dest, createParentDirs = true) {
|
|
147
|
-
const dirents = await fsPromises.readdir(src, { withFileTypes: true });
|
|
148
|
-
await fsPromises.mkdir(dest, { recursive: createParentDirs });
|
|
149
|
-
for (const item of dirents) {
|
|
150
|
-
const srcPath = path.join(src, item.name);
|
|
151
|
-
const destPath = path.join(dest, item.name);
|
|
152
|
-
if (item.isDirectory()) {
|
|
153
|
-
await copyDir(srcPath, destPath);
|
|
154
|
-
} else {
|
|
155
|
-
await fsPromises.copyFile(srcPath, destPath);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
module.exports = {
|
|
161
|
-
getCliLocation,
|
|
162
|
-
download,
|
|
163
|
-
downloadAndSave,
|
|
164
|
-
copy,
|
|
165
|
-
getSourcePath,
|
|
166
|
-
getSource,
|
|
167
|
-
getSourceAsBuffer,
|
|
168
|
-
unzipFile,
|
|
169
|
-
getLocalFileSizeInMB,
|
|
170
|
-
getRunnerVersion,
|
|
171
|
-
getEnginesVersion,
|
|
172
|
-
getEnginesVersionAsync,
|
|
173
|
-
copyDir,
|
|
174
|
-
};
|
package/utils/index.js
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
const os = require('os');
|
|
6
|
-
const _ = require('lodash');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
const fsUtils = require('./fsUtils');
|
|
9
|
-
const argsUtils = require('./argsUtils');
|
|
10
|
-
const timeUtils = require('./timeUtils');
|
|
11
|
-
const stringUtils = require('./stringUtils');
|
|
12
|
-
const promiseUtils = require('./promiseUtils');
|
|
13
|
-
const httpRequest = require('../commons/httpRequest');
|
|
14
|
-
const { W3C_ELEMENT_ID } = require('../player/constants');
|
|
15
|
-
|
|
16
|
-
const HOMEDIR = os.homedir();
|
|
17
|
-
const TESTIM_BROWSER_DIR = path.join(HOMEDIR, '.testim-browser-profile');
|
|
18
|
-
|
|
19
|
-
const OSS = [
|
|
20
|
-
{ osName: 'Linux', bs: { os: 'LINUX' }, sl: { platform: 'Linux' } },
|
|
21
|
-
{ osName: 'Windows 10', bs: { os: 'WINDOWS', os_version: '10' }, sl: { platform: 'Windows 10' } },
|
|
22
|
-
{ osName: 'Windows 8', bs: { os: 'WINDOWS', os_version: '8' }, sl: { platform: 'Windows 8' } },
|
|
23
|
-
{ osName: 'Windows 8.1', bs: { os: 'WINDOWS', os_version: '8.1' }, sl: { platform: 'Windows 8.1' } },
|
|
24
|
-
{ osName: 'Windows 7', bs: { os: 'WINDOWS', os_version: '7' }, sl: { platform: 'Windows 7' } },
|
|
25
|
-
{ osName: 'Windows XP', bs: { os: 'WINDOWS', os_version: 'XP' }, sl: { platform: 'Windows XP' } },
|
|
26
|
-
{ osName: 'macOS Big Sur', bs: { os: 'OS X', os_version: 'Big Sur', safari_version: '14' }, sl: { platform: 'macOS 11', safari_version: '14' } },
|
|
27
|
-
{ osName: 'macOS Catalina', bs: { os: 'OS X', os_version: 'Catalina', safari_version: '13' }, sl: { platform: 'macOS 10.15', safari_version: '13' } },
|
|
28
|
-
{ osName: 'macOS Mojave', bs: { os: 'OS X', os_version: 'Mojave', safari_version: '12' }, sl: { platform: 'macOS 10.14', safari_version: '12' } },
|
|
29
|
-
{ osName: 'macOS High Sierra', bs: { os: 'OS X', os_version: 'High Sierra', safari_version: '11' }, sl: { platform: 'macOS 10.13', safari_version: '11' } },
|
|
30
|
-
{ osName: 'macOS Sierra', bs: { os: 'OS X', os_version: 'Sierra', safari_version: '10' }, sl: { platform: 'macOS 10.12', safari_version: '10.0' } },
|
|
31
|
-
{ osName: 'OS X El Capitan', bs: { os: 'OS X', os_version: 'El Capitan', safari_version: '9.1' }, sl: { platform: 'OS X 10.11', safari_version: '9.0' } },
|
|
32
|
-
{ osName: 'OS X Yosemite', bs: { os: 'OS X', os_version: 'Yosemite', safari_version: '8' }, sl: { platform: 'OS X 10.10', safari_version: '8.0' } },
|
|
33
|
-
{ osName: 'OS X Mavericks', bs: { os: 'OS X', os_version: 'Mavericks', safari_version: '7.1' }, sl: { platform: 'OS X 10.9', safari_version: '7.0' } },
|
|
34
|
-
{ osName: 'OS X Mountain Lion', bs: { os: 'OS X', os_version: 'Mountain Lion', safari_version: '6.2' }, sl: { platform: 'OS X 10.8', safari_version: '6.0' } },
|
|
35
|
-
{ osName: 'OS X Lion', bs: { os: 'OS X', os_version: 'Lion', safari_version: '6' }, sl: {} },
|
|
36
|
-
{ osName: 'OS X Snow Leopard', bs: { os: 'OS X', os_version: 'Snow Leopard', safari_version: '5.1' }, sl: {} },
|
|
37
|
-
|
|
38
|
-
{ osName: 'iOS', bs: { platform: 'MAC' }, sl: { platformName: 'iOS', appiumVersion: '1.6.4' } },
|
|
39
|
-
{ osName: 'Android', bs: { platform: 'ANDROID' }, sl: { platformName: 'Android', appiumVersion: '1.6.4' } },
|
|
40
|
-
];
|
|
41
|
-
|
|
42
|
-
const BROWSERS = [
|
|
43
|
-
{ browserName: 'Chrome', bs: { browser: 'Chrome', browser_version: '94' }, sl: { browserName: 'chrome', version: '94.0' }, browserValue: 'chrome' },
|
|
44
|
-
{ browserName: 'Firefox', bs: { browser: 'Firefox', browser_version: '89' }, sl: { browserName: 'firefox', version: '89.0' }, browserValue: 'firefox' },
|
|
45
|
-
{ browserName: 'Safari', bs: { browser: 'Safari' }, sl: { browserName: 'safari' }, browserValue: 'safari' },
|
|
46
|
-
{ browserName: 'Edge', bs: { browser: 'Edge', browser_version: '18' }, sl: { browserName: 'MicrosoftEdge', version: '18.17763' }, browserValue: 'edge', eol: true },
|
|
47
|
-
// eslint-disable-next-line max-len
|
|
48
|
-
{ browserName: 'Edge Chromium', bs: { browser: 'Edge', browser_version: '94' }, sl: { browserName: 'MicrosoftEdge', version: '94' }, synonyms: ['edge-chromium'], browserValue: 'edge-chromium', seleniumName: 'MicrosoftEdge' },
|
|
49
|
-
// eslint-disable-next-line max-len
|
|
50
|
-
{ browserName: 'Internet Explorer 11', bs: { browser: 'IE', browser_version: '11' }, sl: { browserName: 'internet explorer', version: '11.0' }, synonyms: ['ie11'], browserValue: 'ie11', eol: true },
|
|
51
|
-
{ browserName: 'Browser', bs: {}, sl: { browserName: 'Browser' }, browserValue: 'browser' },
|
|
52
|
-
{ browserName: 'Android', bs: { browserName: 'android' }, sl: {}, browserValue: 'android' },
|
|
53
|
-
{ browserName: 'iPad', bs: { browserName: 'iPad' }, sl: {}, browserValue: 'ipad' },
|
|
54
|
-
{ browserName: 'iPhone', bs: { browserName: 'iPhone' }, sl: {}, browserValue: 'iphone' },
|
|
55
|
-
];
|
|
56
|
-
|
|
57
|
-
function getBrowserInfo(browserValue) {
|
|
58
|
-
browserValue = browserValue.toLowerCase();
|
|
59
|
-
return BROWSERS.find((b) => b.browserValue === browserValue);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function getRunConfigByBrowserName(browser, saucelabs, browserstack) {
|
|
63
|
-
browser = browser.toLowerCase();
|
|
64
|
-
const selectedBrowser = BROWSERS.find(b => b.browserName.toLowerCase() === browser || browser.includes(b.synonyms)) || BROWSERS[0];
|
|
65
|
-
|
|
66
|
-
// BS and SL do not support Linux for newer browser, so use Windows instead.
|
|
67
|
-
let selectedOS = OSS.find(x => x.osName === 'Windows 10');
|
|
68
|
-
if (saucelabs) {
|
|
69
|
-
if (saucelabs.platform) {
|
|
70
|
-
selectedOS = OSS.find(o => o.sl.platform === saucelabs.platform);
|
|
71
|
-
} else if (saucelabs.platformName) {
|
|
72
|
-
selectedOS = OSS.find(o => o.sl.platformName === saucelabs.platformName);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
if (browserstack) {
|
|
76
|
-
if (browserstack.os_version) {
|
|
77
|
-
selectedOS = OSS.find(o => o.bs.os_version === browserstack.os_version);
|
|
78
|
-
} else if (browserstack.platform) {
|
|
79
|
-
selectedOS = OSS.find(o => o.bs.platform === browserstack.platform);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return _.merge(selectedBrowser, selectedOS);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function getEnvironmentGitBranch() {
|
|
87
|
-
return process.env.GIT_BRANCH || process.env.CIRCLE_BRANCH || process.env.TRAVIS_BRANCH || process.env.CI_BRANCH;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function removePropertyFromObject(obj, propName, cmpFunction) {
|
|
91
|
-
for (const prop in obj) {
|
|
92
|
-
if (obj.hasOwnProperty(prop)) {
|
|
93
|
-
if (cmpFunction(prop, propName)) {
|
|
94
|
-
delete obj[prop];
|
|
95
|
-
} else if (typeof obj[prop] === 'object') {
|
|
96
|
-
removePropertyFromObject(obj[prop], propName, cmpFunction);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function extractElementId(element) {
|
|
103
|
-
return element.ELEMENT || element[W3C_ELEMENT_ID];
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function getPlanType(plan) {
|
|
107
|
-
plan = plan || {};
|
|
108
|
-
const now = Date.now();
|
|
109
|
-
const expirationDate = plan.expireAt || plan.expireAT;
|
|
110
|
-
|
|
111
|
-
if (plan.plan !== 'free') {
|
|
112
|
-
return 'pro';
|
|
113
|
-
}
|
|
114
|
-
if (expirationDate) {
|
|
115
|
-
return expirationDate < now ? 'free' : 'trial';
|
|
116
|
-
}
|
|
117
|
-
return 'free';
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const calcPercentile = (arr, percentile) => {
|
|
121
|
-
if (arr.length === 0) return 0;
|
|
122
|
-
if (typeof percentile !== 'number') throw new TypeError('p must be a number');
|
|
123
|
-
|
|
124
|
-
arr = [...arr].sort((a, b) => a - b);
|
|
125
|
-
|
|
126
|
-
if (percentile <= 0) return arr[0];
|
|
127
|
-
if (percentile >= 100) return arr[arr.length - 1];
|
|
128
|
-
|
|
129
|
-
const index = Math.ceil(arr.length * (percentile / 100)) - 1;
|
|
130
|
-
return arr[index];
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
function groupTestsByRetries(testResults = []) { // NOTE: This duplicates a function in services (stream-data/result/resultService.js) since we can't share code between packages.
|
|
134
|
-
return _.chain(testResults)
|
|
135
|
-
.groupBy((tr) => tr.originalTestResultId || tr.resultId)
|
|
136
|
-
.values()
|
|
137
|
-
.reduce((/** @type {any[]} */ all, current) => {
|
|
138
|
-
if (!current) {
|
|
139
|
-
return all;
|
|
140
|
-
}
|
|
141
|
-
if (current.length === 1) {
|
|
142
|
-
all.push(current[0]);
|
|
143
|
-
return all;
|
|
144
|
-
}
|
|
145
|
-
const sorted = _.orderBy(current, (tr) =>
|
|
146
|
-
(typeof tr.retryCount === 'number' ? tr.retryCount : 1)
|
|
147
|
-
);
|
|
148
|
-
const last = _.chain(sorted).last().cloneDeep().value();
|
|
149
|
-
if (!last) {
|
|
150
|
-
return all;
|
|
151
|
-
}
|
|
152
|
-
last.retryTestResults = sorted;
|
|
153
|
-
all.push(last);
|
|
154
|
-
return all;
|
|
155
|
-
}, [])
|
|
156
|
-
.compact()
|
|
157
|
-
.value();
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
async function getCdpAddressForHost(browserInstanceHost, timeout) {
|
|
161
|
-
try {
|
|
162
|
-
/**
|
|
163
|
-
Example response:
|
|
164
|
-
{
|
|
165
|
-
"Browser": "Chrome/81.0.4044.138",
|
|
166
|
-
"Protocol-Version": "1.3",
|
|
167
|
-
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36",
|
|
168
|
-
"V8-Version": "8.1.307.32",
|
|
169
|
-
"WebKit-Version": "537.36 (@8c6c7ba89cc9453625af54f11fd83179e23450fa)",
|
|
170
|
-
"webSocketDebuggerUrl": "ws://localhost:58938/devtools/browser/d4290379-ec08-4d03-a41a-ab9d9d4c36ac"
|
|
171
|
-
}
|
|
172
|
-
*/
|
|
173
|
-
const debuggerAddress = await httpRequest.get(`http://${browserInstanceHost}/json/version`, undefined, undefined, timeout);
|
|
174
|
-
return debuggerAddress.webSocketDebuggerUrl;
|
|
175
|
-
} catch (e) {
|
|
176
|
-
throw new Error('unable to connect to devtools server');
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
module.exports = {
|
|
182
|
-
TESTIM_BROWSER_DIR,
|
|
183
|
-
removePropertyFromObject,
|
|
184
|
-
getEnvironmentGitBranch,
|
|
185
|
-
getRunConfigByBrowserName,
|
|
186
|
-
extractElementId,
|
|
187
|
-
calcPercentile,
|
|
188
|
-
groupTestsByRetries,
|
|
189
|
-
getPlanType,
|
|
190
|
-
getCdpAddressForHost,
|
|
191
|
-
getBrowserInfo,
|
|
192
|
-
...fsUtils,
|
|
193
|
-
...argsUtils,
|
|
194
|
-
...timeUtils,
|
|
195
|
-
...promiseUtils,
|
|
196
|
-
...stringUtils,
|
|
197
|
-
};
|
package/utils/promiseUtils.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
const { TimeoutError } = require('../errors');
|
|
6
|
-
const { OVERRIDE_TIMEOUTS } = require('../commons/config');
|
|
7
|
-
|
|
8
|
-
function isPromise(obj) {
|
|
9
|
-
return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function' && typeof obj.catch === 'function';
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @param time {number} in ms
|
|
14
|
-
* @returns {Promise}
|
|
15
|
-
*/
|
|
16
|
-
function delay(time) {
|
|
17
|
-
return new Promise(((resolve) => {
|
|
18
|
-
setTimeout(resolve, time);
|
|
19
|
-
}));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
let warnedAboutDebugger = false;
|
|
24
|
-
/**
|
|
25
|
-
* @template T
|
|
26
|
-
* @param {Promise<T> | undefined} promise
|
|
27
|
-
* @param {number} timeout
|
|
28
|
-
* @param {string=} errMsg
|
|
29
|
-
*/
|
|
30
|
-
function promiseTimeout(promise, timeout, errMsg = 'Timeout Error') {
|
|
31
|
-
if (OVERRIDE_TIMEOUTS && !warnedAboutDebugger) {
|
|
32
|
-
warnedAboutDebugger = true;
|
|
33
|
-
// eslint-disable-next-line no-console
|
|
34
|
-
console.log('Debugger connected - timeouts were overridden to 10 minutes to improve debugging');
|
|
35
|
-
}
|
|
36
|
-
const timeoutErr = new TimeoutError(errMsg);
|
|
37
|
-
timeout = OVERRIDE_TIMEOUTS ? Number(OVERRIDE_TIMEOUTS) || 600_000 : timeout;
|
|
38
|
-
return Promise.race([
|
|
39
|
-
promise,
|
|
40
|
-
delay(timeout).then(() => { throw timeoutErr; }),
|
|
41
|
-
]);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** @type {import('p-limit').default} */
|
|
45
|
-
let pLimit;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @template T, U
|
|
49
|
-
* @param {ArrayLike<T> | Iterable<T>} arr
|
|
50
|
-
* @param {(item: T, index: number) => PromiseLike<U>} handler
|
|
51
|
-
* @param {{ concurrency?: number }} options
|
|
52
|
-
*/
|
|
53
|
-
async function promiseMap(arr, handler, { concurrency } = {}) {
|
|
54
|
-
pLimit = pLimit || (await import('p-limit')).default;
|
|
55
|
-
if (concurrency) {
|
|
56
|
-
const limit = pLimit(concurrency);
|
|
57
|
-
return await Promise.all(Array.from(arr, (item, index) => limit(() => handler(item, index))));
|
|
58
|
-
}
|
|
59
|
-
return await Promise.all(Array.from(arr, handler));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* @template ErrT, T
|
|
64
|
-
* @param {(callback: (err: ErrT, result: T) => void) => void} resolver
|
|
65
|
-
* @returns {Promise<T>}
|
|
66
|
-
*/
|
|
67
|
-
function promiseFromCallback(resolver) {
|
|
68
|
-
return new Promise((resolve, reject) => {
|
|
69
|
-
resolver((err, result) => {
|
|
70
|
-
if (err) {
|
|
71
|
-
return reject(err);
|
|
72
|
-
}
|
|
73
|
-
return resolve(result);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
module.exports = {
|
|
79
|
-
isPromise,
|
|
80
|
-
delay,
|
|
81
|
-
promiseTimeout,
|
|
82
|
-
promiseMap,
|
|
83
|
-
promiseFromCallback,
|
|
84
|
-
TimeoutError,
|
|
85
|
-
};
|
package/utils/stringUtils.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @param {number} length
|
|
7
|
-
* @returns {string}
|
|
8
|
-
*/
|
|
9
|
-
function randomString(length) {
|
|
10
|
-
const a = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890';
|
|
11
|
-
const index = (Math.random() * (a.length - 1)).toFixed(0);
|
|
12
|
-
return length > 0 ? a[index] + randomString(length - 1) : '';
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @param {string} editorUrl
|
|
17
|
-
* @param {string} projectId
|
|
18
|
-
* @param {string} testId
|
|
19
|
-
* @param {string=} resultId
|
|
20
|
-
* @param {string=} branch
|
|
21
|
-
*/
|
|
22
|
-
function getTestUrl(editorUrl, projectId, testId, resultId, branch) {
|
|
23
|
-
let testUrl = '';
|
|
24
|
-
branch = branch ? encodeURIComponent(branch) : 'master';
|
|
25
|
-
if (projectId && testId) {
|
|
26
|
-
testUrl = `${editorUrl}/#/project/${projectId}/branch/${branch}/test/${testId}`;
|
|
27
|
-
if (resultId) {
|
|
28
|
-
testUrl += `?result-id=${resultId}`;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return testUrl;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @param {string} userName
|
|
36
|
-
* @param {string} password
|
|
37
|
-
*/
|
|
38
|
-
function buildBasicHeader(userName, password) {
|
|
39
|
-
const userAndPasswordBase64 = Buffer.from(`${userName}:${password}`).toString('base64');
|
|
40
|
-
return `Basic ${userAndPasswordBase64}`;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** @param {string} path */
|
|
44
|
-
function isURL(path) {
|
|
45
|
-
const legacyPattern = /^(https?:\/\/)/i;
|
|
46
|
-
|
|
47
|
-
// https://gist.github.com/dperini/729294 (validator.js based on).
|
|
48
|
-
const pattern = new RegExp(
|
|
49
|
-
'^' +
|
|
50
|
-
// protocol identifier (optional)
|
|
51
|
-
// short syntax // still required
|
|
52
|
-
'(?:(?:(?:https?|ftp):)?\\/\\/)' +
|
|
53
|
-
// user:pass BasicAuth (optional)
|
|
54
|
-
'(?:\\S+(?::\\S*)?@)?' +
|
|
55
|
-
'(?:' +
|
|
56
|
-
// IP address exclusion
|
|
57
|
-
// private & local networks
|
|
58
|
-
'(?!(?:10|127)(?:\\.\\d{1,3}){3})' +
|
|
59
|
-
'(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})' +
|
|
60
|
-
'(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})' +
|
|
61
|
-
// IP address dotted notation octets
|
|
62
|
-
// excludes loopback network 0.0.0.0
|
|
63
|
-
// excludes reserved space >= 224.0.0.0
|
|
64
|
-
// excludes network & broadcast addresses
|
|
65
|
-
// (first & last IP address of each class)
|
|
66
|
-
'(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])' +
|
|
67
|
-
'(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}' +
|
|
68
|
-
'(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))' +
|
|
69
|
-
'|' +
|
|
70
|
-
// host & domain names, may end with dot
|
|
71
|
-
// can be replaced by a shortest alternative
|
|
72
|
-
// (?![-_])(?:[-\\w\\u00a1-\\uffff]{0,63}[^-_]\\.)+
|
|
73
|
-
'(?:' +
|
|
74
|
-
'(?:' +
|
|
75
|
-
'[a-z0-9\\u00a1-\\uffff]' +
|
|
76
|
-
'[a-z0-9\\u00a1-\\uffff_-]{0,62}' +
|
|
77
|
-
')?' +
|
|
78
|
-
'[a-z0-9\\u00a1-\\uffff]\\.' +
|
|
79
|
-
')+' +
|
|
80
|
-
// TLD identifier name, may end with dot
|
|
81
|
-
'(?:[a-z\\u00a1-\\uffff]{2,}\\.?)' +
|
|
82
|
-
')' +
|
|
83
|
-
// port number (optional)
|
|
84
|
-
'(?::\\d{2,5})?' +
|
|
85
|
-
// resource path (optional)
|
|
86
|
-
'(?:[/?#]\\S*)?' +
|
|
87
|
-
'$', 'i'
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
return legacyPattern.test(path) || pattern.test(path);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
module.exports = {
|
|
94
|
-
isURL,
|
|
95
|
-
getTestUrl,
|
|
96
|
-
buildBasicHeader,
|
|
97
|
-
guid: (n = 16) => randomString(n),
|
|
98
|
-
};
|