codeceptjs 3.3.5-beta.6 → 3.3.6
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 +69 -2
- package/bin/codecept.js +40 -3
- package/docs/basics.md +24 -1
- package/docs/build/Appium.js +41 -22
- package/docs/build/FileSystem.js +1 -1
- package/docs/build/Nightmare.js +106 -57
- package/docs/build/Playwright.js +187 -111
- package/docs/build/Protractor.js +132 -70
- package/docs/build/Puppeteer.js +143 -76
- package/docs/build/REST.js +2 -2
- package/docs/build/TestCafe.js +107 -57
- package/docs/build/WebDriver.js +162 -89
- package/docs/changelog.md +107 -2
- package/docs/commands.md +5 -3
- package/docs/community-helpers.md +7 -4
- package/docs/configuration.md +5 -5
- package/docs/examples.md +39 -48
- package/docs/helpers/Appium.md +25 -23
- package/docs/helpers/FileSystem.md +1 -1
- package/docs/helpers/Nightmare.md +57 -57
- package/docs/helpers/Playwright.md +76 -75
- package/docs/helpers/Puppeteer.md +76 -85
- package/docs/helpers/REST.md +1 -1
- package/docs/helpers/TestCafe.md +57 -57
- package/docs/helpers/WebDriver.md +84 -97
- package/docs/quickstart.md +1 -1
- package/docs/reports.md +1 -1
- package/docs/secrets.md +1 -1
- package/docs/typescript.md +9 -69
- package/docs/webapi/appendField.mustache +1 -1
- package/docs/webapi/attachFile.mustache +3 -3
- package/docs/webapi/checkOption.mustache +1 -1
- package/docs/webapi/clearCookie.mustache +1 -1
- package/docs/webapi/clearField.mustache +1 -1
- package/docs/webapi/click.mustache +1 -1
- package/docs/webapi/clickLink.mustache +1 -1
- package/docs/webapi/closeCurrentTab.mustache +1 -1
- package/docs/webapi/closeOtherTabs.mustache +1 -1
- package/docs/webapi/dontSee.mustache +1 -1
- package/docs/webapi/dontSeeCheckboxIsChecked.mustache +1 -1
- package/docs/webapi/dontSeeCookie.mustache +1 -1
- package/docs/webapi/dontSeeCurrentUrlEquals.mustache +1 -1
- package/docs/webapi/dontSeeElement.mustache +1 -1
- package/docs/webapi/dontSeeElementInDOM.mustache +1 -1
- package/docs/webapi/dontSeeInCurrentUrl.mustache +1 -1
- package/docs/webapi/dontSeeInField.mustache +1 -1
- package/docs/webapi/dontSeeInSource.mustache +1 -1
- package/docs/webapi/dontSeeInTitle.mustache +1 -1
- package/docs/webapi/doubleClick.mustache +1 -1
- package/docs/webapi/downloadFile.mustache +1 -1
- package/docs/webapi/dragAndDrop.mustache +1 -1
- package/docs/webapi/dragSlider.mustache +1 -1
- package/docs/webapi/executeAsyncScript.mustache +1 -1
- package/docs/webapi/executeScript.mustache +1 -1
- package/docs/webapi/fillField.mustache +1 -1
- package/docs/webapi/forceClick.mustache +1 -1
- package/docs/webapi/forceRightClick.mustache +1 -1
- package/docs/webapi/moveCursorTo.mustache +1 -1
- package/docs/webapi/openNewTab.mustache +1 -1
- package/docs/webapi/pressKey.mustache +1 -1
- package/docs/webapi/pressKeyDown.mustache +1 -1
- package/docs/webapi/pressKeyUp.mustache +1 -1
- package/docs/webapi/pressKeyWithKeyNormalization.mustache +1 -1
- package/docs/webapi/refreshPage.mustache +1 -1
- package/docs/webapi/resizeWindow.mustache +1 -1
- package/docs/webapi/rightClick.mustache +1 -1
- package/docs/webapi/saveElementScreenshot.mustache +2 -2
- package/docs/webapi/saveScreenshot.mustache +2 -2
- package/docs/webapi/say.mustache +1 -1
- package/docs/webapi/scrollIntoView.mustache +1 -1
- package/docs/webapi/scrollPageToBottom.mustache +1 -1
- package/docs/webapi/scrollPageToTop.mustache +1 -1
- package/docs/webapi/scrollTo.mustache +1 -1
- package/docs/webapi/see.mustache +1 -1
- package/docs/webapi/seeAttributesOnElements.mustache +1 -1
- package/docs/webapi/seeCheckboxIsChecked.mustache +1 -1
- package/docs/webapi/seeCookie.mustache +1 -1
- package/docs/webapi/seeCssPropertiesOnElements.mustache +1 -1
- package/docs/webapi/seeCurrentUrlEquals.mustache +1 -1
- package/docs/webapi/seeElement.mustache +1 -1
- package/docs/webapi/seeElementInDOM.mustache +1 -1
- package/docs/webapi/seeInCurrentUrl.mustache +1 -1
- package/docs/webapi/seeInField.mustache +1 -1
- package/docs/webapi/seeInPopup.mustache +1 -1
- package/docs/webapi/seeInSource.mustache +1 -1
- package/docs/webapi/seeInTitle.mustache +1 -1
- package/docs/webapi/seeNumberOfElements.mustache +1 -1
- package/docs/webapi/seeNumberOfVisibleElements.mustache +1 -1
- package/docs/webapi/seeTextEquals.mustache +1 -1
- package/docs/webapi/seeTitleEquals.mustache +1 -1
- package/docs/webapi/selectOption.mustache +1 -1
- package/docs/webapi/setCookie.mustache +1 -1
- package/docs/webapi/setGeoLocation.mustache +1 -1
- package/docs/webapi/switchTo.mustache +1 -1
- package/docs/webapi/switchToNextTab.mustache +1 -1
- package/docs/webapi/switchToPreviousTab.mustache +1 -1
- package/docs/webapi/type.mustache +1 -1
- package/docs/webapi/uncheckOption.mustache +1 -1
- package/docs/webapi/wait.mustache +1 -1
- package/docs/webapi/waitForClickable.mustache +1 -1
- package/docs/webapi/waitForDetached.mustache +1 -1
- package/docs/webapi/waitForElement.mustache +1 -1
- package/docs/webapi/waitForEnabled.mustache +1 -1
- package/docs/webapi/waitForFunction.mustache +1 -1
- package/docs/webapi/waitForInvisible.mustache +1 -1
- package/docs/webapi/waitForText.mustache +1 -1
- package/docs/webapi/waitForValue.mustache +1 -1
- package/docs/webapi/waitForVisible.mustache +1 -1
- package/docs/webapi/waitInUrl.mustache +1 -1
- package/docs/webapi/waitNumberOfVisibleElements.mustache +1 -1
- package/docs/webapi/waitToHide.mustache +1 -1
- package/docs/webapi/waitUrlEquals.mustache +1 -1
- package/lib/command/configMigrate.js +1 -1
- package/lib/command/dryRun.js +2 -1
- package/lib/command/generate.js +35 -18
- package/lib/command/run-rerun.js +38 -0
- package/lib/command/utils.js +13 -3
- package/lib/config.js +2 -2
- package/lib/data/context.js +7 -0
- package/lib/helper/Appium.js +6 -4
- package/lib/helper/FileSystem.js +1 -1
- package/lib/helper/Nightmare.js +1 -1
- package/lib/helper/Playwright.js +48 -38
- package/lib/helper/Protractor.js +1 -1
- package/lib/helper/REST.js +2 -2
- package/lib/helper/TestCafe.js +1 -1
- package/lib/helper/WebDriver.js +7 -7
- package/lib/plugin/wdio.js +11 -2
- package/lib/utils.js +3 -0
- package/package.json +2 -2
- package/typings/index.d.ts +46 -46
- package/typings/types.d.ts +497 -443
- package/docs/wiki/.git/FETCH_HEAD +0 -1
- package/docs/wiki/.git/HEAD +0 -1
- package/docs/wiki/.git/ORIG_HEAD +0 -1
- package/docs/wiki/.git/config +0 -11
- package/docs/wiki/.git/description +0 -1
- package/docs/wiki/.git/hooks/applypatch-msg.sample +0 -15
- package/docs/wiki/.git/hooks/commit-msg.sample +0 -24
- package/docs/wiki/.git/hooks/fsmonitor-watchman.sample +0 -173
- package/docs/wiki/.git/hooks/post-update.sample +0 -8
- package/docs/wiki/.git/hooks/pre-applypatch.sample +0 -14
- package/docs/wiki/.git/hooks/pre-commit.sample +0 -49
- package/docs/wiki/.git/hooks/pre-merge-commit.sample +0 -13
- package/docs/wiki/.git/hooks/pre-push.sample +0 -53
- package/docs/wiki/.git/hooks/pre-rebase.sample +0 -169
- package/docs/wiki/.git/hooks/pre-receive.sample +0 -24
- package/docs/wiki/.git/hooks/prepare-commit-msg.sample +0 -42
- package/docs/wiki/.git/hooks/push-to-checkout.sample +0 -78
- package/docs/wiki/.git/hooks/update.sample +0 -128
- package/docs/wiki/.git/index +0 -0
- package/docs/wiki/.git/info/exclude +0 -6
- package/docs/wiki/.git/logs/HEAD +0 -1
- package/docs/wiki/.git/logs/refs/heads/master +0 -1
- package/docs/wiki/.git/logs/refs/remotes/origin/HEAD +0 -1
- package/docs/wiki/.git/objects/pack/pack-5938044f9d30daf1c195fda4dec1d54850933935.idx +0 -0
- package/docs/wiki/.git/objects/pack/pack-5938044f9d30daf1c195fda4dec1d54850933935.pack +0 -0
- package/docs/wiki/.git/packed-refs +0 -2
- package/docs/wiki/.git/refs/heads/master +0 -1
- package/docs/wiki/.git/refs/remotes/origin/HEAD +0 -1
|
@@ -6,4 +6,4 @@ I.switchTo(); // switch back to main page
|
|
|
6
6
|
```
|
|
7
7
|
|
|
8
8
|
@param {?CodeceptJS.LocatorOrString} [locator=null] (optional, `null` by default) element located by CSS|XPath|strict locator.
|
|
9
|
-
|
|
9
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -7,4 +7,4 @@ I.switchToNextTab(2);
|
|
|
7
7
|
|
|
8
8
|
@param {number} [num] (optional) number of tabs to switch forward, default: 1.
|
|
9
9
|
@param {number | null} [sec] (optional) time in seconds to wait.
|
|
10
|
-
|
|
10
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -7,4 +7,4 @@ I.switchToPreviousTab(2);
|
|
|
7
7
|
|
|
8
8
|
@param {number} [num] (optional) number of tabs to switch backward, default: 1.
|
|
9
9
|
@param {number?} [sec] (optional) time in seconds to wait.
|
|
10
|
-
|
|
10
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -15,4 +15,4 @@ I.type(['T', 'E', 'X', 'T']);
|
|
|
15
15
|
|
|
16
16
|
@param {string|string[]} key or array of keys to type.
|
|
17
17
|
@param {?number} [delay=null] (optional) delay in ms between key presses
|
|
18
|
-
|
|
18
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -10,4 +10,4 @@ I.uncheckOption('agree', '//form');
|
|
|
10
10
|
```
|
|
11
11
|
@param {CodeceptJS.LocatorOrString} field checkbox located by label | name | CSS | XPath | strict locator.
|
|
12
12
|
@param {?CodeceptJS.LocatorOrString} [context=null] (optional, `null` by default) element located by CSS | XPath | strict locator.
|
|
13
|
-
|
|
13
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -8,4 +8,4 @@ I.waitForClickable('.btn.continue', 5); // wait for 5 secs
|
|
|
8
8
|
|
|
9
9
|
@param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
10
10
|
@param {number} [sec] (optional, `1` by default) time in seconds to wait
|
|
11
|
-
|
|
11
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -7,4 +7,4 @@ I.waitForDetached('#popup');
|
|
|
7
7
|
|
|
8
8
|
@param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
9
9
|
@param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
10
|
-
|
|
10
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -8,4 +8,4 @@ I.waitForElement('.btn.continue', 5); // wait for 5 secs
|
|
|
8
8
|
|
|
9
9
|
@param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
10
10
|
@param {number} [sec] (optional, `1` by default) time in seconds to wait
|
|
11
|
-
|
|
11
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -3,4 +3,4 @@ Element can be located by CSS or XPath.
|
|
|
3
3
|
|
|
4
4
|
@param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
5
5
|
@param {number} [sec=1] (optional) time in seconds to wait, 1 by default.
|
|
6
|
-
|
|
6
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -14,4 +14,4 @@ I.waitForFunction((count) => window.requests == count, [3], 5) // pass args and
|
|
|
14
14
|
@param {string|function} fn to be executed in browser context.
|
|
15
15
|
@param {any[]|number} [argsOrSec] (optional, `1` by default) arguments for function or seconds.
|
|
16
16
|
@param {number} [sec] (optional, `1` by default) time in seconds to wait
|
|
17
|
-
|
|
17
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -7,4 +7,4 @@ I.waitForInvisible('#popup');
|
|
|
7
7
|
|
|
8
8
|
@param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
9
9
|
@param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
10
|
-
|
|
10
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -10,4 +10,4 @@ I.waitForText('Thank you, form has been submitted', 5, '#modal');
|
|
|
10
10
|
@param {string }text to wait for.
|
|
11
11
|
@param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
12
12
|
@param {CodeceptJS.LocatorOrString} [context] (optional) element located by CSS|XPath|strict locator.
|
|
13
|
-
|
|
13
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -7,4 +7,4 @@ I.waitForValue('//input', "GoodValue");
|
|
|
7
7
|
@param {LocatorOrString} field input field.
|
|
8
8
|
@param {string }value expected value.
|
|
9
9
|
@param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
10
|
-
|
|
10
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -7,4 +7,4 @@ I.waitForVisible('#popup');
|
|
|
7
7
|
|
|
8
8
|
@param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
9
9
|
@param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
10
|
-
|
|
10
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -6,4 +6,4 @@ I.waitInUrl('/info', 2);
|
|
|
6
6
|
|
|
7
7
|
@param {string} urlPart value to check.
|
|
8
8
|
@param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
9
|
-
|
|
9
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -7,4 +7,4 @@ I.waitNumberOfVisibleElements('a', 3);
|
|
|
7
7
|
@param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
8
8
|
@param {number} num number of elements.
|
|
9
9
|
@param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
10
|
-
|
|
10
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -7,4 +7,4 @@ I.waitToHide('#popup');
|
|
|
7
7
|
|
|
8
8
|
@param {CodeceptJS.LocatorOrString} locator element located by CSS|XPath|strict locator.
|
|
9
9
|
@param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
10
|
-
|
|
10
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -7,4 +7,4 @@ I.waitUrlEquals('http://127.0.0.1:8000/info');
|
|
|
7
7
|
|
|
8
8
|
@param {string} urlPart value to check.
|
|
9
9
|
@param {number} [sec=1] (optional, `1` by default) time in seconds to wait
|
|
10
|
-
|
|
10
|
+
⚠️ returns a _promise_ which is synchronized internally by recorder
|
|
@@ -50,7 +50,7 @@ module.exports = function (initPath) {
|
|
|
50
50
|
},
|
|
51
51
|
]).then((result) => {
|
|
52
52
|
if (result.configFile) {
|
|
53
|
-
const jsonConfigFile = path.join(testsPath, 'codecept.
|
|
53
|
+
const jsonConfigFile = path.join(testsPath, 'codecept.js');
|
|
54
54
|
const config = JSON.parse(fs.readFileSync(jsonConfigFile, 'utf8'));
|
|
55
55
|
config.name = testsPath.split(path.sep).pop();
|
|
56
56
|
|
package/lib/command/dryRun.js
CHANGED
|
@@ -27,7 +27,7 @@ module.exports = async function (test, options) {
|
|
|
27
27
|
codecept = new Codecept(config, options);
|
|
28
28
|
codecept.init(testRoot);
|
|
29
29
|
|
|
30
|
-
if (options.bootstrap) await codecept.
|
|
30
|
+
if (options.bootstrap) await codecept.bootstrap();
|
|
31
31
|
|
|
32
32
|
codecept.loadTests();
|
|
33
33
|
store.dryRun = true;
|
|
@@ -71,6 +71,7 @@ function printTests(files) {
|
|
|
71
71
|
output.print('');
|
|
72
72
|
output.success(` Total: ${numOfSuites} suites | ${numOfTests} tests `);
|
|
73
73
|
printFooter();
|
|
74
|
+
process.exit(0);
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
function printFooter() {
|
package/lib/command/generate.js
CHANGED
|
@@ -3,13 +3,16 @@ const fs = require('fs');
|
|
|
3
3
|
const inquirer = require('inquirer');
|
|
4
4
|
const mkdirp = require('mkdirp');
|
|
5
5
|
const path = require('path');
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const {
|
|
7
|
+
fileExists, ucfirst, lcfirst, beautify,
|
|
8
|
+
} = require('../utils');
|
|
8
9
|
const output = require('../output');
|
|
9
10
|
const {
|
|
10
|
-
getConfig, getTestRoot, safeFileWrite,
|
|
11
|
+
getConfig, getTestRoot, safeFileWrite, readConfig,
|
|
11
12
|
} = require('./utils');
|
|
12
13
|
|
|
14
|
+
let extension = 'js';
|
|
15
|
+
|
|
13
16
|
const testTemplate = `Feature('{{feature}}');
|
|
14
17
|
|
|
15
18
|
Scenario('test something', ({ {{actor}} }) => {
|
|
@@ -26,7 +29,7 @@ module.exports.test = function (genPath) {
|
|
|
26
29
|
output.print('Creating a new test...');
|
|
27
30
|
output.print('----------------------');
|
|
28
31
|
|
|
29
|
-
const defaultExt = config.tests.match(/([^\*/]*?)$/)[1] ||
|
|
32
|
+
const defaultExt = config.tests.match(/([^\*/]*?)$/)[1] || `_test.${extension}`;
|
|
30
33
|
|
|
31
34
|
return inquirer.prompt([
|
|
32
35
|
{
|
|
@@ -79,25 +82,34 @@ module.exports.pageObject = function (genPath, opts) {
|
|
|
79
82
|
const kind = opts.T || 'page';
|
|
80
83
|
if (!config) return;
|
|
81
84
|
|
|
85
|
+
let configFile = path.join(testsPath, `codecept.conf.${extension}`);
|
|
86
|
+
|
|
87
|
+
if (!fileExists(configFile)) {
|
|
88
|
+
extension = 'ts';
|
|
89
|
+
configFile = path.join(testsPath, `codecept.conf.${extension}`);
|
|
90
|
+
}
|
|
82
91
|
output.print(`Creating a new ${kind} object`);
|
|
83
92
|
output.print('--------------------------');
|
|
84
93
|
|
|
85
|
-
return inquirer.prompt([
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
return inquirer.prompt([
|
|
95
|
+
{
|
|
96
|
+
type: 'input',
|
|
97
|
+
name: 'name',
|
|
98
|
+
message: `Name of a ${kind} object`,
|
|
99
|
+
validate: (val) => !!val,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
type: 'input',
|
|
103
|
+
name: 'filename',
|
|
104
|
+
message: 'Where should it be stored',
|
|
105
|
+
default: answers => `./${kind}s/${answers.name}.${extension}`,
|
|
106
|
+
}]).then((result) => {
|
|
96
107
|
const pageObjectFile = path.join(testsPath, result.filename);
|
|
97
108
|
const dir = path.dirname(pageObjectFile);
|
|
98
109
|
if (!fileExists(dir)) fs.mkdirSync(dir);
|
|
99
110
|
|
|
100
111
|
let actor = 'actor';
|
|
112
|
+
|
|
101
113
|
if (config.include.I) {
|
|
102
114
|
let actorPath = config.include.I;
|
|
103
115
|
if (actorPath.charAt(0) === '.') { // relative path
|
|
@@ -107,16 +119,21 @@ module.exports.pageObject = function (genPath, opts) {
|
|
|
107
119
|
}
|
|
108
120
|
if (!safeFileWrite(pageObjectFile, pageObjectTemplate.replace('{{actor}}', actor))) return;
|
|
109
121
|
const name = lcfirst(result.name) + ucfirst(kind);
|
|
122
|
+
let data = readConfig(configFile);
|
|
110
123
|
config.include[name] = result.filename;
|
|
124
|
+
data = data.replace(/include[\s\S][^\}]*/i, `include: ${JSON.stringify(config.include).slice(0, -1)}`);
|
|
125
|
+
|
|
126
|
+
fs.writeFileSync(configFile, beautify(data), 'utf-8');
|
|
111
127
|
|
|
112
128
|
output.success(`${ucfirst(kind)} object for ${result.name} was created in ${pageObjectFile}`);
|
|
113
|
-
output.print(`
|
|
129
|
+
output.print(`Your config file (${colors.cyan('include')} section) has included the new created PO:
|
|
114
130
|
|
|
115
131
|
include: {
|
|
132
|
+
...
|
|
116
133
|
${name}: '${result.filename}',
|
|
117
134
|
},`);
|
|
118
135
|
|
|
119
|
-
output.print(`Use ${output.colors.bold(name)} as parameter in test scenarios to access this object`);
|
|
136
|
+
output.print(`Use ${output.colors.bold(colors.cyan(name))} as parameter in test scenarios to access this object`);
|
|
120
137
|
});
|
|
121
138
|
};
|
|
122
139
|
|
|
@@ -163,7 +180,7 @@ module.exports.helper = function (genPath) {
|
|
|
163
180
|
type: 'input',
|
|
164
181
|
name: 'filename',
|
|
165
182
|
message: 'Where should it be stored',
|
|
166
|
-
default: answers => `./${answers.name.toLowerCase()}_helper
|
|
183
|
+
default: answers => `./${answers.name.toLowerCase()}_helper.${extension}`,
|
|
167
184
|
}]).then((result) => {
|
|
168
185
|
const name = ucfirst(result.name);
|
|
169
186
|
const helperFile = path.join(testsPath, result.filename);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const { getConfig, getTestRoot } = require('./utils');
|
|
2
|
+
const { printError, createOutputDir } = require('./utils');
|
|
3
|
+
const Config = require('../config');
|
|
4
|
+
const Codecept = require('../rerun');
|
|
5
|
+
|
|
6
|
+
module.exports = async function (test, options) {
|
|
7
|
+
// registering options globally to use in config
|
|
8
|
+
// Backward compatibility for --profile
|
|
9
|
+
process.profile = options.profile;
|
|
10
|
+
process.env.profile = options.profile;
|
|
11
|
+
const configFile = options.config;
|
|
12
|
+
|
|
13
|
+
let config = getConfig(configFile);
|
|
14
|
+
if (options.override) {
|
|
15
|
+
config = Config.append(JSON.parse(options.override));
|
|
16
|
+
}
|
|
17
|
+
const testRoot = getTestRoot(configFile);
|
|
18
|
+
createOutputDir(config, testRoot);
|
|
19
|
+
|
|
20
|
+
function processError(err) {
|
|
21
|
+
printError(err);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
const codecept = new Codecept(config, options);
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
codecept.init(testRoot);
|
|
28
|
+
|
|
29
|
+
await codecept.bootstrap();
|
|
30
|
+
codecept.loadTests(test);
|
|
31
|
+
await codecept.run();
|
|
32
|
+
} catch (err) {
|
|
33
|
+
printError(err);
|
|
34
|
+
process.exitCode = 1;
|
|
35
|
+
} finally {
|
|
36
|
+
await codecept.teardown();
|
|
37
|
+
}
|
|
38
|
+
};
|
package/lib/command/utils.js
CHANGED
|
@@ -18,6 +18,15 @@ module.exports.getConfig = function (configFile) {
|
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
+
module.exports.readConfig = function (configFile) {
|
|
22
|
+
try {
|
|
23
|
+
const data = fs.readFileSync(configFile, 'utf8');
|
|
24
|
+
return data;
|
|
25
|
+
} catch (err) {
|
|
26
|
+
output.error(err);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
21
30
|
function getTestRoot(currentPath) {
|
|
22
31
|
if (!currentPath) currentPath = '.';
|
|
23
32
|
if (!path.isAbsolute(currentPath)) currentPath = path.join(process.cwd(), currentPath);
|
|
@@ -33,11 +42,12 @@ function fail(msg) {
|
|
|
33
42
|
|
|
34
43
|
module.exports.fail = fail;
|
|
35
44
|
|
|
36
|
-
function updateConfig(testsPath, config, key) {
|
|
37
|
-
const configFile = path.join(testsPath,
|
|
45
|
+
function updateConfig(testsPath, config, key, extension = 'js') {
|
|
46
|
+
const configFile = path.join(testsPath, `codecept.conf.${extension}`);
|
|
38
47
|
if (!fileExists(configFile)) {
|
|
39
48
|
console.log();
|
|
40
|
-
|
|
49
|
+
const msg = `codecept.conf.${extension} config can\'t be updated automatically`;
|
|
50
|
+
console.log(`${output.colors.bold.red(msg)}`);
|
|
41
51
|
console.log('Please update it manually:');
|
|
42
52
|
console.log();
|
|
43
53
|
console.log(`${key}: ${config[key]}`);
|
package/lib/config.js
CHANGED
|
@@ -41,7 +41,7 @@ let config = {};
|
|
|
41
41
|
const configFileNames = [
|
|
42
42
|
'codecept.config.js',
|
|
43
43
|
'codecept.conf.js',
|
|
44
|
-
'codecept.
|
|
44
|
+
'codecept.js',
|
|
45
45
|
'codecept.config.ts',
|
|
46
46
|
'codecept.conf.ts',
|
|
47
47
|
];
|
|
@@ -69,7 +69,7 @@ class Config {
|
|
|
69
69
|
* If directory provided:
|
|
70
70
|
* * try to load `codecept.config.js` from it
|
|
71
71
|
* * try to load `codecept.conf.js` from it
|
|
72
|
-
* * try to load `codecept.
|
|
72
|
+
* * try to load `codecept.js` from it
|
|
73
73
|
* If none of above: fail.
|
|
74
74
|
*
|
|
75
75
|
* @param {string} configFile
|
package/lib/data/context.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { isGenerator } = require('../utils');
|
|
2
2
|
const DataTable = require('./table');
|
|
3
3
|
const DataScenarioConfig = require('./dataScenarioConfig');
|
|
4
|
+
const Secret = require('../secret');
|
|
4
5
|
|
|
5
6
|
module.exports = function (context) {
|
|
6
7
|
context.Data = function (dataTable) {
|
|
@@ -70,6 +71,12 @@ function replaceTitle(title, dataRow) {
|
|
|
70
71
|
// it should be printed
|
|
71
72
|
if (Object.prototype.toString.call(dataRow.data) === (Object()).toString()
|
|
72
73
|
&& 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
|
+
});
|
|
73
80
|
return `${title} | ${dataRow.data}`;
|
|
74
81
|
}
|
|
75
82
|
|
package/lib/helper/Appium.js
CHANGED
|
@@ -34,7 +34,7 @@ const webRoot = 'body';
|
|
|
34
34
|
*
|
|
35
35
|
* ## Helper configuration
|
|
36
36
|
*
|
|
37
|
-
* This helper should be configured in codecept.
|
|
37
|
+
* This helper should be configured in codecept.conf.ts or codecept.conf.js
|
|
38
38
|
*
|
|
39
39
|
* * `app`: Application path. Local path or remote URL to an .ipa or .apk file, or a .zip containing one of these. Alias to desiredCapabilities.appPackage
|
|
40
40
|
* * `host`: (default: 'localhost') Appium host
|
|
@@ -788,9 +788,11 @@ class Appium extends Webdriver {
|
|
|
788
788
|
* I.startActivity('io.selendroid.testapp', '.RegisterUserActivity');
|
|
789
789
|
* ```
|
|
790
790
|
*
|
|
791
|
-
* @return {Promise<void>}
|
|
792
|
-
*
|
|
793
791
|
* Appium: support only Android
|
|
792
|
+
*
|
|
793
|
+
* @param {string} appPackage
|
|
794
|
+
* @param {string} appActivity
|
|
795
|
+
* @return {Promise<void>}
|
|
794
796
|
*/
|
|
795
797
|
async startActivity(appPackage, appActivity) {
|
|
796
798
|
onlyForApps.call(this, 'Android');
|
|
@@ -1458,7 +1460,7 @@ class Appium extends Webdriver {
|
|
|
1458
1460
|
}
|
|
1459
1461
|
|
|
1460
1462
|
/**
|
|
1461
|
-
* Saves a screenshot to ouput folder (set in codecept.
|
|
1463
|
+
* Saves a screenshot to ouput folder (set in codecept.conf.ts or codecept.conf.js).
|
|
1462
1464
|
* Filename is relative to output folder.
|
|
1463
1465
|
*
|
|
1464
1466
|
* ```js
|
package/lib/helper/FileSystem.js
CHANGED
package/lib/helper/Nightmare.js
CHANGED
|
@@ -35,7 +35,7 @@ let withinStatus = false;
|
|
|
35
35
|
*
|
|
36
36
|
* ## Configuration
|
|
37
37
|
*
|
|
38
|
-
* This helper should be configured in codecept.
|
|
38
|
+
* This helper should be configured in codecept.conf.ts or codecept.conf.js
|
|
39
39
|
*
|
|
40
40
|
* * `url` - base url of website to be tested
|
|
41
41
|
* * `restart` (optional, default: true) - restart browser between tests.
|
package/lib/helper/Playwright.js
CHANGED
|
@@ -62,13 +62,14 @@ const { createValueEngine, createDisabledEngine } = require('./extras/Playwright
|
|
|
62
62
|
* @prop {boolean} [disableScreenshots=false] - don't save screenshot on failure.
|
|
63
63
|
* @prop {any} [emulate] - browser in device emulation mode.
|
|
64
64
|
* @prop {boolean} [video=false] - enables video recording for failed tests; videos are saved into `output/videos` folder
|
|
65
|
+
* @prop {boolean} [keepVideoForPassedTests=false] - save videos for passed tests; videos are saved into `output/videos` folder
|
|
65
66
|
* @prop {boolean} [trace=false] - record [tracing information](https://playwright.dev/docs/trace-viewer) with screenshots and snapshots.
|
|
66
67
|
* @prop {boolean} [fullPageScreenshots=false] - make full page screenshots on failure.
|
|
67
68
|
* @prop {boolean} [uniqueScreenshotNames=false] - option to prevent screenshot override if you have scenarios with the same name in different suites.
|
|
68
69
|
* @prop {boolean} [keepBrowserState=false] - keep browser state between tests when `restart` is set to 'session'.
|
|
69
70
|
* @prop {boolean} [keepCookies=false] - keep cookies between tests when `restart` is set to 'session'.
|
|
70
71
|
* @prop {number} [waitForAction] - how long to wait after click, doubleClick or PressKey actions in ms. Default: 100.
|
|
71
|
-
* @prop {
|
|
72
|
+
* @prop {string} [waitForNavigation] - When to consider navigation succeeded. Possible options: `load`, `domcontentloaded`, `networkidle`. Choose one of those options is possible. See [Playwright API](https://playwright.dev/docs/api/class-page#page-wait-for-navigation).
|
|
72
73
|
* @prop {number} [pressKeyDelay=10] - Delay between key presses in ms. Used when calling Playwrights page.type(...) in fillField/appendField
|
|
73
74
|
* @prop {number} [getPageTimeout] - config option to set maximum navigation time in milliseconds.
|
|
74
75
|
* @prop {number} [waitForTimeout] - default wait* timeout in ms. Default: 1000.
|
|
@@ -548,22 +549,22 @@ class Playwright extends Helper {
|
|
|
548
549
|
}
|
|
549
550
|
|
|
550
551
|
/**
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
552
|
+
* Use Playwright API inside a test.
|
|
553
|
+
*
|
|
554
|
+
* First argument is a description of an action.
|
|
555
|
+
* Second argument is async function that gets this helper as parameter.
|
|
556
|
+
*
|
|
557
|
+
* { [`page`](https://github.com/microsoft/playwright/blob/main/docs/src/api/class-page.md), [`browserContext`](https://github.com/microsoft/playwright/blob/main/docs/src/api/class-browsercontext.md) [`browser`](https://github.com/microsoft/playwright/blob/main/docs/src/api/class-browser.md) } objects from Playwright API are available.
|
|
558
|
+
*
|
|
559
|
+
* ```js
|
|
560
|
+
* I.usePlaywrightTo('emulate offline mode', async ({ browserContext }) => {
|
|
561
|
+
* await browserContext.setOffline(true);
|
|
562
|
+
* });
|
|
563
|
+
* ```
|
|
564
|
+
*
|
|
565
|
+
* @param {string} description used to show in logs.
|
|
566
|
+
* @param {function} fn async function that executed with Playwright helper as argumen
|
|
567
|
+
*/
|
|
567
568
|
usePlaywrightTo(description, fn) {
|
|
568
569
|
return this._useTo(...arguments);
|
|
569
570
|
}
|
|
@@ -2029,7 +2030,11 @@ class Playwright extends Helper {
|
|
|
2029
2030
|
}
|
|
2030
2031
|
|
|
2031
2032
|
if (this.options.recordVideo && this.page && this.page.video()) {
|
|
2033
|
+
const videoPath = `${global.output_dir}/videos/${clearString(test.title)}.failed.webm`;
|
|
2032
2034
|
test.artifacts.video = await this.page.video().path();
|
|
2035
|
+
fs.rename(test.artifacts.video, videoPath, (() => {
|
|
2036
|
+
test.artifacts.video = videoPath;
|
|
2037
|
+
}));
|
|
2033
2038
|
}
|
|
2034
2039
|
|
|
2035
2040
|
if (this.options.trace) {
|
|
@@ -2041,8 +2046,13 @@ class Playwright extends Helper {
|
|
|
2041
2046
|
|
|
2042
2047
|
async _passed(test) {
|
|
2043
2048
|
if (this.options.recordVideo && this.page && this.page.video()) {
|
|
2049
|
+
const videoPath = `${global.output_dir}/videos/${clearString(test.title)}.passed.webm`;
|
|
2050
|
+
|
|
2044
2051
|
if (this.options.keepVideoForPassedTests) {
|
|
2045
2052
|
test.artifacts.video = await this.page.video().path();
|
|
2053
|
+
fs.rename(test.artifacts.video, videoPath, (() => {
|
|
2054
|
+
test.artifacts.video = videoPath;
|
|
2055
|
+
}));
|
|
2046
2056
|
} else {
|
|
2047
2057
|
this.page.video().delete().catch(e => {});
|
|
2048
2058
|
}
|
|
@@ -2456,32 +2466,32 @@ class Playwright extends Helper {
|
|
|
2456
2466
|
}
|
|
2457
2467
|
|
|
2458
2468
|
/**
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
+
* Mocks network request using [`browserContext.route`](https://playwright.dev/docs/api/class-browsercontext#browser-context-route) of Playwright
|
|
2470
|
+
*
|
|
2471
|
+
* ```js
|
|
2472
|
+
* I.mockRoute(/(\.png$)|(\.jpg$)/, route => route.abort());
|
|
2473
|
+
* ```
|
|
2474
|
+
* This method allows intercepting and mocking requests & responses. [Learn more about it](https://playwright.dev/docs/network#handle-requests)
|
|
2475
|
+
*
|
|
2476
|
+
* @param {string|RegExp} [url] URL, regex or pattern for to match URL
|
|
2477
|
+
* @param {function} [handler] a function to process reques
|
|
2478
|
+
*/
|
|
2469
2479
|
async mockRoute(url, handler) {
|
|
2470
2480
|
return this.browserContext.route(...arguments);
|
|
2471
2481
|
}
|
|
2472
2482
|
|
|
2473
2483
|
/**
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2484
|
+
* Stops network mocking created by `mockRoute`.
|
|
2485
|
+
*
|
|
2486
|
+
* ```js
|
|
2487
|
+
* I.stopMockingRoute(/(\.png$)|(\.jpg$)/);
|
|
2488
|
+
* I.stopMockingRoute(/(\.png$)|(\.jpg$)/, previouslySetHandler);
|
|
2489
|
+
* ```
|
|
2490
|
+
* If no handler is passed, all mock requests for the rote are disabled.
|
|
2491
|
+
*
|
|
2492
|
+
* @param {string|RegExp} [url] URL, regex or pattern for to match URL
|
|
2493
|
+
* @param {function} [handler] a function to process reques
|
|
2494
|
+
*/
|
|
2485
2495
|
async stopMockingRoute(url, handler) {
|
|
2486
2496
|
return this.browserContext.unroute(...arguments);
|
|
2487
2497
|
}
|
package/lib/helper/Protractor.js
CHANGED
|
@@ -36,7 +36,7 @@ let Runner;
|
|
|
36
36
|
*
|
|
37
37
|
* ### Configuration
|
|
38
38
|
*
|
|
39
|
-
* This helper should be configured in codecept.
|
|
39
|
+
* This helper should be configured in codecept.conf.ts or codecept.conf.js
|
|
40
40
|
*
|
|
41
41
|
* * `url` - base url of website to be tested
|
|
42
42
|
* * `browser` - browser in which perform testing
|
package/lib/helper/REST.js
CHANGED
|
@@ -9,7 +9,7 @@ const { beautify } = require('../utils');
|
|
|
9
9
|
*
|
|
10
10
|
* @typedef RESTConfig
|
|
11
11
|
* @type {object}
|
|
12
|
-
* @prop {string} endpoint - API base URL
|
|
12
|
+
* @prop {string} [endpoint] - API base URL
|
|
13
13
|
* @prop {boolean} [prettyPrintJson=false] - pretty print json for response/request on console logs
|
|
14
14
|
* @prop {number} [timeout=1000] - timeout for requests in milliseconds. 10000ms by default
|
|
15
15
|
* @prop {object} [defaultHeaders] - a list of default headers
|
|
@@ -138,7 +138,7 @@ class REST extends Helper {
|
|
|
138
138
|
|
|
139
139
|
if (request.data instanceof Secret) {
|
|
140
140
|
_debugRequest.data = '*****';
|
|
141
|
-
request.data = typeof request.data === 'object' ? { ...request.data.toString() } : request.data.toString();
|
|
141
|
+
request.data = (typeof request.data === 'object' && !(request.data instanceof Secret)) ? { ...request.data.toString() } : request.data.toString();
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
if ((typeof request.data) === 'string') {
|
package/lib/helper/TestCafe.js
CHANGED
|
@@ -42,7 +42,7 @@ const getHtmlSource = t => ClientFunction(() => document.getElementsByTagName('h
|
|
|
42
42
|
*
|
|
43
43
|
* ## Configuration
|
|
44
44
|
*
|
|
45
|
-
* This helper should be configured in codecept.
|
|
45
|
+
* This helper should be configured in codecept.conf.ts or codecept.conf.js
|
|
46
46
|
*
|
|
47
47
|
* * `url`: base url of website to be tested
|
|
48
48
|
* * `show`: (optional, default: false) - show browser window.
|