codeceptjs 3.6.6 → 4.0.0-beta.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/bin/codecept.js +81 -84
- package/lib/actor.js +13 -13
- package/lib/ai.js +13 -10
- package/lib/assert/empty.js +21 -20
- package/lib/assert/equal.js +39 -37
- package/lib/assert/error.js +14 -14
- package/lib/assert/include.js +47 -46
- package/lib/assert/throws.js +11 -13
- package/lib/assert/truth.js +22 -19
- package/lib/assert.js +2 -4
- package/lib/cli.js +49 -57
- package/lib/codecept.js +155 -142
- package/lib/colorUtils.js +3 -3
- package/lib/command/configMigrate.js +52 -58
- package/lib/command/definitions.js +89 -88
- package/lib/command/dryRun.js +68 -71
- package/lib/command/generate.js +188 -197
- package/lib/command/gherkin/init.js +16 -27
- package/lib/command/gherkin/snippets.js +20 -20
- package/lib/command/gherkin/steps.js +8 -8
- package/lib/command/info.js +38 -40
- package/lib/command/init.js +288 -290
- package/lib/command/interactive.js +32 -32
- package/lib/command/list.js +26 -26
- package/lib/command/run-multiple/chunk.js +5 -5
- package/lib/command/run-multiple/collection.js +3 -3
- package/lib/command/run-multiple/run.js +2 -6
- package/lib/command/run-multiple.js +93 -113
- package/lib/command/run-rerun.js +25 -20
- package/lib/command/run-workers.js +66 -64
- package/lib/command/run.js +29 -26
- package/lib/command/utils.js +65 -80
- package/lib/command/workers/runTests.js +10 -10
- package/lib/config.js +9 -10
- package/lib/container.js +48 -40
- package/lib/data/context.js +59 -60
- package/lib/data/dataScenarioConfig.js +47 -47
- package/lib/data/dataTableArgument.js +29 -29
- package/lib/data/table.js +20 -26
- package/lib/dirname.js +5 -0
- package/lib/event.js +167 -163
- package/lib/heal.js +17 -13
- package/lib/helper/AI.js +41 -130
- package/lib/helper/ApiDataFactory.js +69 -73
- package/lib/helper/Appium.js +381 -412
- package/lib/helper/Expect.js +425 -0
- package/lib/helper/ExpectHelper.js +48 -40
- package/lib/helper/FileSystem.js +79 -80
- package/lib/helper/GraphQL.js +43 -44
- package/lib/helper/GraphQLDataFactory.js +50 -50
- package/lib/helper/JSONResponse.js +62 -65
- package/lib/helper/Mochawesome.js +28 -28
- package/lib/helper/MockServer.js +14 -12
- package/lib/helper/Nightmare.js +566 -662
- package/lib/helper/Playwright.js +1216 -1361
- package/lib/helper/Protractor.js +627 -663
- package/lib/helper/Puppeteer.js +1128 -1231
- package/lib/helper/REST.js +68 -159
- package/lib/helper/SoftExpectHelper.js +2 -2
- package/lib/helper/TestCafe.js +484 -490
- package/lib/helper/WebDriver.js +1156 -1297
- package/lib/helper/clientscripts/PollyWebDriverExt.js +1 -1
- package/lib/helper/errors/ConnectionRefused.js +1 -1
- package/lib/helper/errors/ElementAssertion.js +2 -2
- package/lib/helper/errors/ElementNotFound.js +2 -2
- package/lib/helper/errors/RemoteBrowserConnectionRefused.js +1 -1
- package/lib/helper/extras/Console.js +1 -1
- package/lib/helper/extras/PlaywrightPropEngine.js +2 -2
- package/lib/helper/extras/PlaywrightReactVueLocator.js +1 -1
- package/lib/helper/extras/PlaywrightRestartOpts.js +18 -21
- package/lib/helper/extras/Popup.js +1 -1
- package/lib/helper/extras/React.js +3 -3
- package/lib/helper/network/actions.js +7 -14
- package/lib/helper/network/utils.js +2 -3
- package/lib/helper/scripts/blurElement.js +1 -1
- package/lib/helper/scripts/focusElement.js +1 -1
- package/lib/helper/scripts/highlightElement.js +1 -1
- package/lib/helper/scripts/isElementClickable.js +1 -1
- package/lib/helper/testcafe/testControllerHolder.js +1 -1
- package/lib/helper/testcafe/testcafe-utils.js +7 -6
- package/lib/helper.js +3 -1
- package/lib/history.js +5 -6
- package/lib/hooks.js +6 -6
- package/lib/html.js +7 -7
- package/lib/index.js +41 -25
- package/lib/interfaces/bdd.js +64 -47
- package/lib/interfaces/featureConfig.js +19 -19
- package/lib/interfaces/gherkin.js +118 -124
- package/lib/interfaces/scenarioConfig.js +29 -29
- package/lib/listener/artifacts.js +9 -9
- package/lib/listener/config.js +24 -24
- package/lib/listener/exit.js +12 -12
- package/lib/listener/helpers.js +42 -42
- package/lib/listener/mocha.js +11 -11
- package/lib/listener/retry.js +30 -32
- package/lib/listener/steps.js +53 -50
- package/lib/listener/timeout.js +54 -54
- package/lib/locator.js +10 -6
- package/lib/mochaFactory.js +15 -18
- package/lib/output.js +10 -6
- package/lib/parser.js +12 -15
- package/lib/pause.js +33 -40
- package/lib/plugin/allure.js +15 -15
- package/lib/plugin/autoDelay.js +37 -29
- package/lib/plugin/autoLogin.js +65 -70
- package/lib/plugin/commentStep.js +18 -18
- package/lib/plugin/coverage.js +67 -115
- package/lib/plugin/customLocator.js +20 -21
- package/lib/plugin/debugErrors.js +24 -24
- package/lib/plugin/eachElement.js +38 -38
- package/lib/plugin/fakerTransform.js +6 -6
- package/lib/plugin/heal.js +108 -67
- package/lib/plugin/pauseOnFail.js +11 -11
- package/lib/plugin/retryFailedStep.js +39 -32
- package/lib/plugin/retryTo.js +40 -46
- package/lib/plugin/screenshotOnFail.js +87 -109
- package/lib/plugin/selenoid.js +118 -131
- package/lib/plugin/standardActingHelpers.js +8 -2
- package/lib/plugin/stepByStepReport.js +91 -110
- package/lib/plugin/stepTimeout.js +23 -24
- package/lib/plugin/subtitles.js +35 -34
- package/lib/plugin/tryTo.js +30 -40
- package/lib/plugin/wdio.js +75 -78
- package/lib/recorder.js +17 -14
- package/lib/rerun.js +10 -11
- package/lib/scenario.js +23 -25
- package/lib/secret.js +2 -4
- package/lib/session.js +10 -10
- package/lib/step.js +9 -12
- package/lib/store.js +3 -2
- package/lib/transform.js +1 -1
- package/lib/translation.js +8 -7
- package/lib/ui.js +14 -12
- package/lib/utils.js +72 -70
- package/lib/within.js +10 -10
- package/lib/workerStorage.js +25 -27
- package/lib/workers.js +32 -29
- package/package.json +53 -51
- package/translations/de-DE.js +1 -1
- package/translations/fr-FR.js +1 -1
- package/translations/index.js +13 -9
- package/translations/it-IT.js +1 -1
- package/translations/ja-JP.js +1 -1
- package/translations/pl-PL.js +1 -1
- package/translations/pt-BR.js +1 -1
- package/translations/ru-RU.js +1 -1
- package/translations/zh-CN.js +1 -1
- package/translations/zh-TW.js +1 -1
- package/typings/index.d.ts +65 -415
- package/typings/promiseBasedTypes.d.ts +32 -0
- package/typings/types.d.ts +32 -0
package/lib/command/init.js
CHANGED
|
@@ -1,37 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import colors from 'chalk';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import mkdirp from 'mkdirp';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { inspect } from 'util';
|
|
7
|
+
import spawn from 'cross-spawn';
|
|
8
|
+
import * as output from '../output.js';
|
|
9
|
+
import { fileExists, beautify, installedLocally } from '../utils.js';
|
|
10
|
+
import { getTestRoot } from './utils.js';
|
|
11
|
+
import generateDefinitions from './definitions.js';
|
|
12
|
+
import { test as generateTest } from './generate.js';
|
|
13
|
+
import * as translations0 from '../../translations/index.js';
|
|
14
|
+
|
|
15
|
+
const isLocal = installedLocally();
|
|
15
16
|
|
|
16
17
|
const defaultConfig = {
|
|
17
18
|
tests: './*_test.js',
|
|
18
19
|
output: '',
|
|
19
20
|
helpers: {},
|
|
20
21
|
include: {},
|
|
21
|
-
}
|
|
22
|
+
};
|
|
22
23
|
|
|
23
|
-
const helpers = ['Playwright', 'WebDriver', 'Puppeteer', 'REST', 'GraphQL', 'Appium', 'TestCafe']
|
|
24
|
-
const translations = Object.keys(
|
|
24
|
+
const helpers = ['Playwright', 'WebDriver', 'Puppeteer', 'REST', 'GraphQL', 'Appium', 'TestCafe'];
|
|
25
|
+
const translations = Object.keys(translations0);
|
|
25
26
|
|
|
26
|
-
const noTranslation = 'English (no localization)'
|
|
27
|
-
translations.unshift(noTranslation)
|
|
27
|
+
const noTranslation = 'English (no localization)';
|
|
28
|
+
translations.unshift(noTranslation);
|
|
28
29
|
|
|
29
|
-
const packages = []
|
|
30
|
-
let isTypeScript = false
|
|
31
|
-
let extension = 'js'
|
|
30
|
+
const packages = [];
|
|
31
|
+
let isTypeScript = false;
|
|
32
|
+
let extension = 'js';
|
|
32
33
|
|
|
33
|
-
const requireCodeceptConfigure = "const { setHeadlessWhen, setCommonPlugins } = require('@codeceptjs/configure');"
|
|
34
|
-
const importCodeceptConfigure = "import { setHeadlessWhen, setCommonPlugins } from '@codeceptjs/configure';"
|
|
34
|
+
const requireCodeceptConfigure = "const { setHeadlessWhen, setCommonPlugins } = require('@codeceptjs/configure');";
|
|
35
|
+
const importCodeceptConfigure = "import { setHeadlessWhen, setCommonPlugins } from '@codeceptjs/configure';";
|
|
35
36
|
|
|
36
37
|
const configHeader = `
|
|
37
38
|
// turn on headless mode when running with HEADLESS=true environment variable
|
|
@@ -41,7 +42,7 @@ setHeadlessWhen(process.env.HEADLESS);
|
|
|
41
42
|
// enable all common plugins https://github.com/codeceptjs/configure#setcommonplugins
|
|
42
43
|
setCommonPlugins();
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
`;
|
|
45
46
|
|
|
46
47
|
const defaultActor = `// in this file you can append custom step methods to 'I' object
|
|
47
48
|
|
|
@@ -53,7 +54,7 @@ module.exports = function() {
|
|
|
53
54
|
|
|
54
55
|
});
|
|
55
56
|
}
|
|
56
|
-
|
|
57
|
+
`;
|
|
57
58
|
|
|
58
59
|
const defaultActorTs = `// in this file you can append custom step methods to 'I' object
|
|
59
60
|
|
|
@@ -65,357 +66,354 @@ export = function() {
|
|
|
65
66
|
|
|
66
67
|
});
|
|
67
68
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const testsPath = getTestRoot(initPath)
|
|
72
|
-
|
|
73
|
-
print()
|
|
74
|
-
print(` Welcome to ${colors.magenta.bold('CodeceptJS')} initialization tool`)
|
|
75
|
-
print(' It will prepare and configure a test environment for you')
|
|
76
|
-
print()
|
|
77
|
-
print(' Useful links:')
|
|
78
|
-
print()
|
|
79
|
-
print(' 👉 How to start testing ASAP: https://codecept.io/quickstart/#init')
|
|
80
|
-
print(' 👉 How to select helper: https://codecept.io/basics/#architecture')
|
|
81
|
-
print(' 👉 TypeScript setup: https://codecept.io/typescript/#getting-started')
|
|
82
|
-
print()
|
|
69
|
+
`;
|
|
70
|
+
|
|
71
|
+
export default function (initPath) {
|
|
72
|
+
const testsPath = getTestRoot(initPath);
|
|
73
|
+
|
|
74
|
+
print();
|
|
75
|
+
print(` Welcome to ${colors.magenta.bold('CodeceptJS')} initialization tool`);
|
|
76
|
+
print(' It will prepare and configure a test environment for you');
|
|
77
|
+
print();
|
|
78
|
+
print(' Useful links:');
|
|
79
|
+
print();
|
|
80
|
+
print(' 👉 How to start testing ASAP: https://codecept.io/quickstart/#init');
|
|
81
|
+
print(' 👉 How to select helper: https://codecept.io/basics/#architecture');
|
|
82
|
+
print(' 👉 TypeScript setup: https://codecept.io/typescript/#getting-started');
|
|
83
|
+
print();
|
|
83
84
|
|
|
84
85
|
if (!path) {
|
|
85
|
-
print('No test root specified.')
|
|
86
|
-
print(`Test root is assumed to be ${colors.yellow.bold(testsPath)}`)
|
|
87
|
-
print('----------------------------------')
|
|
86
|
+
print('No test root specified.');
|
|
87
|
+
print(`Test root is assumed to be ${colors.yellow.bold(testsPath)}`);
|
|
88
|
+
print('----------------------------------');
|
|
88
89
|
} else {
|
|
89
|
-
print(`Installing to ${colors.bold(testsPath)}`)
|
|
90
|
+
print(`Installing to ${colors.bold(testsPath)}`);
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
if (!fileExists(testsPath)) {
|
|
93
|
-
print(`Directory ${testsPath} does not exist, creating...`)
|
|
94
|
-
mkdirp.sync(testsPath)
|
|
94
|
+
print(`Directory ${testsPath} does not exist, creating...`);
|
|
95
|
+
mkdirp.sync(testsPath);
|
|
95
96
|
}
|
|
96
97
|
|
|
97
|
-
const configFile = path.join(testsPath, 'codecept.conf.js')
|
|
98
|
+
const configFile = path.join(testsPath, 'codecept.conf.js');
|
|
98
99
|
if (fileExists(configFile)) {
|
|
99
|
-
error(`Config is already created at ${configFile}`)
|
|
100
|
-
return
|
|
100
|
+
error(`Config is already created at ${configFile}`);
|
|
101
|
+
return;
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
const typeScriptconfigFile = path.join(testsPath, 'codecept.conf.ts')
|
|
104
|
+
const typeScriptconfigFile = path.join(testsPath, 'codecept.conf.ts');
|
|
104
105
|
if (fileExists(typeScriptconfigFile)) {
|
|
105
|
-
error(`Config is already created at ${typeScriptconfigFile}`)
|
|
106
|
-
return
|
|
106
|
+
error(`Config is already created at ${typeScriptconfigFile}`);
|
|
107
|
+
return;
|
|
107
108
|
}
|
|
108
109
|
|
|
109
|
-
inquirer
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
packages.push('@types/node')
|
|
156
|
-
}
|
|
110
|
+
inquirer.prompt([
|
|
111
|
+
{
|
|
112
|
+
name: 'typescript',
|
|
113
|
+
type: 'confirm',
|
|
114
|
+
default: false,
|
|
115
|
+
message: 'Do you plan to write tests in TypeScript?',
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: 'tests',
|
|
119
|
+
type: 'input',
|
|
120
|
+
default: (answers) => `./*_test.${answers.typescript ? 'ts' : 'js'}`,
|
|
121
|
+
message: 'Where are your tests located?',
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: 'helper',
|
|
125
|
+
type: 'list',
|
|
126
|
+
choices: helpers,
|
|
127
|
+
default: 'Playwright',
|
|
128
|
+
message: 'What helpers do you want to use?',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: 'jsonResponse',
|
|
132
|
+
type: 'confirm',
|
|
133
|
+
default: true,
|
|
134
|
+
message: 'Do you want to use JSONResponse helper for assertions on JSON responses? http://bit.ly/3ASVPy9',
|
|
135
|
+
when: (answers) => ['GraphQL', 'REST'].includes(answers.helper) === true,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: 'output',
|
|
139
|
+
default: './output',
|
|
140
|
+
message: 'Where should logs, screenshots, and reports to be stored?',
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: 'translation',
|
|
144
|
+
type: 'list',
|
|
145
|
+
message: 'Do you want to enable localization for tests? http://bit.ly/3GNUBbh',
|
|
146
|
+
choices: translations,
|
|
147
|
+
},
|
|
148
|
+
]).then((result) => {
|
|
149
|
+
if (result.typescript === true) {
|
|
150
|
+
isTypeScript = true;
|
|
151
|
+
extension = isTypeScript === true ? 'ts' : 'js';
|
|
152
|
+
packages.push('typescript');
|
|
153
|
+
packages.push('ts-node');
|
|
154
|
+
packages.push('@types/node');
|
|
155
|
+
}
|
|
157
156
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
157
|
+
const config = defaultConfig;
|
|
158
|
+
config.name = testsPath.split(path.sep).pop();
|
|
159
|
+
config.output = result.output;
|
|
161
160
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
161
|
+
config.tests = result.tests;
|
|
162
|
+
if (isTypeScript) {
|
|
163
|
+
config.tests = `${config.tests.replace(/\.js$/, `.${extension}`)}`;
|
|
164
|
+
}
|
|
166
165
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
166
|
+
// create a directory tests if it is included in tests path
|
|
167
|
+
const matchResults = config.tests.match(/[^*.]+/);
|
|
168
|
+
if (matchResults) {
|
|
169
|
+
mkdirp.sync(path.join(testsPath, matchResults[0]));
|
|
170
|
+
}
|
|
172
171
|
|
|
173
|
-
|
|
172
|
+
if (result.translation !== noTranslation) config.translation = result.translation;
|
|
174
173
|
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
const helperName = result.helper;
|
|
175
|
+
config.helpers[helperName] = {};
|
|
177
176
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
if (result.jsonResponse === true) {
|
|
178
|
+
config.helpers.JSONResponse = {};
|
|
179
|
+
}
|
|
181
180
|
|
|
182
|
-
|
|
181
|
+
let helperConfigs = [];
|
|
183
182
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
if (!Helper._config()) return
|
|
191
|
-
helperConfigs = helperConfigs.concat(
|
|
192
|
-
Helper._config().map((config) => {
|
|
193
|
-
config.message = `[${helperName}] ${config.message}`
|
|
194
|
-
config.name = `${helperName}_${config.name}`
|
|
195
|
-
config.type = config.type || 'input'
|
|
196
|
-
return config
|
|
197
|
-
}),
|
|
198
|
-
)
|
|
199
|
-
} catch (err) {
|
|
200
|
-
error(err)
|
|
183
|
+
try {
|
|
184
|
+
const Helper = require(`../helper/${helperName}`);
|
|
185
|
+
if (Helper._checkRequirements) {
|
|
186
|
+
packages.concat(Helper._checkRequirements());
|
|
201
187
|
}
|
|
202
188
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
189
|
+
if (!Helper._config()) return;
|
|
190
|
+
helperConfigs = helperConfigs.concat(Helper._config().map((config) => {
|
|
191
|
+
config.message = `[${helperName}] ${config.message}`;
|
|
192
|
+
config.name = `${helperName}_${config.name}`;
|
|
193
|
+
config.type = config.type || 'input';
|
|
194
|
+
return config;
|
|
195
|
+
}));
|
|
196
|
+
} catch (err) {
|
|
197
|
+
error(err);
|
|
198
|
+
}
|
|
208
199
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
200
|
+
const finish = async () => {
|
|
201
|
+
// create steps file by default
|
|
202
|
+
// no extra step file for typescript (as it doesn't match TS conventions)
|
|
203
|
+
const stepFile = `./steps_file.${extension}`;
|
|
204
|
+
fs.writeFileSync(path.join(testsPath, stepFile), extension === 'ts' ? defaultActorTs : defaultActor);
|
|
214
205
|
|
|
215
|
-
|
|
206
|
+
if (isTypeScript) {
|
|
207
|
+
config.include = _actorTranslation('./steps_file', config.translation);
|
|
208
|
+
} else {
|
|
209
|
+
config.include = _actorTranslation(stepFile, config.translation);
|
|
210
|
+
}
|
|
216
211
|
|
|
217
|
-
|
|
218
|
-
const hasConfigure = isLocal && !initPath
|
|
212
|
+
print(`Steps file created at ${stepFile}`);
|
|
219
213
|
|
|
220
|
-
|
|
221
|
-
|
|
214
|
+
let configSource;
|
|
215
|
+
const hasConfigure = isLocal && !initPath;
|
|
222
216
|
|
|
223
|
-
|
|
217
|
+
if (isTypeScript) {
|
|
218
|
+
configSource = beautify(`export const config : CodeceptJS.MainConfig = ${inspect(config, false, 4, false)}`);
|
|
224
219
|
|
|
225
|
-
|
|
226
|
-
print(`Config created at ${typeScriptconfigFile}`)
|
|
227
|
-
} else {
|
|
228
|
-
configSource = beautify(
|
|
229
|
-
`/** @type {CodeceptJS.MainConfig} */\nexports.config = ${inspect(config, false, 4, false)}`,
|
|
230
|
-
)
|
|
220
|
+
if (hasConfigure) configSource = importCodeceptConfigure + configHeader + configSource;
|
|
231
221
|
|
|
232
|
-
|
|
222
|
+
fs.writeFileSync(typeScriptconfigFile, configSource, 'utf-8');
|
|
223
|
+
print(`Config created at ${typeScriptconfigFile}`);
|
|
224
|
+
} else {
|
|
225
|
+
configSource = beautify(`/** @type {CodeceptJS.MainConfig} */\nexports.config = ${inspect(config, false, 4, false)}`);
|
|
233
226
|
|
|
234
|
-
|
|
235
|
-
print(`Config created at ${configFile}`)
|
|
236
|
-
}
|
|
227
|
+
if (hasConfigure) configSource = requireCodeceptConfigure + configHeader + configSource;
|
|
237
228
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
print(`Directory for temporary output files created at '${config.output}'`)
|
|
242
|
-
} else {
|
|
243
|
-
print(`Directory for temporary output files is already created at '${config.output}'`)
|
|
244
|
-
}
|
|
245
|
-
}
|
|
229
|
+
fs.writeFileSync(configFile, configSource, 'utf-8');
|
|
230
|
+
print(`Config created at ${configFile}`);
|
|
231
|
+
}
|
|
246
232
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
233
|
+
if (config.output) {
|
|
234
|
+
if (!fileExists(config.output)) {
|
|
235
|
+
mkdirp.sync(path.join(testsPath, config.output));
|
|
236
|
+
print(`Directory for temporary output files created at '${config.output}'`);
|
|
237
|
+
} else {
|
|
238
|
+
print(`Directory for temporary output files is already created at '${config.output}'`);
|
|
251
239
|
}
|
|
240
|
+
}
|
|
252
241
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
242
|
+
const jsconfig = {
|
|
243
|
+
compilerOptions: {
|
|
244
|
+
allowJs: true,
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
const tsconfig = {
|
|
249
|
+
'ts-node': {
|
|
250
|
+
files: true,
|
|
251
|
+
},
|
|
252
|
+
compilerOptions: {
|
|
253
|
+
target: 'es2018',
|
|
254
|
+
lib: ['es2018', 'DOM'],
|
|
255
|
+
esModuleInterop: true,
|
|
256
|
+
module: 'commonjs',
|
|
257
|
+
strictNullChecks: false,
|
|
258
|
+
types: ['codeceptjs', 'node'],
|
|
259
|
+
declaration: true,
|
|
260
|
+
skipLibCheck: true,
|
|
261
|
+
},
|
|
262
|
+
exclude: ['node_modules'],
|
|
263
|
+
};
|
|
269
264
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
} else {
|
|
276
|
-
fs.writeFileSync(tsconfigFile, tsconfigJson)
|
|
277
|
-
}
|
|
265
|
+
if (isTypeScript) {
|
|
266
|
+
const tsconfigJson = beautify(JSON.stringify(tsconfig));
|
|
267
|
+
const tsconfigFile = path.join(testsPath, 'tsconfig.json');
|
|
268
|
+
if (fileExists(tsconfigFile)) {
|
|
269
|
+
print(`tsconfig.json already exists at ${tsconfigFile}`);
|
|
278
270
|
} else {
|
|
279
|
-
|
|
280
|
-
const jsconfigFile = path.join(testsPath, 'jsconfig.json')
|
|
281
|
-
if (fileExists(jsconfigFile)) {
|
|
282
|
-
print(`jsconfig.json already exists at ${jsconfigFile}`)
|
|
283
|
-
} else {
|
|
284
|
-
fs.writeFileSync(jsconfigFile, jsconfigJson)
|
|
285
|
-
print(`Intellisense enabled in ${jsconfigFile}`)
|
|
286
|
-
}
|
|
271
|
+
fs.writeFileSync(tsconfigFile, tsconfigJson);
|
|
287
272
|
}
|
|
288
|
-
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
)
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
} catch (err) {
|
|
297
|
-
print(colors.bold.red(err.toString()))
|
|
298
|
-
print()
|
|
299
|
-
print(colors.bold.red('Please install next packages manually:'))
|
|
300
|
-
print(`npm i ${packages.join(' ')} --save-dev`)
|
|
301
|
-
print()
|
|
302
|
-
print('Things to do after missing packages installed:')
|
|
303
|
-
print('☑', generateDefinitionsManually)
|
|
304
|
-
print('☑ Create first test:', colors.green('npx codeceptjs gt'))
|
|
305
|
-
print(colors.bold.magenta('Find more information at https://codecept.io'))
|
|
306
|
-
return
|
|
307
|
-
}
|
|
273
|
+
} else {
|
|
274
|
+
const jsconfigJson = beautify(JSON.stringify(jsconfig));
|
|
275
|
+
const jsconfigFile = path.join(testsPath, 'jsconfig.json');
|
|
276
|
+
if (fileExists(jsconfigFile)) {
|
|
277
|
+
print(`jsconfig.json already exists at ${jsconfigFile}`);
|
|
278
|
+
} else {
|
|
279
|
+
fs.writeFileSync(jsconfigFile, jsconfigJson);
|
|
280
|
+
print(`Intellisense enabled in ${jsconfigFile}`);
|
|
308
281
|
}
|
|
282
|
+
}
|
|
309
283
|
|
|
284
|
+
const generateDefinitionsManually = colors.bold(`To get auto-completion support, please generate type definitions: ${colors.green('npx codeceptjs def')}`);
|
|
285
|
+
|
|
286
|
+
if (packages) {
|
|
310
287
|
try {
|
|
311
|
-
|
|
288
|
+
install(packages);
|
|
312
289
|
} catch (err) {
|
|
313
|
-
print(colors.bold.red(
|
|
314
|
-
print(
|
|
315
|
-
print('
|
|
316
|
-
print(
|
|
290
|
+
print(colors.bold.red(err.toString()));
|
|
291
|
+
print();
|
|
292
|
+
print(colors.bold.red('Please install next packages manually:'));
|
|
293
|
+
print(`npm i ${packages.join(' ')} --save-dev`);
|
|
294
|
+
print();
|
|
295
|
+
print('Things to do after missing packages installed:');
|
|
296
|
+
print('☑', generateDefinitionsManually);
|
|
297
|
+
print('☑ Create first test:', colors.green('npx codeceptjs gt'));
|
|
298
|
+
print(colors.bold.magenta('Find more information at https://codecept.io'));
|
|
299
|
+
return;
|
|
317
300
|
}
|
|
318
|
-
|
|
319
|
-
print('')
|
|
320
|
-
success(' Almost ready... Next step:')
|
|
321
|
-
|
|
322
|
-
const generatedTest = generateTest(testsPath)
|
|
323
|
-
if (!generatedTest) return
|
|
324
|
-
generatedTest.then(() => {
|
|
325
|
-
print('\n--')
|
|
326
|
-
print(colors.bold.green('CodeceptJS Installed! Enjoy supercharged testing! 🤩'))
|
|
327
|
-
print(colors.bold.magenta('Find more information at https://codecept.io'))
|
|
328
|
-
print()
|
|
329
|
-
})
|
|
330
301
|
}
|
|
331
302
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
303
|
+
try {
|
|
304
|
+
generateDefinitions(testsPath, {});
|
|
305
|
+
} catch (err) {
|
|
306
|
+
print(colors.bold.red('Couldn\'t generate type definitions'));
|
|
307
|
+
print(colors.red(err.toString()));
|
|
308
|
+
print('Skipping type definitions...');
|
|
309
|
+
print(generateDefinitionsManually);
|
|
310
|
+
}
|
|
337
311
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
312
|
+
print('');
|
|
313
|
+
success(' Almost ready... Next step:');
|
|
314
|
+
|
|
315
|
+
const generatedTest = generateTest(testsPath);
|
|
316
|
+
if (!generatedTest) return;
|
|
317
|
+
generatedTest.then(() => {
|
|
318
|
+
print('\n--');
|
|
319
|
+
print(colors.bold.green('CodeceptJS Installed! Enjoy supercharged testing! 🤩'));
|
|
320
|
+
print(colors.bold.magenta('Find more information at https://codecept.io'));
|
|
321
|
+
print();
|
|
322
|
+
});
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
print('Configure helpers...');
|
|
326
|
+
inquirer.prompt(helperConfigs).then(async (helperResult) => {
|
|
327
|
+
if (helperResult.Playwright_browser === 'electron') {
|
|
328
|
+
delete helperResult.Playwright_url;
|
|
329
|
+
delete helperResult.Playwright_show;
|
|
330
|
+
|
|
331
|
+
helperResult.Playwright_electron = {
|
|
332
|
+
executablePath: '// require("electron") or require("electron-forge")',
|
|
333
|
+
args: ['path/to/your/main.js'],
|
|
334
|
+
};
|
|
335
|
+
}
|
|
343
336
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
337
|
+
Object.keys(helperResult).forEach((key) => {
|
|
338
|
+
const parts = key.split('_');
|
|
339
|
+
const helperName = parts[0];
|
|
340
|
+
const configName = parts[1];
|
|
341
|
+
if (!configName) return;
|
|
342
|
+
config.helpers[helperName][configName] = helperResult[key];
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
print('');
|
|
346
|
+
await finish();
|
|
347
|
+
});
|
|
348
|
+
});
|
|
356
349
|
}
|
|
357
350
|
|
|
358
351
|
function install(dependencies) {
|
|
359
|
-
let command
|
|
360
|
-
let args
|
|
352
|
+
let command;
|
|
353
|
+
let args;
|
|
361
354
|
|
|
362
355
|
if (!fs.existsSync(path.join(process.cwd(), 'package.json'))) {
|
|
363
|
-
dependencies.push('codeceptjs')
|
|
364
|
-
throw new Error("Error: 'package.json' file not found. Generate it with 'npm init -y' command.")
|
|
356
|
+
dependencies.push('codeceptjs');
|
|
357
|
+
throw new Error("Error: 'package.json' file not found. Generate it with 'npm init -y' command.");
|
|
365
358
|
}
|
|
366
359
|
|
|
367
360
|
if (!installedLocally()) {
|
|
368
|
-
console.log('CodeceptJS should be installed locally')
|
|
369
|
-
dependencies.push('codeceptjs')
|
|
361
|
+
console.log('CodeceptJS should be installed locally');
|
|
362
|
+
dependencies.push('codeceptjs');
|
|
370
363
|
}
|
|
371
364
|
|
|
372
|
-
console.log('Installing packages: ', colors.green(dependencies.join(', ')))
|
|
365
|
+
console.log('Installing packages: ', colors.green(dependencies.join(', ')));
|
|
373
366
|
|
|
374
367
|
if (fileExists('yarn.lock')) {
|
|
375
|
-
command = 'yarnpkg'
|
|
376
|
-
args = ['add', '-D', '--exact']
|
|
377
|
-
|
|
368
|
+
command = 'yarnpkg';
|
|
369
|
+
args = ['add', '-D', '--exact'];
|
|
370
|
+
[].push.apply(args, dependencies);
|
|
378
371
|
|
|
379
|
-
args.push('--cwd')
|
|
380
|
-
args.push(process.cwd())
|
|
372
|
+
args.push('--cwd');
|
|
373
|
+
args.push(process.cwd());
|
|
381
374
|
} else {
|
|
382
|
-
command = 'npm'
|
|
383
|
-
args = [
|
|
375
|
+
command = 'npm';
|
|
376
|
+
args = [
|
|
377
|
+
'install',
|
|
378
|
+
'--save-dev',
|
|
379
|
+
'--loglevel',
|
|
380
|
+
'error',
|
|
381
|
+
].concat(dependencies);
|
|
384
382
|
}
|
|
385
383
|
|
|
386
384
|
if (process.env._INIT_DRY_RUN_INSTALL) {
|
|
387
|
-
args.push('--dry-run')
|
|
385
|
+
args.push('--dry-run');
|
|
388
386
|
}
|
|
389
387
|
|
|
390
|
-
const { status } = spawn.sync(command, args, { stdio: 'inherit' })
|
|
388
|
+
const { status } = spawn.sync(command, args, { stdio: 'inherit' });
|
|
391
389
|
if (status !== 0) {
|
|
392
|
-
throw new Error(`${command} ${args.join(' ')} failed`)
|
|
390
|
+
throw new Error(`${command} ${args.join(' ')} failed`);
|
|
393
391
|
}
|
|
394
|
-
return true
|
|
392
|
+
return true;
|
|
395
393
|
}
|
|
396
394
|
|
|
397
395
|
function _actorTranslation(stepFile, translationSelected) {
|
|
398
|
-
let actor
|
|
396
|
+
let actor;
|
|
399
397
|
|
|
400
398
|
for (const translationAvailable of translations) {
|
|
401
399
|
if (actor) {
|
|
402
|
-
break
|
|
400
|
+
break;
|
|
403
401
|
}
|
|
404
402
|
|
|
405
403
|
if (translationSelected === translationAvailable) {
|
|
406
|
-
const nameOfActor = require('../../translations')[translationAvailable].I
|
|
404
|
+
const nameOfActor = require('../../translations')[translationAvailable].I;
|
|
407
405
|
|
|
408
406
|
actor = {
|
|
409
407
|
[nameOfActor]: stepFile,
|
|
410
|
-
}
|
|
408
|
+
};
|
|
411
409
|
}
|
|
412
410
|
}
|
|
413
411
|
|
|
414
412
|
if (!actor) {
|
|
415
413
|
actor = {
|
|
416
414
|
I: stepFile,
|
|
417
|
-
}
|
|
415
|
+
};
|
|
418
416
|
}
|
|
419
417
|
|
|
420
|
-
return actor
|
|
418
|
+
return actor;
|
|
421
419
|
}
|