@wdio/cli 8.17.0 → 8.18.2
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/build/commands/config.d.ts.map +1 -1
- package/build/commands/config.js +13 -5
- package/build/constants.d.ts +10 -3
- package/build/constants.d.ts.map +1 -1
- package/build/constants.js +47 -23
- package/build/templates/EjsHelpers.d.ts +18 -0
- package/build/templates/EjsHelpers.d.ts.map +1 -0
- package/build/templates/EjsHelpers.js +59 -0
- package/build/templates/EjsHelpers.ts +84 -0
- package/build/templates/exampleFiles/serenity-js/common/config/serenity.properties.ejs +1 -0
- package/build/templates/exampleFiles/serenity-js/common/serenity/github-api/GitHubStatus.ts.ejs +41 -0
- package/build/templates/exampleFiles/serenity-js/common/serenity/todo-list-app/TodoList.ts.ejs +100 -0
- package/build/templates/exampleFiles/serenity-js/common/serenity/todo-list-app/TodoListItem.ts.ejs +36 -0
- package/build/templates/exampleFiles/serenity-js/cucumber/step-definitions/steps.ts.ejs +37 -0
- package/build/templates/exampleFiles/serenity-js/cucumber/support/parameter.config.ts.ejs +18 -0
- package/build/templates/exampleFiles/serenity-js/cucumber/todo-list/completing_items.feature.ejs +23 -0
- package/build/templates/exampleFiles/serenity-js/cucumber/todo-list/narrative.md.ejs +17 -0
- package/build/templates/exampleFiles/serenity-js/jasmine/example.spec.ts.ejs +86 -0
- package/build/templates/exampleFiles/serenity-js/mocha/example.spec.ts.ejs +88 -0
- package/build/templates/snippets/capabilities.ejs +9 -3
- package/build/templates/snippets/cucumber.ejs +48 -0
- package/build/templates/snippets/jasmine.ejs +20 -0
- package/build/templates/snippets/mocha.ejs +14 -0
- package/build/templates/snippets/serenity.ejs +18 -0
- package/build/templates/wdio.conf.tpl.ejs +11 -86
- package/build/types.d.ts +5 -1
- package/build/types.d.ts.map +1 -1
- package/build/utils.d.ts +4 -2
- package/build/utils.d.ts.map +1 -1
- package/build/utils.js +170 -81
- package/package.json +7 -7
package/build/utils.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
|
-
import util from 'node:util';
|
|
3
|
-
import { dirname } from 'node:path';
|
|
2
|
+
import util, { promisify } from 'node:util';
|
|
3
|
+
import path, { dirname } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { execSync, spawn } from 'node:child_process';
|
|
6
|
-
import { promisify } from 'node:util';
|
|
7
6
|
import ejs from 'ejs';
|
|
8
7
|
import chalk from 'chalk';
|
|
9
|
-
import path from 'node:path';
|
|
10
8
|
import inquirer from 'inquirer';
|
|
11
9
|
import pickBy from 'lodash.pickby';
|
|
12
10
|
import logger from '@wdio/logger';
|
|
@@ -18,7 +16,8 @@ import { resolve } from 'import-meta-resolve';
|
|
|
18
16
|
import { SevereServiceError } from 'webdriverio';
|
|
19
17
|
import { ConfigParser } from '@wdio/config';
|
|
20
18
|
import { CAPABILITY_KEYS } from '@wdio/protocols';
|
|
21
|
-
import { ANDROID_CONFIG,
|
|
19
|
+
import { ANDROID_CONFIG, CompilerOptions, DEPENDENCIES_INSTALLATION_MESSAGE, IOS_CONFIG, pkg, QUESTIONNAIRE, TESTING_LIBRARY_PACKAGES, COMMUNITY_PACKAGES_WITH_TS_SUPPORT, usesSerenity, } from './constants.js';
|
|
20
|
+
import { EjsHelpers } from './templates/EjsHelpers.js';
|
|
22
21
|
const log = logger('@wdio/cli:utils');
|
|
23
22
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
24
23
|
const NPM_COMMAND = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';
|
|
@@ -181,6 +180,44 @@ export function convertPackageHashToObject(pkg, hash = '$--$') {
|
|
|
181
180
|
const [p, short, purpose] = pkg.split(hash);
|
|
182
181
|
return { package: p, short, purpose };
|
|
183
182
|
}
|
|
183
|
+
export function getSerenityPackages(answers) {
|
|
184
|
+
const framework = convertPackageHashToObject(answers.framework);
|
|
185
|
+
if (framework.package !== '@serenity-js/webdriverio') {
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
const isUsingTypeScript = answers.isUsingCompiler === CompilerOptions.TS;
|
|
189
|
+
const packages = {
|
|
190
|
+
cucumber: [
|
|
191
|
+
'@cucumber/cucumber',
|
|
192
|
+
'@serenity-js/cucumber',
|
|
193
|
+
],
|
|
194
|
+
mocha: [
|
|
195
|
+
'@serenity-js/mocha',
|
|
196
|
+
'mocha',
|
|
197
|
+
isUsingTypeScript && '@types/mocha',
|
|
198
|
+
],
|
|
199
|
+
jasmine: [
|
|
200
|
+
'@serenity-js/jasmine',
|
|
201
|
+
'jasmine',
|
|
202
|
+
isUsingTypeScript && '@types/jasmine',
|
|
203
|
+
],
|
|
204
|
+
common: [
|
|
205
|
+
'@serenity-js/assertions',
|
|
206
|
+
'@serenity-js/console-reporter',
|
|
207
|
+
'@serenity-js/core',
|
|
208
|
+
'@serenity-js/rest',
|
|
209
|
+
'@serenity-js/serenity-bdd',
|
|
210
|
+
'@serenity-js/web',
|
|
211
|
+
isUsingTypeScript && '@types/node',
|
|
212
|
+
'npm-failsafe',
|
|
213
|
+
'rimraf',
|
|
214
|
+
]
|
|
215
|
+
};
|
|
216
|
+
return [
|
|
217
|
+
...packages[framework.purpose],
|
|
218
|
+
...packages.common,
|
|
219
|
+
].filter(Boolean).sort();
|
|
220
|
+
}
|
|
184
221
|
export async function getCapabilities(arg) {
|
|
185
222
|
const optionalCapabilites = {
|
|
186
223
|
platformVersion: arg.platformVersion,
|
|
@@ -287,6 +324,9 @@ export async function hasPackage(pkg) {
|
|
|
287
324
|
* generate test files based on CLI answers
|
|
288
325
|
*/
|
|
289
326
|
export async function generateTestFiles(answers) {
|
|
327
|
+
if (answers.serenityAdapter) {
|
|
328
|
+
return generateSerenityExamples(answers);
|
|
329
|
+
}
|
|
290
330
|
if (answers.runner === 'local') {
|
|
291
331
|
return generateLocalRunnerTestFiles(answers);
|
|
292
332
|
}
|
|
@@ -345,6 +385,25 @@ async function generateLocalRunnerTestFiles(answers) {
|
|
|
345
385
|
await fs.writeFile(destPath, renderedTpl);
|
|
346
386
|
}
|
|
347
387
|
}
|
|
388
|
+
async function generateSerenityExamples(answers) {
|
|
389
|
+
const templateDirectories = {
|
|
390
|
+
[answers.projectRootDir]: path.join(TEMPLATE_ROOT_DIR, 'serenity-js', 'common', 'config'),
|
|
391
|
+
[answers.destSpecRootPath]: path.join(TEMPLATE_ROOT_DIR, 'serenity-js', answers.serenityAdapter),
|
|
392
|
+
[answers.destSerenityLibRootPath]: path.join(TEMPLATE_ROOT_DIR, 'serenity-js', 'common', 'serenity'),
|
|
393
|
+
};
|
|
394
|
+
for (const [destinationRootDir, templateRootDir] of Object.entries(templateDirectories)) {
|
|
395
|
+
const pathsToTemplates = await readDir(templateRootDir);
|
|
396
|
+
for (const pathToTemplate of pathsToTemplates) {
|
|
397
|
+
const extension = answers.isUsingTypeScript ? '.ts' : '.js';
|
|
398
|
+
const destination = path.join(destinationRootDir, path.relative(templateRootDir, pathToTemplate))
|
|
399
|
+
.replace(/\.ejs$/, '')
|
|
400
|
+
.replace(/\.ts$/, extension);
|
|
401
|
+
const contents = await renderFile(pathToTemplate, { answers, _: new EjsHelpers({ useEsm: answers.esmSupport, useTypeScript: answers.isUsingTypeScript }) });
|
|
402
|
+
await fs.mkdir(path.dirname(destination), { recursive: true });
|
|
403
|
+
await fs.writeFile(destination, contents);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
348
407
|
export async function getAnswers(yes) {
|
|
349
408
|
if (yes) {
|
|
350
409
|
const ignoredQuestions = ['e2eEnvironment'];
|
|
@@ -430,6 +489,9 @@ export function getPathForFileGeneration(answers, projectRootDir) {
|
|
|
430
489
|
const destPageObjectRootPath = answers.usePageObjects
|
|
431
490
|
? path.resolve(projectRootDir, path.dirname(answers.pages || '').replace(/\*\*$/, ''))
|
|
432
491
|
: '';
|
|
492
|
+
const destSerenityLibRootPath = usesSerenity(answers)
|
|
493
|
+
? path.resolve(projectRootDir, answers.serenityLibPath || 'serenity')
|
|
494
|
+
: '';
|
|
433
495
|
const relativePath = (answers.generateTestFiles && answers.usePageObjects)
|
|
434
496
|
? !(convertPackageHashToObject(answers.framework).short === 'cucumber')
|
|
435
497
|
? path.relative(destSpecRootPath, destPageObjectRootPath)
|
|
@@ -439,6 +501,7 @@ export function getPathForFileGeneration(answers, projectRootDir) {
|
|
|
439
501
|
destSpecRootPath: destSpecRootPath,
|
|
440
502
|
destStepRootPath: destStepRootPath,
|
|
441
503
|
destPageObjectRootPath: destPageObjectRootPath,
|
|
504
|
+
destSerenityLibRootPath: destSerenityLibRootPath,
|
|
442
505
|
relativePath: relativePath.replaceAll(path.sep, '/')
|
|
443
506
|
};
|
|
444
507
|
}
|
|
@@ -628,84 +691,94 @@ export function npmInstall(parsedAnswers, useYarn, npmTag) {
|
|
|
628
691
|
* add ts-node if TypeScript is desired but not installed
|
|
629
692
|
*/
|
|
630
693
|
export async function setupTypeScript(parsedAnswers) {
|
|
631
|
-
|
|
694
|
+
/**
|
|
695
|
+
* don't create a `tsconfig.json` if user doesn't want to use TypeScript
|
|
696
|
+
* or if a `tsconfig.json` already exists
|
|
697
|
+
*/
|
|
698
|
+
if (!parsedAnswers.isUsingTypeScript || parsedAnswers.hasRootTSConfig) {
|
|
632
699
|
return;
|
|
633
700
|
}
|
|
634
701
|
console.log('Setting up TypeScript...');
|
|
635
702
|
const frameworkPackage = convertPackageHashToObject(parsedAnswers.rawAnswers.framework);
|
|
636
703
|
const servicePackages = parsedAnswers.rawAnswers.services.map((service) => convertPackageHashToObject(service));
|
|
637
704
|
parsedAnswers.packagesToInstall.push('ts-node', 'typescript');
|
|
705
|
+
const serenityTypes = parsedAnswers.serenityAdapter === 'jasmine' ? ['jasmine'] : [];
|
|
638
706
|
const types = [
|
|
639
707
|
'node',
|
|
640
708
|
'@wdio/globals/types',
|
|
641
709
|
'expect-webdriverio',
|
|
642
|
-
frameworkPackage.package,
|
|
710
|
+
...(parsedAnswers.serenityAdapter ? serenityTypes : [frameworkPackage.package]),
|
|
643
711
|
...(parsedAnswers.runner === 'browser' ? ['@wdio/browser-runner'] : []),
|
|
644
712
|
...servicePackages
|
|
645
713
|
.map(service => service.package)
|
|
714
|
+
.filter(service => (
|
|
715
|
+
/**
|
|
716
|
+
* given that we know that all "official" services have
|
|
717
|
+
* typescript support we only include them
|
|
718
|
+
*/
|
|
719
|
+
service.startsWith('@wdio') ||
|
|
646
720
|
/**
|
|
647
|
-
*
|
|
648
|
-
*
|
|
721
|
+
* also include community maintained packages with known
|
|
722
|
+
* support for TypeScript
|
|
649
723
|
*/
|
|
650
|
-
.
|
|
724
|
+
COMMUNITY_PACKAGES_WITH_TS_SUPPORT.includes(service)))
|
|
651
725
|
];
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
}
|
|
726
|
+
const preset = getPreset(parsedAnswers);
|
|
727
|
+
const config = {
|
|
728
|
+
compilerOptions: {
|
|
729
|
+
// compiler
|
|
730
|
+
moduleResolution: 'node',
|
|
731
|
+
module: !parsedAnswers.esmSupport ? 'commonjs' : 'ESNext',
|
|
732
|
+
target: 'es2022',
|
|
733
|
+
lib: ['es2022', 'dom'],
|
|
734
|
+
types,
|
|
735
|
+
skipLibCheck: true,
|
|
736
|
+
// bundler
|
|
737
|
+
noEmit: true,
|
|
738
|
+
allowImportingTsExtensions: true,
|
|
739
|
+
resolveJsonModule: true,
|
|
740
|
+
isolatedModules: true,
|
|
741
|
+
// linting
|
|
742
|
+
strict: true,
|
|
743
|
+
noUnusedLocals: true,
|
|
744
|
+
noUnusedParameters: true,
|
|
745
|
+
noFallthroughCasesInSwitch: true,
|
|
746
|
+
...Object.assign(preset === 'lit'
|
|
747
|
+
? {
|
|
748
|
+
experimentalDecorators: true,
|
|
749
|
+
useDefineForClassFields: false
|
|
750
|
+
}
|
|
751
|
+
: {}, preset === 'react'
|
|
752
|
+
? {
|
|
753
|
+
jsx: 'react-jsx'
|
|
754
|
+
}
|
|
755
|
+
: {}, preset === 'preact'
|
|
756
|
+
? {
|
|
757
|
+
jsx: 'react-jsx',
|
|
758
|
+
jsxImportSource: 'preact'
|
|
759
|
+
}
|
|
760
|
+
: {}, preset === 'solid'
|
|
761
|
+
? {
|
|
762
|
+
jsx: 'preserve',
|
|
763
|
+
jsxImportSource: 'solid-js'
|
|
764
|
+
}
|
|
765
|
+
: {}, preset === 'stencil'
|
|
766
|
+
? {
|
|
767
|
+
experimentalDecorators: true,
|
|
768
|
+
jsx: 'react',
|
|
769
|
+
jsxFactory: 'h',
|
|
770
|
+
jsxFragmentFactory: 'Fragment'
|
|
771
|
+
}
|
|
772
|
+
: {})
|
|
773
|
+
},
|
|
774
|
+
include: preset === 'svelte'
|
|
775
|
+
? ['src/**/*.d.ts', 'src/**/*.ts', 'src/**/*.js', 'src/**/*.svelte']
|
|
776
|
+
: preset === 'vue'
|
|
777
|
+
? ['src/**/*.ts', 'src/**/*.d.ts', 'src/**/*.tsx', 'src/**/*.vue']
|
|
778
|
+
: ['test', 'wdio.conf.ts']
|
|
779
|
+
};
|
|
780
|
+
await fs.mkdir(path.dirname(parsedAnswers.tsConfigFilePath), { recursive: true });
|
|
781
|
+
await fs.writeFile(parsedAnswers.tsConfigFilePath, JSON.stringify(config, null, 4));
|
|
709
782
|
console.log(chalk.green.bold('✔ Success!\n'));
|
|
710
783
|
}
|
|
711
784
|
function getPreset(parsedAnswers) {
|
|
@@ -755,7 +828,10 @@ export async function createWDIOConfig(parsedAnswers) {
|
|
|
755
828
|
try {
|
|
756
829
|
console.log('Creating a WebdriverIO config file...');
|
|
757
830
|
const tplPath = path.resolve(__dirname, 'templates', 'wdio.conf.tpl.ejs');
|
|
758
|
-
const renderedTpl = await renderFile(tplPath, {
|
|
831
|
+
const renderedTpl = await renderFile(tplPath, {
|
|
832
|
+
answers: parsedAnswers,
|
|
833
|
+
_: new EjsHelpers({ useEsm: parsedAnswers.esmSupport, useTypeScript: parsedAnswers.isUsingTypeScript })
|
|
834
|
+
});
|
|
759
835
|
await fs.writeFile(parsedAnswers.wdioConfigPath, renderedTpl);
|
|
760
836
|
console.log(chalk.green.bold('✔ Success!\n'));
|
|
761
837
|
if (parsedAnswers.generateTestFiles) {
|
|
@@ -770,20 +846,33 @@ export async function createWDIOConfig(parsedAnswers) {
|
|
|
770
846
|
}
|
|
771
847
|
export async function createWDIOScript(parsedAnswers) {
|
|
772
848
|
const projectProps = await getProjectProps(process.cwd());
|
|
773
|
-
const
|
|
774
|
-
const
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
849
|
+
const pathToWdioConfig = `./${path.join('.', parsedAnswers.wdioConfigPath.replace(projectProps?.path || process.cwd(), ''))}`;
|
|
850
|
+
const wdioScripts = {
|
|
851
|
+
'wdio': `wdio run ${pathToWdioConfig}`,
|
|
852
|
+
};
|
|
853
|
+
const serenityScripts = {
|
|
854
|
+
'serenity': 'failsafe serenity:update serenity:clean wdio serenity:report',
|
|
855
|
+
'serenity:update': 'serenity-bdd update',
|
|
856
|
+
'serenity:clean': 'rimraf target',
|
|
857
|
+
'wdio': `wdio run ${pathToWdioConfig}`,
|
|
858
|
+
'serenity:report': 'serenity-bdd run',
|
|
859
|
+
};
|
|
860
|
+
const scripts = parsedAnswers.serenityAdapter ? serenityScripts : wdioScripts;
|
|
861
|
+
for (const [script, command] of Object.entries(scripts)) {
|
|
862
|
+
const args = ['pkg', 'set', `scripts.${script}=${command}`];
|
|
863
|
+
try {
|
|
864
|
+
console.log(`Adding ${chalk.bold(`"${script}"`)} script to package.json`);
|
|
865
|
+
await runProgram(NPM_COMMAND, args, { cwd: parsedAnswers.projectRootDir });
|
|
866
|
+
}
|
|
867
|
+
catch (err) {
|
|
868
|
+
const [preArgs, scriptPath] = args.join(' ').split('=');
|
|
869
|
+
console.error(`⚠️ Couldn't add script to package.json: "${err.message}", you can add it manually ` +
|
|
870
|
+
`by running:\n\n\t${NPM_COMMAND} ${preArgs}="${scriptPath}"`);
|
|
871
|
+
return false;
|
|
872
|
+
}
|
|
786
873
|
}
|
|
874
|
+
console.log(chalk.green.bold('✔ Success!'));
|
|
875
|
+
return true;
|
|
787
876
|
}
|
|
788
877
|
export async function runAppiumInstaller(parsedAnswers) {
|
|
789
878
|
if (parsedAnswers.e2eEnvironment !== 'mobile') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wdio/cli",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.18.2",
|
|
4
4
|
"description": "WebdriverIO testrunner command line interface",
|
|
5
5
|
"author": "Christian Bromann <mail@bromann.dev>",
|
|
6
6
|
"homepage": "https://github.com/webdriverio/webdriverio/tree/main/packages/wdio-cli",
|
|
@@ -46,12 +46,12 @@
|
|
|
46
46
|
"typeScriptVersion": "3.8.3",
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@types/node": "^20.1.1",
|
|
49
|
-
"@wdio/config": "8.
|
|
50
|
-
"@wdio/globals": "8.
|
|
49
|
+
"@wdio/config": "8.18.2",
|
|
50
|
+
"@wdio/globals": "8.18.2",
|
|
51
51
|
"@wdio/logger": "8.16.17",
|
|
52
|
-
"@wdio/protocols": "8.
|
|
52
|
+
"@wdio/protocols": "8.18.0",
|
|
53
53
|
"@wdio/types": "8.17.0",
|
|
54
|
-
"@wdio/utils": "8.
|
|
54
|
+
"@wdio/utils": "8.18.2",
|
|
55
55
|
"async-exit-hook": "^2.0.1",
|
|
56
56
|
"chalk": "^5.2.0",
|
|
57
57
|
"chokidar": "^3.5.3",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"lodash.union": "^4.6.0",
|
|
67
67
|
"read-pkg-up": "10.1.0",
|
|
68
68
|
"recursive-readdir": "^2.2.3",
|
|
69
|
-
"webdriverio": "8.
|
|
69
|
+
"webdriverio": "8.18.2",
|
|
70
70
|
"yargs": "^17.7.2",
|
|
71
71
|
"yarn-install": "^1.0.0"
|
|
72
72
|
},
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"publishConfig": {
|
|
84
84
|
"access": "public"
|
|
85
85
|
},
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "910c79f1640f0100e763a507fdcaee9e4f52560f"
|
|
87
87
|
}
|