@wdio/cli
Version:
WebdriverIO testrunner command line interface
201 lines (200 loc) • 8.06 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.missingConfigurationPrompt = exports.handler = exports.builder = exports.cmdArgs = exports.desc = exports.command = void 0;
const util_1 = __importDefault(require("util"));
const inquirer_1 = __importDefault(require("inquirer"));
const yarn_install_1 = __importDefault(require("yarn-install"));
const constants_1 = require("../constants");
const utils_1 = require("../utils");
const pkg = require('../../package.json');
exports.command = 'config';
exports.desc = 'Initialize WebdriverIO and setup configuration in your current project.';
exports.cmdArgs = {
yarn: {
type: 'boolean',
desc: 'Install packages via yarn package manager.',
default: utils_1.hasFile('yarn.lock')
},
yes: {
alias: 'y',
desc: 'will fill in all config defaults without prompting',
type: 'boolean',
default: false
}
};
exports.builder = (yargs) => {
return yargs
.options(exports.cmdArgs)
.epilogue(constants_1.CLI_EPILOGUE)
.help();
};
const runConfig = async function (useYarn, yes, exit = false) {
console.log(constants_1.CONFIG_HELPER_INTRO);
const answers = await utils_1.getAnswers(yes);
const frameworkPackage = utils_1.convertPackageHashToObject(answers.framework);
const runnerPackage = utils_1.convertPackageHashToObject(answers.runner || constants_1.SUPPORTED_PACKAGES.runner[0].value);
const servicePackages = answers.services.map((service) => utils_1.convertPackageHashToObject(service));
const reporterPackages = answers.reporters.map((reporter) => utils_1.convertPackageHashToObject(reporter));
let packagesToInstall = [
runnerPackage.package,
frameworkPackage.package,
...reporterPackages.map(reporter => reporter.package),
...servicePackages.map(service => service.package)
];
const syncExecution = answers.executionMode === 'sync';
if (syncExecution) {
packagesToInstall.push('@wdio/sync');
}
/**
* add ts-node if TypeScript is desired but not installed
*/
if (answers.isUsingCompiler === constants_1.COMPILER_OPTIONS.ts) {
try {
/**
* this is only for testing purposes as we want to check whether
* we add `ts-node` to the packages to install when resolving fails
*/
if (process.env.JEST_WORKER_ID && process.env.WDIO_TEST_THROW_RESOLVE) {
throw new Error('resolve error');
}
require.resolve('ts-node');
}
catch (e) {
packagesToInstall.push('ts-node', 'typescript');
}
}
/**
* add @babel/register package if not installed
*/
if (answers.isUsingCompiler === constants_1.COMPILER_OPTIONS.babel) {
try {
/**
* this is only for testing purposes as we want to check whether
* we add `@babel/register` to the packages to install when resolving fails
*/
if (process.env.JEST_WORKER_ID && process.env.WDIO_TEST_THROW_RESOLVE) {
throw new Error('resolve error');
}
require.resolve('@babel/register');
}
catch (e) {
packagesToInstall.push('@babel/register');
}
}
/**
* add packages that are required by services
*/
utils_1.addServiceDeps(servicePackages, packagesToInstall);
/**
* ensure wdio packages have the same dist tag as cli
*/
if (pkg._requested && pkg._requested.fetchSpec) {
const { fetchSpec } = pkg._requested;
packagesToInstall = packagesToInstall.map((p) => (p.startsWith('@wdio') || ['devtools', 'webdriver', 'webdriverio'].includes(p)) &&
(fetchSpec.match(/(v)?\d+\.\d+\.\d+/) === null)
? `${p}@${fetchSpec}`
: p);
}
console.log('\nInstalling wdio packages:\n-', packagesToInstall.join('\n- '));
const result = yarn_install_1.default({ deps: packagesToInstall, dev: true, respectNpm5: !useYarn });
if (result.status !== 0) {
throw new Error(result.stderr);
}
console.log('\nPackages installed successfully, creating configuration file...');
/**
* find relative paths between tests and pages
*/
const parsedPaths = utils_1.getPathForFileGeneration(answers);
const parsedAnswers = {
...answers,
runner: runnerPackage.short,
framework: frameworkPackage.short,
reporters: reporterPackages.map(({ short }) => short),
services: servicePackages.map(({ short }) => short),
packagesToInstall,
isUsingTypeScript: answers.isUsingCompiler === constants_1.COMPILER_OPTIONS.ts,
isUsingBabel: answers.isUsingCompiler === constants_1.COMPILER_OPTIONS.babel,
isSync: syncExecution,
_async: syncExecution ? '' : 'async ',
_await: syncExecution ? '' : 'await ',
destSpecRootPath: parsedPaths.destSpecRootPath,
destPageObjectRootPath: parsedPaths.destPageObjectRootPath,
relativePath: parsedPaths.relativePath
};
try {
await utils_1.renderConfigurationFile(parsedAnswers);
if (answers.generateTestFiles) {
console.log('\nConfig file installed successfully, creating test files...');
await utils_1.generateTestFiles(parsedAnswers);
}
}
catch (e) {
throw new Error(`Couldn't write config file: ${e.stack}`);
}
/**
* print TypeScript configuration message
*/
if (answers.isUsingCompiler === constants_1.COMPILER_OPTIONS.ts) {
const wdioTypes = syncExecution ? 'webdriverio/sync' : 'webdriverio/async';
const tsPkgs = `"${[
wdioTypes,
frameworkPackage.package,
...servicePackages
.map(service => service.package)
/**
* given that we know that all "offical" services have
* typescript support we only include them
*/
.filter(service => service.startsWith('@wdio'))
].join('", "')}"`;
console.log(util_1.default.format(constants_1.TS_COMPILER_INSTRUCTIONS, tsPkgs));
}
console.log(constants_1.CONFIG_HELPER_SUCCESS_MESSAGE);
/**
* don't exit if running unit tests
*/
if (exit /* istanbul ignore next */ && !process.env.JEST_WORKER_ID) {
/* istanbul ignore next */
process.exit(0);
}
return {
success: true,
parsedAnswers,
installedPackages: packagesToInstall.map((pkg) => pkg.split('--')[0])
};
};
function handler(argv) {
return runConfig(argv.yarn, argv.yes);
}
exports.handler = handler;
/**
* Helper utility used in `run` and `install` command to create config if none exist
* @param {string} command to be executed by user
* @param {string} message to show when no config is suppose to be created
* @param {boolean} useYarn parameter set to true if yarn is used
* @param {Function} runConfigCmd runConfig method to be replaceable for unit testing
*/
async function missingConfigurationPrompt(command, message, useYarn = false, runConfigCmd = runConfig) {
const { config } = await inquirer_1.default.prompt([
{
type: 'confirm',
name: 'config',
message: `Error: Could not execute "${command}" due to missing configuration. Would you like to create one?`,
default: false
}
]);
/**
* don't exit if running unit tests
*/
if (!config && !process.env.JEST_WORKER_ID) {
/* istanbul ignore next */
console.log(message);
/* istanbul ignore next */
return process.exit(0);
}
return await runConfigCmd(useYarn, false, true);
}
exports.missingConfigurationPrompt = missingConfigurationPrompt;