@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
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const express = require('express');
|
|
4
|
-
|
|
5
|
-
const router = express.Router();
|
|
6
|
-
const logger = require('../../../commons/logger').getLogger('codim-router');
|
|
7
|
-
|
|
8
|
-
const {
|
|
9
|
-
findTests,
|
|
10
|
-
getLocalLocators,
|
|
11
|
-
getLocalLocatorContents,
|
|
12
|
-
saveTest,
|
|
13
|
-
saveLocators,
|
|
14
|
-
compileFunctionsLibrary,
|
|
15
|
-
} = require('./service');
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
router.get('/tests', async (req, res) => {
|
|
19
|
-
const tests = await findTests();
|
|
20
|
-
res.json({ tests, success: true });
|
|
21
|
-
});
|
|
22
|
-
router.get('/locators', async (req, res) => {
|
|
23
|
-
const locators = await getLocalLocators();
|
|
24
|
-
const contents = await getLocalLocatorContents(locators, req.query.full);
|
|
25
|
-
res.json({ locators, contents, success: true });
|
|
26
|
-
});
|
|
27
|
-
router.post('/locators', async (req, res) => {
|
|
28
|
-
if (!req.body) {
|
|
29
|
-
res.status(400).send({ success: false, reason: 'missing body' });
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
if (!req.body.locators) {
|
|
33
|
-
res.status(400).send({ success: false, reason: 'missing locators' });
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const { locators, mergeIntoExisting } = req.body;
|
|
38
|
-
|
|
39
|
-
await saveLocators(locators, { mergeIntoExisting: mergeIntoExisting || false });
|
|
40
|
-
res.status(200).send({ success: true });
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
router.get('/compile', async (req, res) => {
|
|
44
|
-
try {
|
|
45
|
-
const code = await compileFunctionsLibrary(req.body.name);
|
|
46
|
-
res.send({ success: true, code });
|
|
47
|
-
} catch (e) {
|
|
48
|
-
logger.error(e);
|
|
49
|
-
res.json({ success: false, reason: e.message });
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
router.post('/saveTest', async (req, res) => {
|
|
54
|
-
if (!req.body) {
|
|
55
|
-
res.status(400).send({ success: false, reason: 'missing body' });
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
try {
|
|
59
|
-
await saveTest(req.body);
|
|
60
|
-
res.send({ success: true });
|
|
61
|
-
} catch (e) {
|
|
62
|
-
res.json({ success: false, reason: e.message });
|
|
63
|
-
logger.error(e);
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
module.exports.router = router;
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const router = require('./router');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const os = require('os');
|
|
6
|
-
const compression = require('compression');
|
|
7
|
-
const express = require('express');
|
|
8
|
-
const bodyParser = require('body-parser');
|
|
9
|
-
const superagent = require('superagent');
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
const { expect } = require('chai'); // eslint-disable-line import/no-extraneous-dependencies
|
|
12
|
-
|
|
13
|
-
const app = express();
|
|
14
|
-
|
|
15
|
-
app.use(bodyParser.urlencoded({ extended: false, limit: '50mb' }));
|
|
16
|
-
app.use(compression());
|
|
17
|
-
app.use(bodyParser.json({ limit: '50mb' }));
|
|
18
|
-
|
|
19
|
-
app.use('/files', router.router);
|
|
20
|
-
|
|
21
|
-
describe('codim router', () => {
|
|
22
|
-
let listener;
|
|
23
|
-
async function saveLocators(locatorsObject) {
|
|
24
|
-
const request = superagent.post(`http://localhost:${listener.address().port}/files/locators`).send(locatorsObject);
|
|
25
|
-
await request;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async function loadLocators() {
|
|
29
|
-
const request = superagent.get(`http://localhost:${listener.address().port}/files/locators`);
|
|
30
|
-
const response = await request;
|
|
31
|
-
return JSON.parse(response.text);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
let tmpDir;
|
|
35
|
-
|
|
36
|
-
before((done) => {
|
|
37
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'tdk-test-'));
|
|
38
|
-
process.chdir(tmpDir);
|
|
39
|
-
listener = app.listen(0, () => done());
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
after(async () => {
|
|
43
|
-
await fs.promises.unlink(tmpDir).catch(() => {});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('saves locators', async () => {
|
|
47
|
-
await saveLocators({
|
|
48
|
-
locators: [{ id: 'foo', name: 'foo', body: { internal: 'bar' } }],
|
|
49
|
-
mergeIntoExisting: false,
|
|
50
|
-
});
|
|
51
|
-
const locators = await loadLocators();
|
|
52
|
-
expect(locators).to.deep.eq({
|
|
53
|
-
contents: {},
|
|
54
|
-
locators: {
|
|
55
|
-
foo: 'foo',
|
|
56
|
-
},
|
|
57
|
-
success: true,
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
});
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const _ = require('lodash');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const fsPromises = require('fs/promises');
|
|
6
|
-
const { fromPairs } = require('lodash');
|
|
7
|
-
const { buildCodeTests } = require('../../../runners/buildCodeTests');
|
|
8
|
-
const { AbortError } = require('../../../commons/AbortError');
|
|
9
|
-
|
|
10
|
-
const findTestFolder = _.memoize(async (fromFolder) => {
|
|
11
|
-
const files = await fsPromises.readdir(fromFolder);
|
|
12
|
-
// this is either invoked by running the Testim CLI from inside the tests folder or from inside the `init` folder
|
|
13
|
-
// so deal with the case we're inside tests.
|
|
14
|
-
const isInProjectFolder = files.includes('tests') && (await fsPromises.stat(path.join(fromFolder, 'tests'))).isDirectory();
|
|
15
|
-
if (isInProjectFolder) {
|
|
16
|
-
return path.join(fromFolder, 'tests');
|
|
17
|
-
}
|
|
18
|
-
return fromFolder;
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
async function getLocalLocators() {
|
|
22
|
-
const folder = await findTestFolder(process.cwd());
|
|
23
|
-
const locatorsFilePath = path.join(folder, 'locators', 'locators.js');
|
|
24
|
-
function parseLocators(buffer) {
|
|
25
|
-
// remove require calls to not read all the locators into memory when evaluating
|
|
26
|
-
// eslint-disable-next-line no-eval
|
|
27
|
-
return eval(buffer.toString().replace(/require/g, '(x => /locator\.(.*)\.json/.exec(x)[1])'));
|
|
28
|
-
}
|
|
29
|
-
const locators = await fsPromises.readFile(locatorsFilePath).then(parseLocators, () => ({}));
|
|
30
|
-
return _(Object.keys(locators)).map((id) => {
|
|
31
|
-
const escapedId = id.replace(/"/g, '\\"');
|
|
32
|
-
return [escapedId, locators[id]];
|
|
33
|
-
}).fromPairs().value();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async function findTests(folder = process.cwd()) {
|
|
37
|
-
const testFolder = await findTestFolder(folder);
|
|
38
|
-
const filesWithStat = await fsPromises.readdir(testFolder, { withFileTypes: true });
|
|
39
|
-
|
|
40
|
-
// things we know are not tests but end in js
|
|
41
|
-
const excluded = ['webpack.config.js', 'tsconfig.js', '.DS_Store', 'functions.js'];
|
|
42
|
-
const excludedFileTypes = ['.html', '.json'];
|
|
43
|
-
return filesWithStat
|
|
44
|
-
.filter(x =>
|
|
45
|
-
!excluded.includes(x.name) &&
|
|
46
|
-
!excludedFileTypes.some(type => x.name.endsWith(type)) &&
|
|
47
|
-
x.isFile() &&
|
|
48
|
-
!x.name.startsWith('.'),
|
|
49
|
-
)
|
|
50
|
-
.map(x => x.name);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* @param {Record<string, object | Promise<object>>} propsObject
|
|
55
|
-
* @returns {Promise<Record<string, object>>}
|
|
56
|
-
* */
|
|
57
|
-
async function promiseFromProps(propsObject) {
|
|
58
|
-
const entries = Object.entries(propsObject);
|
|
59
|
-
const values = entries.map(([, value]) => value);
|
|
60
|
-
const resolvedValues = await Promise.all(values);
|
|
61
|
-
for (let i = 0; i < resolvedValues.length; i++) {
|
|
62
|
-
entries[i][1] = resolvedValues[i];
|
|
63
|
-
}
|
|
64
|
-
return Object.fromEntries(entries);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async function getLocalLocatorContents(locators, full = false, originFolder = process.cwd()) {
|
|
68
|
-
const props = {};
|
|
69
|
-
if (full) {
|
|
70
|
-
const folder = await findTestFolder(originFolder);
|
|
71
|
-
for (const key of Object.values(locators)) {
|
|
72
|
-
props[key] = fsPromises.readFile(path.join(folder, 'locators', `locator.${key}.json`)).then(JSON.parse);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
try {
|
|
76
|
-
const contents = await promiseFromProps(props);
|
|
77
|
-
return contents;
|
|
78
|
-
} catch (e) {
|
|
79
|
-
// eslint-disable-next-line no-console
|
|
80
|
-
console.error(e);
|
|
81
|
-
return {};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
async function saveTest({
|
|
85
|
-
body, name, locators, language = 'javascript',
|
|
86
|
-
}) {
|
|
87
|
-
const folder = await findTestFolder(process.cwd());
|
|
88
|
-
const locatorsFilePath = path.join(folder, 'locators', 'locators.js');
|
|
89
|
-
let filename = path.join(folder, name);
|
|
90
|
-
if (!filename.startsWith(folder)) {
|
|
91
|
-
throw new Error('A test name must be a valid file name and inside the tests directory');
|
|
92
|
-
}
|
|
93
|
-
if (language === 'javascript') {
|
|
94
|
-
if (filename.endsWith('.js') && !filename.endsWith('.test.js')) {
|
|
95
|
-
filename = `${filename.substr(0, filename.length - 3)}.test.js`;
|
|
96
|
-
} else if (!filename.endsWith('.test.js')) {
|
|
97
|
-
filename += '.test.js';
|
|
98
|
-
}
|
|
99
|
-
} else if (filename.endsWith('.ts') && !filename.endsWith('.test.ts')) {
|
|
100
|
-
filename = `${filename.substr(0, filename.length - 3)}.test.ts`;
|
|
101
|
-
} else if (!filename.endsWith('.test.ts')) {
|
|
102
|
-
filename = `${filename}.test.ts`;
|
|
103
|
-
}
|
|
104
|
-
if (filename.endsWith('locators/locators.js')) {
|
|
105
|
-
throw new Error('Cannot override locators file from the internet as it is evaluated by the runner');
|
|
106
|
-
}
|
|
107
|
-
await fsPromises.writeFile(filename, body);
|
|
108
|
-
await fsPromises.mkdir(path.join(folder, 'locators')).catch(() => {});
|
|
109
|
-
for (const { id, body } of locators) {
|
|
110
|
-
await fsPromises.writeFile(path.join(folder, 'locators', `locator.${id}.json`), JSON.stringify(body));
|
|
111
|
-
}
|
|
112
|
-
const locatorMap = fromPairs(locators.map(({ name, id }) => [name, id]));
|
|
113
|
-
const localLocatorMap = await getLocalLocators();
|
|
114
|
-
Object.assign(localLocatorMap, locatorMap);
|
|
115
|
-
await writeLocators(locatorsFilePath, localLocatorMap);
|
|
116
|
-
}
|
|
117
|
-
async function writeLocators(locatorsFilePath, locatorMap) {
|
|
118
|
-
let content = 'module.exports = {\n';
|
|
119
|
-
for (const [key, value] of Object.entries(locatorMap)) {
|
|
120
|
-
content += ` "${key}": require('./locator.${value}.json'),\n`;
|
|
121
|
-
}
|
|
122
|
-
content += '};';
|
|
123
|
-
await fsPromises.writeFile(locatorsFilePath, content);
|
|
124
|
-
}
|
|
125
|
-
async function saveLocators(locators, { mergeIntoExisting } = { mergeIntoExisting: false }) {
|
|
126
|
-
const folder = await findTestFolder(process.cwd());
|
|
127
|
-
const locatorsFilePath = path.join(folder, 'locators', 'locators.js');
|
|
128
|
-
await fsPromises.mkdir(path.join(folder, 'locators')).catch(() => {});
|
|
129
|
-
|
|
130
|
-
for (const { name, id, elementLocator } of locators) {
|
|
131
|
-
await fsPromises.writeFile(path.join(folder, 'locators', `locator.${id}.json`), JSON.stringify({ name, id, elementLocator }));
|
|
132
|
-
}
|
|
133
|
-
const locatorMap = fromPairs(locators.map(({ name, id }) => [name, id]));
|
|
134
|
-
if (mergeIntoExisting) {
|
|
135
|
-
const localLocatorMap = await getLocalLocators();
|
|
136
|
-
Object.assign(locatorMap, localLocatorMap);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
await writeLocators(locatorsFilePath, locatorMap);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
async function compileFunctionsLibrary({ fileSystem, bypassWebpack } = {}, optionalAbortSignal = undefined) {
|
|
143
|
-
const folder = await findTestFolder(process.cwd());
|
|
144
|
-
if (optionalAbortSignal?.aborted) {
|
|
145
|
-
throw new AbortError();
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const functionsFile = path.join(folder, 'functions.js');
|
|
149
|
-
if (bypassWebpack?.testim) {
|
|
150
|
-
const Module = require('module');
|
|
151
|
-
// attempt to require without webpack compile - useful for puppeteer/selenium hybrid
|
|
152
|
-
const originalRequire = Module.prototype.require;
|
|
153
|
-
Module.prototype.require = function requireThatOverridesTestimTDK(id) {
|
|
154
|
-
if (id === 'testim') {
|
|
155
|
-
return bypassWebpack.testim;
|
|
156
|
-
}
|
|
157
|
-
// eslint-disable-next-line prefer-rest-params
|
|
158
|
-
return originalRequire.apply(this, arguments);
|
|
159
|
-
};
|
|
160
|
-
try {
|
|
161
|
-
// delete references to the old __testim from previous invocations
|
|
162
|
-
delete require.cache[require.resolve(functionsFile)];
|
|
163
|
-
const functions = require(functionsFile); // eslint-disable-line import/no-dynamic-require
|
|
164
|
-
// asynchronous require not supported - is this fine?
|
|
165
|
-
return functions;
|
|
166
|
-
} finally {
|
|
167
|
-
Module.prototype.require = originalRequire;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
const functionsAsAWebpackModule = await buildCodeTests([functionsFile], {
|
|
171
|
-
output: {
|
|
172
|
-
libraryTarget: 'umd',
|
|
173
|
-
library: 'tdk',
|
|
174
|
-
globalObject: 'globalThis',
|
|
175
|
-
},
|
|
176
|
-
cache: {
|
|
177
|
-
type: 'memory',
|
|
178
|
-
},
|
|
179
|
-
mode: 'development', // better debugging
|
|
180
|
-
}, {}, fileSystem, optionalAbortSignal);
|
|
181
|
-
// we always compile a single suite and a single file here
|
|
182
|
-
return functionsAsAWebpackModule.tests[0][0].code;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
module.exports = {
|
|
186
|
-
findTestFolder,
|
|
187
|
-
findTests,
|
|
188
|
-
getLocalLocators,
|
|
189
|
-
getLocalLocatorContents,
|
|
190
|
-
saveTest,
|
|
191
|
-
saveLocators,
|
|
192
|
-
compileFunctionsLibrary,
|
|
193
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { getPackageVersion } = require('../../../testimNpmDriver');
|
|
4
|
-
const { doLogin } = require('../../../credentialsManager');
|
|
5
|
-
const { getStartedWithStart } = require('../../../cliAgentMode');
|
|
6
|
-
|
|
7
|
-
module.exports = (app) => {
|
|
8
|
-
/**
|
|
9
|
-
* root endpoint
|
|
10
|
-
*/
|
|
11
|
-
app.get('/', (req, res) => {
|
|
12
|
-
const isStartMode = getStartedWithStart();
|
|
13
|
-
|
|
14
|
-
return res.status(200).json({ success: true, isTestimAgent: true, startMode: isStartMode });
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Get version route
|
|
19
|
-
*/
|
|
20
|
-
app.get('/version', (req, res) => {
|
|
21
|
-
res.status(200).json({
|
|
22
|
-
node: process.version,
|
|
23
|
-
app: getPackageVersion(),
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
app.get('/loginInfo', (req, res) => {
|
|
28
|
-
try {
|
|
29
|
-
const projects = JSON.parse(Buffer.from(req.query.info, 'base64').toString());
|
|
30
|
-
doLogin({ overwriteExisting: false, projects });
|
|
31
|
-
res.status(200).end();
|
|
32
|
-
} catch (err) {
|
|
33
|
-
res.status(400).end();
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
};
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const service = require('../../../stepPlayers/hybridStepPlayback');
|
|
4
|
-
const express = require('express');
|
|
5
|
-
const lazyRequire = require('../../../commons/lazyRequire');
|
|
6
|
-
const logger = require('../../../commons/logger').getLogger('hybrid-router');
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @param {{
|
|
10
|
-
webdriverApi: import("../../../player/WebdriverioWebDriverApi")
|
|
11
|
-
}} [testimStandaloneBrowser]
|
|
12
|
-
*/
|
|
13
|
-
module.exports.hybridRoutes = function hybridRoutes(testimStandaloneBrowser) {
|
|
14
|
-
const router = express.Router();
|
|
15
|
-
|
|
16
|
-
router.post('/run', (req, res) => {
|
|
17
|
-
if (!req.body || !req.body.step) {
|
|
18
|
-
res.status(400).send({
|
|
19
|
-
error: 'Missing step',
|
|
20
|
-
});
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const {
|
|
25
|
-
step,
|
|
26
|
-
context,
|
|
27
|
-
loginData, // is this safe to pass here?
|
|
28
|
-
} = req.body;
|
|
29
|
-
if (!testimStandaloneBrowser.webdriverApi) {
|
|
30
|
-
res.status(503).send({ success: false, reason: 'Testim Agent was not started with Testim Start.' });
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// The step run might take very long time, and it will still be valid
|
|
34
|
-
// so we set here unlimited timeout
|
|
35
|
-
req.setTimeout(0);
|
|
36
|
-
|
|
37
|
-
service.execute(
|
|
38
|
-
step,
|
|
39
|
-
context,
|
|
40
|
-
testimStandaloneBrowser.webdriverApi,
|
|
41
|
-
loginData,
|
|
42
|
-
undefined, // don't pass frameManager,
|
|
43
|
-
'agent'
|
|
44
|
-
).then((result) => {
|
|
45
|
-
res.status(200).send(result);
|
|
46
|
-
}).catch(e => {
|
|
47
|
-
logger.error('failed to run hybrid code', { e });
|
|
48
|
-
res.status(500).send(Object.assign({ success: false, error: e }));
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
router.post('/abort', (req, res) => {
|
|
53
|
-
if (!req.body || !req.body.stepResultId) {
|
|
54
|
-
res.status(400).send({
|
|
55
|
-
error: 'missing stepResultId',
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
try {
|
|
62
|
-
service.abort(req.body.stepResultId);
|
|
63
|
-
res.status(204).end();
|
|
64
|
-
} catch (e) {
|
|
65
|
-
if (e && e.message === 'No such stepResultId') {
|
|
66
|
-
res.status(400).send({
|
|
67
|
-
error: 'No such stepResultId',
|
|
68
|
-
});
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
logger.error('hybrid code abort unexpected error', { e });
|
|
73
|
-
res.status(500).send({
|
|
74
|
-
error: 'unexpected error',
|
|
75
|
-
info: `${e ? e.message : 'N/A'}`,
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
return router;
|
|
81
|
-
};
|
package/agent/routers/index.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const compression = require('compression');
|
|
4
|
-
const express = require('express');
|
|
5
|
-
const bodyParser = require('body-parser');
|
|
6
|
-
const cors = require('cors');
|
|
7
|
-
const { IS_ON_PREM, DISABLE_AGENT_ORIGIN_CHECK } = require('../../commons/config');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
module.exports = function (beforeMiddleware, standaloneBrowserInfo) {
|
|
11
|
-
const app = express();
|
|
12
|
-
beforeMiddleware(app);
|
|
13
|
-
|
|
14
|
-
// view engine setup
|
|
15
|
-
app.use(bodyParser.urlencoded({ extended: false, limit: '50mb' }));
|
|
16
|
-
app.use(compression());
|
|
17
|
-
app.use(bodyParser.json({ limit: '50mb' }));
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* set cors options
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
const whitelist = ['http://localhost:3000', 'https://app.testim.io', 'https://staging.testim.io', 'https://playground.testim.io',
|
|
24
|
-
'https://app.staging.testim.cc', 'chrome-extension://pebeiooilphfmbohdbhbomomkkoghoia', 'https://tta-crm.tricentis.com'];
|
|
25
|
-
const corsOptions = {
|
|
26
|
-
methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'],
|
|
27
|
-
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
28
|
-
credentials: true,
|
|
29
|
-
maxAge: 86400,
|
|
30
|
-
origin: (IS_ON_PREM || DISABLE_AGENT_ORIGIN_CHECK) ? '*' : whitelist,
|
|
31
|
-
};
|
|
32
|
-
app.use('*', cors(corsOptions));
|
|
33
|
-
|
|
34
|
-
// Routes
|
|
35
|
-
require('./general')(app);
|
|
36
|
-
|
|
37
|
-
app.use('/files', require('./codim/router').router);
|
|
38
|
-
|
|
39
|
-
app.use('/playground', require('./playground/router').router);
|
|
40
|
-
|
|
41
|
-
const cliJsCode = require('./cliJsCode');
|
|
42
|
-
app.use('/cliJs', cliJsCode.router);
|
|
43
|
-
|
|
44
|
-
app.use('/standalone-browser',
|
|
45
|
-
require('./standalone-browser/registerRoutes').standaloneBrowserRoutes(standaloneBrowserInfo)
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
app.use('/hybrid', require('./hybrid/registerRoutes').hybridRoutes(standaloneBrowserInfo));
|
|
49
|
-
|
|
50
|
-
// catch 404
|
|
51
|
-
app.use((req, res) => {
|
|
52
|
-
res.status(404).send('Endpoint Not Found');
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
return app;
|
|
56
|
-
};
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const express = require('express');
|
|
4
|
-
|
|
5
|
-
const router = express.Router();
|
|
6
|
-
const logger = require('../../../commons/logger').getLogger('playground-router');
|
|
7
|
-
const { ClientError, PlaygroundCodeError } = require('../../../errors');
|
|
8
|
-
const { runPlaygroundTest, stopPlaygroundTest, CODE_TYPES } = require('./service');
|
|
9
|
-
const { DISABLE_AGENT_ORIGIN_CHECK } = require('../../../commons/config');
|
|
10
|
-
|
|
11
|
-
const VALID_HOSTS = ['localhost', 'app.testim.io', 'playground.testim.io', 'staging.testim.io', 'app.staging.testim.cc', 'tta-crm.tricentis.com'];
|
|
12
|
-
|
|
13
|
-
const parseUrl = (url) => {
|
|
14
|
-
if (!url) {
|
|
15
|
-
return {};
|
|
16
|
-
}
|
|
17
|
-
try {
|
|
18
|
-
return new URL(url);
|
|
19
|
-
} catch (e) {
|
|
20
|
-
return {};
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const checkReferer = (req, res, next) => {
|
|
25
|
-
if (DISABLE_AGENT_ORIGIN_CHECK) {
|
|
26
|
-
return next();
|
|
27
|
-
}
|
|
28
|
-
const referer = req.headers.referer;
|
|
29
|
-
const origin = req.headers.origin;
|
|
30
|
-
if (!referer && !origin) {
|
|
31
|
-
return res.status(400).send();
|
|
32
|
-
}
|
|
33
|
-
const refererUrl = parseUrl(referer);
|
|
34
|
-
const originUrl = parseUrl(origin);
|
|
35
|
-
if (!VALID_HOSTS.includes(refererUrl.hostname) && !VALID_HOSTS.includes(originUrl.hostname)) {
|
|
36
|
-
return res.status(400).send();
|
|
37
|
-
}
|
|
38
|
-
return next();
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
router.post('/run', [checkReferer], async (req, res) => {
|
|
42
|
-
const body = req.body || {};
|
|
43
|
-
const { code, type } = body;
|
|
44
|
-
|
|
45
|
-
if (!code || !CODE_TYPES.includes(type)) {
|
|
46
|
-
res.status(400).send({ success: false, reason: 'missing arguments' });
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
await runPlaygroundTest(body);
|
|
52
|
-
res.send({ success: true });
|
|
53
|
-
} catch (e) {
|
|
54
|
-
if (e instanceof ClientError) {
|
|
55
|
-
res.status(404).send({ success: false });
|
|
56
|
-
return undefined;
|
|
57
|
-
}
|
|
58
|
-
if (e instanceof PlaygroundCodeError) {
|
|
59
|
-
res.json({ success: false, type: 'playground-error', stack: e.innerStack });
|
|
60
|
-
return undefined;
|
|
61
|
-
}
|
|
62
|
-
res.json({ success: false, reason: e.message });
|
|
63
|
-
logger.error(e);
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
router.post('/stop', (req, res) => {
|
|
68
|
-
try {
|
|
69
|
-
stopPlaygroundTest();
|
|
70
|
-
res.send({ success: true });
|
|
71
|
-
} catch (e) {
|
|
72
|
-
res.json({ success: false, reason: e.message });
|
|
73
|
-
logger.error(e);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
module.exports.router = router;
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const os = require('os');
|
|
6
|
-
const { fork } = require('child_process');
|
|
7
|
-
const { ClientError, PlaygroundCodeError } = require('../../../errors');
|
|
8
|
-
|
|
9
|
-
const CODE_TYPES = ['playwright', 'selenium', 'puppeteer'];
|
|
10
|
-
|
|
11
|
-
const runForks = {};
|
|
12
|
-
|
|
13
|
-
async function createTempFile(fileName, data, encoding = 'utf8') {
|
|
14
|
-
const fullPath = path.join(os.tmpdir(), fileName);
|
|
15
|
-
await fs.promises.writeFile(fullPath, data, encoding);
|
|
16
|
-
return fullPath;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const forkAsync = (fileFullPath) => {
|
|
20
|
-
let gotResolved;
|
|
21
|
-
const promise = new Promise(resolve => { gotResolved = resolve; });
|
|
22
|
-
|
|
23
|
-
const child = fork(fileFullPath, { stdio: ['inherit', 'inherit', 'inherit', 'ipc'] });
|
|
24
|
-
promise.child = child;
|
|
25
|
-
child.on('message', (message) => {
|
|
26
|
-
if (!message) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
const { type, error } = message;
|
|
30
|
-
if (error && ['uncaughtException', 'unhandledRejection'].includes(type)) {
|
|
31
|
-
gotResolved({ error: Object.assign(new PlaygroundCodeError(), { innerStack: message.error.stack }) });
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
child.on('error', (error) => {
|
|
35
|
-
gotResolved({ error });
|
|
36
|
-
});
|
|
37
|
-
child.on('exit', (exitCode) => {
|
|
38
|
-
gotResolved({ exitCode });
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
return promise;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
async function runCodeLocally({ code }) {
|
|
45
|
-
const forkId = Date.now();
|
|
46
|
-
try {
|
|
47
|
-
const codeWithExtra = `
|
|
48
|
-
module.paths = ${JSON.stringify(module.paths)};
|
|
49
|
-
process.on('unhandledRejection', (error) => {
|
|
50
|
-
process.send({type: 'unhandledRejection', error: {message: error.message, stack: error.stack}});
|
|
51
|
-
process.exit(1);
|
|
52
|
-
});
|
|
53
|
-
process.on('uncaughtException', (error) => {
|
|
54
|
-
process.send({type: 'uncaughtException', error: {message: error.message, stack: error.stack}});
|
|
55
|
-
process.exit(1);
|
|
56
|
-
});
|
|
57
|
-
${code};
|
|
58
|
-
`;
|
|
59
|
-
const fileFullPath = await createTempFile(`tst-playground-${Date.now()}.js`, codeWithExtra);
|
|
60
|
-
const promiseExec = forkAsync(fileFullPath);
|
|
61
|
-
runForks[forkId] = promiseExec.child;
|
|
62
|
-
const { error, exitCode } = await promiseExec;
|
|
63
|
-
if (error) {
|
|
64
|
-
throw error;
|
|
65
|
-
}
|
|
66
|
-
if (exitCode !== 0) {
|
|
67
|
-
throw new Error(`Process exited with exit code: ${exitCode}`);
|
|
68
|
-
}
|
|
69
|
-
return undefined;
|
|
70
|
-
} finally {
|
|
71
|
-
if (runForks[forkId]) {
|
|
72
|
-
runForks[forkId].kill();
|
|
73
|
-
delete runForks[forkId];
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async function runPlaygroundTest({ code, type }) {
|
|
79
|
-
if (['playwright', 'puppeteer', 'selenium'].includes(type)) {
|
|
80
|
-
return runCodeLocally({ code });
|
|
81
|
-
}
|
|
82
|
-
throw new ClientError();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async function stopPlaygroundTest() {
|
|
86
|
-
Object.keys(runForks).forEach((forkId) => {
|
|
87
|
-
runForks[forkId].kill();
|
|
88
|
-
delete runForks[forkId];
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
module.exports = {
|
|
93
|
-
CODE_TYPES,
|
|
94
|
-
runPlaygroundTest,
|
|
95
|
-
stopPlaygroundTest,
|
|
96
|
-
};
|