codeceptjs 2.3.4 → 2.4.1
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/CHANGELOG.md +52 -0
- package/README.md +28 -6
- package/bin/codecept.js +42 -0
- package/docs/advanced.md +45 -1
- package/docs/angular.md +3 -3
- package/docs/basics.md +162 -118
- package/docs/bdd.md +30 -5
- package/docs/best.md +8 -6
- package/docs/books.md +6 -1
- package/docs/build/Appium.js +95 -85
- package/docs/build/FileSystem.js +48 -3
- package/docs/build/GraphQL.js +3 -2
- package/docs/build/GraphQLDataFactory.js +1 -0
- package/docs/build/Mochawesome.js +3 -2
- package/docs/build/MockRequest.js +23 -5
- package/docs/build/Nightmare.js +87 -128
- package/docs/build/Protractor.js +107 -155
- package/docs/build/Puppeteer.js +190 -174
- package/docs/build/REST.js +13 -9
- package/docs/build/SeleniumWebdriver.js +0 -17
- package/docs/build/TestCafe.js +164 -158
- package/docs/build/WebDriver.js +236 -211
- package/docs/build/WebDriverIO.js +218 -187
- package/docs/changelog.md +57 -1
- package/docs/commands.md +41 -2
- package/docs/community-helpers.md +12 -1
- package/docs/configuration.md +5 -2
- package/docs/continuous-integration.md +22 -0
- package/docs/{helpers.md → custom-helpers.md} +16 -10
- package/docs/data.md +7 -6
- package/docs/detox.md +6 -6
- package/docs/email.md +4 -2
- package/docs/examples.md +22 -3
- package/docs/helpers/ApiDataFactory.md +15 -13
- package/docs/helpers/Appium.md +1011 -468
- package/docs/helpers/Detox.md +33 -26
- package/docs/helpers/FileSystem.md +43 -13
- package/docs/helpers/GraphQL.md +17 -15
- package/docs/helpers/GraphQLDataFactory.md +15 -13
- package/docs/helpers/Mochawesome.md +3 -1
- package/docs/helpers/MockRequest.md +37 -19
- package/docs/helpers/Nightmare.md +129 -240
- package/docs/helpers/Polly.md +1 -1
- package/docs/helpers/Protractor.md +157 -298
- package/docs/helpers/Puppeteer.md +216 -335
- package/docs/helpers/REST.md +29 -24
- package/docs/helpers/TestCafe.md +137 -235
- package/docs/helpers/WebDriver.md +250 -347
- package/docs/hooks.md +14 -10
- package/docs/index.md +112 -0
- package/docs/installation.md +3 -1
- package/docs/locators.md +19 -8
- package/docs/mobile-react-native-locators.md +2 -2
- package/docs/mobile.md +5 -3
- package/docs/nightmare.md +2 -1
- package/docs/pageobjects.md +4 -2
- package/docs/parallel.md +4 -2
- package/docs/plugins.md +41 -15
- package/docs/puppeteer.md +8 -6
- package/docs/quickstart.md +130 -0
- package/docs/react.md +4 -2
- package/docs/reports.md +6 -4
- package/docs/testcafe.md +10 -8
- package/docs/translation.md +4 -2
- package/docs/ui.md +56 -0
- package/docs/videos.md +11 -2
- package/docs/visual.md +7 -5
- package/docs/vue.md +121 -0
- package/docs/webapi/appendField.mustache +1 -1
- package/docs/webapi/attachFile.mustache +1 -1
- package/docs/webapi/checkOption.mustache +2 -2
- package/docs/webapi/clearCookie.mustache +1 -1
- package/docs/webapi/click.mustache +2 -2
- package/docs/webapi/clickLink.mustache +2 -2
- package/docs/webapi/dontSee.mustache +1 -2
- package/docs/webapi/dontSeeCheckboxIsChecked.mustache +1 -1
- package/docs/webapi/dontSeeElement.mustache +1 -1
- package/docs/webapi/dontSeeElementInDOM.mustache +1 -1
- package/docs/webapi/dontSeeInField.mustache +1 -1
- package/docs/webapi/doubleClick.mustache +2 -2
- package/docs/webapi/downloadFile.mustache +1 -1
- package/docs/webapi/dragSlider.mustache +1 -1
- package/docs/webapi/executeAsyncScript.mustache +2 -1
- package/docs/webapi/executeScript.mustache +2 -1
- package/docs/webapi/fillField.mustache +1 -1
- package/docs/webapi/grabAttributeFrom.mustache +1 -1
- package/docs/webapi/grabBrowserLogs.mustache +1 -1
- package/docs/webapi/grabCookie.mustache +2 -2
- package/docs/webapi/grabCssPropertyFrom.mustache +1 -1
- package/docs/webapi/grabHTMLFrom.mustache +1 -1
- package/docs/webapi/grabNumberOfVisibleElements.mustache +1 -1
- package/docs/webapi/grabPageScrollPosition.mustache +1 -1
- package/docs/webapi/grabTextFrom.mustache +2 -2
- package/docs/webapi/grabValueFrom.mustache +1 -1
- package/docs/webapi/moveCursorTo.mustache +3 -3
- package/docs/webapi/pressKey.mustache +1 -1
- package/docs/webapi/pressKeyWithKeyNormalization.mustache +1 -1
- package/docs/webapi/rightClick.mustache +2 -2
- package/docs/webapi/saveScreenshot.mustache +1 -1
- package/docs/webapi/scrollIntoView.mustache +10 -0
- package/docs/webapi/scrollTo.mustache +3 -3
- package/docs/webapi/see.mustache +1 -1
- package/docs/webapi/seeAttributesOnElements.mustache +1 -1
- package/docs/webapi/seeCheckboxIsChecked.mustache +1 -1
- package/docs/webapi/seeCssPropertiesOnElements.mustache +1 -1
- package/docs/webapi/seeElement.mustache +1 -1
- package/docs/webapi/seeElementInDOM.mustache +1 -1
- package/docs/webapi/seeInField.mustache +1 -1
- package/docs/webapi/seeNumberOfElements.mustache +1 -1
- package/docs/webapi/seeNumberOfVisibleElements.mustache +1 -1
- package/docs/webapi/seeTextEquals.mustache +8 -0
- package/docs/webapi/selectOption.mustache +2 -2
- package/docs/webapi/switchTo.mustache +1 -1
- package/docs/webapi/uncheckOption.mustache +2 -2
- package/docs/webapi/waitForClickable.mustache +10 -0
- package/docs/webapi/waitForDetached.mustache +2 -2
- package/docs/webapi/waitForElement.mustache +2 -2
- package/docs/webapi/waitForEnabled.mustache +2 -2
- package/docs/webapi/waitForFunction.mustache +2 -2
- package/docs/webapi/waitForInvisible.mustache +2 -2
- package/docs/webapi/waitForText.mustache +2 -2
- package/docs/webapi/waitForValue.mustache +1 -1
- package/docs/webapi/waitForVisible.mustache +2 -2
- package/docs/webapi/waitInUrl.mustache +1 -1
- package/docs/webapi/waitNumberOfVisibleElements.mustache +2 -2
- package/docs/webapi/waitToHide.mustache +2 -2
- package/docs/webapi/waitUntil.mustache +3 -2
- package/docs/webapi/waitUrlEquals.mustache +1 -1
- package/docs/webdriver.md +20 -18
- package/docs/wiki/.git/FETCH_HEAD +1 -0
- package/docs/wiki/.git/HEAD +1 -0
- package/docs/wiki/.git/ORIG_HEAD +1 -0
- package/docs/wiki/.git/config +11 -0
- package/docs/wiki/.git/description +1 -0
- package/docs/wiki/.git/hooks/applypatch-msg.sample +15 -0
- package/docs/wiki/.git/hooks/commit-msg.sample +24 -0
- package/docs/wiki/.git/hooks/fsmonitor-watchman.sample +114 -0
- package/docs/wiki/.git/hooks/post-update.sample +8 -0
- package/docs/wiki/.git/hooks/pre-applypatch.sample +14 -0
- package/docs/wiki/.git/hooks/pre-commit.sample +49 -0
- package/docs/wiki/.git/hooks/pre-push.sample +53 -0
- package/docs/wiki/.git/hooks/pre-rebase.sample +169 -0
- package/docs/wiki/.git/hooks/pre-receive.sample +24 -0
- package/docs/wiki/.git/hooks/prepare-commit-msg.sample +42 -0
- package/docs/wiki/.git/hooks/update.sample +128 -0
- package/docs/wiki/.git/index +0 -0
- package/docs/wiki/.git/info/exclude +6 -0
- package/docs/wiki/.git/logs/HEAD +4 -0
- package/docs/wiki/.git/logs/refs/heads/master +4 -0
- package/docs/wiki/.git/logs/refs/remotes/origin/HEAD +1 -0
- package/docs/wiki/.git/logs/refs/remotes/origin/master +3 -0
- package/docs/wiki/.git/objects/00/d216b0774d15db2d0a2a0d4ce249b5251acc55 +3 -0
- package/docs/wiki/.git/objects/09/01d87c5241905fdfe3493cfe8f04df4a2685ea +0 -0
- package/docs/wiki/.git/objects/0d/bdd0c20c4deb6a8cc81dbbf32ecf8c09238983 +2 -0
- package/docs/wiki/.git/objects/1a/c29e4fa82422c52392f22f0f2b8d1a759535bf +0 -0
- package/docs/wiki/.git/objects/27/12f92898d3e8f68e229b6cda76570d6c66d781 +0 -0
- package/docs/wiki/.git/objects/2d/dbe22c257166b648928eeb9460ecfb71ba702d +0 -0
- package/docs/wiki/.git/objects/2f/c942ec3773efd2678d9ff98035c61fcded81a1 +0 -0
- package/docs/wiki/.git/objects/40/a2856342c67796b48911a256b764fb06888b94 +5 -0
- package/docs/wiki/.git/objects/47/53181844fc4dc563cf3aa5e80462243cb58d38 +0 -0
- package/docs/wiki/.git/objects/4e/24a95fb2e4f8ffef51f19b694451a205c06f10 +3 -0
- package/docs/wiki/.git/objects/73/31ebd96f3c7e08a9f63f05a25f939afa0d4de1 +0 -0
- package/docs/wiki/.git/objects/86/19cbb2289caa502e33fccf0ed14eecf6ba2ba0 +0 -0
- package/docs/wiki/.git/objects/a4/72f797d9d74b87c9f71a2b1539d75bb07d1e35 +0 -0
- package/docs/wiki/.git/objects/c9/9f3e4bd227d6b050b2e416f9876df49583dbf6 +0 -0
- package/docs/wiki/.git/objects/ca/e609b4ef3e0ef85fcbe0d68d1a58246584b915 +0 -0
- package/docs/wiki/.git/objects/d5/8386ca72f6d550548f3d71d74e3ac73d5ad488 +0 -0
- package/docs/wiki/.git/objects/d9/c6874a6de524bdafeb563a20d847f4fdd59a86 +0 -0
- package/docs/wiki/.git/objects/f1/c944675bb38b40ae553b0be36c14674c79af54 +0 -0
- package/docs/wiki/.git/objects/pack/pack-28da0fc7e6c08d4c5350717bfbb7b1c53e8198ad.idx +0 -0
- package/docs/wiki/.git/objects/pack/pack-28da0fc7e6c08d4c5350717bfbb7b1c53e8198ad.pack +0 -0
- package/docs/wiki/.git/packed-refs +2 -0
- package/docs/wiki/.git/refs/heads/master +1 -0
- package/docs/wiki/.git/refs/remotes/origin/HEAD +1 -0
- package/docs/wiki/.git/refs/remotes/origin/master +1 -0
- package/docs/wiki/Books-&-Posts.md +27 -0
- package/docs/wiki/Community-Helpers.md +41 -0
- package/docs/wiki/Examples.md +138 -0
- package/docs/wiki/Home.md +11 -0
- package/docs/wiki/Release-process.md +25 -0
- package/docs/wiki/Roadmap.md +23 -0
- package/docs/wiki/Videos.md +19 -0
- package/lib/actor.js +18 -1
- package/lib/assert/error.js +3 -3
- package/lib/codecept.js +9 -6
- package/lib/command/configMigrate.js +7 -6
- package/lib/command/definitions.js +98 -350
- package/lib/command/generate.js +22 -17
- package/lib/command/gherkin/init.js +2 -1
- package/lib/command/gherkin/snippets.js +6 -6
- package/lib/command/gherkin/steps.js +0 -1
- package/lib/command/info.js +40 -0
- package/lib/command/init.js +54 -41
- package/lib/command/run-multiple.js +5 -4
- package/lib/command/run-rerun.js +39 -0
- package/lib/command/run-workers.js +4 -6
- package/lib/command/run.js +8 -18
- package/lib/command/utils.js +23 -2
- package/lib/command/workers/runTests.js +1 -2
- package/lib/config.js +10 -4
- package/lib/container.js +31 -6
- package/lib/data/dataTableArgument.js +31 -0
- package/lib/data/table.js +4 -0
- package/lib/event.js +65 -1
- package/lib/helper/Appium.js +52 -38
- package/lib/helper/FileSystem.js +48 -3
- package/lib/helper/GraphQL.js +3 -2
- package/lib/helper/GraphQLDataFactory.js +1 -0
- package/lib/helper/Mochawesome.js +3 -2
- package/lib/helper/MockRequest.js +23 -5
- package/lib/helper/Nightmare.js +5 -6
- package/lib/helper/Protractor.js +7 -8
- package/lib/helper/Puppeteer.js +76 -20
- package/lib/helper/REST.js +13 -9
- package/lib/helper/SeleniumWebdriver.js +0 -17
- package/lib/helper/TestCafe.js +84 -36
- package/lib/helper/WebDriver.js +113 -59
- package/lib/helper/WebDriverIO.js +43 -59
- package/lib/helper/clientscripts/nightmare.js +66 -4
- package/lib/helper/scripts/isElementClickable.js +24 -0
- package/lib/helper.js +34 -10
- package/lib/history.js +1 -1
- package/lib/hooks.js +2 -1
- package/lib/index.js +19 -0
- package/lib/interfaces/bdd.js +4 -0
- package/lib/interfaces/featureConfig.js +10 -3
- package/lib/interfaces/gherkin.js +6 -2
- package/lib/interfaces/scenarioConfig.js +17 -6
- package/lib/listener/config.js +1 -1
- package/lib/listener/exit.js +6 -0
- package/lib/listener/steps.js +0 -1
- package/lib/listener/trace.js +0 -1
- package/lib/locator.js +67 -2
- package/lib/output.js +53 -0
- package/lib/parser.js +2 -71
- package/lib/pause.js +3 -2
- package/lib/plugin/allure.js +41 -22
- package/lib/plugin/autoLogin.js +4 -1
- package/lib/plugin/pauseOnFail.js +38 -0
- package/lib/plugin/puppeteerCoverage.js +8 -7
- package/lib/plugin/screenshotOnFail.js +13 -8
- package/lib/plugin/stepByStepReport.js +7 -6
- package/lib/plugin/wdio.js +2 -1
- package/lib/recorder.js +85 -7
- package/lib/rerun.js +81 -0
- package/lib/secret.js +6 -0
- package/lib/session.js +9 -2
- package/lib/step.js +37 -2
- package/lib/store.js +5 -1
- package/lib/ui.js +34 -8
- package/lib/utils.js +6 -13
- package/lib/within.js +5 -0
- package/package.json +49 -29
- package/typings/Mocha.d.ts +21 -0
- package/typings/Protractor.d.ts +16 -0
- package/typings/index.d.ts +169 -0
- package/typings/jsdoc.conf.js +34 -0
- package/typings/jsdoc.namespace.js +29 -0
- package/typings/types.d.ts +9827 -0
- package/typings/utils.d.ts +7 -0
- package/docs/acceptance.md +0 -409
- package/docs/api/codecept.md +0 -75
- package/docs/api/config.md +0 -49
- package/docs/api/container.md +0 -66
- package/docs/api/helper.md +0 -116
- package/docs/api/output.md +0 -67
- package/docs/api/recorder.md +0 -63
- package/docs/helpers/SeleniumWebdriver.md +0 -92
- package/docs/helpers/WebDriverIO.md +0 -1671
package/lib/command/init.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
const { print, success, error } = require('../output');
|
|
2
1
|
const colors = require('chalk');
|
|
3
2
|
const fs = require('fs');
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
const mkdirp = require('mkdirp');
|
|
4
5
|
const path = require('path');
|
|
6
|
+
const { inspect } = require('util');
|
|
7
|
+
|
|
8
|
+
const { print, success, error } = require('../output');
|
|
5
9
|
const { fileExists, beautify } = require('../utils');
|
|
6
|
-
const inquirer = require('inquirer');
|
|
7
10
|
const { getTestRoot } = require('./utils');
|
|
8
11
|
const generateDefinitions = require('./definitions');
|
|
12
|
+
const { test: generateTest } = require('./generate');
|
|
9
13
|
const isLocal = require('../utils').installedLocally();
|
|
10
|
-
const mkdirp = require('mkdirp');
|
|
11
|
-
const { inspect } = require('util');
|
|
12
14
|
|
|
13
15
|
const defaultConfig = {
|
|
14
16
|
tests: './*_test.js',
|
|
@@ -27,8 +29,15 @@ translations.unshift(noTranslation);
|
|
|
27
29
|
|
|
28
30
|
let packages;
|
|
29
31
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
+
const configHeader = `const { setHeadlessWhen } = require('@codeceptjs/configure');
|
|
33
|
+
|
|
34
|
+
// turn on headless mode when running with HEADLESS=true environment variable
|
|
35
|
+
// HEADLESS=true npx codecept run
|
|
36
|
+
setHeadlessWhen(process.env.HEADLESS);
|
|
37
|
+
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
const defaultActor = `// in this file you can append custom step methods to 'I' object
|
|
32
41
|
|
|
33
42
|
module.exports = function() {
|
|
34
43
|
return actor({
|
|
@@ -88,21 +97,6 @@ module.exports = function (initPath) {
|
|
|
88
97
|
default: './output',
|
|
89
98
|
message: 'Where should logs, screenshots, and reports to be stored?',
|
|
90
99
|
},
|
|
91
|
-
{
|
|
92
|
-
name: 'steps',
|
|
93
|
-
type: 'confirm',
|
|
94
|
-
message: 'Would you like to extend the "I" object with custom steps?',
|
|
95
|
-
default: true,
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
name: 'steps_file',
|
|
99
|
-
type: 'input',
|
|
100
|
-
message: 'Where would you like to place custom steps?',
|
|
101
|
-
default: './steps_file.js',
|
|
102
|
-
when(answers) {
|
|
103
|
-
return answers.steps;
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
100
|
{
|
|
107
101
|
name: 'translation',
|
|
108
102
|
type: 'list',
|
|
@@ -124,7 +118,7 @@ module.exports = function (initPath) {
|
|
|
124
118
|
// append file mask to the end of tests
|
|
125
119
|
if (!config.tests.match(/\*(.*?)$/)) {
|
|
126
120
|
config.tests = `${config.tests.replace(/\/+$/, '')}/*_test.js`;
|
|
127
|
-
|
|
121
|
+
print(`Adding default test mask: ${config.tests}`);
|
|
128
122
|
}
|
|
129
123
|
|
|
130
124
|
if (result.translation !== noTranslation) config.translation = result.translation;
|
|
@@ -152,17 +146,29 @@ module.exports = function (initPath) {
|
|
|
152
146
|
}
|
|
153
147
|
|
|
154
148
|
const finish = () => {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
149
|
+
// create steps file by default
|
|
150
|
+
const stepFile = './steps_file.js';
|
|
151
|
+
fs.writeFileSync(path.join(testsPath, stepFile), defaultActor);
|
|
152
|
+
config.include.I = stepFile;
|
|
153
|
+
print(`Steps file created at ${stepFile}`);
|
|
154
|
+
|
|
155
|
+
config.plugins = {
|
|
156
|
+
retryFailedStep: {
|
|
157
|
+
enabled: true,
|
|
158
|
+
},
|
|
159
|
+
screenshotOnFail: {
|
|
160
|
+
enabled: true,
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
let configSource = beautify(`exports.config = ${inspect(config, false, 4, false)}`);
|
|
165
|
+
|
|
166
|
+
if (require.resolve('@codeceptjs/configure') && isLocal && !initPath) {
|
|
167
|
+
// prepend @codeceptjs/configure only when this module can be required in config
|
|
168
|
+
configSource = configHeader + configSource;
|
|
163
169
|
}
|
|
164
170
|
|
|
165
|
-
fs.writeFileSync(configFile,
|
|
171
|
+
fs.writeFileSync(configFile, configSource, 'utf-8');
|
|
166
172
|
print(`Config created at ${configFile}`);
|
|
167
173
|
|
|
168
174
|
if (config.output) {
|
|
@@ -174,7 +180,6 @@ module.exports = function (initPath) {
|
|
|
174
180
|
}
|
|
175
181
|
}
|
|
176
182
|
|
|
177
|
-
|
|
178
183
|
const jsconfig = {
|
|
179
184
|
compilerOption: {
|
|
180
185
|
allowJs: true,
|
|
@@ -183,7 +188,7 @@ module.exports = function (initPath) {
|
|
|
183
188
|
const jsconfigJson = beautify(JSON.stringify(jsconfig));
|
|
184
189
|
const jsconfigFile = path.join(testsPath, 'jsconfig.json');
|
|
185
190
|
if (fileExists(jsconfigFile)) {
|
|
186
|
-
print(`jsconfig.json
|
|
191
|
+
print(`jsconfig.json already exists at ${jsconfigFile}`);
|
|
187
192
|
} else {
|
|
188
193
|
fs.writeFileSync(jsconfigFile, jsconfigJson);
|
|
189
194
|
print(`Intellisense enabled in ${jsconfigFile}`);
|
|
@@ -192,17 +197,25 @@ module.exports = function (initPath) {
|
|
|
192
197
|
generateDefinitions(testsPath, {});
|
|
193
198
|
|
|
194
199
|
print('');
|
|
195
|
-
success(' Almost
|
|
196
|
-
|
|
200
|
+
success(' Almost ready... Next step:');
|
|
201
|
+
|
|
197
202
|
|
|
198
|
-
|
|
203
|
+
const generatedTest = generateTest(testsPath);
|
|
204
|
+
if (!generatedTest) return;
|
|
205
|
+
generatedTest.then(() => {
|
|
199
206
|
print('\n--');
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
207
|
+
print(colors.bold.green('CodeceptJS Installed! Enjoy supercharged testing! 🤩'));
|
|
208
|
+
print(colors.bold.magenta('Find more information at https://codecept.io'));
|
|
209
|
+
print();
|
|
210
|
+
if (packages) {
|
|
211
|
+
print('\n--');
|
|
212
|
+
if (isLocal) {
|
|
213
|
+
success(`Please install dependent packages locally: ${colors.bold(`npm install --save-dev ${packages.join(' ')}`)}`);
|
|
214
|
+
} else {
|
|
215
|
+
success(`Please install dependent packages globally: [sudo] ${colors.bold(`npm install -g ${packages.join(' ')}`)}`);
|
|
216
|
+
}
|
|
204
217
|
}
|
|
205
|
-
}
|
|
218
|
+
});
|
|
206
219
|
};
|
|
207
220
|
|
|
208
221
|
print('Configure helpers...');
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
const {
|
|
2
|
-
getConfig, getTestRoot, fail,
|
|
3
|
-
} = require('./utils');
|
|
4
1
|
const fork = require('child_process').fork;
|
|
5
2
|
const path = require('path');
|
|
6
3
|
const crypto = require('crypto');
|
|
4
|
+
|
|
7
5
|
const runHook = require('../hooks');
|
|
8
6
|
const event = require('../event');
|
|
9
7
|
const collection = require('./run-multiple/collection');
|
|
10
8
|
const clearString = require('../utils').clearString;
|
|
11
9
|
const replaceValueDeep = require('../utils').replaceValueDeep;
|
|
10
|
+
const {
|
|
11
|
+
getConfig, getTestRoot, fail,
|
|
12
|
+
} = require('./utils');
|
|
12
13
|
|
|
13
14
|
const runner = path.join(__dirname, '/../../bin/codecept');
|
|
14
15
|
let config;
|
|
@@ -113,7 +114,7 @@ module.exports = function (selectedRuns, options) {
|
|
|
113
114
|
|
|
114
115
|
function executeRun(runName, runConfig) {
|
|
115
116
|
// clone config
|
|
116
|
-
let overriddenConfig =
|
|
117
|
+
let overriddenConfig = { ...config };
|
|
117
118
|
|
|
118
119
|
// get configuration
|
|
119
120
|
const browserConfig = runConfig.browser;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const getConfig = require('./utils').getConfig;
|
|
2
|
+
const getTestRoot = require('./utils').getTestRoot;
|
|
3
|
+
const printError = require('./utils').printError;
|
|
4
|
+
const createOutputDir = require('./utils').createOutputDir;
|
|
5
|
+
const Config = require('../config');
|
|
6
|
+
const Codecept = require('../rerun');
|
|
7
|
+
|
|
8
|
+
module.exports = function (test, options) {
|
|
9
|
+
// registering options globally to use in config
|
|
10
|
+
process.profile = options.profile;
|
|
11
|
+
const configFile = options.config;
|
|
12
|
+
let codecept;
|
|
13
|
+
|
|
14
|
+
let config = getConfig(configFile);
|
|
15
|
+
if (options.override) {
|
|
16
|
+
config = Config.append(JSON.parse(options.override));
|
|
17
|
+
}
|
|
18
|
+
const testRoot = getTestRoot(configFile);
|
|
19
|
+
createOutputDir(config, testRoot);
|
|
20
|
+
|
|
21
|
+
function processError(err) {
|
|
22
|
+
printError(err);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
codecept = new Codecept(config, options);
|
|
28
|
+
codecept.init(testRoot);
|
|
29
|
+
|
|
30
|
+
codecept.runBootstrap((err) => {
|
|
31
|
+
if (err) throw new Error(`Error while running bootstrap file :${err}`);
|
|
32
|
+
|
|
33
|
+
codecept.loadTests();
|
|
34
|
+
codecept.run(test).catch(processError);
|
|
35
|
+
});
|
|
36
|
+
} catch (err) {
|
|
37
|
+
processError(err);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
const { satisfyNodeVersion, getConfig, getTestRoot } = require('./utils');
|
|
2
1
|
// For Node version >=10.5.0, have to use experimental flag
|
|
3
2
|
|
|
4
|
-
const
|
|
3
|
+
const { Suite, Test, reporters: { Base } } = require('mocha');
|
|
5
4
|
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const { satisfyNodeVersion, getConfig, getTestRoot } = require('./utils');
|
|
6
7
|
const Codecept = require('../codecept');
|
|
7
8
|
const Container = require('../container');
|
|
8
9
|
const { tryOrDefault } = require('../utils');
|
|
9
10
|
const output = require('../output');
|
|
10
11
|
const event = require('../event');
|
|
11
12
|
const runHook = require('../hooks');
|
|
12
|
-
const { Suite, Test, reporters: { Base } } = require('mocha');
|
|
13
13
|
|
|
14
14
|
const stats = {
|
|
15
15
|
suites: 0,
|
|
@@ -46,8 +46,6 @@ module.exports = function (workers, options) {
|
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
const testRoot = getTestRoot(configPath);
|
|
49
|
-
config.tests = path.resolve(testRoot, config.tests);
|
|
50
|
-
|
|
51
49
|
|
|
52
50
|
const codecept = new Codecept(config, options);
|
|
53
51
|
codecept.init(testRoot);
|
|
@@ -121,7 +119,7 @@ function printResults() {
|
|
|
121
119
|
stats.end = new Date();
|
|
122
120
|
stats.duration = stats.end - stats.start;
|
|
123
121
|
output.print();
|
|
124
|
-
if (stats.passes && !errors.length) {
|
|
122
|
+
if (stats.tests === 0 || (stats.passes && !errors.length)) {
|
|
125
123
|
output.result(stats.passes, stats.failures, 0, `${stats.duration / 1000}s`);
|
|
126
124
|
}
|
|
127
125
|
if (stats.failures) {
|
package/lib/command/run.js
CHANGED
|
@@ -1,32 +1,25 @@
|
|
|
1
|
+
const mkdirp = require('mkdirp');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
1
4
|
const getConfig = require('./utils').getConfig;
|
|
2
5
|
const getTestRoot = require('./utils').getTestRoot;
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const mkdirp = require('mkdirp');
|
|
6
|
+
const printError = require('./utils').printError;
|
|
7
|
+
const createOutputDir = require('./utils').createOutputDir;
|
|
6
8
|
const Config = require('../config');
|
|
7
9
|
const Codecept = require('../codecept');
|
|
8
|
-
const output = require('../output');
|
|
9
10
|
|
|
10
11
|
module.exports = function (test, options) {
|
|
11
12
|
// registering options globally to use in config
|
|
12
13
|
process.profile = options.profile;
|
|
13
14
|
const configFile = options.config;
|
|
14
15
|
let codecept;
|
|
15
|
-
let outputDir;
|
|
16
16
|
|
|
17
|
-
const testRoot = getTestRoot(configFile);
|
|
18
17
|
let config = getConfig(configFile);
|
|
19
18
|
if (options.override) {
|
|
20
19
|
config = Config.append(JSON.parse(options.override));
|
|
21
20
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
else outputDir = path.join(testRoot, config.output);
|
|
25
|
-
|
|
26
|
-
if (!fileExists(outputDir)) {
|
|
27
|
-
output.print(`creating output directory: ${outputDir}`);
|
|
28
|
-
mkdirp.sync(outputDir);
|
|
29
|
-
}
|
|
21
|
+
const testRoot = getTestRoot(configFile);
|
|
22
|
+
createOutputDir(config, testRoot);
|
|
30
23
|
|
|
31
24
|
try {
|
|
32
25
|
codecept = new Codecept(config, options);
|
|
@@ -39,10 +32,7 @@ module.exports = function (test, options) {
|
|
|
39
32
|
codecept.run(test);
|
|
40
33
|
});
|
|
41
34
|
} catch (err) {
|
|
42
|
-
|
|
43
|
-
output.error(err.message);
|
|
44
|
-
output.print('');
|
|
45
|
-
output.print(output.colors.grey(err.stack.replace(err.message, '')));
|
|
35
|
+
printError(err);
|
|
46
36
|
process.exit(1);
|
|
47
37
|
}
|
|
48
38
|
};
|
package/lib/command/utils.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const semver = require('semver');
|
|
4
|
+
const util = require('util');
|
|
5
|
+
const mkdirp = require('mkdirp');
|
|
6
|
+
|
|
3
7
|
const output = require('../output');
|
|
4
8
|
const { fileExists, beautify } = require('../utils');
|
|
5
|
-
|
|
6
|
-
const semver = require('semver');
|
|
9
|
+
|
|
7
10
|
|
|
8
11
|
// alias to deep merge
|
|
9
12
|
module.exports.deepMerge = require('../utils').deepMerge;
|
|
@@ -84,3 +87,21 @@ module.exports.captureStream = (stream) => {
|
|
|
84
87
|
getData: () => buffer,
|
|
85
88
|
};
|
|
86
89
|
};
|
|
90
|
+
|
|
91
|
+
module.exports.printError = (err) => {
|
|
92
|
+
output.print('');
|
|
93
|
+
output.error(err.message);
|
|
94
|
+
output.print('');
|
|
95
|
+
output.print(output.colors.grey(err.stack.replace(err.message, '')));
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
module.exports.createOutputDir = (config, testRoot) => {
|
|
99
|
+
let outputDir;
|
|
100
|
+
if (path.isAbsolute(config.output)) outputDir = config.output;
|
|
101
|
+
else outputDir = path.join(testRoot, config.output);
|
|
102
|
+
|
|
103
|
+
if (!fileExists(outputDir)) {
|
|
104
|
+
output.print(`creating output directory: ${outputDir}`);
|
|
105
|
+
mkdirp.sync(outputDir);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
@@ -20,7 +20,7 @@ const stderr = '';
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
// Requiring of Codecept need to be after tty.getWindowSize is available.
|
|
23
|
-
const Codecept = require('../../codecept');
|
|
23
|
+
const Codecept = require(process.env.CODECEPT_CLASS_PATH || '../../codecept');
|
|
24
24
|
|
|
25
25
|
const {
|
|
26
26
|
options, tests, testRoot, workerIndex,
|
|
@@ -30,7 +30,6 @@ const {
|
|
|
30
30
|
if (!options.debug && !options.verbose) process.stdout.write = (string, encoding, fd) => { stdout += string; return true; };
|
|
31
31
|
|
|
32
32
|
const config = getConfig(options.config || testRoot);
|
|
33
|
-
config.tests = path.resolve(testRoot, config.tests);
|
|
34
33
|
|
|
35
34
|
// Load test and run
|
|
36
35
|
const codecept = new Codecept(config, options);
|
package/lib/config.js
CHANGED
|
@@ -34,6 +34,7 @@ class Config {
|
|
|
34
34
|
* Create a config with default options
|
|
35
35
|
*
|
|
36
36
|
* @param {*} newConfig
|
|
37
|
+
* @return {Object<string, *>}
|
|
37
38
|
*/
|
|
38
39
|
static create(newConfig) {
|
|
39
40
|
config = deepMerge(deepClone(defaultConfig), newConfig);
|
|
@@ -50,7 +51,8 @@ class Config {
|
|
|
50
51
|
* * try to load `codecept.json` from it
|
|
51
52
|
* If none of above: fail.
|
|
52
53
|
*
|
|
53
|
-
* @param {
|
|
54
|
+
* @param {string} configFile
|
|
55
|
+
* @return {*}
|
|
54
56
|
*/
|
|
55
57
|
static load(configFile) {
|
|
56
58
|
configFile = path.resolve(configFile || '.');
|
|
@@ -81,6 +83,9 @@ class Config {
|
|
|
81
83
|
|
|
82
84
|
/**
|
|
83
85
|
* Get current config.
|
|
86
|
+
* @param {string} key
|
|
87
|
+
* @param {*} val
|
|
88
|
+
* @return {*}
|
|
84
89
|
*/
|
|
85
90
|
static get(key, val) {
|
|
86
91
|
if (key) {
|
|
@@ -96,7 +101,8 @@ class Config {
|
|
|
96
101
|
/**
|
|
97
102
|
* Appends values to current config
|
|
98
103
|
*
|
|
99
|
-
* @param {
|
|
104
|
+
* @param {Object<string, *>} additionalConfig
|
|
105
|
+
* @return {Object<string, *>}
|
|
100
106
|
*/
|
|
101
107
|
static append(additionalConfig) {
|
|
102
108
|
return config = deepMerge(config, additionalConfig);
|
|
@@ -104,10 +110,11 @@ class Config {
|
|
|
104
110
|
|
|
105
111
|
/**
|
|
106
112
|
* Resets config to default
|
|
113
|
+
* @return {Object<string, *>}
|
|
107
114
|
*/
|
|
108
115
|
static reset() {
|
|
109
116
|
hooks = [];
|
|
110
|
-
return config =
|
|
117
|
+
return config = { ...defaultConfig };
|
|
111
118
|
}
|
|
112
119
|
}
|
|
113
120
|
|
|
@@ -125,4 +132,3 @@ function loadConfigFile(configFile) {
|
|
|
125
132
|
}
|
|
126
133
|
throw new Error(`Config file ${configFile} can't be loaded`);
|
|
127
134
|
}
|
|
128
|
-
|
package/lib/container.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
const glob = require('glob');
|
|
1
2
|
const path = require('path');
|
|
3
|
+
|
|
2
4
|
const fileExists = require('./utils').fileExists;
|
|
3
5
|
const Translation = require('./translation');
|
|
4
6
|
const MochaFactory = require('./mochaFactory');
|
|
@@ -9,6 +11,10 @@ let container = {
|
|
|
9
11
|
helpers: {},
|
|
10
12
|
support: {},
|
|
11
13
|
plugins: {},
|
|
14
|
+
/**
|
|
15
|
+
* @type {Mocha | {}}
|
|
16
|
+
* @ignore
|
|
17
|
+
*/
|
|
12
18
|
mocha: {},
|
|
13
19
|
translation: {},
|
|
14
20
|
};
|
|
@@ -29,7 +35,10 @@ class Container {
|
|
|
29
35
|
if (config.grep && !opts.grep) {
|
|
30
36
|
mochaConfig.grep = config.grep;
|
|
31
37
|
}
|
|
32
|
-
|
|
38
|
+
this.createMocha = () => {
|
|
39
|
+
container.mocha = MochaFactory.create(mochaConfig, opts || {});
|
|
40
|
+
};
|
|
41
|
+
this.createMocha();
|
|
33
42
|
container.helpers = createHelpers(config.helpers || {});
|
|
34
43
|
container.translation = loadTranslation(config.translation || null);
|
|
35
44
|
container.support = createSupportObjects(config.include || {});
|
|
@@ -55,6 +64,7 @@ class Container {
|
|
|
55
64
|
*
|
|
56
65
|
* @api
|
|
57
66
|
* @param {string} [name]
|
|
67
|
+
* @returns { * }
|
|
58
68
|
*/
|
|
59
69
|
static support(name) {
|
|
60
70
|
if (!name) {
|
|
@@ -89,6 +99,7 @@ class Container {
|
|
|
89
99
|
* Get Mocha instance
|
|
90
100
|
*
|
|
91
101
|
* @api
|
|
102
|
+
* @returns {Mocha | {}}
|
|
92
103
|
*/
|
|
93
104
|
static mocha() {
|
|
94
105
|
return container.mocha;
|
|
@@ -98,6 +109,7 @@ class Container {
|
|
|
98
109
|
* Append new services to container
|
|
99
110
|
*
|
|
100
111
|
* @api
|
|
112
|
+
* @param {Object<string, *>} newContainer
|
|
101
113
|
*/
|
|
102
114
|
static append(newContainer) {
|
|
103
115
|
const deepMerge = require('./utils').deepMerge;
|
|
@@ -107,8 +119,9 @@ class Container {
|
|
|
107
119
|
/**
|
|
108
120
|
* Clear container
|
|
109
121
|
*
|
|
110
|
-
* @param {
|
|
111
|
-
* @param {
|
|
122
|
+
* @param {Object<string, *>} newHelpers
|
|
123
|
+
* @param {Object<string, *>} newSupport
|
|
124
|
+
* @param {Object<string, *>} newPlugins
|
|
112
125
|
*/
|
|
113
126
|
static clear(newHelpers, newSupport, newPlugins) {
|
|
114
127
|
container.helpers = newHelpers || {};
|
|
@@ -278,8 +291,20 @@ function loadGherkinSteps(paths) {
|
|
|
278
291
|
global.After = fn => event.dispatcher.on(event.test.finished, fn);
|
|
279
292
|
global.Fail = fn => event.dispatcher.on(event.test.failed, fn);
|
|
280
293
|
|
|
281
|
-
|
|
282
|
-
|
|
294
|
+
// If gherkin.steps is string, then this will iterate through that folder and send all step def js files to loadSupportObject
|
|
295
|
+
// If gherkin.steps is Array, it will go the old way
|
|
296
|
+
// This is done so that we need not enter all Step Definition files under config.gherkin.steps
|
|
297
|
+
if (Array.isArray(paths)) {
|
|
298
|
+
for (const path of paths) {
|
|
299
|
+
loadSupportObject(path, `Step Definition from ${path}`);
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
const folderPath = paths.startsWith('.') ? path.join(global.codecept_dir, paths) : '';
|
|
303
|
+
if (folderPath !== '') {
|
|
304
|
+
glob.sync(folderPath).forEach((file) => {
|
|
305
|
+
loadSupportObject(file, `Step Definition from ${file}`);
|
|
306
|
+
});
|
|
307
|
+
}
|
|
283
308
|
}
|
|
284
309
|
|
|
285
310
|
delete global.Before;
|
|
@@ -339,7 +364,7 @@ function loadTranslation(translation) {
|
|
|
339
364
|
if (require('../translations')[translation]) {
|
|
340
365
|
vocabulary = require('../translations')[translation];
|
|
341
366
|
return new Translation(vocabulary);
|
|
342
|
-
}
|
|
367
|
+
} if (fileExists(path.join(global.codecept_dir, translation))) {
|
|
343
368
|
// get from a provided file instead
|
|
344
369
|
vocabulary = require(path.join(global.codecept_dir, translation));
|
|
345
370
|
} else {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
class DataTableArgument {
|
|
2
|
+
constructor(gherkinDataTable) {
|
|
3
|
+
this.rawData = gherkinDataTable.rows.map((row) => {
|
|
4
|
+
return row.cells.map((cell) => {
|
|
5
|
+
return cell.value;
|
|
6
|
+
});
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
raw() {
|
|
11
|
+
return this.rawData.slice(0);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
rows() {
|
|
15
|
+
const copy = this.raw();
|
|
16
|
+
copy.shift();
|
|
17
|
+
return copy;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
hashes() {
|
|
21
|
+
const copy = this.raw();
|
|
22
|
+
const header = copy.shift();
|
|
23
|
+
return copy.map((row) => {
|
|
24
|
+
const r = {};
|
|
25
|
+
row.forEach((cell, index) => r[header[index]] = cell);
|
|
26
|
+
return r;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = DataTableArgument;
|
package/lib/data/table.js
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
* Datatable class to provide data driven testing
|
|
3
3
|
*/
|
|
4
4
|
class DataTable {
|
|
5
|
+
/** @param {Array<*>} array */
|
|
5
6
|
constructor(array) {
|
|
6
7
|
this.array = array;
|
|
7
8
|
this.rows = new Array(0);
|
|
8
9
|
}
|
|
9
10
|
|
|
11
|
+
/** @param {Array<*>} array */
|
|
10
12
|
add(array) {
|
|
11
13
|
if (array.length !== this.array.length) throw new Error(`There is too many elements in given data array. Please provide data in this format: ${this.array}`);
|
|
12
14
|
const tempObj = {};
|
|
@@ -19,6 +21,7 @@ class DataTable {
|
|
|
19
21
|
this.rows.push({ skip: false, data: tempObj });
|
|
20
22
|
}
|
|
21
23
|
|
|
24
|
+
/** @param {Array<*>} array */
|
|
22
25
|
xadd(array) {
|
|
23
26
|
if (array.length !== this.array.length) throw new Error(`There is too many elements in given data array. Please provide data in this format: ${this.array}`);
|
|
24
27
|
const tempObj = {};
|
|
@@ -31,6 +34,7 @@ class DataTable {
|
|
|
31
34
|
this.rows.push({ skip: true, data: tempObj });
|
|
32
35
|
}
|
|
33
36
|
|
|
37
|
+
/** @param {Function} func */
|
|
34
38
|
filter(func) {
|
|
35
39
|
return this.rows.filter(row => func(row.data));
|
|
36
40
|
}
|