@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/cliAgentMode.js
DELETED
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
/* eslint-disable camelcase */
|
|
2
|
-
// @ts-check
|
|
3
|
-
|
|
4
|
-
'use strict';
|
|
5
|
-
|
|
6
|
-
const path = require('path');
|
|
7
|
-
const fs = require('fs-extra');
|
|
8
|
-
const ms = require('ms');
|
|
9
|
-
const WebSocket = require('ws');
|
|
10
|
-
const ChromeLauncher = require('chrome-launcher');
|
|
11
|
-
const config = require('./commons/config');
|
|
12
|
-
const { ArgError } = require('./errors');
|
|
13
|
-
const lazyRequire = require('./commons/lazyRequire');
|
|
14
|
-
const prepareUtils = require('./commons/prepareRunnerAndTestimStartUtils');
|
|
15
|
-
const { downloadAndSave, unzipFile, getCdpAddressForHost, TESTIM_BROWSER_DIR, promiseFromCallback } = require('./utils');
|
|
16
|
-
const ora = require('ora');
|
|
17
|
-
const { downloadAndInstallChromium, CHROMIUM_VERSION } = require('./chromiumInstaller');
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const LOG_LEVEL = config.WEBDRIVER_DEBUG ? 'verbose' : 'silent';
|
|
21
|
-
const EXTENSION_CACHE_TIME = ms('1h');
|
|
22
|
-
const USER_DATA_DIR = path.join(TESTIM_BROWSER_DIR, 'profile');
|
|
23
|
-
|
|
24
|
-
// https://github.com/bayandin/chromedriver/blob/5013f2124888c50fff15dc2ff8287288f780b046/chrome_launcher.cc#L105
|
|
25
|
-
const CHOMEDRIVER_DEVTOOLS_ACTIVE_PORT_FILENAME = 'DevToolsActivePort';
|
|
26
|
-
const CHOMEDRIVER_DEVTOOLS_ACTIVE_PORT_FILE_PATH = path.join(USER_DATA_DIR, CHOMEDRIVER_DEVTOOLS_ACTIVE_PORT_FILENAME);
|
|
27
|
-
|
|
28
|
-
module.exports = {
|
|
29
|
-
shouldStartAgentMode,
|
|
30
|
-
runAgentMode,
|
|
31
|
-
getStartedWithStart,
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @type {(options: import('./runOptions').Options) => options is import('./runOptions').AgentModeOptions}
|
|
36
|
-
*/
|
|
37
|
-
function shouldStartAgentMode(options) {
|
|
38
|
-
// @ts-ignore should be `as any`
|
|
39
|
-
return options.agentMode;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** @param {import('./runOptions').AgentModeOptions} options */
|
|
43
|
-
async function runAgentMode(options) {
|
|
44
|
-
let testimStandaloneBrowser;
|
|
45
|
-
|
|
46
|
-
await prepareUtils.preparePlayer(options.playerLocation, options.canary);
|
|
47
|
-
|
|
48
|
-
if (options.startTestimBrowser) {
|
|
49
|
-
await getRidOfPossiblyRunningChromeWithOurDataDir();
|
|
50
|
-
try {
|
|
51
|
-
// Consider moving that into the agent server and add endpoint to start browser?
|
|
52
|
-
testimStandaloneBrowser = await startTestimStandaloneBrowser(options);
|
|
53
|
-
} catch (e) {
|
|
54
|
-
if (e?.message?.includes('user data directory is already in use')) {
|
|
55
|
-
throw new ArgError('Please close all chrome browsers that were opened with "testim start" and try again');
|
|
56
|
-
}
|
|
57
|
-
throw e;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const agentServer = require('./agent/server');
|
|
62
|
-
|
|
63
|
-
if (testimStandaloneBrowser?.webdriverApi) {
|
|
64
|
-
// if we're starting the agent here, pre-load the sessionPlayer so it loads faster
|
|
65
|
-
// on first play
|
|
66
|
-
const LOAD_PLAYER_DELAY = 6000;
|
|
67
|
-
setTimeout(async () => {
|
|
68
|
-
setTimeout(() => require('./player/seleniumTestPlayer'));
|
|
69
|
-
|
|
70
|
-
const packages = [
|
|
71
|
-
'webpack',
|
|
72
|
-
// We may build/static analyze functions file to do it here
|
|
73
|
-
// silent full-blown build will require additional work,
|
|
74
|
-
// But actually can be valuable as general speedup if we cache the webpack instance
|
|
75
|
-
// "puppeteer",
|
|
76
|
-
// "selenium-webdriver"
|
|
77
|
-
// "playwright"
|
|
78
|
-
];
|
|
79
|
-
|
|
80
|
-
for (const packageToInstall of packages) {
|
|
81
|
-
await lazyRequire(packageToInstall, { silent: true }).catch(() => { });
|
|
82
|
-
}
|
|
83
|
-
}, LOAD_PLAYER_DELAY);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return agentServer.init(
|
|
87
|
-
options,
|
|
88
|
-
// @ts-ignore
|
|
89
|
-
testimStandaloneBrowser
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
let startedWithStart = false;
|
|
94
|
-
|
|
95
|
-
function getStartedWithStart() {
|
|
96
|
-
return startedWithStart;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function isPidRunning(pid) {
|
|
100
|
-
try {
|
|
101
|
-
return process.kill(pid, 0);
|
|
102
|
-
} catch {
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async function startFixedVersionChromium(options, extensionBase64, downloadedExtensionPathUnzipped) {
|
|
108
|
-
const CHROMIUM_PROCESS_INFO_FILE = path.join(TESTIM_BROWSER_DIR, `chrome-${CHROMIUM_VERSION}-process`);
|
|
109
|
-
const CHECK_CHROMIUM_RUNNING_INTERVAL = 3000;
|
|
110
|
-
|
|
111
|
-
const onBrowserClosed = () => {
|
|
112
|
-
fs.removeSync(CHROMIUM_PROCESS_INFO_FILE);
|
|
113
|
-
// eslint-disable-next-line no-console
|
|
114
|
-
console.log('\n\nBrowser session ended');
|
|
115
|
-
process.exit(0);
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (fs.existsSync(CHROMIUM_PROCESS_INFO_FILE)) {
|
|
120
|
-
const processInfo = fs.readJSONSync(CHROMIUM_PROCESS_INFO_FILE);
|
|
121
|
-
if (isPidRunning(processInfo.pid)) { // if a previous instance of our browser is still running, use it and exit if it does
|
|
122
|
-
const monitorPidForExit = () => (isPidRunning(processInfo.pid) ? setTimeout(monitorPidForExit, CHECK_CHROMIUM_RUNNING_INTERVAL) : onBrowserClosed());
|
|
123
|
-
monitorPidForExit();
|
|
124
|
-
return {
|
|
125
|
-
webdriverApi: processInfo,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
const chromeBinary = await downloadAndInstallChromium();
|
|
130
|
-
|
|
131
|
-
if (!(await fs.pathExists(USER_DATA_DIR))) {
|
|
132
|
-
await fs.mkdirp(USER_DATA_DIR);
|
|
133
|
-
}
|
|
134
|
-
const capabilities = buildSeleniumOptions(USER_DATA_DIR, extensionBase64, downloadedExtensionPathUnzipped, chromeBinary);
|
|
135
|
-
const chromeFlags = [
|
|
136
|
-
...capabilities.desiredCapabilities.chromeOptions.args,
|
|
137
|
-
...ChromeLauncher.Launcher.defaultFlags().filter(flag => ![
|
|
138
|
-
'--disable-extensions',
|
|
139
|
-
'--disable-component-extensions-with-background-pages', // causes google connect to disallow some accounts (eg gmail accounts get a "This browser or app may not be secure" error)
|
|
140
|
-
].includes(flag)),
|
|
141
|
-
];
|
|
142
|
-
// Chromium needs API keys to communicate with google APIs (https://www.chromium.org/developers/how-tos/api-keys/)
|
|
143
|
-
// These are keys are keys that were included in some chrome builds
|
|
144
|
-
const envVars = {
|
|
145
|
-
GOOGLE_API_KEY: 'AIzaSyCkfPOPZXDKNn8hhgu3JrA62wIgC93d44k',
|
|
146
|
-
GOOGLE_DEFAULT_CLIENT_ID: '811574891467.apps.googleusercontent.com',
|
|
147
|
-
GOOGLE_DEFAULT_CLIENT_SECRET: 'kdloedMFGdGla2P1zacGjAQh',
|
|
148
|
-
};
|
|
149
|
-
const appUrl = `${options.extensionPath ? 'http://localhost:3000/app/' : 'https://app.testim.io'}?startMode=true`;
|
|
150
|
-
const chrome = await ChromeLauncher.launch({ chromeFlags, startingUrl: appUrl, ignoreDefaultFlags: true, userDataDir: USER_DATA_DIR, chromePath: chromeBinary, envVars });
|
|
151
|
-
const processInfo = { port: chrome.port, pid: chrome.pid, cdpUrl: await getCdpAddressForHost(`localhost:${chrome.port}`) };
|
|
152
|
-
fs.writeJSONSync(CHROMIUM_PROCESS_INFO_FILE, processInfo);
|
|
153
|
-
chrome.process.once('exit', onBrowserClosed);
|
|
154
|
-
chrome.process.once('close', onBrowserClosed);
|
|
155
|
-
return {
|
|
156
|
-
webdriverApi: processInfo,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/** @param {import('./runOptions').AgentModeOptions} options */
|
|
161
|
-
async function startTestimStandaloneBrowser(options) {
|
|
162
|
-
// After next clickim release we will have also testim-full.zip
|
|
163
|
-
// const fullExtensionUrl = "https://testimstatic.blob.core.windows.net/extension/testim-full-master.zip";
|
|
164
|
-
// CDN url
|
|
165
|
-
const fullExtensionUrl = `${config.EDGE_URL}/extension/testim-full-master.zip`;
|
|
166
|
-
const extensionFilename = path.basename(fullExtensionUrl);
|
|
167
|
-
|
|
168
|
-
const downloadedExtensionPath = path.join(TESTIM_BROWSER_DIR, extensionFilename);
|
|
169
|
-
const downloadedExtensionPathUnzipped = path.join(TESTIM_BROWSER_DIR, `${extensionFilename}__unzipped__`);
|
|
170
|
-
|
|
171
|
-
let shouldDownloadExtension = !(options.ext || options.extensionPath);
|
|
172
|
-
|
|
173
|
-
if (shouldDownloadExtension && await fs.pathExists(downloadedExtensionPath)) {
|
|
174
|
-
const stat = await fs.stat(downloadedExtensionPath);
|
|
175
|
-
shouldDownloadExtension = (Date.now() - EXTENSION_CACHE_TIME > stat.mtimeMs);
|
|
176
|
-
}
|
|
177
|
-
await fs.mkdirp(TESTIM_BROWSER_DIR);
|
|
178
|
-
|
|
179
|
-
if (shouldDownloadExtension) {
|
|
180
|
-
const spinner = ora('Downloading Testim Editor').start();
|
|
181
|
-
await downloadAndSave(fullExtensionUrl, downloadedExtensionPath);
|
|
182
|
-
|
|
183
|
-
try {
|
|
184
|
-
// Ensure the zip is ok
|
|
185
|
-
await unzipFile(downloadedExtensionPath, downloadedExtensionPathUnzipped);
|
|
186
|
-
} catch (e) {
|
|
187
|
-
// The downloaded zip is corrupted, try re download once
|
|
188
|
-
await fs.remove(downloadedExtensionPath);
|
|
189
|
-
await downloadAndSave(fullExtensionUrl, downloadedExtensionPath);
|
|
190
|
-
try {
|
|
191
|
-
await unzipFile(downloadedExtensionPath, downloadedExtensionPathUnzipped);
|
|
192
|
-
} catch (err) {
|
|
193
|
-
// zip is bad again.
|
|
194
|
-
await fs.remove(downloadedExtensionPath);
|
|
195
|
-
spinner.fail('Failed to download Testim Editor');
|
|
196
|
-
throw new Error('Failed to download Testim Editor');
|
|
197
|
-
}
|
|
198
|
-
} finally {
|
|
199
|
-
if (!options.downloadBrowser) {
|
|
200
|
-
await fs.remove(downloadedExtensionPathUnzipped);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
spinner.succeed();
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const extensionBase64 = options.extensionPath ? null : (await fs.readFile(options.ext || downloadedExtensionPath)).toString('base64');
|
|
208
|
-
if (options.downloadBrowser) {
|
|
209
|
-
return await startFixedVersionChromium(options, extensionBase64, downloadedExtensionPathUnzipped);
|
|
210
|
-
}
|
|
211
|
-
await prepareUtils.prepareChromeDriver(
|
|
212
|
-
{ projectId: options.project },
|
|
213
|
-
// @ts-expect-error not clear where chromeBinaryLocations comes from
|
|
214
|
-
{ chromeBinaryLocation: options.chromeBinaryLocations },
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
// @ts-expect-error not clear where chromeBinaryLocations comes from
|
|
218
|
-
const seleniumOptions = buildSeleniumOptions(USER_DATA_DIR, extensionBase64, options.extensionPath, options.chromeBinaryLocations);
|
|
219
|
-
|
|
220
|
-
const WebDriver = require('./player/webdriver');
|
|
221
|
-
const { SeleniumPerfStats } = require('./commons/SeleniumPerfStats');
|
|
222
|
-
|
|
223
|
-
const webdriverApi = new WebDriver();
|
|
224
|
-
webdriverApi.seleniumPerfStats = new SeleniumPerfStats();
|
|
225
|
-
|
|
226
|
-
// starts chrome via selenium, note this is intentionally initClient and not init to bypass desired capabilities parsing
|
|
227
|
-
const webdriverInitResponse = await webdriverApi.initClient(seleniumOptions);
|
|
228
|
-
|
|
229
|
-
// example values from webdriverIntRespons
|
|
230
|
-
// webdriverInitResponse.sessionId
|
|
231
|
-
// webdriverInitResponse.value["goog:chromeOptions"].debuggerAddress
|
|
232
|
-
// webdriverInitResponse.chrome.userDataDir;
|
|
233
|
-
|
|
234
|
-
// require user token, so we can't use it for now
|
|
235
|
-
// const { getEditorUrl } = require('./commons/testimServicesApi');
|
|
236
|
-
|
|
237
|
-
startedWithStart = true;
|
|
238
|
-
const appUrl = `${options.extensionPath ? 'http://localhost:3000/app/' : 'https://app.testim.io'}?startMode=true`;
|
|
239
|
-
|
|
240
|
-
await webdriverApi.url(appUrl);
|
|
241
|
-
// save the initial URL we navigated to so we don't consider it the AuT
|
|
242
|
-
webdriverApi.initialUrl = appUrl;
|
|
243
|
-
try {
|
|
244
|
-
//TODO(Benji) do we want this to be exactly getCdpAddressForHost or should this fail less gracefully indicating the agent did not start correctly?
|
|
245
|
-
webdriverApi.cdpUrl = await getCdpAddressForHost(webdriverInitResponse.value['goog:chromeOptions'].debuggerAddress);
|
|
246
|
-
} catch (e) {
|
|
247
|
-
// ignore error
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return {
|
|
251
|
-
webdriverApi,
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* @param {string} userDataDir
|
|
257
|
-
* @param {string | null} fullExtensionPath
|
|
258
|
-
*/
|
|
259
|
-
function buildSeleniumOptions(userDataDir, fullExtensionPath, unpackedExtensionPath, chromeBinaryPath) {
|
|
260
|
-
const extensions = fullExtensionPath ? [fullExtensionPath] : [];
|
|
261
|
-
const args = [
|
|
262
|
-
`--user-data-dir=${userDataDir}`, // crashes chromium, re-enable if using chrome
|
|
263
|
-
'--log-level=OFF',
|
|
264
|
-
'--silent-debugger-extension-api',
|
|
265
|
-
'--no-first-run',
|
|
266
|
-
];
|
|
267
|
-
if (unpackedExtensionPath) {
|
|
268
|
-
args.push(`--load-extension=${unpackedExtensionPath}`);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
return {
|
|
272
|
-
logLevel: LOG_LEVEL,
|
|
273
|
-
desiredCapabilities: {
|
|
274
|
-
chromeOptions: {
|
|
275
|
-
args,
|
|
276
|
-
extensions,
|
|
277
|
-
binary: chromeBinaryPath,
|
|
278
|
-
},
|
|
279
|
-
browserName: 'chrome',
|
|
280
|
-
},
|
|
281
|
-
host: 'localhost',
|
|
282
|
-
port: 9515, // chromedriver port
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Overview of what we do here:
|
|
288
|
-
* we check if CHOMEDRIVER_DEVTOOLS_ACTIVE_PORT_FILE_PATH is exists
|
|
289
|
-
* If we can read the port & CDP url info from that file.
|
|
290
|
-
* If we can read, but we can't send http request to the devtools server we assume it's closed and just delete the file
|
|
291
|
-
* If we can read and send HTTP request, send CDP command of Browser.close to CDP, and delete the file.
|
|
292
|
-
* If any of these fails we assume we couldn't kill the browser, and the user will get the "close the running chromes errors down the line"
|
|
293
|
-
*/
|
|
294
|
-
async function getRidOfPossiblyRunningChromeWithOurDataDir() {
|
|
295
|
-
if (!await fs.pathExists(CHOMEDRIVER_DEVTOOLS_ACTIVE_PORT_FILE_PATH)) {
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
try {
|
|
300
|
-
const { webSocketDebuggerUrl } = await readAndValidateChromedriverDevToolsActivePortFile();
|
|
301
|
-
await tryToCloseBrowserWithCDPUrl(webSocketDebuggerUrl);
|
|
302
|
-
await fs.unlink(CHOMEDRIVER_DEVTOOLS_ACTIVE_PORT_FILE_PATH);
|
|
303
|
-
} catch (e) {
|
|
304
|
-
// chrome is probably not really running, we are cool
|
|
305
|
-
if (e && e.message === 'unable to connect to devtools http server') {
|
|
306
|
-
await fs.unlink(CHOMEDRIVER_DEVTOOLS_ACTIVE_PORT_FILE_PATH);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
async function readAndValidateChromedriverDevToolsActivePortFile() {
|
|
312
|
-
/**
|
|
313
|
-
* file content example:
|
|
314
|
-
|
|
315
|
-
58938
|
|
316
|
-
/devtools/browser/d4290379-ec08-4d03-a41a-ab9d9d4c36ac
|
|
317
|
-
|
|
318
|
-
*/
|
|
319
|
-
|
|
320
|
-
const fileContent = await fs.readFile(CHOMEDRIVER_DEVTOOLS_ACTIVE_PORT_FILE_PATH, { encoding: 'utf8' });
|
|
321
|
-
|
|
322
|
-
const [portLine, browserCDPURLLine] = fileContent.split('\n').map(line => line.trim());
|
|
323
|
-
|
|
324
|
-
const port = Number.parseInt(portLine, 10);
|
|
325
|
-
|
|
326
|
-
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
327
|
-
throw new Error('invalid port number');
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if (!browserCDPURLLine.startsWith('/devtools/browser/')) {
|
|
331
|
-
throw new Error('invalid devtools browser url');
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
const webSocketDebuggerUrl = await getCdpAddressForHost(`localhost:${port}`, 500);
|
|
335
|
-
// invariant check
|
|
336
|
-
if (!webSocketDebuggerUrl.endsWith(browserCDPURLLine)) {
|
|
337
|
-
throw new Error('invariant webSocketDebuggerUrl miss match');
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
return {
|
|
341
|
-
port,
|
|
342
|
-
webSocketDebuggerUrl,
|
|
343
|
-
};
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* @param {string | import("url").URL} webSocketDebuggerUrl
|
|
349
|
-
* @param {number=} timeout
|
|
350
|
-
*/
|
|
351
|
-
async function tryToCloseBrowserWithCDPUrl(webSocketDebuggerUrl, timeout = 100) {
|
|
352
|
-
const websocketConnection = await wsConnectAndOpen(webSocketDebuggerUrl, timeout);
|
|
353
|
-
|
|
354
|
-
return promiseFromCallback(cb => {
|
|
355
|
-
websocketConnection.send(JSON.stringify({
|
|
356
|
-
id: 0,
|
|
357
|
-
method: 'Browser.close',
|
|
358
|
-
}), cb);
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* @param {string | import("url").URL} webSocketDebuggerUrl
|
|
364
|
-
* @param {number=} timeout
|
|
365
|
-
*/
|
|
366
|
-
async function wsConnectAndOpen(webSocketDebuggerUrl, timeout = 100) {
|
|
367
|
-
const websocket = new WebSocket(webSocketDebuggerUrl, { timeout });
|
|
368
|
-
|
|
369
|
-
const openPromise = promiseFromCallback((cb) => {
|
|
370
|
-
websocket.once('open', cb);
|
|
371
|
-
}).then(() => {
|
|
372
|
-
websocket.removeAllListeners();
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
const errorPromise = promiseFromCallback((cb) => {
|
|
376
|
-
websocket.once('error', cb);
|
|
377
|
-
}).catch(() => {
|
|
378
|
-
websocket.close();
|
|
379
|
-
websocket.removeAllListeners();
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
return Promise.race([openPromise, errorPromise]).then(() => websocket);
|
|
383
|
-
}
|
|
384
|
-
|
package/codim/codim-cli.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
/* eslint-disable no-console */
|
|
4
|
-
|
|
5
|
-
'use strict';
|
|
6
|
-
|
|
7
|
-
const fs = require('fs');
|
|
8
|
-
const childProcess = require('child_process');
|
|
9
|
-
const path = require('path');
|
|
10
|
-
const chalk = require('chalk');
|
|
11
|
-
const validateNpmPackageName = require('validate-npm-package-name');
|
|
12
|
-
const { promisify } = require('util');
|
|
13
|
-
const { ArgError } = require('../errors.js');
|
|
14
|
-
const { copyDir } = require('../utils/fsUtils');
|
|
15
|
-
|
|
16
|
-
const exec = promisify(childProcess.exec);
|
|
17
|
-
|
|
18
|
-
/** @param {string} name */
|
|
19
|
-
module.exports.init = async function init(name) {
|
|
20
|
-
const ora = require('ora');
|
|
21
|
-
const prompts = require('prompts');
|
|
22
|
-
|
|
23
|
-
if (typeof name !== 'string' || !name.trim()) {
|
|
24
|
-
const response = await prompts({
|
|
25
|
-
type: 'text',
|
|
26
|
-
name: 'project',
|
|
27
|
-
message: 'Please enter Project name',
|
|
28
|
-
validate: value => String(value).length > 3,
|
|
29
|
-
});
|
|
30
|
-
name = response.project;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const fullPath = path.resolve(name);
|
|
34
|
-
|
|
35
|
-
if (fs.existsSync(fullPath) && fs.readdirSync(fullPath).length !== 0) {
|
|
36
|
-
console.log(`${fullPath} is not empty. Quitting...`);
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const packageName = fullPath.substr(Math.max(fullPath.lastIndexOf('/'), fullPath.lastIndexOf('\\')) + 1);
|
|
41
|
-
|
|
42
|
-
const nameValidity = validateNpmPackageName(packageName);
|
|
43
|
-
|
|
44
|
-
if (!nameValidity.validForNewPackages) {
|
|
45
|
-
const message = `The name '${packageName}' is not a valid package name:`;
|
|
46
|
-
console.log(chalk.red(message));
|
|
47
|
-
if (nameValidity.errors) nameValidity.errors.forEach((e) => console.log(chalk.red(e)));
|
|
48
|
-
if (nameValidity.warnings) nameValidity.warnings.forEach((e) => console.log(chalk.yellowBright(`warning: ${e}`)));
|
|
49
|
-
|
|
50
|
-
throw new ArgError(`${message}\nvalidation errors:\n${nameValidity.errors?.join('\n') || ''}\nwarnings:\n${nameValidity.warnings?.join('\n') || ''}`);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const response = await prompts({
|
|
54
|
-
type: 'toggle',
|
|
55
|
-
name: 'isJs',
|
|
56
|
-
message: 'Add support for TypeScript?',
|
|
57
|
-
initial: true,
|
|
58
|
-
active: 'no',
|
|
59
|
-
inactive: 'yes',
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
const sourceFolder = response.isJs ? 'template.js' : 'template.ts'; // these are directories and not file names
|
|
63
|
-
|
|
64
|
-
const source = path.join(__dirname, sourceFolder);
|
|
65
|
-
const destDir = path.join(process.cwd(), name);
|
|
66
|
-
|
|
67
|
-
let spinner = ora(`Creating new test project in ${destDir}`).start();
|
|
68
|
-
|
|
69
|
-
await copyDir(source, destDir);
|
|
70
|
-
|
|
71
|
-
const sourcePackageJson = path.join(__dirname, sourceFolder, 'package.json');
|
|
72
|
-
const destPackageJson = path.join(process.cwd(), name, 'package.json');
|
|
73
|
-
|
|
74
|
-
const packageContents = await fs.promises.readFile(sourcePackageJson);
|
|
75
|
-
|
|
76
|
-
const newPackageJson = packageContents.toString().replace('~testim-codeful-test-project~', packageName);
|
|
77
|
-
|
|
78
|
-
await fs.promises.writeFile(destPackageJson, newPackageJson);
|
|
79
|
-
|
|
80
|
-
const gitIgnore = 'node_modules';
|
|
81
|
-
const gitIgnoreFilePath = path.join(process.cwd(), name, '.gitignore');
|
|
82
|
-
await fs.promises.writeFile(gitIgnoreFilePath, gitIgnore);
|
|
83
|
-
|
|
84
|
-
spinner.succeed();
|
|
85
|
-
spinner = ora('Installing dependencies').start();
|
|
86
|
-
await exec('npm install', { cwd: destDir });
|
|
87
|
-
|
|
88
|
-
spinner.succeed();
|
|
89
|
-
|
|
90
|
-
console.log(`Testim Dev Kit project folder successfully created in ${destDir}.`);
|
|
91
|
-
};
|