codeceptjs 3.4.1 → 3.5.1-2.beta.7
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/README.md +31 -30
- package/bin/codecept.js +1 -1
- package/lib/actor.js +6 -3
- package/lib/ai.js +180 -0
- package/lib/cli.js +13 -3
- package/lib/codecept.js +8 -0
- package/lib/colorUtils.js +10 -0
- package/lib/command/definitions.js +2 -7
- package/lib/command/dryRun.js +11 -2
- package/lib/command/generate.js +46 -3
- package/lib/command/info.js +24 -0
- package/lib/command/init.js +64 -6
- package/lib/command/interactive.js +15 -1
- package/lib/command/run-multiple/collection.js +17 -5
- package/lib/command/run-multiple.js +4 -2
- package/lib/command/run-workers.js +68 -5
- package/lib/command/run.js +7 -0
- package/lib/command/workers/runTests.js +39 -0
- package/lib/container.js +13 -3
- package/lib/data/context.js +14 -6
- package/lib/event.js +4 -0
- package/lib/helper/ApiDataFactory.js +2 -1
- package/lib/helper/Appium.js +116 -29
- package/lib/helper/Expect.js +422 -0
- package/lib/helper/FileSystem.js +1 -1
- package/lib/helper/GraphQL.js +25 -0
- package/lib/helper/JSONResponse.js +4 -4
- package/lib/helper/Nightmare.js +10 -5
- package/lib/helper/OpenAI.js +126 -0
- package/lib/helper/Playwright.js +1298 -229
- package/lib/helper/Protractor.js +12 -7
- package/lib/helper/Puppeteer.js +204 -64
- package/lib/helper/REST.js +15 -5
- package/lib/helper/TestCafe.js +45 -10
- package/lib/helper/WebDriver.js +252 -83
- package/lib/helper/errors/ElementNotFound.js +2 -1
- package/lib/helper/extras/PlaywrightReactVueLocator.js +38 -0
- package/lib/helper/scripts/blurElement.js +17 -0
- package/lib/helper/scripts/focusElement.js +17 -0
- package/lib/helper/scripts/highlightElement.js +20 -0
- package/lib/html.js +258 -0
- package/lib/interfaces/bdd.js +1 -1
- package/lib/interfaces/gherkin.js +37 -3
- package/lib/interfaces/scenarioConfig.js +1 -0
- package/lib/listener/retry.js +2 -1
- package/lib/locator.js +17 -4
- package/lib/mochaFactory.js +2 -1
- package/lib/output.js +1 -1
- package/lib/pause.js +78 -19
- package/lib/plugin/autoLogin.js +45 -10
- package/lib/plugin/debugErrors.js +67 -0
- package/lib/plugin/fakerTransform.js +4 -6
- package/lib/plugin/heal.js +209 -0
- package/lib/plugin/retryFailedStep.js +10 -1
- package/lib/plugin/retryTo.js +2 -4
- package/lib/plugin/screenshotOnFail.js +11 -2
- package/lib/plugin/selenoid.js +6 -1
- package/lib/plugin/standardActingHelpers.js +0 -2
- package/lib/plugin/stepByStepReport.js +2 -2
- package/lib/plugin/tryTo.js +5 -7
- package/lib/plugin/wdio.js +0 -1
- package/lib/recorder.js +22 -11
- package/lib/secret.js +5 -4
- package/lib/session.js +1 -1
- package/lib/step.js +36 -12
- package/lib/ui.js +5 -3
- package/lib/utils.js +22 -1
- package/lib/workers.js +83 -10
- package/package.json +117 -95
- package/translations/de-DE.js +5 -0
- package/translations/fr-FR.js +14 -1
- package/translations/it-IT.js +1 -0
- package/translations/ja-JP.js +14 -9
- package/translations/pl-PL.js +5 -0
- package/translations/pt-BR.js +1 -0
- package/translations/ru-RU.js +1 -0
- package/translations/zh-CN.js +5 -0
- package/translations/zh-TW.js +5 -0
- package/typings/index.d.ts +51 -15
- package/typings/promiseBasedTypes.d.ts +864 -802
- package/typings/types.d.ts +1339 -744
- package/CHANGELOG.md +0 -2427
- package/docs/advanced.md +0 -351
- package/docs/api.md +0 -323
- package/docs/basics.md +0 -980
- package/docs/bdd.md +0 -535
- package/docs/best.md +0 -237
- package/docs/books.md +0 -37
- package/docs/bootstrap.md +0 -135
- package/docs/build/ApiDataFactory.js +0 -409
- package/docs/build/Appium.js +0 -1938
- package/docs/build/FileSystem.js +0 -228
- package/docs/build/GraphQL.js +0 -204
- package/docs/build/GraphQLDataFactory.js +0 -309
- package/docs/build/JSONResponse.js +0 -338
- package/docs/build/Mochawesome.js +0 -71
- package/docs/build/Nightmare.js +0 -2145
- package/docs/build/Playwright.js +0 -3986
- package/docs/build/Polly.js +0 -42
- package/docs/build/Protractor.js +0 -2699
- package/docs/build/Puppeteer.js +0 -3710
- package/docs/build/REST.js +0 -334
- package/docs/build/SeleniumWebdriver.js +0 -76
- package/docs/build/TestCafe.js +0 -2057
- package/docs/build/WebDriver.js +0 -4017
- package/docs/changelog.md +0 -2436
- package/docs/commands.md +0 -254
- package/docs/community-helpers.md +0 -58
- package/docs/configuration.md +0 -157
- package/docs/continuous-integration.md +0 -22
- package/docs/custom-helpers.md +0 -306
- package/docs/data.md +0 -375
- package/docs/detox.md +0 -235
- package/docs/docker.md +0 -137
- package/docs/email.md +0 -183
- package/docs/examples.md +0 -149
- package/docs/helpers/ApiDataFactory.md +0 -266
- package/docs/helpers/Appium.md +0 -1312
- package/docs/helpers/Detox.md +0 -586
- package/docs/helpers/FileSystem.md +0 -152
- package/docs/helpers/GraphQL.md +0 -130
- package/docs/helpers/GraphQLDataFactory.md +0 -226
- package/docs/helpers/JSONResponse.md +0 -254
- package/docs/helpers/Mochawesome.md +0 -8
- package/docs/helpers/MockRequest.md +0 -377
- package/docs/helpers/Nightmare.md +0 -1256
- package/docs/helpers/Playwright.md +0 -2208
- package/docs/helpers/Polly.md +0 -44
- package/docs/helpers/Puppeteer-firefox.md +0 -86
- package/docs/helpers/Puppeteer.md +0 -2141
- package/docs/helpers/REST.md +0 -217
- package/docs/helpers/TestCafe.md +0 -1222
- package/docs/helpers/WebDriver.md +0 -2319
- package/docs/hooks.md +0 -340
- package/docs/index.md +0 -111
- package/docs/installation.md +0 -75
- package/docs/internal-api.md +0 -265
- package/docs/locators.md +0 -331
- package/docs/mobile-react-native-locators.md +0 -67
- package/docs/mobile.md +0 -297
- package/docs/nightmare.md +0 -223
- package/docs/pageobjects.md +0 -291
- package/docs/parallel.md +0 -232
- package/docs/playwright.md +0 -609
- package/docs/plugins.md +0 -1171
- package/docs/puppeteer.md +0 -316
- package/docs/quickstart.md +0 -163
- package/docs/react.md +0 -69
- package/docs/reports.md +0 -392
- package/docs/secrets.md +0 -30
- package/docs/shadow.md +0 -68
- package/docs/shared/keys.mustache +0 -31
- package/docs/shared/react.mustache +0 -1
- package/docs/testcafe.md +0 -174
- package/docs/translation.md +0 -247
- package/docs/tutorial.md +0 -271
- package/docs/typescript.md +0 -180
- package/docs/ui.md +0 -59
- package/docs/videos.md +0 -28
- package/docs/visual.md +0 -202
- package/docs/vue.md +0 -121
- package/docs/webapi/amOnPage.mustache +0 -11
- package/docs/webapi/appendField.mustache +0 -9
- package/docs/webapi/attachFile.mustache +0 -12
- package/docs/webapi/checkOption.mustache +0 -13
- package/docs/webapi/clearCookie.mustache +0 -10
- package/docs/webapi/clearField.mustache +0 -9
- package/docs/webapi/click.mustache +0 -25
- package/docs/webapi/clickLink.mustache +0 -8
- package/docs/webapi/closeCurrentTab.mustache +0 -7
- package/docs/webapi/closeOtherTabs.mustache +0 -8
- package/docs/webapi/dontSee.mustache +0 -11
- package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
- package/docs/webapi/dontSeeCookie.mustache +0 -8
- package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
- package/docs/webapi/dontSeeElement.mustache +0 -8
- package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
- package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
- package/docs/webapi/dontSeeInField.mustache +0 -11
- package/docs/webapi/dontSeeInSource.mustache +0 -8
- package/docs/webapi/dontSeeInTitle.mustache +0 -8
- package/docs/webapi/doubleClick.mustache +0 -13
- package/docs/webapi/downloadFile.mustache +0 -12
- package/docs/webapi/dragAndDrop.mustache +0 -9
- package/docs/webapi/dragSlider.mustache +0 -11
- package/docs/webapi/executeAsyncScript.mustache +0 -24
- package/docs/webapi/executeScript.mustache +0 -26
- package/docs/webapi/fillField.mustache +0 -16
- package/docs/webapi/forceClick.mustache +0 -28
- package/docs/webapi/forceRightClick.mustache +0 -18
- package/docs/webapi/grabAllWindowHandles.mustache +0 -7
- package/docs/webapi/grabAttributeFrom.mustache +0 -10
- package/docs/webapi/grabAttributeFromAll.mustache +0 -9
- package/docs/webapi/grabBrowserLogs.mustache +0 -9
- package/docs/webapi/grabCookie.mustache +0 -11
- package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
- package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
- package/docs/webapi/grabCurrentUrl.mustache +0 -9
- package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
- package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
- package/docs/webapi/grabElementBoundingRect.mustache +0 -20
- package/docs/webapi/grabGeoLocation.mustache +0 -8
- package/docs/webapi/grabHTMLFrom.mustache +0 -10
- package/docs/webapi/grabHTMLFromAll.mustache +0 -9
- package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
- package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
- package/docs/webapi/grabPageScrollPosition.mustache +0 -8
- package/docs/webapi/grabPopupText.mustache +0 -5
- package/docs/webapi/grabSource.mustache +0 -8
- package/docs/webapi/grabTextFrom.mustache +0 -10
- package/docs/webapi/grabTextFromAll.mustache +0 -9
- package/docs/webapi/grabTitle.mustache +0 -8
- package/docs/webapi/grabValueFrom.mustache +0 -9
- package/docs/webapi/grabValueFromAll.mustache +0 -8
- package/docs/webapi/moveCursorTo.mustache +0 -12
- package/docs/webapi/openNewTab.mustache +0 -7
- package/docs/webapi/pressKey.mustache +0 -12
- package/docs/webapi/pressKeyDown.mustache +0 -12
- package/docs/webapi/pressKeyUp.mustache +0 -12
- package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
- package/docs/webapi/refreshPage.mustache +0 -6
- package/docs/webapi/resizeWindow.mustache +0 -6
- package/docs/webapi/rightClick.mustache +0 -14
- package/docs/webapi/saveElementScreenshot.mustache +0 -10
- package/docs/webapi/saveScreenshot.mustache +0 -12
- package/docs/webapi/say.mustache +0 -10
- package/docs/webapi/scrollIntoView.mustache +0 -11
- package/docs/webapi/scrollPageToBottom.mustache +0 -6
- package/docs/webapi/scrollPageToTop.mustache +0 -6
- package/docs/webapi/scrollTo.mustache +0 -12
- package/docs/webapi/see.mustache +0 -11
- package/docs/webapi/seeAttributesOnElements.mustache +0 -9
- package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
- package/docs/webapi/seeCookie.mustache +0 -8
- package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
- package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
- package/docs/webapi/seeElement.mustache +0 -8
- package/docs/webapi/seeElementInDOM.mustache +0 -8
- package/docs/webapi/seeInCurrentUrl.mustache +0 -8
- package/docs/webapi/seeInField.mustache +0 -12
- package/docs/webapi/seeInPopup.mustache +0 -8
- package/docs/webapi/seeInSource.mustache +0 -7
- package/docs/webapi/seeInTitle.mustache +0 -8
- package/docs/webapi/seeNumberOfElements.mustache +0 -11
- package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
- package/docs/webapi/seeTextEquals.mustache +0 -9
- package/docs/webapi/seeTitleEquals.mustache +0 -8
- package/docs/webapi/selectOption.mustache +0 -21
- package/docs/webapi/setCookie.mustache +0 -16
- package/docs/webapi/setGeoLocation.mustache +0 -12
- package/docs/webapi/switchTo.mustache +0 -9
- package/docs/webapi/switchToNextTab.mustache +0 -10
- package/docs/webapi/switchToPreviousTab.mustache +0 -10
- package/docs/webapi/type.mustache +0 -18
- package/docs/webapi/uncheckOption.mustache +0 -13
- package/docs/webapi/wait.mustache +0 -8
- package/docs/webapi/waitForClickable.mustache +0 -11
- package/docs/webapi/waitForDetached.mustache +0 -10
- package/docs/webapi/waitForElement.mustache +0 -11
- package/docs/webapi/waitForEnabled.mustache +0 -6
- package/docs/webapi/waitForFunction.mustache +0 -17
- package/docs/webapi/waitForInvisible.mustache +0 -10
- package/docs/webapi/waitForText.mustache +0 -13
- package/docs/webapi/waitForValue.mustache +0 -10
- package/docs/webapi/waitForVisible.mustache +0 -10
- package/docs/webapi/waitInUrl.mustache +0 -9
- package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
- package/docs/webapi/waitToHide.mustache +0 -10
- package/docs/webapi/waitUrlEquals.mustache +0 -10
- package/docs/webdriver.md +0 -657
- package/docs/wiki/Books-&-Posts.md +0 -27
- package/docs/wiki/Community-Helpers-&-Plugins.md +0 -49
- package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +0 -29
- package/docs/wiki/Examples.md +0 -139
- package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -68
- package/docs/wiki/Home.md +0 -16
- package/docs/wiki/Release-Process.md +0 -24
- package/docs/wiki/Roadmap.md +0 -23
- package/docs/wiki/Tests.md +0 -1393
- package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -153
- package/docs/wiki/Videos.md +0 -19
package/lib/command/info.js
CHANGED
|
@@ -37,3 +37,27 @@ module.exports = async function (path) {
|
|
|
37
37
|
output.print('Please copy environment info when you report issues on GitHub: https://github.com/Codeception/CodeceptJS/issues');
|
|
38
38
|
output.print('***************************************');
|
|
39
39
|
};
|
|
40
|
+
|
|
41
|
+
module.exports.getMachineInfo = async () => {
|
|
42
|
+
const info = {
|
|
43
|
+
nodeInfo: await envinfo.helpers.getNodeInfo(),
|
|
44
|
+
osInfo: await envinfo.helpers.getOSInfo(),
|
|
45
|
+
cpuInfo: await envinfo.helpers.getCPUInfo(),
|
|
46
|
+
chromeInfo: await envinfo.helpers.getChromeInfo(),
|
|
47
|
+
edgeInfo: await envinfo.helpers.getEdgeInfo(),
|
|
48
|
+
firefoxInfo: await envinfo.helpers.getFirefoxInfo(),
|
|
49
|
+
safariInfo: await envinfo.helpers.getSafariInfo(),
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
output.print('***************************************');
|
|
53
|
+
for (const [key, value] of Object.entries(info)) {
|
|
54
|
+
if (Array.isArray(value)) {
|
|
55
|
+
output.print(`${key}: ${value[1]}`);
|
|
56
|
+
} else {
|
|
57
|
+
output.print(`${key}: ${JSON.stringify(value, null, ' ')}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
output.print('If you need more detailed info, just run this: npx codeceptjs info');
|
|
61
|
+
output.print('***************************************');
|
|
62
|
+
return info;
|
|
63
|
+
};
|
package/lib/command/init.js
CHANGED
|
@@ -20,7 +20,7 @@ const defaultConfig = {
|
|
|
20
20
|
include: {},
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
const helpers = ['Playwright', 'WebDriver', 'Puppeteer', 'REST', 'GraphQL', 'Appium', 'TestCafe'
|
|
23
|
+
const helpers = ['Playwright', 'WebDriver', 'Puppeteer', 'REST', 'GraphQL', 'Appium', 'TestCafe'];
|
|
24
24
|
const translations = Object.keys(require('../../translations'));
|
|
25
25
|
|
|
26
26
|
const noTranslation = 'English (no localization)';
|
|
@@ -55,6 +55,18 @@ module.exports = function() {
|
|
|
55
55
|
}
|
|
56
56
|
`;
|
|
57
57
|
|
|
58
|
+
const defaultActorTs = `// in this file you can append custom step methods to 'I' object
|
|
59
|
+
|
|
60
|
+
export = function() {
|
|
61
|
+
return actor({
|
|
62
|
+
|
|
63
|
+
// Define custom steps here, use 'this' to access default methods of I.
|
|
64
|
+
// It is recommended to place a general 'login' function here.
|
|
65
|
+
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
69
|
+
|
|
58
70
|
module.exports = function (initPath) {
|
|
59
71
|
const testsPath = getTestRoot(initPath);
|
|
60
72
|
|
|
@@ -188,8 +200,14 @@ module.exports = function (initPath) {
|
|
|
188
200
|
// create steps file by default
|
|
189
201
|
// no extra step file for typescript (as it doesn't match TS conventions)
|
|
190
202
|
const stepFile = `./steps_file.${extension}`;
|
|
191
|
-
fs.writeFileSync(path.join(testsPath, stepFile), defaultActor);
|
|
192
|
-
|
|
203
|
+
fs.writeFileSync(path.join(testsPath, stepFile), extension === 'ts' ? defaultActorTs : defaultActor);
|
|
204
|
+
|
|
205
|
+
if (isTypeScript) {
|
|
206
|
+
config.include = _actorTranslation('./steps_file', config.translation);
|
|
207
|
+
} else {
|
|
208
|
+
config.include = _actorTranslation(stepFile, config.translation);
|
|
209
|
+
}
|
|
210
|
+
|
|
193
211
|
print(`Steps file created at ${stepFile}`);
|
|
194
212
|
|
|
195
213
|
let configSource;
|
|
@@ -304,7 +322,17 @@ module.exports = function (initPath) {
|
|
|
304
322
|
};
|
|
305
323
|
|
|
306
324
|
print('Configure helpers...');
|
|
307
|
-
inquirer.prompt(helperConfigs).then((helperResult) => {
|
|
325
|
+
inquirer.prompt(helperConfigs).then(async (helperResult) => {
|
|
326
|
+
if (helperResult.Playwright_browser === 'electron') {
|
|
327
|
+
delete helperResult.Playwright_url;
|
|
328
|
+
delete helperResult.Playwright_show;
|
|
329
|
+
|
|
330
|
+
helperResult.Playwright_electron = {
|
|
331
|
+
executablePath: '// require("electron") or require("electron-forge")',
|
|
332
|
+
args: ['path/to/your/main.js'],
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
308
336
|
Object.keys(helperResult).forEach((key) => {
|
|
309
337
|
const parts = key.split('_');
|
|
310
338
|
const helperName = parts[0];
|
|
@@ -314,12 +342,12 @@ module.exports = function (initPath) {
|
|
|
314
342
|
});
|
|
315
343
|
|
|
316
344
|
print('');
|
|
317
|
-
finish();
|
|
345
|
+
await finish();
|
|
318
346
|
});
|
|
319
347
|
});
|
|
320
348
|
};
|
|
321
349
|
|
|
322
|
-
function install(dependencies
|
|
350
|
+
function install(dependencies) {
|
|
323
351
|
let command;
|
|
324
352
|
let args;
|
|
325
353
|
|
|
@@ -352,9 +380,39 @@ function install(dependencies, verbose) {
|
|
|
352
380
|
].concat(dependencies);
|
|
353
381
|
}
|
|
354
382
|
|
|
383
|
+
if (process.env._INIT_DRY_RUN_INSTALL) {
|
|
384
|
+
args.push('--dry-run');
|
|
385
|
+
}
|
|
386
|
+
|
|
355
387
|
const { status } = spawn.sync(command, args, { stdio: 'inherit' });
|
|
356
388
|
if (status !== 0) {
|
|
357
389
|
throw new Error(`${command} ${args.join(' ')} failed`);
|
|
358
390
|
}
|
|
359
391
|
return true;
|
|
360
392
|
}
|
|
393
|
+
|
|
394
|
+
function _actorTranslation(stepFile, translationSelected) {
|
|
395
|
+
let actor;
|
|
396
|
+
|
|
397
|
+
for (const translationAvailable of translations) {
|
|
398
|
+
if (actor) {
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (translationSelected === translationAvailable) {
|
|
403
|
+
const nameOfActor = require('../../translations')[translationAvailable].I;
|
|
404
|
+
|
|
405
|
+
actor = {
|
|
406
|
+
[nameOfActor]: stepFile,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (!actor) {
|
|
412
|
+
actor = {
|
|
413
|
+
I: stepFile,
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return actor;
|
|
418
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
const { getConfig, getTestRoot } = require('./utils');
|
|
2
2
|
const recorder = require('../recorder');
|
|
3
3
|
const Codecept = require('../codecept');
|
|
4
|
+
const Container = require('../container');
|
|
4
5
|
const event = require('../event');
|
|
5
6
|
const output = require('../output');
|
|
7
|
+
const webHelpers = require('../plugin/standardActingHelpers');
|
|
6
8
|
|
|
7
9
|
module.exports = async function (path, options) {
|
|
8
10
|
// Backward compatibility for --profile
|
|
@@ -29,9 +31,21 @@ module.exports = async function (path, options) {
|
|
|
29
31
|
});
|
|
30
32
|
event.emit(event.test.before, {
|
|
31
33
|
title: '',
|
|
34
|
+
artifacts: {},
|
|
32
35
|
});
|
|
36
|
+
|
|
37
|
+
const enabledHelpers = Container.helpers();
|
|
38
|
+
for (const helperName of Object.keys(enabledHelpers)) {
|
|
39
|
+
if (webHelpers.includes(helperName)) {
|
|
40
|
+
const I = enabledHelpers[helperName];
|
|
41
|
+
recorder.add(() => I.amOnPage('/'));
|
|
42
|
+
recorder.catchWithoutStop(e => output.print(`Error while loading home page: ${e.message}}`));
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
33
46
|
require('../pause')();
|
|
34
|
-
recorder.
|
|
47
|
+
// recorder.catchWithoutStop((err) => console.log(err.stack));
|
|
48
|
+
recorder.add(() => event.emit(event.test.after, {}));
|
|
35
49
|
recorder.add(() => event.emit(event.suite.after, {}));
|
|
36
50
|
recorder.add(() => event.emit(event.all.result, {}));
|
|
37
51
|
recorder.add(() => codecept.teardown());
|
|
@@ -47,14 +47,26 @@ class Collection {
|
|
|
47
47
|
*/
|
|
48
48
|
prepareRuns(selectedRuns, config) {
|
|
49
49
|
selectedRuns.forEach((selectedRun) => {
|
|
50
|
-
const
|
|
51
|
-
const
|
|
50
|
+
const runConfig = [];
|
|
51
|
+
const runName = [];
|
|
52
52
|
|
|
53
|
-
if (
|
|
54
|
-
|
|
53
|
+
if (selectedRun === 'all') {
|
|
54
|
+
Object.keys(config.multiple).forEach(name => {
|
|
55
|
+
runName.push(name);
|
|
56
|
+
runConfig.push(config.multiple[name]);
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
runName.push(selectedRun.split(':')[0]);
|
|
60
|
+
runConfig.push(config.multiple[runName[0]]);
|
|
55
61
|
}
|
|
56
62
|
|
|
57
|
-
|
|
63
|
+
for (let i = 0; i < runConfig.length; i++) {
|
|
64
|
+
if (!runConfig[i]) {
|
|
65
|
+
throw new Error(`run ${runName[i]} was not configured in "multiple" section of config`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this.addRun(createRun(runName[i], runConfig[i]));
|
|
69
|
+
}
|
|
58
70
|
});
|
|
59
71
|
|
|
60
72
|
return this;
|
|
@@ -28,7 +28,9 @@ let processesDone;
|
|
|
28
28
|
|
|
29
29
|
module.exports = async function (selectedRuns, options) {
|
|
30
30
|
// registering options globally to use in config
|
|
31
|
-
|
|
31
|
+
if (options.profile) {
|
|
32
|
+
process.env.profile = options.profile;
|
|
33
|
+
}
|
|
32
34
|
const configFile = options.config;
|
|
33
35
|
|
|
34
36
|
const testRoot = getTestRoot(configFile);
|
|
@@ -124,7 +126,7 @@ function executeRun(runName, runConfig) {
|
|
|
124
126
|
if (browserConfig.outputName) {
|
|
125
127
|
outputDir += typeof browserConfig.outputName === 'function' ? browserConfig.outputName() : browserConfig.outputName;
|
|
126
128
|
} else {
|
|
127
|
-
const hash = crypto.createHash('
|
|
129
|
+
const hash = crypto.createHash('sha256');
|
|
128
130
|
hash.update(JSON.stringify(browserConfig));
|
|
129
131
|
outputDir += hash.digest('hex');
|
|
130
132
|
}
|
|
@@ -4,9 +4,15 @@ const output = require('../output');
|
|
|
4
4
|
const event = require('../event');
|
|
5
5
|
const Workers = require('../workers');
|
|
6
6
|
|
|
7
|
-
module.exports = async function (workerCount, options) {
|
|
7
|
+
module.exports = async function (workerCount, selectedRuns, options) {
|
|
8
8
|
process.env.profile = options.profile;
|
|
9
9
|
|
|
10
|
+
const suiteArr = [];
|
|
11
|
+
const passedTestArr = [];
|
|
12
|
+
const failedTestArr = [];
|
|
13
|
+
const skippedTestArr = [];
|
|
14
|
+
const stepArr = [];
|
|
15
|
+
|
|
10
16
|
const { config: testConfig, override = '' } = options;
|
|
11
17
|
const overrideConfigs = tryOrDefault(() => JSON.parse(override), {});
|
|
12
18
|
const by = options.suites ? 'suite' : 'test';
|
|
@@ -15,6 +21,7 @@ module.exports = async function (workerCount, options) {
|
|
|
15
21
|
by,
|
|
16
22
|
testConfig,
|
|
17
23
|
options,
|
|
24
|
+
selectedRuns,
|
|
18
25
|
};
|
|
19
26
|
|
|
20
27
|
const numberOfWorkers = parseInt(workerCount, 10);
|
|
@@ -25,19 +32,75 @@ module.exports = async function (workerCount, options) {
|
|
|
25
32
|
|
|
26
33
|
const workers = new Workers(numberOfWorkers, config);
|
|
27
34
|
workers.overrideConfig(overrideConfigs);
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
|
|
36
|
+
workers.on(event.suite.before, (suite) => {
|
|
37
|
+
suiteArr.push(suite);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
workers.on(event.step.passed, (step) => {
|
|
41
|
+
stepArr.push(step);
|
|
30
42
|
});
|
|
31
43
|
|
|
32
|
-
workers.on(event.
|
|
33
|
-
|
|
44
|
+
workers.on(event.step.failed, (step) => {
|
|
45
|
+
stepArr.push(step);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
workers.on(event.test.failed, (test) => {
|
|
49
|
+
failedTestArr.push(test);
|
|
50
|
+
output.test.failed(test);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
workers.on(event.test.passed, (test) => {
|
|
54
|
+
passedTestArr.push(test);
|
|
55
|
+
output.test.passed(test);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
workers.on(event.test.skipped, (test) => {
|
|
59
|
+
skippedTestArr.push(test);
|
|
60
|
+
output.test.skipped(test);
|
|
34
61
|
});
|
|
35
62
|
|
|
36
63
|
workers.on(event.all.result, () => {
|
|
64
|
+
// expose test stats after all workers finished their execution
|
|
65
|
+
function addStepsToTest(test, stepArr) {
|
|
66
|
+
stepArr.test.steps.forEach(step => {
|
|
67
|
+
if (test.steps.length === 0) {
|
|
68
|
+
test.steps.push(step);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
stepArr.forEach(step => {
|
|
74
|
+
passedTestArr.forEach(test => {
|
|
75
|
+
if (step.test.title === test.title) {
|
|
76
|
+
addStepsToTest(test, step);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
failedTestArr.forEach(test => {
|
|
81
|
+
if (step.test.title === test.title) {
|
|
82
|
+
addStepsToTest(test, step);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
event.dispatcher.emit(event.workers.result, {
|
|
88
|
+
suites: suiteArr,
|
|
89
|
+
tests: {
|
|
90
|
+
passed: passedTestArr,
|
|
91
|
+
failed: failedTestArr,
|
|
92
|
+
skipped: skippedTestArr,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
37
95
|
workers.printResults();
|
|
38
96
|
});
|
|
39
97
|
|
|
40
98
|
try {
|
|
99
|
+
if (options.verbose) {
|
|
100
|
+
global.debugMode = true;
|
|
101
|
+
const { getMachineInfo } = require('./info');
|
|
102
|
+
await getMachineInfo();
|
|
103
|
+
}
|
|
41
104
|
await workers.bootstrapAll();
|
|
42
105
|
await workers.run();
|
|
43
106
|
} catch (err) {
|
package/lib/command/run.js
CHANGED
|
@@ -28,6 +28,13 @@ module.exports = async function (test, options) {
|
|
|
28
28
|
codecept.init(testRoot);
|
|
29
29
|
await codecept.bootstrap();
|
|
30
30
|
codecept.loadTests(test);
|
|
31
|
+
|
|
32
|
+
if (options.verbose) {
|
|
33
|
+
global.debugMode = true;
|
|
34
|
+
const { getMachineInfo } = require('./info');
|
|
35
|
+
await getMachineInfo();
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
await codecept.run();
|
|
32
39
|
} catch (err) {
|
|
33
40
|
printError(err);
|
|
@@ -132,9 +132,48 @@ function initializeListeners() {
|
|
|
132
132
|
duration: test.duration || 0,
|
|
133
133
|
err,
|
|
134
134
|
parent,
|
|
135
|
+
steps: test.steps && test.steps.length > 0 ? simplifyStepsInTestObject(test.steps, err) : [],
|
|
135
136
|
};
|
|
136
137
|
}
|
|
137
138
|
|
|
139
|
+
function simplifyStepsInTestObject(steps, err) {
|
|
140
|
+
steps = [...steps];
|
|
141
|
+
const _steps = [];
|
|
142
|
+
|
|
143
|
+
for (step of steps) {
|
|
144
|
+
const _args = [];
|
|
145
|
+
|
|
146
|
+
if (step.args) {
|
|
147
|
+
for (const arg of step.args) {
|
|
148
|
+
// check if arg is a JOI object
|
|
149
|
+
if (arg && arg.$_root) {
|
|
150
|
+
_args.push(JSON.stringify(arg).slice(0, 300));
|
|
151
|
+
// check if arg is a function
|
|
152
|
+
} else if (arg && typeof arg === 'function') {
|
|
153
|
+
_args.push(arg.name);
|
|
154
|
+
} else {
|
|
155
|
+
_args.push(arg);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
_steps.push({
|
|
161
|
+
actor: step.actor,
|
|
162
|
+
name: step.name,
|
|
163
|
+
status: step.status,
|
|
164
|
+
args: _args,
|
|
165
|
+
startedAt: step.startedAt,
|
|
166
|
+
startTime: step.startTime,
|
|
167
|
+
endTime: step.endTime,
|
|
168
|
+
finishedAt: step.finishedAt,
|
|
169
|
+
duration: step.duration,
|
|
170
|
+
err,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return _steps;
|
|
175
|
+
}
|
|
176
|
+
|
|
138
177
|
function simplifyStep(step, err = null) {
|
|
139
178
|
step = { ...step };
|
|
140
179
|
|
package/lib/container.js
CHANGED
|
@@ -165,7 +165,17 @@ function createHelpers(config) {
|
|
|
165
165
|
} else {
|
|
166
166
|
moduleName = `./helper/${helperName}`; // built-in helper
|
|
167
167
|
}
|
|
168
|
-
|
|
168
|
+
|
|
169
|
+
// @ts-ignore
|
|
170
|
+
let HelperClass;
|
|
171
|
+
// check if the helper is the built-in, use the require() syntax.
|
|
172
|
+
if (moduleName.startsWith('./helper/')) {
|
|
173
|
+
HelperClass = require(moduleName);
|
|
174
|
+
} else {
|
|
175
|
+
// check if the new syntax export default HelperName is used and loads the Helper, otherwise loads the module that used old syntax export = HelperName.
|
|
176
|
+
HelperClass = require(moduleName).default || require(moduleName);
|
|
177
|
+
}
|
|
178
|
+
|
|
169
179
|
if (HelperClass._checkRequirements) {
|
|
170
180
|
const requirements = HelperClass._checkRequirements();
|
|
171
181
|
if (requirements) {
|
|
@@ -351,8 +361,8 @@ function loadSupportObject(modulePath, supportObjectName) {
|
|
|
351
361
|
}
|
|
352
362
|
}
|
|
353
363
|
if (typeof obj !== 'function'
|
|
354
|
-
|
|
355
|
-
|
|
364
|
+
&& Object.getPrototypeOf(obj) !== Object.prototype
|
|
365
|
+
&& !Array.isArray(obj)
|
|
356
366
|
) {
|
|
357
367
|
const methods = getObjectMethods(obj);
|
|
358
368
|
Object.keys(methods)
|
package/lib/data/context.js
CHANGED
|
@@ -23,6 +23,7 @@ module.exports = function (context) {
|
|
|
23
23
|
.inject({ current: dataRow.data }));
|
|
24
24
|
}
|
|
25
25
|
});
|
|
26
|
+
maskSecretInTitle(scenarios);
|
|
26
27
|
return new DataScenarioConfig(scenarios);
|
|
27
28
|
},
|
|
28
29
|
only: {
|
|
@@ -42,6 +43,7 @@ module.exports = function (context) {
|
|
|
42
43
|
.inject({ current: dataRow.data }));
|
|
43
44
|
}
|
|
44
45
|
});
|
|
46
|
+
maskSecretInTitle(scenarios);
|
|
45
47
|
return new DataScenarioConfig(scenarios);
|
|
46
48
|
},
|
|
47
49
|
},
|
|
@@ -71,12 +73,6 @@ function replaceTitle(title, dataRow) {
|
|
|
71
73
|
// it should be printed
|
|
72
74
|
if (Object.prototype.toString.call(dataRow.data) === (Object()).toString()
|
|
73
75
|
&& dataRow.data.toString() !== (Object()).toString()) {
|
|
74
|
-
Object.entries(dataRow.data).forEach(entry => {
|
|
75
|
-
const [key, value] = entry;
|
|
76
|
-
if (value instanceof Secret) {
|
|
77
|
-
dataRow.data[key] = value.getMasked();
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
76
|
return `${title} | ${dataRow.data}`;
|
|
81
77
|
}
|
|
82
78
|
|
|
@@ -119,3 +115,15 @@ function detectDataType(dataTable) {
|
|
|
119
115
|
|
|
120
116
|
throw new Error('Invalid data type. Data accepts either: DataTable || generator || Array || function');
|
|
121
117
|
}
|
|
118
|
+
|
|
119
|
+
function maskSecretInTitle(scenarios) {
|
|
120
|
+
scenarios.forEach(scenario => {
|
|
121
|
+
const res = [];
|
|
122
|
+
|
|
123
|
+
scenario.test.title.split(',').forEach(item => {
|
|
124
|
+
res.push(item.replace(/{"_secret":"(.*)"}/, '"*****"'));
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
scenario.test.title = res.join(',');
|
|
128
|
+
});
|
|
129
|
+
}
|
package/lib/event.js
CHANGED
|
@@ -91,6 +91,8 @@ module.exports = {
|
|
|
91
91
|
bddStep: {
|
|
92
92
|
before: 'bddStep.before',
|
|
93
93
|
after: 'bddStep.after',
|
|
94
|
+
started: 'bddStep.started',
|
|
95
|
+
finished: 'bddStep.finished',
|
|
94
96
|
},
|
|
95
97
|
/**
|
|
96
98
|
* @type {object}
|
|
@@ -125,10 +127,12 @@ module.exports = {
|
|
|
125
127
|
* @inner
|
|
126
128
|
* @property {'workers.before'} before
|
|
127
129
|
* @property {'workers.after'} after
|
|
130
|
+
* @property {'workers.result'} result
|
|
128
131
|
*/
|
|
129
132
|
workers: {
|
|
130
133
|
before: 'workers.before',
|
|
131
134
|
after: 'workers.after',
|
|
135
|
+
result: 'workers.result',
|
|
132
136
|
},
|
|
133
137
|
|
|
134
138
|
/**
|
|
@@ -309,7 +309,8 @@ class ApiDataFactory extends Helper {
|
|
|
309
309
|
} catch (e) {
|
|
310
310
|
modulePath = path.join(global.codecept_dir, modulePath);
|
|
311
311
|
}
|
|
312
|
-
|
|
312
|
+
// check if the new syntax `export default new Factory()` is used and loads the builder, otherwise loads the module that used old syntax `module.exports = new Factory()`.
|
|
313
|
+
const builder = require(modulePath).default || require(modulePath);
|
|
313
314
|
return builder.build(data, options);
|
|
314
315
|
} catch (err) {
|
|
315
316
|
throw new Error(`Couldn't load factory file from ${modulePath}, check that
|