123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- 'use strict';
- var _templateObject = _taggedTemplateLiteral(['\n\n ', ' Warning: Cypress failed to start.\n\n This is likely due to a misconfigured DISPLAY environment variable.\n\n DISPLAY was set to: "', '"\n\n Cypress will attempt to fix the problem and rerun.\n '], ['\n\n ', ' Warning: Cypress failed to start.\n\n This is likely due to a misconfigured DISPLAY environment variable.\n\n DISPLAY was set to: "', '"\n\n Cypress will attempt to fix the problem and rerun.\n ']);
- function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
- function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
- var _ = require('lodash');
- var R = require('ramda');
- var os = require('os');
- var crypto = require('crypto');
- var la = require('lazy-ass');
- var is = require('check-more-types');
- var tty = require('tty');
- var path = require('path');
- var _isCi = require('is-ci');
- var execa = require('execa');
- var getos = require('getos');
- var chalk = require('chalk');
- var Promise = require('bluebird');
- var cachedir = require('cachedir');
- var logSymbols = require('log-symbols');
- var executable = require('executable');
- var _require = require('common-tags'),
- stripIndent = _require.stripIndent;
- var _supportsColor = require('supports-color');
- var _isInstalledGlobally = require('is-installed-globally');
- var pkg = require(path.join(__dirname, '..', 'package.json'));
- var logger = require('./logger');
- var debug = require('debug')('cypress:cli');
- var fs = require('./fs');
- var issuesUrl = 'https://github.com/cypress-io/cypress/issues';
- var getosAsync = Promise.promisify(getos);
- /**
- * Returns SHA512 of a file
- *
- * Implementation lifted from https://github.com/sindresorhus/hasha
- * but without bringing that dependency (since hasha is Node v8+)
- */
- var getFileChecksum = function getFileChecksum(filename) {
- la(is.unemptyString(filename), 'expected filename', filename);
- var hashStream = function hashStream() {
- var s = crypto.createHash('sha512');
- s.setEncoding('hex');
- return s;
- };
- return new Promise(function (resolve, reject) {
- var stream = fs.createReadStream(filename);
- stream.on('error', reject).pipe(hashStream()).on('error', reject).on('finish', function () {
- resolve(this.read());
- });
- });
- };
- var getFileSize = function getFileSize(filename) {
- la(is.unemptyString(filename), 'expected filename', filename);
- return fs.statAsync(filename).get('size');
- };
- var isBrokenGtkDisplayRe = /Gtk: cannot open display/;
- var stringify = function stringify(val) {
- return _.isObject(val) ? JSON.stringify(val) : val;
- };
- function normalizeModuleOptions() {
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- return _.mapValues(options, stringify);
- }
- /**
- * Returns true if the platform is Linux. We do a lot of different
- * stuff on Linux (like Xvfb) and it helps to has readable code
- */
- var isLinux = function isLinux() {
- return os.platform() === 'linux';
- };
- /**
- * If the DISPLAY variable is set incorrectly, when trying to spawn
- * Cypress executable we get an error like this:
- ```
- [1005:0509/184205.663837:WARNING:browser_main_loop.cc(258)] Gtk: cannot open display: 99
- ```
- */
- var isBrokenGtkDisplay = function isBrokenGtkDisplay(str) {
- return isBrokenGtkDisplayRe.test(str);
- };
- var isPossibleLinuxWithIncorrectDisplay = function isPossibleLinuxWithIncorrectDisplay() {
- return isLinux() && process.env.DISPLAY;
- };
- var logBrokenGtkDisplayWarning = function logBrokenGtkDisplayWarning() {
- debug('Cypress exited due to a broken gtk display because of a potential invalid DISPLAY env... retrying after starting Xvfb');
- // if we get this error, we are on Linux and DISPLAY is set
- logger.warn(stripIndent(_templateObject, logSymbols.warning, process.env.DISPLAY));
- logger.warn();
- };
- function stdoutLineMatches(expectedLine, stdout) {
- var lines = stdout.split('\n').map(R.trim);
- var lineMatches = R.equals(expectedLine);
- return lines.some(lineMatches);
- }
- /**
- * Confirms if given value is a valid CYPRESS_ENV value. Undefined values
- * are valid, because the system can set the default one.
- *
- * @param {string} value
- * @example util.isValidCypressEnvValue(process.env.CYPRESS_ENV)
- */
- function isValidCypressEnvValue(value) {
- if (_.isUndefined(value)) {
- // will get default value
- return true;
- }
- // names of config environments, see "packages/server/config/app.yml"
- var names = ['development', 'test', 'staging', 'production'];
- return _.includes(names, value);
- }
- /**
- * Prints NODE_OPTIONS using debug() module, but only
- * if DEBUG=cypress... is set
- */
- function printNodeOptions() {
- var log = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : debug;
- if (!log.enabled) {
- return;
- }
- if (process.env.NODE_OPTIONS) {
- log('NODE_OPTIONS=%s', process.env.NODE_OPTIONS);
- } else {
- log('NODE_OPTIONS is not set');
- }
- }
- /**
- * Removes double quote characters
- * from the start and end of the given string IF they are both present
- *
- * @param {string} str Input string
- * @returns {string} Trimmed string or the original string if there are no double quotes around it.
- * @example
- ```
- dequote('"foo"')
- // returns string 'foo'
- dequote('foo')
- // returns string 'foo'
- ```
- */
- var dequote = function dequote(str) {
- la(is.string(str), 'expected a string to remove double quotes', str);
- if (str.length > 1 && str[0] === '"' && str[str.length - 1] === '"') {
- return str.substr(1, str.length - 2);
- }
- return str;
- };
- var parseOpts = function parseOpts(opts) {
- opts = _.pick(opts, 'project', 'spec', 'reporter', 'reporterOptions', 'path', 'destination', 'port', 'env', 'cypressVersion', 'config', 'record', 'key', 'configFile', 'browser', 'detached', 'headed', 'global', 'dev', 'force', 'exit', 'cachePath', 'cacheList', 'cacheClear', 'parallel', 'group', 'ciBuildId');
- if (opts.exit) {
- opts = _.omit(opts, 'exit');
- }
- // some options might be quoted - which leads to unexpected results
- // remove double quotes from certain options
- var removeQuotes = {
- group: dequote,
- ciBuildId: dequote
- };
- var cleanOpts = R.evolve(removeQuotes, opts);
- debug('parsed cli options %o', cleanOpts);
- return cleanOpts;
- };
- var util = {
- normalizeModuleOptions: normalizeModuleOptions,
- parseOpts: parseOpts,
- isValidCypressEnvValue: isValidCypressEnvValue,
- printNodeOptions: printNodeOptions,
- isCi: function isCi() {
- return _isCi;
- },
- getEnvOverrides: function getEnvOverrides() {
- return _.chain({}).extend(util.getEnvColors()).extend(util.getForceTty()).omitBy(_.isUndefined) // remove undefined values
- .mapValues(function (value) {
- // stringify to 1 or 0
- return value ? '1' : '0';
- }).value();
- },
- getForceTty: function getForceTty() {
- return {
- FORCE_STDIN_TTY: util.isTty(process.stdin.fd),
- FORCE_STDOUT_TTY: util.isTty(process.stdout.fd),
- FORCE_STDERR_TTY: util.isTty(process.stderr.fd)
- };
- },
- getEnvColors: function getEnvColors() {
- var sc = util.supportsColor();
- return {
- FORCE_COLOR: sc,
- DEBUG_COLORS: sc,
- MOCHA_COLORS: sc ? true : undefined
- };
- },
- isTty: function isTty(fd) {
- return tty.isatty(fd);
- },
- supportsColor: function supportsColor() {
- // if we've been explictly told not to support
- // color then turn this off
- if (process.env.NO_COLOR) {
- return false;
- }
- // https://github.com/cypress-io/cypress/issues/1747
- // always return true in CI providers
- if (process.env.CI) {
- return true;
- }
- // ensure that both stdout and stderr support color
- return Boolean(_supportsColor.stdout) && Boolean(_supportsColor.stderr);
- },
- cwd: function cwd() {
- return process.cwd();
- },
- pkgVersion: function pkgVersion() {
- return pkg.version;
- },
- exit: function exit(code) {
- process.exit(code);
- },
- logErrorExit1: function logErrorExit1(err) {
- logger.error(err.message);
- process.exit(1);
- },
- dequote: dequote,
- titleize: function titleize() {
- for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
- // prepend first arg with space
- // and pad so that all messages line up
- args[0] = _.padEnd(' ' + args[0], 24);
- // get rid of any falsy values
- args = _.compact(args);
- return chalk.blue.apply(chalk, _toConsumableArray(args));
- },
- calculateEta: function calculateEta(percent, elapsed) {
- // returns the number of seconds remaining
- // if we're at 100% already just return 0
- if (percent === 100) {
- return 0;
- }
- // take the percentage and divide by one
- // and multiple that against elapsed
- // subtracting what's already elapsed
- return elapsed * (1 / (percent / 100)) - elapsed;
- },
- convertPercentToPercentage: function convertPercentToPercentage(num) {
- // convert a percent with values between 0 and 1
- // with decimals, so that it is between 0 and 100
- // and has no decimal places
- return Math.round(_.isFinite(num) ? num * 100 : 0);
- },
- secsRemaining: function secsRemaining(eta) {
- // calculate the seconds reminaing with no decimal places
- return (_.isFinite(eta) ? eta / 1000 : 0).toFixed(0);
- },
- setTaskTitle: function setTaskTitle(task, title, renderer) {
- // only update the renderer title when not running in CI
- if (renderer === 'default' && task.title !== title) {
- task.title = title;
- }
- },
- isInstalledGlobally: function isInstalledGlobally() {
- return _isInstalledGlobally;
- },
- isSemver: function isSemver(str) {
- return (/^(\d+\.)?(\d+\.)?(\*|\d+)$/.test(str)
- );
- },
- isExecutableAsync: function isExecutableAsync(filePath) {
- return Promise.resolve(executable(filePath));
- },
- isLinux: isLinux,
- getOsVersionAsync: function getOsVersionAsync() {
- return Promise.try(function () {
- if (isLinux()) {
- return getosAsync().then(function (osInfo) {
- return [osInfo.dist, osInfo.release].join(' - ');
- }).catch(function () {
- return os.release();
- });
- }
- return os.release();
- });
- },
- // attention:
- // when passing relative path to NPM post install hook, the current working
- // directory is set to the `node_modules/cypress` folder
- // the user is probably passing relative path with respect to root package folder
- formAbsolutePath: function formAbsolutePath(filename) {
- if (path.isAbsolute(filename)) {
- return filename;
- }
- return path.join(process.cwd(), '..', '..', filename);
- },
- getEnv: function getEnv(varName, trim) {
- la(is.unemptyString(varName), 'expected environment variable name, not', varName);
- var envVar = process.env[varName];
- var configVar = process.env['npm_config_' + varName];
- var packageConfigVar = process.env['npm_package_config_' + varName];
- var result = void 0;
- if (envVar) {
- debug('Using ' + varName + ' from environment variable');
- result = envVar;
- } else if (configVar) {
- debug('Using ' + varName + ' from npm config');
- result = configVar;
- } else if (packageConfigVar) {
- debug('Using ' + varName + ' from package.json config');
- result = packageConfigVar;
- }
- // environment variables are often set double quotes to escape characters
- // and on Windows it can lead to weird things: for example
- // set FOO="C:\foo.txt" && node -e "console.log('>>>%s<<<', process.env.FOO)"
- // will print
- // >>>"C:\foo.txt" <<<
- // see https://github.com/cypress-io/cypress/issues/4506#issuecomment-506029942
- // so for sanity sake we should first trim whitespace characters and remove
- // double quotes around environment strings if the caller is expected to
- // use this environment string as a file path
- return trim ? dequote(_.trim(result)) : result;
- },
- getCacheDir: function getCacheDir() {
- return cachedir('Cypress');
- },
- isPostInstall: function isPostInstall() {
- return process.env.npm_lifecycle_event === 'postinstall';
- },
- exec: execa,
- stdoutLineMatches: stdoutLineMatches,
- issuesUrl: issuesUrl,
- isBrokenGtkDisplay: isBrokenGtkDisplay,
- logBrokenGtkDisplayWarning: logBrokenGtkDisplayWarning,
- isPossibleLinuxWithIncorrectDisplay: isPossibleLinuxWithIncorrectDisplay,
- getGitHubIssueUrl: function getGitHubIssueUrl(number) {
- la(is.positive(number), 'github issue should be a positive number', number);
- la(_.isInteger(number), 'github issue should be an integer', number);
- return issuesUrl + '/' + number;
- },
- getFileChecksum: getFileChecksum,
- getFileSize: getFileSize
- };
- module.exports = util;
|