@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,419 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const _ = require('lodash');
|
|
4
|
-
const utils = require('../utils');
|
|
5
|
-
const Logger = require('../commons/logger');
|
|
6
|
-
const config = require('../commons/config');
|
|
7
|
-
const reporter = require('../reports/reporter');
|
|
8
|
-
const constants = require('../commons/constants');
|
|
9
|
-
const TestRunStatus = require('../testRunStatus');
|
|
10
|
-
const perf = require('../commons/performance-logger');
|
|
11
|
-
const gridService = require('../services/gridService');
|
|
12
|
-
const branchService = require('../services/branchService');
|
|
13
|
-
const ParallelWorkerManager = require('./ParallelWorkerManager');
|
|
14
|
-
const analyticsService = require('../services/analyticsService');
|
|
15
|
-
const testimServicesApi = require('../commons/testimServicesApi');
|
|
16
|
-
const testimCustomToken = require('../commons/testimCustomToken');
|
|
17
|
-
const RealDataService = require('../commons/socket/realDataService');
|
|
18
|
-
const { StopRunOnError, ArgError } = require('../errors');
|
|
19
|
-
const { getSuite, calcTestResultStatus, validateConfig } = require('./runnerUtils');
|
|
20
|
-
|
|
21
|
-
const guid = utils.guid;
|
|
22
|
-
const TESTIM_RUN_STATUS = constants.testRunStatus;
|
|
23
|
-
const logger = Logger.getLogger('test-plan-runner');
|
|
24
|
-
const TDK_CHILD_RESULTS_TIMEOUT = 1000 * 60 * 5;
|
|
25
|
-
|
|
26
|
-
/** @typedef {Awaited<ReturnType<typeof getSuite>>['tests'][number]} ExecutionList */
|
|
27
|
-
|
|
28
|
-
class TestPlanRunner {
|
|
29
|
-
/** @param {string=} customExtensionLocalLocation */
|
|
30
|
-
constructor(customExtensionLocalLocation) {
|
|
31
|
-
this.workerManager = new ParallelWorkerManager(customExtensionLocalLocation);
|
|
32
|
-
this.startTime = Date.now();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* @private
|
|
37
|
-
* @param {ExecutionList} beforeTests
|
|
38
|
-
* @param {ExecutionList} tests
|
|
39
|
-
* @param {ExecutionList} afterTests
|
|
40
|
-
* @param {string} branchToUse
|
|
41
|
-
* @param {import('../runOptions').RunnerOptions} tpOptions
|
|
42
|
-
* @param {string} executionId
|
|
43
|
-
* @param {string} executionName
|
|
44
|
-
* @param {TestRunStatus} testStatus
|
|
45
|
-
*/
|
|
46
|
-
async runTestAllPhases(beforeTests, tests, afterTests, branchToUse, tpOptions, executionId, executionName, testStatus) {
|
|
47
|
-
/** @type {{ [testResultId: string]: any; }} */
|
|
48
|
-
const executionResults = {};
|
|
49
|
-
const authData = testimCustomToken.getTokenV3UserData();
|
|
50
|
-
|
|
51
|
-
const runBeforeTests = async () => {
|
|
52
|
-
const workerCount = tpOptions.beforeParallel || 1;
|
|
53
|
-
const stopOnError = true;
|
|
54
|
-
const beforeTestsResults = await this.workerManager.runTests(beforeTests, testStatus, executionId, executionName, tpOptions, branchToUse, authData, workerCount, stopOnError);
|
|
55
|
-
Object.assign(executionResults, beforeTestsResults);
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const runTestPlanTests = async () => {
|
|
59
|
-
const workerCount = config.TESTIM_CONCURRENT_WORKER_COUNT || tpOptions.parallel;
|
|
60
|
-
const stopOnError = false;
|
|
61
|
-
perf.log('right before this.workerManager.runTests');
|
|
62
|
-
const testsResults = await this.workerManager.runTests(tests, testStatus, executionId, executionName, tpOptions, branchToUse, authData, workerCount, stopOnError);
|
|
63
|
-
perf.log('right after this.workerManager.runTests');
|
|
64
|
-
Object.assign(executionResults, testsResults);
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const runAfterTests = async () => {
|
|
68
|
-
const workerCount = tpOptions.afterParallel || 1;
|
|
69
|
-
const stopOnError = false;
|
|
70
|
-
const afterTestsResults = await this.workerManager.runTests(afterTests, testStatus, executionId, executionName, tpOptions, branchToUse, authData, workerCount, stopOnError);
|
|
71
|
-
Object.assign(executionResults, afterTestsResults);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const sessionType = utils.getSessionType(tpOptions);
|
|
75
|
-
analyticsService.analyticsExecsStart({ authData, executionId, projectId: tpOptions.project, sessionType });
|
|
76
|
-
perf.log('right before runBeforeTests');
|
|
77
|
-
try {
|
|
78
|
-
await runBeforeTests();
|
|
79
|
-
perf.log('right before runTestPlanTests');
|
|
80
|
-
await runTestPlanTests();
|
|
81
|
-
perf.log('right after runTestPlanTests');
|
|
82
|
-
await runAfterTests();
|
|
83
|
-
return executionResults;
|
|
84
|
-
} catch (err) {
|
|
85
|
-
logger.error('error running test plan', { err });
|
|
86
|
-
if (err instanceof StopRunOnError) {
|
|
87
|
-
return testStatus.markAllQueuedTests(executionId, constants.runnerTestStatus.ABORTED, 'aborted', false);
|
|
88
|
-
}
|
|
89
|
-
throw err;
|
|
90
|
-
} finally {
|
|
91
|
-
await handlePixelValidationBatches();
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async function handlePixelValidationBatches() {
|
|
95
|
-
if (tpOptions.lightweightMode?.disablePixelValidation) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
// When sessionPlayer is available, use it - as it only attempts to close batches that exist.
|
|
99
|
-
if (tpOptions.mode === constants.CLI_MODE.SELENIUM) {
|
|
100
|
-
const { EyeSdkBuilder } = require('../commons/getSessionPlayerRequire').getSessionPlayer();
|
|
101
|
-
await EyeSdkBuilder.closeBatch(executionId);
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
/** @type {Awaited<ReturnType<typeof testimServicesApi['getApplitoolsIntegrationData']>>} */
|
|
105
|
-
let applitoolsIntegrationData;
|
|
106
|
-
try {
|
|
107
|
-
if (!tpOptions.company?.activePlan?.premiumFeatures?.applitools) {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
applitoolsIntegrationData = await testimServicesApi.getApplitoolsIntegrationData(tpOptions.project);
|
|
111
|
-
if (_.isEmpty(applitoolsIntegrationData) || !executionId) {
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
const { runKey: apiKey, url: serverUrl } = applitoolsIntegrationData;
|
|
115
|
-
const tmpSDK = require('@applitools/eyes-sdk-core').makeSDK({ name: 'Testim.io', version: '4.0.0', spec: {} });
|
|
116
|
-
await tmpSDK.closeBatches({ settings: { batchIds: [executionId], serverUrl, apiKey } });
|
|
117
|
-
} catch (err) {
|
|
118
|
-
// If a batch with this name did not exist, do not log an error.
|
|
119
|
-
if (err.message && (err.message.startsWith('Request failed with status code 404') || err.message.startsWith('no batchIds were set'))) {
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
logger.error('Failed closing batch in extension mode', { err, projectId: tpOptions.project, applitoolsIntegrationData, batchIds: [executionId] });
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* @private
|
|
129
|
-
* @param {string} projectId
|
|
130
|
-
*/
|
|
131
|
-
async initRealDataService(projectId) {
|
|
132
|
-
const realDataService = new RealDataService();
|
|
133
|
-
await realDataService.init(projectId);
|
|
134
|
-
return realDataService;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* @private
|
|
139
|
-
* @param {RealDataService} realDataService
|
|
140
|
-
* @param {string} projectId
|
|
141
|
-
* @param {string} runId
|
|
142
|
-
* @param {TestRunStatus} testStatus
|
|
143
|
-
*/
|
|
144
|
-
async listenToTestCreatedInFile(realDataService, projectId, runId, testStatus) {
|
|
145
|
-
const childTestResults = {};
|
|
146
|
-
realDataService.joinToTestResultsByRunId(runId, projectId);
|
|
147
|
-
let isPromisePending = true;
|
|
148
|
-
/** @type {Promise<any[]>} */
|
|
149
|
-
const promise = new Promise(_resolve => {
|
|
150
|
-
const resolve = (val) => {
|
|
151
|
-
isPromisePending = false;
|
|
152
|
-
_resolve(val);
|
|
153
|
-
};
|
|
154
|
-
realDataService.listenToTestResultsByRunId(runId, testResult => {
|
|
155
|
-
const resultId = testResult.id;
|
|
156
|
-
if (!testStatus.getTestResult(resultId)) {
|
|
157
|
-
const prevTestResult = childTestResults[resultId];
|
|
158
|
-
const mergedTestResult = _.merge({}, prevTestResult, testResult, { resultId });
|
|
159
|
-
childTestResults[resultId] = mergedTestResult;
|
|
160
|
-
if (!prevTestResult || prevTestResult.status !== testResult.status) {
|
|
161
|
-
const parentTestResult = testStatus.getTestResult(mergedTestResult.parentResultId) || { workerId: 1 };
|
|
162
|
-
const workerId = parentTestResult.workerId;
|
|
163
|
-
if ([TESTIM_RUN_STATUS.RUNNING].includes(testResult.status)) {
|
|
164
|
-
reporter.onTestStarted(mergedTestResult, workerId);
|
|
165
|
-
}
|
|
166
|
-
if ([TESTIM_RUN_STATUS.COMPLETED].includes(testResult.status)) {
|
|
167
|
-
mergedTestResult.duration = (mergedTestResult.endTime - mergedTestResult.startTime) || 0;
|
|
168
|
-
reporter.onTestFinished(mergedTestResult, workerId);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const allChildTestResultCompleted = !(Object.values(childTestResults)
|
|
174
|
-
.some(result => ['QUEUED', 'RUNNING'].includes(result.runnerStatus)));
|
|
175
|
-
|
|
176
|
-
const allParentTestResultCompleted = !(Object.values(testStatus.getAllTestResults())
|
|
177
|
-
.some(result => ['QUEUED', 'RUNNING'].includes(result.status)));
|
|
178
|
-
|
|
179
|
-
if (allChildTestResultCompleted && allParentTestResultCompleted) {
|
|
180
|
-
return resolve(Object.values(childTestResults));
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (allParentTestResultCompleted && !allChildTestResultCompleted) {
|
|
184
|
-
// wait 10 sec to handle race condition when parent test result (file) finished before child test result
|
|
185
|
-
return utils.delay(10000)
|
|
186
|
-
.then(() => {
|
|
187
|
-
if (isPromisePending) {
|
|
188
|
-
// TODO(Benji) we are missing the child test results here.
|
|
189
|
-
// we are resolving here with partial data - we should consider fetching it
|
|
190
|
-
// from the server
|
|
191
|
-
resolve(childTestResults);
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
return undefined;
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
return await promise;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* @private
|
|
204
|
-
* @param {string} projectId
|
|
205
|
-
* @param {string} executionId
|
|
206
|
-
* @param {TestRunStatus} testStatus
|
|
207
|
-
*/
|
|
208
|
-
async initRealDataServiceAndListenToTestsCreatedInFile(projectId, executionId, testStatus) {
|
|
209
|
-
const realDataService = await this.initRealDataService(projectId);
|
|
210
|
-
return this.listenToTestCreatedInFile(realDataService, projectId, executionId, testStatus);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* @private
|
|
215
|
-
* @param {ExecutionList} beforeTests
|
|
216
|
-
* @param {ExecutionList} tests
|
|
217
|
-
* @param {ExecutionList} afterTests
|
|
218
|
-
* @param {import('../runOptions').RunnerOptions} tpOptions
|
|
219
|
-
* @param {string} testPlanName
|
|
220
|
-
* @param {string | null} testPlanId
|
|
221
|
-
* @param {string} branch
|
|
222
|
-
* @param {boolean=} isAnonymous
|
|
223
|
-
*/
|
|
224
|
-
async runTestPlan(beforeTests, tests, afterTests, tpOptions, testPlanName, testPlanId, branch, isAnonymous) {
|
|
225
|
-
const executionId = guid();
|
|
226
|
-
const projectId = tpOptions.project;
|
|
227
|
-
Logger.setExecutionId(executionId);
|
|
228
|
-
beforeTests.forEach(test => { test.isBeforeTestPlan = true; });
|
|
229
|
-
afterTests.forEach(test => { test.isAfterTestPlan = true; });
|
|
230
|
-
const testStatus = new TestRunStatus([].concat(beforeTests, tests, afterTests), tpOptions, testPlanId, branch);
|
|
231
|
-
|
|
232
|
-
const configs = _.chain([].concat(beforeTests, tests, afterTests))
|
|
233
|
-
.map(test => test.overrideTestConfig?.name || '')
|
|
234
|
-
.uniq()
|
|
235
|
-
.compact()
|
|
236
|
-
.value();
|
|
237
|
-
/** @type {string | null} */
|
|
238
|
-
const configName = configs?.length === 1 ? configs[0] : null;
|
|
239
|
-
|
|
240
|
-
const isCodeMode = tpOptions.files.length > 0;
|
|
241
|
-
const testNames = tpOptions.lightweightMode?.onlyTestIdsNoSuite ? [] : [].concat(beforeTests, tests, afterTests).map(test => test.name);
|
|
242
|
-
|
|
243
|
-
const testListInfoPromise = tpOptions.lightweightMode?.onlyTestIdsNoSuite ?
|
|
244
|
-
{ beforeTests, tests, afterTests } :
|
|
245
|
-
testStatus.executionStart(executionId, projectId, this.startTime, testPlanName, testNames);
|
|
246
|
-
let childTestResults;
|
|
247
|
-
if (isCodeMode) {
|
|
248
|
-
childTestResults = this.initRealDataServiceAndListenToTestsCreatedInFile(projectId, executionId, testStatus);
|
|
249
|
-
}
|
|
250
|
-
perf.log('before testListInfoPromise');
|
|
251
|
-
const testListInfo = await testListInfoPromise;
|
|
252
|
-
if (!tpOptions.lightweightMode?.onlyTestIdsNoSuite) {
|
|
253
|
-
reporter.onTestPlanStarted(testListInfo.beforeTests, testListInfo.tests, testListInfo.afterTests, testPlanName, executionId, isAnonymous, configName, isCodeMode);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
perf.log('before runTestAllPhases');
|
|
257
|
-
const results = await this.runTestAllPhases(testListInfo.beforeTests, testListInfo.tests, testListInfo.afterTests, branch, tpOptions, executionId, testPlanName || 'All Tests', testStatus);
|
|
258
|
-
const childResults = await utils.promiseTimeout(childTestResults, TDK_CHILD_RESULTS_TIMEOUT)
|
|
259
|
-
.catch(async () => {
|
|
260
|
-
logger.warn('timed out waiting for child results on websocket. using REST fallback', { projectId, executionId });
|
|
261
|
-
const testResults = await testimServicesApi.getRealData(projectId, 'testResult', `runId=${executionId}&sort=runOrder`);
|
|
262
|
-
return _.chain((testResults?.data?.docs) || [])
|
|
263
|
-
.groupBy('parentResultId')
|
|
264
|
-
.omit('undefined')
|
|
265
|
-
.values()
|
|
266
|
-
.flatten()
|
|
267
|
-
.value();
|
|
268
|
-
});
|
|
269
|
-
perf.log('before executionEnd');
|
|
270
|
-
await testStatus.executionEnd(executionId);
|
|
271
|
-
perf.log('after executionEnd');
|
|
272
|
-
return { results, executionId, testPlanName, configName, childTestResults: childResults };
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* @private
|
|
277
|
-
* @param {import('../runOptions').RunnerOptions} options
|
|
278
|
-
* @param {string} branchToUse
|
|
279
|
-
*/
|
|
280
|
-
async runTestPlans(options, branchToUse) {
|
|
281
|
-
logger.info('start to run test plan', {
|
|
282
|
-
options: Object.assign({}, options, { token: undefined, userParamsData: undefined }),
|
|
283
|
-
branchToUse,
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
function flattenTestListData(testPlansData) {
|
|
287
|
-
return _.flattenDeep(Object.values(testPlansData)).reduce((all, testRun) => all.concat(testRun.beforeTests, testRun.tests, testRun.afterTests), []);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
const testPlansResults = {};
|
|
291
|
-
const testPlansTests = {};
|
|
292
|
-
const projectId = options.project;
|
|
293
|
-
|
|
294
|
-
const data = await testimServicesApi.getTestPlanTestList(projectId, options.testPlan, options.testPlanIds, branchToUse, options.intersections);
|
|
295
|
-
const testPlans = data.testPlans;
|
|
296
|
-
const testPlansData = data.testPlansData;
|
|
297
|
-
if (!testPlans || testPlans.length === 0) {
|
|
298
|
-
throw new ArgError(`no test plan to run ${options.testPlan}`);
|
|
299
|
-
}
|
|
300
|
-
if (!testPlansData || Object.keys(testPlansData).length === 0) {
|
|
301
|
-
if (options.passZeroTests) {
|
|
302
|
-
return [];
|
|
303
|
-
}
|
|
304
|
-
throw new ArgError(`no test to run in test plan ${options.testPlan}`);
|
|
305
|
-
}
|
|
306
|
-
await validateConfig(options, flattenTestListData(testPlansData));
|
|
307
|
-
return await utils.promiseMap(testPlans, async testPlan => {
|
|
308
|
-
const id = testPlan.testPlanId;
|
|
309
|
-
testPlansResults[id] = {};
|
|
310
|
-
|
|
311
|
-
const tpOptions = Object.assign({}, options);
|
|
312
|
-
tpOptions.baseUrl = options.baseUrl || testPlan.startUrl;
|
|
313
|
-
tpOptions.host = options.host;
|
|
314
|
-
tpOptions.port = options.port;
|
|
315
|
-
tpOptions.gridId = options.gridId || testPlan.gridId;
|
|
316
|
-
|
|
317
|
-
//if user pass --grid with test plan we want to use grid option instead of host and port
|
|
318
|
-
if (options.grid) {
|
|
319
|
-
delete tpOptions.gridId;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
tpOptions.gridData = await gridService.getTestPlanGridData(options, testPlan);
|
|
324
|
-
|
|
325
|
-
const testPlanName = tpOptions.overrideExecutionName || testPlan.name;
|
|
326
|
-
return await utils.promiseMap(testPlansData[id], async testPlanTests => {
|
|
327
|
-
const res = await this.runTestPlan(testPlanTests.beforeTests, testPlanTests.tests, testPlanTests.afterTests, tpOptions, testPlanName, id, branchToUse);
|
|
328
|
-
const isCodeMode = options.files.length > 0;
|
|
329
|
-
reporter.onTestPlanFinished(res.results, testPlan.name, this.startTime, res.executionId, false, isCodeMode, res.childTestResults);
|
|
330
|
-
testPlansResults[id][res.executionId] = res.results;
|
|
331
|
-
|
|
332
|
-
const executions = Object.keys(testPlansResults[id]).map(exeId => ({
|
|
333
|
-
executionId: exeId,
|
|
334
|
-
status: calcTestResultStatus(testPlansResults[id][exeId]),
|
|
335
|
-
}));
|
|
336
|
-
const tests = Object.keys(testPlansResults[id]).map(exeId => testPlansResults[id][exeId]).reduce((testResult, test) => Object.assign(testResult, test), {});
|
|
337
|
-
const success = calcTestResultStatus(tests);
|
|
338
|
-
Object.assign(testPlansTests, tests);
|
|
339
|
-
const executionId = success ? executions[0].executionId : executions.find(exec => !exec.success).executionId;
|
|
340
|
-
await testimServicesApi.saveTestPlanResult(projectId, id, { success, executions, executionId });
|
|
341
|
-
return res;
|
|
342
|
-
});
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* @private
|
|
348
|
-
* @param {import('../runOptions').RunnerOptions} options
|
|
349
|
-
* @param {string} branchToUse
|
|
350
|
-
*/
|
|
351
|
-
async runAnonymousTestPlan(options, branchToUse) {
|
|
352
|
-
logger.info('start to run anonymous', {
|
|
353
|
-
options: Object.assign({}, options, { token: undefined }),
|
|
354
|
-
branchToUse,
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
perf.log('before getSuite');
|
|
358
|
-
const suiteResult = await getSuite(options, branchToUse);
|
|
359
|
-
perf.log('after getSuite');
|
|
360
|
-
|
|
361
|
-
if (!suiteResult?.tests[0]?.length) {
|
|
362
|
-
if (options.rerunFailedByRunId) {
|
|
363
|
-
throw new ArgError('No failed tests found in the provided run');
|
|
364
|
-
}
|
|
365
|
-
if (options.passZeroTests) {
|
|
366
|
-
return [];
|
|
367
|
-
}
|
|
368
|
-
throw new ArgError('No tests to run');
|
|
369
|
-
}
|
|
370
|
-
branchToUse = suiteResult.branch || branchToUse;
|
|
371
|
-
if (options.rerunFailedByRunId && !suiteResult.runName) {
|
|
372
|
-
if (!suiteResult.runExists) {
|
|
373
|
-
throw new ArgError('Invalid run ID - no such run.');
|
|
374
|
-
}
|
|
375
|
-
const isAnonymouslyNamedRun = suiteResult.runName === '';
|
|
376
|
-
if (isAnonymouslyNamedRun) {
|
|
377
|
-
suiteResult.runName = `rerun-${options.rerunFailedByRunId}`;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
const testPlanName = options.overrideExecutionName || suiteResult.runName || [].concat(options.label, options.name, options.suites).join(' ');
|
|
381
|
-
const isAnonymous = true;
|
|
382
|
-
perf.log('Right before validateConfig + runAnonymousTestPlan tests map');
|
|
383
|
-
return await utils.promiseMap(suiteResult.tests, async suiteTests => { // array of results per execution
|
|
384
|
-
//override result id for remote run mode and run only the first test data
|
|
385
|
-
if (options.resultId) {
|
|
386
|
-
const firstTest = suiteTests[0];
|
|
387
|
-
firstTest.resultId = options.resultId;
|
|
388
|
-
suiteTests = [firstTest];
|
|
389
|
-
}
|
|
390
|
-
await validateConfig(options, suiteTests);
|
|
391
|
-
perf.log('right before runTestPlan');
|
|
392
|
-
const res = await this.runTestPlan([], suiteTests, [], options, testPlanName, null, branchToUse, isAnonymous);
|
|
393
|
-
perf.log('right after runTestPlan');
|
|
394
|
-
const isCodeMode = options.files.length > 0;
|
|
395
|
-
await reporter.onTestPlanFinished(res.results, testPlanName, this.startTime, res.executionId, isAnonymous, isCodeMode, res.childTestResults);
|
|
396
|
-
return res;
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* @param {import('../runOptions').RunnerOptions} options
|
|
402
|
-
*/
|
|
403
|
-
async run(options) {
|
|
404
|
-
const branchToUse = branchService.getCurrentBranch();
|
|
405
|
-
let results = [];
|
|
406
|
-
if (utils.hasTestPlanFlag(options)) {
|
|
407
|
-
results = await this.runTestPlans(options, branchToUse);
|
|
408
|
-
} else {
|
|
409
|
-
results = await this.runAnonymousTestPlan(options, branchToUse);
|
|
410
|
-
}
|
|
411
|
-
const flattenResults = _.flattenDeep(results);
|
|
412
|
-
perf.log('right before onAllTestPlansFinished');
|
|
413
|
-
await reporter.onAllTestPlansFinished(flattenResults);
|
|
414
|
-
perf.log('right after onAllTestPlansFinished');
|
|
415
|
-
return flattenResults.map(res => res.results).reduce((total, cur) => Object.assign(total, cur), {});
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
module.exports = TestPlanRunner;
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const _ = require('lodash');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const MemoryFS = require('memory-fs');
|
|
6
|
-
const utils = require('../utils');
|
|
7
|
-
const lazyRequire = require('../commons/lazyRequire');
|
|
8
|
-
const { AbortError } = require('../commons/AbortError');
|
|
9
|
-
|
|
10
|
-
// compiler instance we can reuse between calls
|
|
11
|
-
const state = {
|
|
12
|
-
compiler: null,
|
|
13
|
-
webpackConfig: null,
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
exports.buildCodeTests = async function buildCodeTestsGuarded(
|
|
17
|
-
files,
|
|
18
|
-
webpackConfig,
|
|
19
|
-
runnerOptionsToMaybeCopyToTestEnvironment,
|
|
20
|
-
fileSystem,
|
|
21
|
-
optionalAbortSignal
|
|
22
|
-
) {
|
|
23
|
-
try {
|
|
24
|
-
return await buildCodeTests(files, webpackConfig, runnerOptionsToMaybeCopyToTestEnvironment, fileSystem, optionalAbortSignal);
|
|
25
|
-
} catch (e) {
|
|
26
|
-
if (e && e.code === 'ENOENT') {
|
|
27
|
-
// this is a webpack config error - it means webpack didn't pick up on a file change and didn't generate the correct bundle
|
|
28
|
-
// according to the guid hash
|
|
29
|
-
state.compiler = null;
|
|
30
|
-
state.webpackConfig = null;
|
|
31
|
-
fileSystem.data = {}; // reset the memory filesystem in case we left a mess there in the previous invocation
|
|
32
|
-
return await buildCodeTests(files, webpackConfig, runnerOptionsToMaybeCopyToTestEnvironment, fileSystem, optionalAbortSignal);
|
|
33
|
-
}
|
|
34
|
-
throw e;
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
async function buildCodeTests(files, webpackConfig = { mode: 'development' }, runnerOptionsToMaybeCopyToTestEnvironment = undefined, fileSystem = undefined, optionalAbortSignal = undefined) {
|
|
39
|
-
const webpack = await lazyRequire('webpack');
|
|
40
|
-
|
|
41
|
-
const suite = {};
|
|
42
|
-
const webpackConfigBeforeOurChanges = _.cloneDeep(webpackConfig);
|
|
43
|
-
|
|
44
|
-
webpackConfig.externals = { // define testim as an external
|
|
45
|
-
testim: '__testim',
|
|
46
|
-
// 'chai': '__chai'
|
|
47
|
-
};
|
|
48
|
-
webpackConfig.devtool = webpackConfig.devtool || 'inline-source-map';
|
|
49
|
-
|
|
50
|
-
webpackConfig.plugins = webpackConfig.plugins || [];
|
|
51
|
-
|
|
52
|
-
webpackConfig.plugins.push(new webpack.DefinePlugin(getEnvironmentVariables(runnerOptionsToMaybeCopyToTestEnvironment)), new webpack.DefinePlugin({
|
|
53
|
-
'process.argv': JSON.stringify(process.argv),
|
|
54
|
-
}));
|
|
55
|
-
files = files.map(f => path.resolve(f));
|
|
56
|
-
|
|
57
|
-
const fileHashes = files.map(() => utils.guid(30));
|
|
58
|
-
|
|
59
|
-
webpackConfig.optimization = { minimize: false };
|
|
60
|
-
|
|
61
|
-
const majorNodeVersion = Number(process.versions.node.split('.')[0]);
|
|
62
|
-
if (majorNodeVersion >= 17) {
|
|
63
|
-
// TODO ugly hack to be removed once using Webpack 5 - https://stackoverflow.com/a/73465262 + https://github.com/webpack/webpack/issues/14532
|
|
64
|
-
const crypto = require('crypto');
|
|
65
|
-
const originalCryptoCreateHash = crypto.createHash;
|
|
66
|
-
crypto.createHash = (algorithm, options) => originalCryptoCreateHash(algorithm === 'md4' ? 'sha256' : algorithm, options);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
webpackConfig.entry = Object.fromEntries(_.zip(files, fileHashes).map(([filename, hash]) => [hash, filename]));
|
|
70
|
-
webpackConfig.output = Object.assign({
|
|
71
|
-
devtoolModuleFilenameTemplate: (info) => `file:///${info.absoluteResourcePath}`,
|
|
72
|
-
filename: '[name].bundle.js',
|
|
73
|
-
}, webpackConfig.output);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
let compiler;
|
|
77
|
-
// if we are passed a filesystem, assume reuse between calls and turn on watch mode
|
|
78
|
-
if (fileSystem) {
|
|
79
|
-
// were we passed a filesystem before to compile the same thing?
|
|
80
|
-
if (_.isEqual(state.webpackConfig, webpackConfigBeforeOurChanges) && state.compiler) {
|
|
81
|
-
// we already have a compiler up and running
|
|
82
|
-
compiler = state.compiler;
|
|
83
|
-
} else {
|
|
84
|
-
state.webpackConfig = webpackConfigBeforeOurChanges;
|
|
85
|
-
state.compiler = webpack(webpackConfig);
|
|
86
|
-
compiler = state.compiler;
|
|
87
|
-
}
|
|
88
|
-
} else {
|
|
89
|
-
compiler = webpack(webpackConfig); // no caching
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const mfs = fileSystem || new MemoryFS();
|
|
93
|
-
compiler.outputFileSystem = mfs; // no need to write compiled tests to disk
|
|
94
|
-
|
|
95
|
-
// This can only reject
|
|
96
|
-
const abortSignalPromise = utils.promiseFromCallback(cb => {
|
|
97
|
-
if (optionalAbortSignal) {
|
|
98
|
-
optionalAbortSignal.addEventListener('abort', () => {
|
|
99
|
-
cb(new AbortError());
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// run compiler:
|
|
105
|
-
try {
|
|
106
|
-
const stats = await Promise.race([utils.promiseFromCallback(cb => compiler.run(cb)), abortSignalPromise]);
|
|
107
|
-
if (stats.hasErrors()) {
|
|
108
|
-
throw new Error(stats.toJson().errors);
|
|
109
|
-
}
|
|
110
|
-
} catch (e) {
|
|
111
|
-
const { ArgError } = require('../errors');
|
|
112
|
-
|
|
113
|
-
const cantFindFile = e.message.match(/Entry module not found: Error: Can't resolve '(.*)'/);
|
|
114
|
-
if (cantFindFile && cantFindFile.length === 2) {
|
|
115
|
-
if (webpackConfig.output && webpackConfig.output.library === 'tdk') {
|
|
116
|
-
throw new ArgError(`Could not open dev-kit functions file in ${cantFindFile[1]}`);
|
|
117
|
-
}
|
|
118
|
-
throw new ArgError(`Can't find test files in: '${cantFindFile[1]}'`);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
throw new ArgError(`Compilation Webpack Error in tests: ${e.message}`);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/** @type {{ code: string; name: string; }[]} */
|
|
125
|
-
const fileResults = files.map((file, i) => ({ code: mfs.readFileSync(path.resolve('./dist', `${fileHashes[i]}.bundle.js`)), name: file })); // read all files
|
|
126
|
-
|
|
127
|
-
suite.tests = [fileResults.map(({ code, name }) => ({
|
|
128
|
-
code: code.toString(),
|
|
129
|
-
baseUrl: '', // not supported at the moment
|
|
130
|
-
name: path.resolve(name),
|
|
131
|
-
testConfig: {},
|
|
132
|
-
testConfigId: null,
|
|
133
|
-
testId: utils.guid(),
|
|
134
|
-
resultId: utils.guid(),
|
|
135
|
-
isTestsContainer: true,
|
|
136
|
-
}))];
|
|
137
|
-
suite.runName = `Testim Dev Kit Run ${new Date().toLocaleString()}`;
|
|
138
|
-
return suite;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// copied mostly from facebook/create-react-app/blob/8b7b819b4b9e6ba457e011e92e33266690e26957/packages/react-scripts/config/env.js
|
|
142
|
-
function getEnvironmentVariables(runnerOptionsToMaybeCopyToTestEnvironment) {
|
|
143
|
-
const fromEnvironment = _.fromPairs(
|
|
144
|
-
Object.keys(process.env)
|
|
145
|
-
.filter(key => /^TDK_/i.test(key) || key === 'BASE_URL')
|
|
146
|
-
.map(key => [key, process.env[key]])
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
const fromConfig = {
|
|
150
|
-
BASE_URL: runnerOptionsToMaybeCopyToTestEnvironment.baseUrl,
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
return {
|
|
154
|
-
'process.env': stringifyValues({ ...fromConfig, ...fromEnvironment }),
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
function stringifyValues(object) {
|
|
158
|
-
return _.fromPairs(Object.entries(object).map(([key, value]) => [key, JSON.stringify(value)]));
|
|
159
|
-
}
|
package/runners/runnerUtils.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const _ = require('lodash');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const utils = require('../utils');
|
|
6
|
-
const analytics = require('../commons/testimAnalytics');
|
|
7
|
-
const { ArgError } = require('../errors');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @param {import('../runOptions').RunnerOptions} options
|
|
12
|
-
* @param {string} branchToUse
|
|
13
|
-
*/
|
|
14
|
-
async function getSuite(options, branchToUse) {
|
|
15
|
-
if (options.lightweightMode?.onlyTestIdsNoSuite && options.testId) {
|
|
16
|
-
return { tests: [options.testId.map(testId => ({ testId, testConfig: {}, resultId: utils.guid() }))] };
|
|
17
|
-
}
|
|
18
|
-
// local code test
|
|
19
|
-
if (options.files.length > 0) {
|
|
20
|
-
const { buildCodeTests } = require('./buildCodeTests');
|
|
21
|
-
let webpackConfig = {};
|
|
22
|
-
if (options.webpackConfig) {
|
|
23
|
-
const webpackConfigPath = path.join(process.cwd(), options.webpackConfig);
|
|
24
|
-
webpackConfig = require(webpackConfigPath); // eslint-disable-line import/no-dynamic-require
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return buildCodeTests(options.files, webpackConfig, { baseUrl: options.baseUrl });
|
|
28
|
-
}
|
|
29
|
-
// regular test
|
|
30
|
-
const servicesApi = require('../commons/testimServicesApi');
|
|
31
|
-
return await servicesApi.getSuiteTestList({
|
|
32
|
-
projectId: options.project,
|
|
33
|
-
labels: options.label,
|
|
34
|
-
testIds: options.testId,
|
|
35
|
-
testNames: options.name,
|
|
36
|
-
testConfigNames: options.testConfigNames,
|
|
37
|
-
suiteNames: options.suites,
|
|
38
|
-
suiteIds: options.suiteIds,
|
|
39
|
-
branch: branchToUse,
|
|
40
|
-
rerunFailedByRunId: options.rerunFailedByRunId,
|
|
41
|
-
testConfigIds: options.testConfigIds,
|
|
42
|
-
intersections: options.intersections,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
function calcTestResultStatus(tests) {
|
|
48
|
-
const total = Object.keys(tests).length;
|
|
49
|
-
const passed = Object.keys(tests).reduce((count, resultId) => count + (tests[resultId].success === true ? 1 : 0), 0);
|
|
50
|
-
return total === passed;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @param {import('../runOptions').RunnerOptions} options
|
|
56
|
-
* @param {import('./TestPlanRunner').ExecutionList} testList
|
|
57
|
-
*/
|
|
58
|
-
async function validateConfig(options, testList) {
|
|
59
|
-
const supportedBrowsers = options.mode === 'extension' ? [
|
|
60
|
-
'edge-chromium', 'chrome',
|
|
61
|
-
] : [
|
|
62
|
-
'firefox', 'chrome', 'edge-chromium', 'safari', 'safari technology preview', 'browser', 'android', 'ios', 'iphone', 'ipad',
|
|
63
|
-
];
|
|
64
|
-
const diff = _.difference(utils.getUniqBrowsers(options, testList), supportedBrowsers);
|
|
65
|
-
|
|
66
|
-
if (diff.length > 0) {
|
|
67
|
-
analytics.trackWithCIUser('invalid-config-run', {
|
|
68
|
-
browser: diff.join(', '),
|
|
69
|
-
mode: 'runner',
|
|
70
|
-
});
|
|
71
|
-
throw new ArgError(`browser type <${diff}> is not supported in ${options.mode} mode.`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return testList;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
module.exports = {
|
|
78
|
-
getSuite,
|
|
79
|
-
calcTestResultStatus,
|
|
80
|
-
validateConfig,
|
|
81
|
-
};
|