údržba
This commit is contained in:
58
CyLukTs/lukan/node_modules/cypress/lib/VerboseRenderer.js
generated
vendored
Normal file
58
CyLukTs/lukan/node_modules/cypress/lib/VerboseRenderer.js
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
"use strict";
|
||||
|
||||
// Vendored from @cypress/listr-verbose-renderer
|
||||
const figures = require('figures');
|
||||
const cliCursor = require('cli-cursor');
|
||||
const chalk = require('chalk');
|
||||
const dayjs = require('dayjs');
|
||||
const formattedLog = (options, output) => {
|
||||
const timestamp = dayjs().format(options.dateFormat);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`${chalk.dim(`[${timestamp}]`)} ${output}`);
|
||||
};
|
||||
const renderHelper = (task, event, options) => {
|
||||
const log = formattedLog.bind(undefined, options);
|
||||
if (event.type === 'STATE') {
|
||||
const message = task.isPending() ? 'started' : task.state;
|
||||
log(`${task.title} [${message}]`);
|
||||
if (task.isSkipped() && task.output) {
|
||||
log(`${figures.arrowRight} ${task.output}`);
|
||||
}
|
||||
} else if (event.type === 'TITLE') {
|
||||
log(`${task.title} [title changed]`);
|
||||
}
|
||||
};
|
||||
const render = (tasks, options) => {
|
||||
for (const task of tasks) {
|
||||
task.subscribe(event => {
|
||||
if (event.type === 'SUBTASKS') {
|
||||
render(task.subtasks, options);
|
||||
return;
|
||||
}
|
||||
renderHelper(task, event, options);
|
||||
}, err => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
};
|
||||
class VerboseRenderer {
|
||||
constructor(tasks, options) {
|
||||
this._tasks = tasks;
|
||||
this._options = Object.assign({
|
||||
dateFormat: 'HH:mm:ss'
|
||||
}, options);
|
||||
}
|
||||
static get nonTTY() {
|
||||
return true;
|
||||
}
|
||||
render() {
|
||||
cliCursor.hide();
|
||||
render(this._tasks, this._options);
|
||||
}
|
||||
end() {
|
||||
cliCursor.show();
|
||||
}
|
||||
}
|
||||
module.exports = VerboseRenderer;
|
439
CyLukTs/lukan/node_modules/cypress/lib/cli.js
generated
vendored
Normal file
439
CyLukTs/lukan/node_modules/cypress/lib/cli.js
generated
vendored
Normal file
@ -0,0 +1,439 @@
|
||||
"use strict";
|
||||
|
||||
// @ts-check
|
||||
const _ = require('lodash');
|
||||
const commander = require('commander');
|
||||
const {
|
||||
stripIndent
|
||||
} = require('common-tags');
|
||||
const logSymbols = require('log-symbols');
|
||||
const debug = require('debug')('cypress:cli:cli');
|
||||
const util = require('./util');
|
||||
const logger = require('./logger');
|
||||
const errors = require('./errors');
|
||||
const cache = require('./tasks/cache');
|
||||
|
||||
// patch "commander" method called when a user passed an unknown option
|
||||
// we want to print help for the current command and exit with an error
|
||||
function unknownOption(flag, type = 'option') {
|
||||
if (this._allowUnknownOption) return;
|
||||
logger.error();
|
||||
logger.error(` error: unknown ${type}:`, flag);
|
||||
logger.error();
|
||||
this.outputHelp();
|
||||
util.exit(1);
|
||||
}
|
||||
commander.Command.prototype.unknownOption = unknownOption;
|
||||
const coerceFalse = arg => {
|
||||
return arg !== 'false';
|
||||
};
|
||||
const coerceAnyStringToInt = arg => {
|
||||
return typeof arg === 'string' ? parseInt(arg) : arg;
|
||||
};
|
||||
const spaceDelimitedArgsMsg = (flag, args) => {
|
||||
let msg = `
|
||||
${logSymbols.warning} Warning: It looks like you're passing --${flag} a space-separated list of arguments:
|
||||
|
||||
"${args.join(' ')}"
|
||||
|
||||
This will work, but it's not recommended.
|
||||
|
||||
If you are trying to pass multiple arguments, separate them with commas instead:
|
||||
cypress run --${flag} arg1,arg2,arg3
|
||||
`;
|
||||
if (flag === 'spec') {
|
||||
msg += `
|
||||
The most common cause of this warning is using an unescaped glob pattern. If you are
|
||||
trying to pass a glob pattern, escape it using quotes:
|
||||
cypress run --spec "**/*.spec.js"
|
||||
`;
|
||||
}
|
||||
logger.log();
|
||||
logger.warn(stripIndent(msg));
|
||||
logger.log();
|
||||
};
|
||||
const parseVariableOpts = (fnArgs, args) => {
|
||||
const [opts, unknownArgs] = fnArgs;
|
||||
if (unknownArgs && unknownArgs.length && (opts.spec || opts.tag)) {
|
||||
// this will capture space-delimited args after
|
||||
// flags that could have possible multiple args
|
||||
// but before the next option
|
||||
// --spec spec1 spec2 or --tag foo bar
|
||||
|
||||
const multiArgFlags = _.compact([opts.spec ? 'spec' : opts.spec, opts.tag ? 'tag' : opts.tag]);
|
||||
_.forEach(multiArgFlags, flag => {
|
||||
const argIndex = _.indexOf(args, `--${flag}`) + 2;
|
||||
const nextOptOffset = _.findIndex(_.slice(args, argIndex), arg => {
|
||||
return _.startsWith(arg, '--');
|
||||
});
|
||||
const endIndex = nextOptOffset !== -1 ? argIndex + nextOptOffset : args.length;
|
||||
const maybeArgs = _.slice(args, argIndex, endIndex);
|
||||
const extraArgs = _.intersection(maybeArgs, unknownArgs);
|
||||
if (extraArgs.length) {
|
||||
opts[flag] = [opts[flag]].concat(extraArgs);
|
||||
spaceDelimitedArgsMsg(flag, opts[flag]);
|
||||
opts[flag] = opts[flag].join(',');
|
||||
}
|
||||
});
|
||||
}
|
||||
debug('variable-length opts parsed %o', {
|
||||
args,
|
||||
opts
|
||||
});
|
||||
return util.parseOpts(opts);
|
||||
};
|
||||
const descriptions = {
|
||||
autoCancelAfterFailures: 'overrides the project-level Cloud configuration to set the failed test threshold for auto cancellation or to disable auto cancellation when recording to the Cloud',
|
||||
browser: 'runs Cypress in the browser with the given name. if a filesystem path is supplied, Cypress will attempt to use the browser at that path.',
|
||||
cacheClear: 'delete all cached binaries',
|
||||
cachePrune: 'deletes all cached binaries except for the version currently in use',
|
||||
cacheList: 'list cached binary versions',
|
||||
cachePath: 'print the path to the binary cache',
|
||||
cacheSize: 'Used with the list command to show the sizes of the cached folders',
|
||||
ciBuildId: 'the unique identifier for a run on your CI provider. typically a "BUILD_ID" env var. this value is automatically detected for most CI providers',
|
||||
component: 'runs component tests',
|
||||
config: 'sets configuration values. separate multiple values with a comma. overrides any value in cypress.config.{js,ts,mjs,cjs}.',
|
||||
configFile: 'path to script file where configuration values are set. defaults to "cypress.config.{js,ts,mjs,cjs}".',
|
||||
detached: 'runs Cypress application in detached mode',
|
||||
dev: 'runs cypress in development and bypasses binary check',
|
||||
e2e: 'runs end to end tests',
|
||||
env: 'sets environment variables. separate multiple values with a comma. overrides any value in cypress.config.{js,ts,mjs,cjs} or cypress.env.json',
|
||||
exit: 'keep the browser open after tests finish',
|
||||
forceInstall: 'force install the Cypress binary',
|
||||
global: 'force Cypress into global mode as if its globally installed',
|
||||
group: 'a named group for recorded runs in Cypress Cloud',
|
||||
headed: 'displays the browser instead of running headlessly',
|
||||
headless: 'hide the browser instead of running headed (default for cypress run)',
|
||||
key: 'your secret Record Key. you can omit this if you set a CYPRESS_RECORD_KEY environment variable.',
|
||||
parallel: 'enables concurrent runs and automatic load balancing of specs across multiple machines or processes',
|
||||
port: 'runs Cypress on a specific port. overrides any value in cypress.config.{js,ts,mjs,cjs}.',
|
||||
project: 'path to the project',
|
||||
quiet: 'run quietly, using only the configured reporter',
|
||||
record: 'records the run. sends test results, screenshots and videos to Cypress Cloud.',
|
||||
reporter: 'runs a specific mocha reporter. pass a path to use a custom reporter. defaults to "spec"',
|
||||
reporterOptions: 'options for the mocha reporter. defaults to "null"',
|
||||
spec: 'runs specific spec file(s). defaults to "all"',
|
||||
tag: 'named tag(s) for recorded runs in Cypress Cloud',
|
||||
version: 'prints Cypress version'
|
||||
};
|
||||
const knownCommands = ['cache', 'help', '-h', '--help', 'install', 'open', 'run', 'open-ct', 'run-ct', 'verify', '-v', '--version', 'version', 'info'];
|
||||
const text = description => {
|
||||
if (!descriptions[description]) {
|
||||
throw new Error(`Could not find description for: ${description}`);
|
||||
}
|
||||
return descriptions[description];
|
||||
};
|
||||
function includesVersion(args) {
|
||||
return _.includes(args, '--version') || _.includes(args, '-v');
|
||||
}
|
||||
function showVersions(opts) {
|
||||
debug('printing Cypress version');
|
||||
debug('additional arguments %o', opts);
|
||||
debug('parsed version arguments %o', opts);
|
||||
const reportAllVersions = versions => {
|
||||
logger.always('Cypress package version:', versions.package);
|
||||
logger.always('Cypress binary version:', versions.binary);
|
||||
logger.always('Electron version:', versions.electronVersion);
|
||||
logger.always('Bundled Node version:', versions.electronNodeVersion);
|
||||
};
|
||||
const reportComponentVersion = (componentName, versions) => {
|
||||
const names = {
|
||||
package: 'package',
|
||||
binary: 'binary',
|
||||
electron: 'electronVersion',
|
||||
node: 'electronNodeVersion'
|
||||
};
|
||||
if (!names[componentName]) {
|
||||
throw new Error(`Unknown component name "${componentName}"`);
|
||||
}
|
||||
const name = names[componentName];
|
||||
if (!versions[name]) {
|
||||
throw new Error(`Cannot find version for component "${componentName}" under property "${name}"`);
|
||||
}
|
||||
const version = versions[name];
|
||||
logger.always(version);
|
||||
};
|
||||
const defaultVersions = {
|
||||
package: undefined,
|
||||
binary: undefined,
|
||||
electronVersion: undefined,
|
||||
electronNodeVersion: undefined
|
||||
};
|
||||
return require('./exec/versions').getVersions().then((versions = defaultVersions) => {
|
||||
if (opts !== null && opts !== void 0 && opts.component) {
|
||||
reportComponentVersion(opts.component, versions);
|
||||
} else {
|
||||
reportAllVersions(versions);
|
||||
}
|
||||
process.exit(0);
|
||||
}).catch(util.logErrorExit1);
|
||||
}
|
||||
const createProgram = () => {
|
||||
const program = new commander.Command();
|
||||
|
||||
// bug in commander not printing name
|
||||
// in usage help docs
|
||||
program._name = 'cypress';
|
||||
program.usage('<command> [options]');
|
||||
return program;
|
||||
};
|
||||
const addCypressRunCommand = program => {
|
||||
return program.command('run').usage('[options]').description('Runs Cypress tests from the CLI without the GUI').option('--auto-cancel-after-failures <test-failure-count || false>', text('autoCancelAfterFailures')).option('-b, --browser <browser-name-or-path>', text('browser')).option('--ci-build-id <id>', text('ciBuildId')).option('--component', text('component')).option('-c, --config <config>', text('config')).option('-C, --config-file <config-file>', text('configFile')).option('--e2e', text('e2e')).option('-e, --env <env>', text('env')).option('--group <name>', text('group')).option('-k, --key <record-key>', text('key')).option('--headed', text('headed')).option('--headless', text('headless')).option('--no-exit', text('exit')).option('--parallel', text('parallel')).option('-p, --port <port>', text('port')).option('-P, --project <project-path>', text('project')).option('-q, --quiet', text('quiet')).option('--record [bool]', text('record'), coerceFalse).option('-r, --reporter <reporter>', text('reporter')).option('-o, --reporter-options <reporter-options>', text('reporterOptions')).option('-s, --spec <spec>', text('spec')).option('-t, --tag <tag>', text('tag')).option('--dev', text('dev'), coerceFalse);
|
||||
};
|
||||
const addCypressOpenCommand = program => {
|
||||
return program.command('open').usage('[options]').description('Opens Cypress in the interactive GUI.').option('-b, --browser <browser-path>', text('browser')).option('--component', text('component')).option('-c, --config <config>', text('config')).option('-C, --config-file <config-file>', text('configFile')).option('-d, --detached [bool]', text('detached'), coerceFalse).option('--e2e', text('e2e')).option('-e, --env <env>', text('env')).option('--global', text('global')).option('-p, --port <port>', text('port')).option('-P, --project <project-path>', text('project')).option('--dev', text('dev'), coerceFalse);
|
||||
};
|
||||
const maybeAddInspectFlags = program => {
|
||||
if (process.argv.includes('--dev')) {
|
||||
return program.option('--inspect', 'Node option').option('--inspect-brk', 'Node option');
|
||||
}
|
||||
return program;
|
||||
};
|
||||
|
||||
/**
|
||||
* Casts known command line options for "cypress run" to their intended type.
|
||||
* For example if the user passes "--port 5005" the ".port" property should be
|
||||
* a number 5005 and not a string "5005".
|
||||
*
|
||||
* Returns a clone of the original object.
|
||||
*/
|
||||
const castCypressOptions = opts => {
|
||||
// only properties that have type "string | false" in our TS definition
|
||||
// require special handling, because CLI parsing takes care of purely
|
||||
// boolean arguments
|
||||
const castOpts = {
|
||||
...opts
|
||||
};
|
||||
if (_.has(opts, 'port')) {
|
||||
castOpts.port = coerceAnyStringToInt(opts.port);
|
||||
}
|
||||
return castOpts;
|
||||
};
|
||||
module.exports = {
|
||||
/**
|
||||
* Parses `cypress run` command line option array into an object
|
||||
* with options that you can feed into a `cypress.run()` module API call.
|
||||
* @example
|
||||
* const options = parseRunCommand(['cypress', 'run', '--browser', 'chrome'])
|
||||
* // options is {browser: 'chrome'}
|
||||
*/
|
||||
parseRunCommand(args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!Array.isArray(args)) {
|
||||
return reject(new Error('Expected array of arguments'));
|
||||
}
|
||||
|
||||
// make a copy of the input arguments array
|
||||
// and add placeholders where "node ..." would usually be
|
||||
// also remove "cypress" keyword at the start if present
|
||||
const cliArgs = args[0] === 'cypress' ? [...args.slice(1)] : [...args];
|
||||
cliArgs.unshift(null, null);
|
||||
debug('creating program parser');
|
||||
const program = createProgram();
|
||||
maybeAddInspectFlags(addCypressRunCommand(program)).action((...fnArgs) => {
|
||||
debug('parsed Cypress run %o', fnArgs);
|
||||
const options = parseVariableOpts(fnArgs, cliArgs);
|
||||
debug('parsed options %o', options);
|
||||
const casted = castCypressOptions(options);
|
||||
debug('casted options %o', casted);
|
||||
resolve(casted);
|
||||
});
|
||||
debug('parsing args: %o', cliArgs);
|
||||
program.parse(cliArgs);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Parses `cypress open` command line option array into an object
|
||||
* with options that you can feed into cy.openModeSystemTest test calls
|
||||
* @example
|
||||
* const options = parseOpenCommand(['cypress', 'open', '--browser', 'chrome'])
|
||||
* // options is {browser: 'chrome'}
|
||||
*/
|
||||
parseOpenCommand(args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!Array.isArray(args)) {
|
||||
return reject(new Error('Expected array of arguments'));
|
||||
}
|
||||
|
||||
// make a copy of the input arguments array
|
||||
// and add placeholders where "node ..." would usually be
|
||||
// also remove "cypress" keyword at the start if present
|
||||
const cliArgs = args[0] === 'cypress' ? [...args.slice(1)] : [...args];
|
||||
cliArgs.unshift(null, null);
|
||||
debug('creating program parser');
|
||||
const program = createProgram();
|
||||
maybeAddInspectFlags(addCypressOpenCommand(program)).action((...fnArgs) => {
|
||||
debug('parsed Cypress open %o', fnArgs);
|
||||
const options = parseVariableOpts(fnArgs, cliArgs);
|
||||
debug('parsed options %o', options);
|
||||
const casted = castCypressOptions(options);
|
||||
debug('casted options %o', casted);
|
||||
resolve(casted);
|
||||
});
|
||||
debug('parsing args: %o', cliArgs);
|
||||
program.parse(cliArgs);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Parses the command line and kicks off Cypress process.
|
||||
*/
|
||||
init(args) {
|
||||
if (!args) {
|
||||
args = process.argv;
|
||||
}
|
||||
const {
|
||||
CYPRESS_INTERNAL_ENV,
|
||||
CYPRESS_DOWNLOAD_USE_CA
|
||||
} = process.env;
|
||||
if (process.env.CYPRESS_DOWNLOAD_USE_CA) {
|
||||
let msg = `
|
||||
${logSymbols.warning} Warning: It looks like you're setting CYPRESS_DOWNLOAD_USE_CA=${CYPRESS_DOWNLOAD_USE_CA}
|
||||
|
||||
The environment variable "CYPRESS_DOWNLOAD_USE_CA" is no longer required to be set.
|
||||
|
||||
You can safely unset this environment variable.
|
||||
`;
|
||||
logger.log();
|
||||
logger.warn(stripIndent(msg));
|
||||
logger.log();
|
||||
}
|
||||
if (!util.isValidCypressInternalEnvValue(CYPRESS_INTERNAL_ENV)) {
|
||||
debug('invalid CYPRESS_INTERNAL_ENV value', CYPRESS_INTERNAL_ENV);
|
||||
return errors.exitWithError(errors.errors.invalidCypressEnv)(`CYPRESS_INTERNAL_ENV=${CYPRESS_INTERNAL_ENV}`);
|
||||
}
|
||||
if (util.isNonProductionCypressInternalEnvValue(CYPRESS_INTERNAL_ENV)) {
|
||||
debug('non-production CYPRESS_INTERNAL_ENV value', CYPRESS_INTERNAL_ENV);
|
||||
let msg = `
|
||||
${logSymbols.warning} Warning: It looks like you're passing CYPRESS_INTERNAL_ENV=${CYPRESS_INTERNAL_ENV}
|
||||
|
||||
The environment variable "CYPRESS_INTERNAL_ENV" is reserved and should only be used internally.
|
||||
|
||||
Unset the "CYPRESS_INTERNAL_ENV" environment variable and run Cypress again.
|
||||
`;
|
||||
logger.log();
|
||||
logger.warn(stripIndent(msg));
|
||||
logger.log();
|
||||
}
|
||||
const program = createProgram();
|
||||
program.command('help').description('Shows CLI help and exits').action(() => {
|
||||
program.help();
|
||||
});
|
||||
const handleVersion = cmd => {
|
||||
return cmd.option('--component <package|binary|electron|node>', 'component to report version for').action((opts, ...other) => {
|
||||
showVersions(util.parseOpts(opts));
|
||||
});
|
||||
};
|
||||
handleVersion(program.storeOptionsAsProperties().option('-v, --version', text('version')).command('version').description(text('version')));
|
||||
maybeAddInspectFlags(addCypressOpenCommand(program)).action(opts => {
|
||||
debug('opening Cypress');
|
||||
require('./exec/open').start(util.parseOpts(opts)).then(util.exit).catch(util.logErrorExit1);
|
||||
});
|
||||
maybeAddInspectFlags(addCypressRunCommand(program)).action((...fnArgs) => {
|
||||
debug('running Cypress with args %o', fnArgs);
|
||||
require('./exec/run').start(parseVariableOpts(fnArgs, args)).then(util.exit).catch(util.logErrorExit1);
|
||||
});
|
||||
program.command('open-ct').usage('[options]').description('Opens Cypress component testing interactive mode. Deprecated: use "open --component"').option('-b, --browser <browser-path>', text('browser')).option('-c, --config <config>', text('config')).option('-C, --config-file <config-file>', text('configFile')).option('-d, --detached [bool]', text('detached'), coerceFalse).option('-e, --env <env>', text('env')).option('--global', text('global')).option('-p, --port <port>', text('port')).option('-P, --project <project-path>', text('project')).option('--dev', text('dev'), coerceFalse).action(opts => {
|
||||
debug('opening Cypress');
|
||||
const msg = `
|
||||
${logSymbols.warning} Warning: open-ct is deprecated and will be removed in a future release.
|
||||
|
||||
Use \`cypress open --component\` instead.
|
||||
`;
|
||||
logger.warn();
|
||||
logger.warn(stripIndent(msg));
|
||||
logger.warn();
|
||||
require('./exec/open').start({
|
||||
...util.parseOpts(opts),
|
||||
testingType: 'component'
|
||||
}).then(util.exit).catch(util.logErrorExit1);
|
||||
});
|
||||
program.command('run-ct').usage('[options]').description('Runs all Cypress component testing suites. Deprecated: use "run --component"').option('-b, --browser <browser-name-or-path>', text('browser')).option('--ci-build-id <id>', text('ciBuildId')).option('-c, --config <config>', text('config')).option('-C, --config-file <config-file>', text('configFile')).option('-e, --env <env>', text('env')).option('--group <name>', text('group')).option('-k, --key <record-key>', text('key')).option('--headed', text('headed')).option('--headless', text('headless')).option('--no-exit', text('exit')).option('--parallel', text('parallel')).option('-p, --port <port>', text('port')).option('-P, --project <project-path>', text('project')).option('-q, --quiet', text('quiet')).option('--record [bool]', text('record'), coerceFalse).option('-r, --reporter <reporter>', text('reporter')).option('-o, --reporter-options <reporter-options>', text('reporterOptions')).option('-s, --spec <spec>', text('spec')).option('-t, --tag <tag>', text('tag')).option('--dev', text('dev'), coerceFalse).action(opts => {
|
||||
debug('running Cypress run-ct');
|
||||
const msg = `
|
||||
${logSymbols.warning} Warning: run-ct is deprecated and will be removed in a future release.
|
||||
Use \`cypress run --component\` instead.
|
||||
`;
|
||||
logger.warn();
|
||||
logger.warn(stripIndent(msg));
|
||||
logger.warn();
|
||||
require('./exec/run').start({
|
||||
...util.parseOpts(opts),
|
||||
testingType: 'component'
|
||||
}).then(util.exit).catch(util.logErrorExit1);
|
||||
});
|
||||
program.command('install').usage('[options]').description('Installs the Cypress executable matching this package\'s version').option('-f, --force', text('forceInstall')).action(opts => {
|
||||
require('./tasks/install').start(util.parseOpts(opts)).catch(util.logErrorExit1);
|
||||
});
|
||||
program.command('verify').usage('[options]').description('Verifies that Cypress is installed correctly and executable').option('--dev', text('dev'), coerceFalse).action(opts => {
|
||||
const defaultOpts = {
|
||||
force: true,
|
||||
welcomeMessage: false
|
||||
};
|
||||
const parsedOpts = util.parseOpts(opts);
|
||||
const options = _.extend(parsedOpts, defaultOpts);
|
||||
require('./tasks/verify').start(options).catch(util.logErrorExit1);
|
||||
});
|
||||
program.command('cache').usage('[command]').description('Manages the Cypress binary cache').option('list', text('cacheList')).option('path', text('cachePath')).option('clear', text('cacheClear')).option('prune', text('cachePrune')).option('--size', text('cacheSize')).action(function (opts, args) {
|
||||
if (!args || !args.length) {
|
||||
this.outputHelp();
|
||||
util.exit(1);
|
||||
}
|
||||
const [command] = args;
|
||||
if (!_.includes(['list', 'path', 'clear', 'prune'], command)) {
|
||||
unknownOption.call(this, `cache ${command}`, 'command');
|
||||
}
|
||||
if (command === 'list') {
|
||||
debug('cache command %o', {
|
||||
command,
|
||||
size: opts.size
|
||||
});
|
||||
return cache.list(opts.size).catch({
|
||||
code: 'ENOENT'
|
||||
}, () => {
|
||||
logger.always('No cached binary versions were found.');
|
||||
process.exit(0);
|
||||
}).catch(e => {
|
||||
debug('cache list command failed with "%s"', e.message);
|
||||
util.logErrorExit1(e);
|
||||
});
|
||||
}
|
||||
cache[command]();
|
||||
});
|
||||
program.command('info').usage('[command]').description('Prints Cypress and system information').option('--dev', text('dev'), coerceFalse).action(opts => {
|
||||
require('./exec/info').start(opts).then(util.exit).catch(util.logErrorExit1);
|
||||
});
|
||||
debug('cli starts with arguments %j', args);
|
||||
util.printNodeOptions();
|
||||
|
||||
// if there are no arguments
|
||||
if (args.length <= 2) {
|
||||
debug('printing help');
|
||||
program.help();
|
||||
// exits
|
||||
}
|
||||
|
||||
const firstCommand = args[2];
|
||||
if (!_.includes(knownCommands, firstCommand)) {
|
||||
debug('unknown command %s', firstCommand);
|
||||
logger.error('Unknown command', `"${firstCommand}"`);
|
||||
program.outputHelp();
|
||||
return util.exit(1);
|
||||
}
|
||||
if (includesVersion(args)) {
|
||||
// commander 2.11.0 changes behavior
|
||||
// and now does not understand top level options
|
||||
// .option('-v, --version').command('version')
|
||||
// so we have to manually catch '-v, --version'
|
||||
handleVersion(program);
|
||||
}
|
||||
debug('program parsing arguments');
|
||||
return program.parse(args);
|
||||
}
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
if (!module.parent) {
|
||||
logger.error('This CLI module should be required from another Node module');
|
||||
logger.error('and not executed directly');
|
||||
process.exit(-1);
|
||||
}
|
98
CyLukTs/lukan/node_modules/cypress/lib/cypress.js
generated
vendored
Normal file
98
CyLukTs/lukan/node_modules/cypress/lib/cypress.js
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
"use strict";
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/316
|
||||
|
||||
const Promise = require('bluebird');
|
||||
const tmp = Promise.promisifyAll(require('tmp'));
|
||||
const fs = require('./fs');
|
||||
const open = require('./exec/open');
|
||||
const run = require('./exec/run');
|
||||
const util = require('./util');
|
||||
const cli = require('./cli');
|
||||
const cypressModuleApi = {
|
||||
/**
|
||||
* Opens Cypress GUI
|
||||
* @see https://on.cypress.io/module-api#cypress-open
|
||||
*/
|
||||
open(options = {}) {
|
||||
options = util.normalizeModuleOptions(options);
|
||||
return open.start(options);
|
||||
},
|
||||
/**
|
||||
* Runs Cypress tests in the current project
|
||||
* @see https://on.cypress.io/module-api#cypress-run
|
||||
*/
|
||||
run(options = {}) {
|
||||
if (!run.isValidProject(options.project)) {
|
||||
return Promise.reject(new Error(`Invalid project path parameter: ${options.project}`));
|
||||
}
|
||||
options = util.normalizeModuleOptions(options);
|
||||
tmp.setGracefulCleanup();
|
||||
return tmp.fileAsync().then(outputPath => {
|
||||
options.outputPath = outputPath;
|
||||
return run.start(options).then(failedTests => {
|
||||
return fs.readJsonAsync(outputPath, {
|
||||
throws: false
|
||||
}).then(output => {
|
||||
if (!output) {
|
||||
return {
|
||||
status: 'failed',
|
||||
failures: failedTests,
|
||||
message: 'Could not find Cypress test run results'
|
||||
};
|
||||
}
|
||||
return output;
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
cli: {
|
||||
/**
|
||||
* Parses CLI arguments into an object that you can pass to "cypress.run"
|
||||
* @example
|
||||
* const cypress = require('cypress')
|
||||
* const cli = ['cypress', 'run', '--browser', 'firefox']
|
||||
* const options = await cypress.cli.parseRunArguments(cli)
|
||||
* // options is {browser: 'firefox'}
|
||||
* await cypress.run(options)
|
||||
* @see https://on.cypress.io/module-api
|
||||
*/
|
||||
parseRunArguments(args) {
|
||||
return cli.parseRunCommand(args);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Provides automatic code completion for configuration in many popular code editors.
|
||||
* While it's not strictly necessary for Cypress to parse your configuration, we
|
||||
* recommend wrapping your config object with `defineConfig()`
|
||||
* @example
|
||||
* module.exports = defineConfig({
|
||||
* viewportWith: 400
|
||||
* })
|
||||
*
|
||||
* @see ../types/cypress-npm-api.d.ts
|
||||
* @param {Cypress.ConfigOptions} config
|
||||
* @returns {Cypress.ConfigOptions} the configuration passed in parameter
|
||||
*/
|
||||
defineConfig(config) {
|
||||
return config;
|
||||
},
|
||||
/**
|
||||
* Provides automatic code completion for Component Frameworks Definitions.
|
||||
* While it's not strictly necessary for Cypress to parse your configuration, we
|
||||
* recommend wrapping your Component Framework Definition object with `defineComponentFramework()`
|
||||
* @example
|
||||
* module.exports = defineComponentFramework({
|
||||
* type: 'cypress-ct-solid-js'
|
||||
* // ...
|
||||
* })
|
||||
*
|
||||
* @see ../types/cypress-npm-api.d.ts
|
||||
* @param {Cypress.ThirdPartyComponentFrameworkDefinition} config
|
||||
* @returns {Cypress.ThirdPartyComponentFrameworkDefinition} the configuration passed in parameter
|
||||
*/
|
||||
defineComponentFramework(config) {
|
||||
return config;
|
||||
}
|
||||
};
|
||||
module.exports = cypressModuleApi;
|
392
CyLukTs/lukan/node_modules/cypress/lib/errors.js
generated
vendored
Normal file
392
CyLukTs/lukan/node_modules/cypress/lib/errors.js
generated
vendored
Normal file
@ -0,0 +1,392 @@
|
||||
"use strict";
|
||||
|
||||
const chalk = require('chalk');
|
||||
const {
|
||||
stripIndent,
|
||||
stripIndents
|
||||
} = require('common-tags');
|
||||
const la = require('lazy-ass');
|
||||
const is = require('check-more-types');
|
||||
const util = require('./util');
|
||||
const state = require('./tasks/state');
|
||||
const docsUrl = 'https://on.cypress.io';
|
||||
const requiredDependenciesUrl = `${docsUrl}/required-dependencies`;
|
||||
const runDocumentationUrl = `${docsUrl}/cypress-run`;
|
||||
|
||||
// TODO it would be nice if all error objects could be enforced via types
|
||||
// to only have description + solution properties
|
||||
|
||||
const hr = '----------';
|
||||
const genericErrorSolution = stripIndent`
|
||||
Search for an existing issue or open a GitHub issue at
|
||||
|
||||
${chalk.blue(util.issuesUrl)}
|
||||
`;
|
||||
|
||||
// common errors Cypress application can encounter
|
||||
const unknownError = {
|
||||
description: 'Unknown Cypress CLI error',
|
||||
solution: genericErrorSolution
|
||||
};
|
||||
const invalidRunProjectPath = {
|
||||
description: 'Invalid --project path',
|
||||
solution: stripIndent`
|
||||
Please provide a valid project path.
|
||||
|
||||
Learn more about ${chalk.cyan('cypress run')} at:
|
||||
|
||||
${chalk.blue(runDocumentationUrl)}
|
||||
`
|
||||
};
|
||||
const invalidOS = {
|
||||
description: 'The Cypress App could not be installed. Your machine does not meet the operating system requirements.',
|
||||
solution: stripIndent`
|
||||
|
||||
${chalk.blue('https://on.cypress.io/guides/getting-started/installing-cypress#system-requirements')}`
|
||||
};
|
||||
const failedDownload = {
|
||||
description: 'The Cypress App could not be downloaded.',
|
||||
solution: stripIndent`
|
||||
Does your workplace require a proxy to be used to access the Internet? If so, you must configure the HTTP_PROXY environment variable before downloading Cypress. Read more: https://on.cypress.io/proxy-configuration
|
||||
|
||||
Otherwise, please check network connectivity and try again:`
|
||||
};
|
||||
const failedUnzip = {
|
||||
description: 'The Cypress App could not be unzipped.',
|
||||
solution: genericErrorSolution
|
||||
};
|
||||
const failedUnzipWindowsMaxPathLength = {
|
||||
description: 'The Cypress App could not be unzipped.',
|
||||
solution: `This is most likely because the maximum path length is being exceeded on your system.
|
||||
|
||||
Read here for solutions to this problem: https://on.cypress.io/win-max-path-length-error`
|
||||
};
|
||||
const missingApp = binaryDir => {
|
||||
return {
|
||||
description: `No version of Cypress is installed in: ${chalk.cyan(binaryDir)}`,
|
||||
solution: stripIndent`
|
||||
\nPlease reinstall Cypress by running: ${chalk.cyan('cypress install')}
|
||||
`
|
||||
};
|
||||
};
|
||||
const binaryNotExecutable = executable => {
|
||||
return {
|
||||
description: `Cypress cannot run because this binary file does not have executable permissions here:\n\n${executable}`,
|
||||
solution: stripIndent`\n
|
||||
Reasons this may happen:
|
||||
|
||||
- node was installed as 'root' or with 'sudo'
|
||||
- the cypress npm package as 'root' or with 'sudo'
|
||||
|
||||
Please check that you have the appropriate user permissions.
|
||||
|
||||
You can also try clearing the cache with 'cypress cache clear' and reinstalling.
|
||||
`
|
||||
};
|
||||
};
|
||||
const notInstalledCI = executable => {
|
||||
return {
|
||||
description: 'The cypress npm package is installed, but the Cypress binary is missing.',
|
||||
solution: stripIndent`\n
|
||||
We expected the binary to be installed here: ${chalk.cyan(executable)}
|
||||
|
||||
Reasons it may be missing:
|
||||
|
||||
- You're caching 'node_modules' but are not caching this path: ${util.getCacheDir()}
|
||||
- You ran 'npm install' at an earlier build step but did not persist: ${util.getCacheDir()}
|
||||
|
||||
Properly caching the binary will fix this error and avoid downloading and unzipping Cypress.
|
||||
|
||||
Alternatively, you can run 'cypress install' to download the binary again.
|
||||
|
||||
${chalk.blue('https://on.cypress.io/not-installed-ci-error')}
|
||||
`
|
||||
};
|
||||
};
|
||||
const nonZeroExitCodeXvfb = {
|
||||
description: 'Xvfb exited with a non zero exit code.',
|
||||
solution: stripIndent`
|
||||
There was a problem spawning Xvfb.
|
||||
|
||||
This is likely a problem with your system, permissions, or installation of Xvfb.
|
||||
`
|
||||
};
|
||||
const missingXvfb = {
|
||||
description: 'Your system is missing the dependency: Xvfb',
|
||||
solution: stripIndent`
|
||||
Install Xvfb and run Cypress again.
|
||||
|
||||
Read our documentation on dependencies for more information:
|
||||
|
||||
${chalk.blue(requiredDependenciesUrl)}
|
||||
|
||||
If you are using Docker, we provide containers with all required dependencies installed.
|
||||
`
|
||||
};
|
||||
const smokeTestFailure = (smokeTestCommand, timedOut) => {
|
||||
return {
|
||||
description: `Cypress verification ${timedOut ? 'timed out' : 'failed'}.`,
|
||||
solution: stripIndent`
|
||||
This command failed with the following output:
|
||||
|
||||
${smokeTestCommand}
|
||||
|
||||
`
|
||||
};
|
||||
};
|
||||
const invalidSmokeTestDisplayError = {
|
||||
code: 'INVALID_SMOKE_TEST_DISPLAY_ERROR',
|
||||
description: 'Cypress verification failed.',
|
||||
solution(msg) {
|
||||
return stripIndent`
|
||||
Cypress failed to start after spawning a new Xvfb server.
|
||||
|
||||
The error logs we received were:
|
||||
|
||||
${hr}
|
||||
|
||||
${msg}
|
||||
|
||||
${hr}
|
||||
|
||||
This may be due to a missing library or dependency. ${chalk.blue(requiredDependenciesUrl)}
|
||||
|
||||
Please refer to the error above for more detail.
|
||||
`;
|
||||
}
|
||||
};
|
||||
const missingDependency = {
|
||||
description: 'Cypress failed to start.',
|
||||
// this message is too Linux specific
|
||||
solution: stripIndent`
|
||||
This may be due to a missing library or dependency. ${chalk.blue(requiredDependenciesUrl)}
|
||||
|
||||
Please refer to the error below for more details.
|
||||
`
|
||||
};
|
||||
const invalidCacheDirectory = {
|
||||
description: 'Cypress cannot write to the cache directory due to file permissions',
|
||||
solution: stripIndent`
|
||||
See discussion and possible solutions at
|
||||
${chalk.blue(util.getGitHubIssueUrl(1281))}
|
||||
`
|
||||
};
|
||||
const versionMismatch = {
|
||||
description: 'Installed version does not match package version.',
|
||||
solution: 'Install Cypress and verify app again'
|
||||
};
|
||||
const incompatibleHeadlessFlags = {
|
||||
description: '`--headed` and `--headless` cannot both be passed.',
|
||||
solution: 'Either pass `--headed` or `--headless`, but not both.'
|
||||
};
|
||||
const solutionUnknown = stripIndent`
|
||||
Please search Cypress documentation for possible solutions:
|
||||
|
||||
${chalk.blue(docsUrl)}
|
||||
|
||||
Check if there is a GitHub issue describing this crash:
|
||||
|
||||
${chalk.blue(util.issuesUrl)}
|
||||
|
||||
Consider opening a new issue.
|
||||
`;
|
||||
const unexpected = {
|
||||
description: 'An unexpected error occurred while verifying the Cypress executable.',
|
||||
solution: solutionUnknown
|
||||
};
|
||||
const invalidCypressEnv = {
|
||||
description: chalk.red('The environment variable with the reserved name "CYPRESS_INTERNAL_ENV" is set.'),
|
||||
solution: chalk.red('Unset the "CYPRESS_INTERNAL_ENV" environment variable and run Cypress again.'),
|
||||
exitCode: 11
|
||||
};
|
||||
const invalidTestingType = {
|
||||
description: 'Invalid testingType',
|
||||
solution: `Please provide a valid testingType. Valid test types are ${chalk.cyan('\'e2e\'')} and ${chalk.cyan('\'component\'')}.`
|
||||
};
|
||||
const incompatibleTestTypeFlags = {
|
||||
description: '`--e2e` and `--component` cannot both be passed.',
|
||||
solution: 'Either pass `--e2e` or `--component`, but not both.'
|
||||
};
|
||||
const incompatibleTestingTypeAndFlag = {
|
||||
description: 'Set a `testingType` and also passed `--e2e` or `--component` flags.',
|
||||
solution: 'Either set `testingType` or pass a testing type flag, but not both.'
|
||||
};
|
||||
const invalidConfigFile = {
|
||||
description: '`--config-file` cannot be false.',
|
||||
solution: 'Either pass a relative path to a valid Cypress config file or remove this option.'
|
||||
};
|
||||
|
||||
/**
|
||||
* This error happens when CLI detects that the child Test Runner process
|
||||
* was killed with a signal, like SIGBUS
|
||||
* @see https://github.com/cypress-io/cypress/issues/5808
|
||||
* @param {'close'|'event'} eventName Child close event name
|
||||
* @param {string} signal Signal that closed the child process, like "SIGBUS"
|
||||
*/
|
||||
const childProcessKilled = (eventName, signal) => {
|
||||
return {
|
||||
description: `The Test Runner unexpectedly exited via a ${chalk.cyan(eventName)} event with signal ${chalk.cyan(signal)}`,
|
||||
solution: solutionUnknown
|
||||
};
|
||||
};
|
||||
const CYPRESS_RUN_BINARY = {
|
||||
notValid: value => {
|
||||
const properFormat = `**/${state.getPlatformExecutable()}`;
|
||||
return {
|
||||
description: `Could not run binary set by environment variable: CYPRESS_RUN_BINARY=${value}`,
|
||||
solution: `Ensure the environment variable is a path to the Cypress binary, matching ${properFormat}`
|
||||
};
|
||||
}
|
||||
};
|
||||
function addPlatformInformation(info) {
|
||||
return util.getPlatformInfo().then(platform => {
|
||||
return {
|
||||
...info,
|
||||
platform
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an error object (see the errors above), forms error message text with details,
|
||||
* then resolves with Error instance you can throw or reject with.
|
||||
* @param {object} errorObject
|
||||
* @returns {Promise<Error>} resolves with an Error
|
||||
* @example
|
||||
```js
|
||||
// inside a Promise with "resolve" and "reject"
|
||||
const errorObject = childProcessKilled('exit', 'SIGKILL')
|
||||
return getError(errorObject).then(reject)
|
||||
```
|
||||
*/
|
||||
function getError(errorObject) {
|
||||
return formErrorText(errorObject).then(errorMessage => {
|
||||
const err = new Error(errorMessage);
|
||||
err.known = true;
|
||||
return err;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Forms nice error message with error and platform information,
|
||||
* and if possible a way to solve it. Resolves with a string.
|
||||
*/
|
||||
function formErrorText(info, msg, prevMessage) {
|
||||
return addPlatformInformation(info).then(obj => {
|
||||
const formatted = [];
|
||||
function add(msg) {
|
||||
formatted.push(stripIndents(msg));
|
||||
}
|
||||
la(is.unemptyString(obj.description), 'expected error description to be text', obj.description);
|
||||
|
||||
// assuming that if there the solution is a function it will handle
|
||||
// error message and (optional previous error message)
|
||||
if (is.fn(obj.solution)) {
|
||||
const text = obj.solution(msg, prevMessage);
|
||||
la(is.unemptyString(text), 'expected solution to be text', text);
|
||||
add(`
|
||||
${obj.description}
|
||||
|
||||
${text}
|
||||
|
||||
`);
|
||||
} else {
|
||||
la(is.unemptyString(obj.solution), 'expected error solution to be text', obj.solution);
|
||||
add(`
|
||||
${obj.description}
|
||||
|
||||
${obj.solution}
|
||||
|
||||
`);
|
||||
if (msg) {
|
||||
add(`
|
||||
${hr}
|
||||
|
||||
${msg}
|
||||
|
||||
`);
|
||||
}
|
||||
}
|
||||
add(`
|
||||
${hr}
|
||||
|
||||
${obj.platform}
|
||||
`);
|
||||
if (obj.footer) {
|
||||
add(`
|
||||
|
||||
${hr}
|
||||
|
||||
${obj.footer}
|
||||
`);
|
||||
}
|
||||
return formatted.join('\n\n');
|
||||
});
|
||||
}
|
||||
const raise = info => {
|
||||
return text => {
|
||||
const err = new Error(text);
|
||||
if (info.code) {
|
||||
err.code = info.code;
|
||||
}
|
||||
err.known = true;
|
||||
throw err;
|
||||
};
|
||||
};
|
||||
const throwFormErrorText = info => {
|
||||
return (msg, prevMessage) => {
|
||||
return formErrorText(info, msg, prevMessage).then(raise(info));
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Forms full error message with error and OS details, prints to the error output
|
||||
* and then exits the process.
|
||||
* @param {ErrorInformation} info Error information {description, solution}
|
||||
* @example return exitWithError(errors.invalidCypressEnv)('foo')
|
||||
*/
|
||||
const exitWithError = info => {
|
||||
return msg => {
|
||||
return formErrorText(info, msg).then(text => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(text);
|
||||
process.exit(info.exitCode || 1);
|
||||
});
|
||||
};
|
||||
};
|
||||
module.exports = {
|
||||
raise,
|
||||
exitWithError,
|
||||
// formError,
|
||||
formErrorText,
|
||||
throwFormErrorText,
|
||||
getError,
|
||||
hr,
|
||||
errors: {
|
||||
unknownError,
|
||||
nonZeroExitCodeXvfb,
|
||||
missingXvfb,
|
||||
missingApp,
|
||||
notInstalledCI,
|
||||
missingDependency,
|
||||
invalidOS,
|
||||
invalidSmokeTestDisplayError,
|
||||
versionMismatch,
|
||||
binaryNotExecutable,
|
||||
unexpected,
|
||||
failedDownload,
|
||||
failedUnzip,
|
||||
failedUnzipWindowsMaxPathLength,
|
||||
invalidCypressEnv,
|
||||
invalidCacheDirectory,
|
||||
CYPRESS_RUN_BINARY,
|
||||
smokeTestFailure,
|
||||
childProcessKilled,
|
||||
incompatibleHeadlessFlags,
|
||||
invalidRunProjectPath,
|
||||
invalidTestingType,
|
||||
incompatibleTestTypeFlags,
|
||||
incompatibleTestingTypeAndFlag,
|
||||
invalidConfigFile
|
||||
}
|
||||
};
|
92
CyLukTs/lukan/node_modules/cypress/lib/exec/info.js
generated
vendored
Normal file
92
CyLukTs/lukan/node_modules/cypress/lib/exec/info.js
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable no-console */
|
||||
const spawn = require('./spawn');
|
||||
const util = require('../util');
|
||||
const state = require('../tasks/state');
|
||||
const os = require('os');
|
||||
const chalk = require('chalk');
|
||||
const prettyBytes = require('pretty-bytes');
|
||||
const _ = require('lodash');
|
||||
|
||||
// color for numbers and show values
|
||||
const g = chalk.green;
|
||||
// color for paths
|
||||
const p = chalk.cyan;
|
||||
const red = chalk.red;
|
||||
// urls
|
||||
const link = chalk.blue.underline;
|
||||
|
||||
// to be exported
|
||||
const methods = {};
|
||||
methods.findProxyEnvironmentVariables = () => {
|
||||
return _.pick(process.env, ['HTTP_PROXY', 'HTTPS_PROXY', 'NO_PROXY']);
|
||||
};
|
||||
const maskSensitiveVariables = obj => {
|
||||
const masked = {
|
||||
...obj
|
||||
};
|
||||
if (masked.CYPRESS_RECORD_KEY) {
|
||||
masked.CYPRESS_RECORD_KEY = '<redacted>';
|
||||
}
|
||||
return masked;
|
||||
};
|
||||
methods.findCypressEnvironmentVariables = () => {
|
||||
const isCyVariable = (val, key) => key.startsWith('CYPRESS_');
|
||||
return _.pickBy(process.env, isCyVariable);
|
||||
};
|
||||
const formatCypressVariables = () => {
|
||||
const vars = methods.findCypressEnvironmentVariables();
|
||||
return maskSensitiveVariables(vars);
|
||||
};
|
||||
methods.start = async (options = {}) => {
|
||||
const args = ['--mode=info'];
|
||||
await spawn.start(args, {
|
||||
dev: options.dev
|
||||
});
|
||||
console.log();
|
||||
const proxyVars = methods.findProxyEnvironmentVariables();
|
||||
if (_.isEmpty(proxyVars)) {
|
||||
console.log('Proxy Settings: none detected');
|
||||
} else {
|
||||
console.log('Proxy Settings:');
|
||||
_.forEach(proxyVars, (value, key) => {
|
||||
console.log('%s: %s', key, g(value));
|
||||
});
|
||||
console.log();
|
||||
console.log('Learn More: %s', link('https://on.cypress.io/proxy-configuration'));
|
||||
console.log();
|
||||
}
|
||||
const cyVars = formatCypressVariables();
|
||||
if (_.isEmpty(cyVars)) {
|
||||
console.log('Environment Variables: none detected');
|
||||
} else {
|
||||
console.log('Environment Variables:');
|
||||
_.forEach(cyVars, (value, key) => {
|
||||
console.log('%s: %s', key, g(value));
|
||||
});
|
||||
}
|
||||
console.log();
|
||||
console.log('Application Data:', p(util.getApplicationDataFolder()));
|
||||
console.log('Browser Profiles:', p(util.getApplicationDataFolder('browsers')));
|
||||
console.log('Binary Caches: %s', p(state.getCacheDir()));
|
||||
console.log();
|
||||
const osVersion = await util.getOsVersionAsync();
|
||||
const buildInfo = util.pkgBuildInfo();
|
||||
const isStable = buildInfo && buildInfo.stable;
|
||||
console.log('Cypress Version: %s', g(util.pkgVersion()), isStable ? g('(stable)') : red('(pre-release)'));
|
||||
console.log('System Platform: %s (%s)', g(os.platform()), g(osVersion));
|
||||
console.log('System Memory: %s free %s', g(prettyBytes(os.totalmem())), g(prettyBytes(os.freemem())));
|
||||
if (!buildInfo) {
|
||||
console.log();
|
||||
console.log('This is the', red('development'), '(un-built) Cypress CLI.');
|
||||
} else if (!isStable) {
|
||||
console.log();
|
||||
console.log('This is a', red('pre-release'), 'build of Cypress.');
|
||||
console.log('Build info:');
|
||||
console.log(' Commit SHA:', g(buildInfo.commitSha));
|
||||
console.log(' Commit Branch:', g(buildInfo.commitBranch));
|
||||
console.log(' Commit Date:', g(buildInfo.commitDate));
|
||||
}
|
||||
};
|
||||
module.exports = methods;
|
90
CyLukTs/lukan/node_modules/cypress/lib/exec/open.js
generated
vendored
Normal file
90
CyLukTs/lukan/node_modules/cypress/lib/exec/open.js
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
"use strict";
|
||||
|
||||
const debug = require('debug')('cypress:cli');
|
||||
const util = require('../util');
|
||||
const spawn = require('./spawn');
|
||||
const verify = require('../tasks/verify');
|
||||
const {
|
||||
processTestingType,
|
||||
checkConfigFile
|
||||
} = require('./shared');
|
||||
const {
|
||||
exitWithError
|
||||
} = require('../errors');
|
||||
|
||||
/**
|
||||
* Maps options collected by the CLI
|
||||
* and forms list of CLI arguments to the server.
|
||||
*
|
||||
* Note: there is lightweight validation, with errors
|
||||
* thrown synchronously.
|
||||
*
|
||||
* @returns {string[]} list of CLI arguments
|
||||
*/
|
||||
const processOpenOptions = (options = {}) => {
|
||||
// In addition to setting the project directory, setting the project option
|
||||
// here ultimately decides whether cypress is run in global mode or not.
|
||||
// It's first based off whether it's installed globally by npm/yarn (-g).
|
||||
// A global install can be overridden by the --project flag, putting Cypress
|
||||
// in project mode. A non-global install can be overridden by the --global
|
||||
// flag, putting it in global mode.
|
||||
if (!util.isInstalledGlobally() && !options.global && !options.project) {
|
||||
options.project = process.cwd();
|
||||
}
|
||||
const args = [];
|
||||
if (options.config) {
|
||||
args.push('--config', options.config);
|
||||
}
|
||||
if (options.configFile !== undefined) {
|
||||
checkConfigFile(options);
|
||||
args.push('--config-file', options.configFile);
|
||||
}
|
||||
if (options.browser) {
|
||||
args.push('--browser', options.browser);
|
||||
}
|
||||
if (options.env) {
|
||||
args.push('--env', options.env);
|
||||
}
|
||||
if (options.port) {
|
||||
args.push('--port', options.port);
|
||||
}
|
||||
if (options.project) {
|
||||
args.push('--project', options.project);
|
||||
}
|
||||
if (options.global) {
|
||||
args.push('--global', options.global);
|
||||
}
|
||||
if (options.inspect) {
|
||||
args.push('--inspect');
|
||||
}
|
||||
if (options.inspectBrk) {
|
||||
args.push('--inspectBrk');
|
||||
}
|
||||
args.push(...processTestingType(options));
|
||||
debug('opening from options %j', options);
|
||||
debug('command line arguments %j', args);
|
||||
return args;
|
||||
};
|
||||
module.exports = {
|
||||
processOpenOptions,
|
||||
start(options = {}) {
|
||||
function open() {
|
||||
try {
|
||||
const args = processOpenOptions(options);
|
||||
return spawn.start(args, {
|
||||
dev: options.dev,
|
||||
detached: Boolean(options.detached)
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.details) {
|
||||
return exitWithError(err.details)();
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
if (options.dev) {
|
||||
return open();
|
||||
}
|
||||
return verify.start().then(open);
|
||||
}
|
||||
};
|
173
CyLukTs/lukan/node_modules/cypress/lib/exec/run.js
generated
vendored
Normal file
173
CyLukTs/lukan/node_modules/cypress/lib/exec/run.js
generated
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
"use strict";
|
||||
|
||||
const _ = require('lodash');
|
||||
const debug = require('debug')('cypress:cli:run');
|
||||
const util = require('../util');
|
||||
const spawn = require('./spawn');
|
||||
const verify = require('../tasks/verify');
|
||||
const {
|
||||
exitWithError,
|
||||
errors
|
||||
} = require('../errors');
|
||||
const {
|
||||
processTestingType,
|
||||
throwInvalidOptionError,
|
||||
checkConfigFile
|
||||
} = require('./shared');
|
||||
|
||||
/**
|
||||
* Typically a user passes a string path to the project.
|
||||
* But "cypress open" allows using `false` to open in global mode,
|
||||
* and the user can accidentally execute `cypress run --project false`
|
||||
* which should be invalid.
|
||||
*/
|
||||
const isValidProject = v => {
|
||||
if (typeof v === 'boolean') {
|
||||
return false;
|
||||
}
|
||||
if (v === '' || v === 'false' || v === 'true') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Maps options collected by the CLI
|
||||
* and forms list of CLI arguments to the server.
|
||||
*
|
||||
* Note: there is lightweight validation, with errors
|
||||
* thrown synchronously.
|
||||
*
|
||||
* @returns {string[]} list of CLI arguments
|
||||
*/
|
||||
const processRunOptions = (options = {}) => {
|
||||
debug('processing run options %o', options);
|
||||
if (!isValidProject(options.project)) {
|
||||
debug('invalid project option %o', {
|
||||
project: options.project
|
||||
});
|
||||
return throwInvalidOptionError(errors.invalidRunProjectPath);
|
||||
}
|
||||
const args = ['--run-project', options.project];
|
||||
if (options.autoCancelAfterFailures || options.autoCancelAfterFailures === 0 || options.autoCancelAfterFailures === false) {
|
||||
args.push('--auto-cancel-after-failures', options.autoCancelAfterFailures);
|
||||
}
|
||||
if (options.browser) {
|
||||
args.push('--browser', options.browser);
|
||||
}
|
||||
if (options.ciBuildId) {
|
||||
args.push('--ci-build-id', options.ciBuildId);
|
||||
}
|
||||
if (options.config) {
|
||||
args.push('--config', options.config);
|
||||
}
|
||||
if (options.configFile !== undefined) {
|
||||
checkConfigFile(options);
|
||||
args.push('--config-file', options.configFile);
|
||||
}
|
||||
if (options.env) {
|
||||
args.push('--env', options.env);
|
||||
}
|
||||
if (options.exit === false) {
|
||||
args.push('--no-exit');
|
||||
}
|
||||
if (options.group) {
|
||||
args.push('--group', options.group);
|
||||
}
|
||||
if (options.headed) {
|
||||
args.push('--headed', options.headed);
|
||||
}
|
||||
if (options.headless) {
|
||||
if (options.headed) {
|
||||
return throwInvalidOptionError(errors.incompatibleHeadlessFlags);
|
||||
}
|
||||
args.push('--headed', !options.headless);
|
||||
}
|
||||
|
||||
// if key is set use that - else attempt to find it by environment variable
|
||||
if (options.key == null) {
|
||||
debug('--key is not set, looking up environment variable CYPRESS_RECORD_KEY');
|
||||
options.key = util.getEnv('CYPRESS_RECORD_KEY');
|
||||
}
|
||||
|
||||
// if we have a key assume we're in record mode
|
||||
if (options.key) {
|
||||
args.push('--key', options.key);
|
||||
}
|
||||
if (options.outputPath) {
|
||||
args.push('--output-path', options.outputPath);
|
||||
}
|
||||
if (options.parallel) {
|
||||
args.push('--parallel');
|
||||
}
|
||||
if (options.port) {
|
||||
args.push('--port', options.port);
|
||||
}
|
||||
if (options.quiet) {
|
||||
args.push('--quiet');
|
||||
}
|
||||
|
||||
// if record is defined and we're not
|
||||
// already in ci mode, then send it up
|
||||
if (options.record != null) {
|
||||
args.push('--record', options.record);
|
||||
}
|
||||
|
||||
// if we have a specific reporter push that into the args
|
||||
if (options.reporter) {
|
||||
args.push('--reporter', options.reporter);
|
||||
}
|
||||
|
||||
// if we have a specific reporter push that into the args
|
||||
if (options.reporterOptions) {
|
||||
args.push('--reporter-options', options.reporterOptions);
|
||||
}
|
||||
|
||||
// if we have specific spec(s) push that into the args
|
||||
if (options.spec) {
|
||||
args.push('--spec', options.spec);
|
||||
}
|
||||
if (options.tag) {
|
||||
args.push('--tag', options.tag);
|
||||
}
|
||||
if (options.inspect) {
|
||||
args.push('--inspect');
|
||||
}
|
||||
if (options.inspectBrk) {
|
||||
args.push('--inspectBrk');
|
||||
}
|
||||
args.push(...processTestingType(options));
|
||||
return args;
|
||||
};
|
||||
module.exports = {
|
||||
processRunOptions,
|
||||
isValidProject,
|
||||
// resolves with the number of failed tests
|
||||
start(options = {}) {
|
||||
_.defaults(options, {
|
||||
key: null,
|
||||
spec: null,
|
||||
reporter: null,
|
||||
reporterOptions: null,
|
||||
project: process.cwd()
|
||||
});
|
||||
function run() {
|
||||
try {
|
||||
const args = processRunOptions(options);
|
||||
debug('run to spawn.start args %j', args);
|
||||
return spawn.start(args, {
|
||||
dev: options.dev
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.details) {
|
||||
return exitWithError(err.details)();
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
if (options.dev) {
|
||||
return run();
|
||||
}
|
||||
return verify.start().then(run);
|
||||
}
|
||||
};
|
62
CyLukTs/lukan/node_modules/cypress/lib/exec/shared.js
generated
vendored
Normal file
62
CyLukTs/lukan/node_modules/cypress/lib/exec/shared.js
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
errors
|
||||
} = require('../errors');
|
||||
|
||||
/**
|
||||
* Throws an error with "details" property from
|
||||
* "errors" object.
|
||||
* @param {Object} details - Error details
|
||||
*/
|
||||
const throwInvalidOptionError = details => {
|
||||
if (!details) {
|
||||
details = errors.unknownError;
|
||||
}
|
||||
|
||||
// throw this error synchronously, it will be caught later on and
|
||||
// the details will be propagated to the promise chain
|
||||
const err = new Error();
|
||||
err.details = details;
|
||||
throw err;
|
||||
};
|
||||
|
||||
/**
|
||||
* Selects exec args based on the configured `testingType`
|
||||
* @param {string} testingType The type of tests being executed
|
||||
* @returns {string[]} The array of new exec arguments
|
||||
*/
|
||||
const processTestingType = options => {
|
||||
if (options.e2e && options.component) {
|
||||
return throwInvalidOptionError(errors.incompatibleTestTypeFlags);
|
||||
}
|
||||
if (options.testingType && (options.component || options.e2e)) {
|
||||
return throwInvalidOptionError(errors.incompatibleTestTypeFlags);
|
||||
}
|
||||
if (options.testingType === 'component' || options.component || options.ct) {
|
||||
return ['--testing-type', 'component'];
|
||||
}
|
||||
if (options.testingType === 'e2e' || options.e2e) {
|
||||
return ['--testing-type', 'e2e'];
|
||||
}
|
||||
if (options.testingType) {
|
||||
return throwInvalidOptionError(errors.invalidTestingType);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Throws an error if configFile is string 'false' or boolean false
|
||||
* @param {*} options
|
||||
*/
|
||||
const checkConfigFile = options => {
|
||||
// CLI will parse as string, module API can pass in boolean
|
||||
if (options.configFile === 'false' || options.configFile === false) {
|
||||
throwInvalidOptionError(errors.invalidConfigFile);
|
||||
}
|
||||
};
|
||||
module.exports = {
|
||||
throwInvalidOptionError,
|
||||
processTestingType,
|
||||
checkConfigFile
|
||||
};
|
289
CyLukTs/lukan/node_modules/cypress/lib/exec/spawn.js
generated
vendored
Normal file
289
CyLukTs/lukan/node_modules/cypress/lib/exec/spawn.js
generated
vendored
Normal file
@ -0,0 +1,289 @@
|
||||
"use strict";
|
||||
|
||||
const _ = require('lodash');
|
||||
const os = require('os');
|
||||
const cp = require('child_process');
|
||||
const path = require('path');
|
||||
const Promise = require('bluebird');
|
||||
const debug = require('debug')('cypress:cli');
|
||||
const debugElectron = require('debug')('cypress:electron');
|
||||
const util = require('../util');
|
||||
const state = require('../tasks/state');
|
||||
const xvfb = require('./xvfb');
|
||||
const verify = require('../tasks/verify');
|
||||
const errors = require('../errors');
|
||||
const isXlibOrLibudevRe = /^(?:Xlib|libudev)/;
|
||||
const isHighSierraWarningRe = /\*\*\* WARNING/;
|
||||
const isRenderWorkerRe = /\.RenderWorker-/;
|
||||
|
||||
// Chromium (which Electron uses) always makes several attempts to connect to the system dbus.
|
||||
// This works fine in most desktop environments, but in a docker container, there is no dbus service
|
||||
// and Chromium emits several error lines, similar to these:
|
||||
|
||||
// [1957:0406/160550.146820:ERROR:bus.cc(392)] Failed to connect to the bus: Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory
|
||||
// [1957:0406/160550.147994:ERROR:bus.cc(392)] Failed to connect to the bus: Address does not contain a colon
|
||||
|
||||
// These warnings are absolutely harmless. Failure to connect to dbus means that electron won't be able to access the user's
|
||||
// credential wallet (none exists in a docker container) and won't show up in the system tray (again, none exists).
|
||||
// Failure to connect is expected and normal here, but users frequently misidentify these errors as the cause of their problems.
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/19299
|
||||
const isDbusWarning = /Failed to connect to the bus:/;
|
||||
|
||||
// Electron began logging these on self-signed certs with 17.0.0-alpha.4.
|
||||
// Once this is fixed upstream this regex can be removed: https://github.com/electron/electron/issues/34583
|
||||
// Sample:
|
||||
// [3801:0606/152837.383892:ERROR:cert_verify_proc_builtin.cc(681)] CertVerifyProcBuiltin for www.googletagmanager.com failed:
|
||||
// ----- Certificate i=0 (OU=Cypress Proxy Server Certificate,O=Cypress Proxy CA,L=Internet,ST=Internet,C=Internet,CN=www.googletagmanager.com) -----
|
||||
// ERROR: No matching issuer found
|
||||
const isCertVerifyProcBuiltin = /(^\[.*ERROR:cert_verify_proc_builtin\.cc|^----- Certificate i=0 \(OU=Cypress Proxy|^ERROR: No matching issuer found$)/;
|
||||
|
||||
// Electron logs a benign warning about WebSwapCGLLayer on MacOS v12 and Electron v18 due to a naming collision in shared libraries.
|
||||
// Once this is fixed upstream this regex can be removed: https://github.com/electron/electron/issues/33685
|
||||
// Sample:
|
||||
// objc[60540]: Class WebSwapCGLLayer is implemented in both /System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks/WebCore.framework/Versions/A/Frameworks/libANGLE-shared.dylib (0x7ffa5a006318) and /{path/to/app}/node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libGLESv2.dylib (0x10f8a89c8). One of the two will be used. Which one is undefined.
|
||||
const isMacOSElectronWebSwapCGLLayerWarning = /^objc\[\d+\]: Class WebSwapCGLLayer is implemented in both.*Which one is undefined\./;
|
||||
const GARBAGE_WARNINGS = [isXlibOrLibudevRe, isHighSierraWarningRe, isRenderWorkerRe, isDbusWarning, isCertVerifyProcBuiltin, isMacOSElectronWebSwapCGLLayerWarning];
|
||||
const isGarbageLineWarning = str => {
|
||||
return _.some(GARBAGE_WARNINGS, re => {
|
||||
return re.test(str);
|
||||
});
|
||||
};
|
||||
function isPlatform(platform) {
|
||||
return os.platform() === platform;
|
||||
}
|
||||
function needsStderrPiped(needsXvfb) {
|
||||
return _.some([isPlatform('darwin'), needsXvfb && isPlatform('linux'), util.isPossibleLinuxWithIncorrectDisplay()]);
|
||||
}
|
||||
function needsEverythingPipedDirectly() {
|
||||
return isPlatform('win32');
|
||||
}
|
||||
function getStdio(needsXvfb) {
|
||||
if (needsEverythingPipedDirectly()) {
|
||||
return 'pipe';
|
||||
}
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/921
|
||||
// https://github.com/cypress-io/cypress/issues/1143
|
||||
// https://github.com/cypress-io/cypress/issues/1745
|
||||
if (needsStderrPiped(needsXvfb)) {
|
||||
// returning pipe here so we can massage stderr
|
||||
// and remove garbage from Xlib and libuv
|
||||
// due to starting the Xvfb process on linux
|
||||
return ['inherit', 'inherit', 'pipe'];
|
||||
}
|
||||
return 'inherit';
|
||||
}
|
||||
module.exports = {
|
||||
isGarbageLineWarning,
|
||||
start(args, options = {}) {
|
||||
const needsXvfb = xvfb.isNeeded();
|
||||
let executable = state.getPathToExecutable(state.getBinaryDir());
|
||||
if (util.getEnv('CYPRESS_RUN_BINARY')) {
|
||||
executable = path.resolve(util.getEnv('CYPRESS_RUN_BINARY'));
|
||||
}
|
||||
debug('needs to start own Xvfb?', needsXvfb);
|
||||
|
||||
// Always push cwd into the args
|
||||
// which additionally acts as a signal to the
|
||||
// binary that it was invoked through the NPM module
|
||||
args = args || [];
|
||||
if (typeof args === 'string') {
|
||||
args = [args];
|
||||
}
|
||||
args = [...args, '--cwd', process.cwd(), '--userNodePath', process.execPath, '--userNodeVersion', process.versions.node];
|
||||
_.defaults(options, {
|
||||
dev: false,
|
||||
env: process.env,
|
||||
detached: false,
|
||||
stdio: getStdio(needsXvfb)
|
||||
});
|
||||
const spawn = (overrides = {}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
_.defaults(overrides, {
|
||||
onStderrData: false,
|
||||
electronLogging: false
|
||||
});
|
||||
const {
|
||||
onStderrData,
|
||||
electronLogging
|
||||
} = overrides;
|
||||
const envOverrides = util.getEnvOverrides(options);
|
||||
const electronArgs = [];
|
||||
const node11WindowsFix = isPlatform('win32');
|
||||
let startScriptPath;
|
||||
if (options.dev) {
|
||||
executable = 'node';
|
||||
// if we're in dev then reset
|
||||
// the launch cmd to be 'npm run dev'
|
||||
startScriptPath = path.resolve(__dirname, '..', '..', '..', 'scripts', 'start.js'), debug('in dev mode the args became %o', args);
|
||||
}
|
||||
if (!options.dev && verify.needsSandbox()) {
|
||||
electronArgs.push('--no-sandbox');
|
||||
}
|
||||
|
||||
// strip dev out of child process options
|
||||
/**
|
||||
* @type {import('child_process').ForkOptions}
|
||||
*/
|
||||
let stdioOptions = _.pick(options, 'env', 'detached', 'stdio');
|
||||
|
||||
// figure out if we're going to be force enabling or disabling colors.
|
||||
// also figure out whether we should force stdout and stderr into thinking
|
||||
// it is a tty as opposed to a pipe.
|
||||
stdioOptions.env = _.extend({}, stdioOptions.env, envOverrides);
|
||||
if (node11WindowsFix) {
|
||||
stdioOptions = _.extend({}, stdioOptions, {
|
||||
windowsHide: false
|
||||
});
|
||||
}
|
||||
if (electronLogging) {
|
||||
stdioOptions.env.ELECTRON_ENABLE_LOGGING = true;
|
||||
}
|
||||
if (util.isPossibleLinuxWithIncorrectDisplay()) {
|
||||
// make sure we use the latest DISPLAY variable if any
|
||||
debug('passing DISPLAY', process.env.DISPLAY);
|
||||
stdioOptions.env.DISPLAY = process.env.DISPLAY;
|
||||
}
|
||||
if (stdioOptions.env.ELECTRON_RUN_AS_NODE) {
|
||||
// Since we are running electron as node, we need to add an entry point file.
|
||||
startScriptPath = path.join(state.getBinaryPkgPath(path.dirname(executable)), '..', 'index.js');
|
||||
} else {
|
||||
// Start arguments with "--" so Electron knows these are OUR
|
||||
// arguments and does not try to sanitize them. Otherwise on Windows
|
||||
// an url in one of the arguments crashes it :(
|
||||
// https://github.com/cypress-io/cypress/issues/5466
|
||||
args = [...electronArgs, '--', ...args];
|
||||
}
|
||||
if (startScriptPath) {
|
||||
args.unshift(startScriptPath);
|
||||
}
|
||||
if (process.env.CYPRESS_INTERNAL_DEV_DEBUG) {
|
||||
args.unshift(process.env.CYPRESS_INTERNAL_DEV_DEBUG);
|
||||
}
|
||||
debug('spawn args %o %o', args, _.omit(stdioOptions, 'env'));
|
||||
debug('spawning Cypress with executable: %s', executable);
|
||||
const child = cp.spawn(executable, args, stdioOptions);
|
||||
function resolveOn(event) {
|
||||
return function (code, signal) {
|
||||
debug('child event fired %o', {
|
||||
event,
|
||||
code,
|
||||
signal
|
||||
});
|
||||
if (code === null) {
|
||||
const errorObject = errors.errors.childProcessKilled(event, signal);
|
||||
return errors.getError(errorObject).then(reject);
|
||||
}
|
||||
resolve(code);
|
||||
};
|
||||
}
|
||||
child.on('close', resolveOn('close'));
|
||||
child.on('exit', resolveOn('exit'));
|
||||
child.on('error', reject);
|
||||
|
||||
// if stdio options is set to 'pipe', then
|
||||
// we should set up pipes:
|
||||
// process STDIN (read stream) => child STDIN (writeable)
|
||||
// child STDOUT => process STDOUT
|
||||
// child STDERR => process STDERR with additional filtering
|
||||
if (child.stdin) {
|
||||
debug('piping process STDIN into child STDIN');
|
||||
process.stdin.pipe(child.stdin);
|
||||
}
|
||||
if (child.stdout) {
|
||||
debug('piping child STDOUT to process STDOUT');
|
||||
child.stdout.pipe(process.stdout);
|
||||
}
|
||||
|
||||
// if this is defined then we are manually piping for linux
|
||||
// to filter out the garbage
|
||||
if (child.stderr) {
|
||||
debug('piping child STDERR to process STDERR');
|
||||
child.stderr.on('data', data => {
|
||||
const str = data.toString();
|
||||
|
||||
// bail if this is warning line garbage
|
||||
if (isGarbageLineWarning(str)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if we have a callback and this explictly returns
|
||||
// false then bail
|
||||
if (onStderrData && onStderrData(str) === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// else pass it along!
|
||||
process.stderr.write(data);
|
||||
});
|
||||
}
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/1841
|
||||
// https://github.com/cypress-io/cypress/issues/5241
|
||||
// In some versions of node, it will throw on windows
|
||||
// when you close the parent process after piping
|
||||
// into the child process. unpiping does not seem
|
||||
// to have any effect. so we're just catching the
|
||||
// error here and not doing anything.
|
||||
process.stdin.on('error', err => {
|
||||
if (['EPIPE', 'ENOTCONN'].includes(err.code)) {
|
||||
return;
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
if (stdioOptions.detached) {
|
||||
child.unref();
|
||||
}
|
||||
});
|
||||
};
|
||||
const spawnInXvfb = () => {
|
||||
return xvfb.start().then(userFriendlySpawn).finally(xvfb.stop);
|
||||
};
|
||||
const userFriendlySpawn = linuxWithDisplayEnv => {
|
||||
debug('spawning, should retry on display problem?', Boolean(linuxWithDisplayEnv));
|
||||
let brokenGtkDisplay;
|
||||
const overrides = {};
|
||||
if (linuxWithDisplayEnv) {
|
||||
_.extend(overrides, {
|
||||
electronLogging: true,
|
||||
onStderrData(str) {
|
||||
// if we receive a broken pipe anywhere
|
||||
// then we know that's why cypress exited early
|
||||
if (util.isBrokenGtkDisplay(str)) {
|
||||
brokenGtkDisplay = true;
|
||||
}
|
||||
|
||||
// we should attempt to always slurp up
|
||||
// the stderr logs unless we've explicitly
|
||||
// enabled the electron debug logging
|
||||
if (!debugElectron.enabled) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return spawn(overrides).then(code => {
|
||||
if (code !== 0 && brokenGtkDisplay) {
|
||||
util.logBrokenGtkDisplayWarning();
|
||||
return spawnInXvfb();
|
||||
}
|
||||
return code;
|
||||
})
|
||||
// we can format and handle an error message from the code above
|
||||
// prevent wrapping error again by using "known: undefined" filter
|
||||
.catch({
|
||||
known: undefined
|
||||
}, errors.throwFormErrorText(errors.errors.unexpected));
|
||||
};
|
||||
if (needsXvfb) {
|
||||
return spawnInXvfb();
|
||||
}
|
||||
|
||||
// if we are on linux and there's already a DISPLAY
|
||||
// set, then we may need to rerun cypress after
|
||||
// spawning our own Xvfb server
|
||||
const linuxWithDisplayEnv = util.isPossibleLinuxWithIncorrectDisplay();
|
||||
return userFriendlySpawn(linuxWithDisplayEnv);
|
||||
}
|
||||
};
|
53
CyLukTs/lukan/node_modules/cypress/lib/exec/versions.js
generated
vendored
Normal file
53
CyLukTs/lukan/node_modules/cypress/lib/exec/versions.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
"use strict";
|
||||
|
||||
const Promise = require('bluebird');
|
||||
const debug = require('debug')('cypress:cli');
|
||||
const path = require('path');
|
||||
const util = require('../util');
|
||||
const state = require('../tasks/state');
|
||||
const {
|
||||
throwFormErrorText,
|
||||
errors
|
||||
} = require('../errors');
|
||||
const getVersions = () => {
|
||||
return Promise.try(() => {
|
||||
if (util.getEnv('CYPRESS_RUN_BINARY')) {
|
||||
let envBinaryPath = path.resolve(util.getEnv('CYPRESS_RUN_BINARY'));
|
||||
return state.parseRealPlatformBinaryFolderAsync(envBinaryPath).then(envBinaryDir => {
|
||||
if (!envBinaryDir) {
|
||||
return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))();
|
||||
}
|
||||
debug('CYPRESS_RUN_BINARY has binaryDir:', envBinaryDir);
|
||||
return envBinaryDir;
|
||||
}).catch({
|
||||
code: 'ENOENT'
|
||||
}, err => {
|
||||
return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))(err.message);
|
||||
});
|
||||
}
|
||||
return state.getBinaryDir();
|
||||
}).then(state.getBinaryPkgAsync).then(pkg => {
|
||||
const versions = {
|
||||
binary: state.getBinaryPkgVersion(pkg),
|
||||
electronVersion: state.getBinaryElectronVersion(pkg),
|
||||
electronNodeVersion: state.getBinaryElectronNodeVersion(pkg)
|
||||
};
|
||||
debug('binary versions %o', versions);
|
||||
return versions;
|
||||
}).then(binaryVersions => {
|
||||
const buildInfo = util.pkgBuildInfo();
|
||||
let packageVersion = util.pkgVersion();
|
||||
if (!buildInfo) packageVersion += ' (development)';else if (!buildInfo.stable) packageVersion += ' (pre-release)';
|
||||
const versions = {
|
||||
package: packageVersion,
|
||||
binary: binaryVersions.binary || 'not installed',
|
||||
electronVersion: binaryVersions.electronVersion || 'not found',
|
||||
electronNodeVersion: binaryVersions.electronNodeVersion || 'not found'
|
||||
};
|
||||
debug('combined versions %o', versions);
|
||||
return versions;
|
||||
});
|
||||
};
|
||||
module.exports = {
|
||||
getVersions
|
||||
};
|
94
CyLukTs/lukan/node_modules/cypress/lib/exec/xvfb.js
generated
vendored
Normal file
94
CyLukTs/lukan/node_modules/cypress/lib/exec/xvfb.js
generated
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
"use strict";
|
||||
|
||||
const os = require('os');
|
||||
const Promise = require('bluebird');
|
||||
const Xvfb = require('@cypress/xvfb');
|
||||
const {
|
||||
stripIndent
|
||||
} = require('common-tags');
|
||||
const Debug = require('debug');
|
||||
const {
|
||||
throwFormErrorText,
|
||||
errors
|
||||
} = require('../errors');
|
||||
const util = require('../util');
|
||||
const debug = Debug('cypress:cli');
|
||||
const debugXvfb = Debug('cypress:xvfb');
|
||||
debug.Debug = debugXvfb.Debug = Debug;
|
||||
const xvfbOptions = {
|
||||
displayNum: process.env.XVFB_DISPLAY_NUM,
|
||||
timeout: 30000,
|
||||
// milliseconds
|
||||
// need to explicitly define screen otherwise electron will crash
|
||||
// https://github.com/cypress-io/cypress/issues/6184
|
||||
xvfb_args: ['-screen', '0', '1280x1024x24'],
|
||||
onStderrData(data) {
|
||||
if (debugXvfb.enabled) {
|
||||
debugXvfb(data.toString());
|
||||
}
|
||||
}
|
||||
};
|
||||
const xvfb = Promise.promisifyAll(new Xvfb(xvfbOptions));
|
||||
module.exports = {
|
||||
_debugXvfb: debugXvfb,
|
||||
// expose for testing
|
||||
|
||||
_xvfb: xvfb,
|
||||
// expose for testing
|
||||
|
||||
_xvfbOptions: xvfbOptions,
|
||||
// expose for testing
|
||||
|
||||
start() {
|
||||
debug('Starting Xvfb');
|
||||
return xvfb.startAsync().return(null).catch({
|
||||
nonZeroExitCode: true
|
||||
}, throwFormErrorText(errors.nonZeroExitCodeXvfb)).catch(err => {
|
||||
if (err.known) {
|
||||
throw err;
|
||||
}
|
||||
return throwFormErrorText(errors.missingXvfb)(err);
|
||||
});
|
||||
},
|
||||
stop() {
|
||||
debug('Stopping Xvfb');
|
||||
return xvfb.stopAsync().return(null).catch(() => {
|
||||
// noop
|
||||
});
|
||||
},
|
||||
isNeeded() {
|
||||
if (process.env.ELECTRON_RUN_AS_NODE) {
|
||||
debug('Environment variable ELECTRON_RUN_AS_NODE detected, xvfb is not needed');
|
||||
return false; // xvfb required for electron processes only.
|
||||
}
|
||||
|
||||
if (os.platform() !== 'linux') {
|
||||
return false;
|
||||
}
|
||||
if (process.env.DISPLAY) {
|
||||
const issueUrl = util.getGitHubIssueUrl(4034);
|
||||
const message = stripIndent`
|
||||
DISPLAY environment variable is set to ${process.env.DISPLAY} on Linux
|
||||
Assuming this DISPLAY points at working X11 server,
|
||||
Cypress will not spawn own Xvfb
|
||||
|
||||
NOTE: if the X11 server is NOT working, Cypress will exit without explanation,
|
||||
see ${issueUrl}
|
||||
Solution: Unset the DISPLAY variable and try again:
|
||||
DISPLAY= npx cypress run ...
|
||||
`;
|
||||
debug(message);
|
||||
return false;
|
||||
}
|
||||
debug('undefined DISPLAY environment variable');
|
||||
debug('Cypress will spawn its own Xvfb');
|
||||
return true;
|
||||
},
|
||||
// async method, resolved with Boolean
|
||||
verify() {
|
||||
return xvfb.startAsync().return(true).catch(err => {
|
||||
debug('Could not verify xvfb: %s', err.message);
|
||||
return false;
|
||||
}).finally(xvfb.stopAsync);
|
||||
}
|
||||
};
|
4
CyLukTs/lukan/node_modules/cypress/lib/fs.js
generated
vendored
Normal file
4
CyLukTs/lukan/node_modules/cypress/lib/fs.js
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
"use strict";
|
||||
|
||||
const Promise = require('bluebird');
|
||||
module.exports = Promise.promisifyAll(require('fs-extra'));
|
53
CyLukTs/lukan/node_modules/cypress/lib/logger.js
generated
vendored
Normal file
53
CyLukTs/lukan/node_modules/cypress/lib/logger.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
"use strict";
|
||||
|
||||
const chalk = require('chalk');
|
||||
let logs = [];
|
||||
const logLevel = () => {
|
||||
return process.env.npm_config_loglevel || 'notice';
|
||||
};
|
||||
const error = (...messages) => {
|
||||
logs.push(messages.join(' '));
|
||||
console.log(chalk.red(...messages)); // eslint-disable-line no-console
|
||||
};
|
||||
|
||||
const warn = (...messages) => {
|
||||
if (logLevel() === 'silent') return;
|
||||
logs.push(messages.join(' '));
|
||||
console.log(chalk.yellow(...messages)); // eslint-disable-line no-console
|
||||
};
|
||||
|
||||
const log = (...messages) => {
|
||||
if (logLevel() === 'silent' || logLevel() === 'warn') return;
|
||||
logs.push(messages.join(' '));
|
||||
console.log(...messages); // eslint-disable-line no-console
|
||||
};
|
||||
|
||||
const always = (...messages) => {
|
||||
logs.push(messages.join(' '));
|
||||
console.log(...messages); // eslint-disable-line no-console
|
||||
};
|
||||
|
||||
// splits long text into lines and calls log()
|
||||
// on each one to allow easy unit testing for specific message
|
||||
const logLines = text => {
|
||||
const lines = text.split('\n');
|
||||
for (const line of lines) {
|
||||
log(line);
|
||||
}
|
||||
};
|
||||
const print = () => {
|
||||
return logs.join('\n');
|
||||
};
|
||||
const reset = () => {
|
||||
logs = [];
|
||||
};
|
||||
module.exports = {
|
||||
log,
|
||||
warn,
|
||||
error,
|
||||
always,
|
||||
logLines,
|
||||
print,
|
||||
reset,
|
||||
logLevel
|
||||
};
|
132
CyLukTs/lukan/node_modules/cypress/lib/tasks/cache.js
generated
vendored
Normal file
132
CyLukTs/lukan/node_modules/cypress/lib/tasks/cache.js
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
"use strict";
|
||||
|
||||
const state = require('./state');
|
||||
const logger = require('../logger');
|
||||
const fs = require('../fs');
|
||||
const util = require('../util');
|
||||
const {
|
||||
join
|
||||
} = require('path');
|
||||
const Table = require('cli-table3');
|
||||
const dayjs = require('dayjs');
|
||||
const relativeTime = require('dayjs/plugin/relativeTime');
|
||||
const chalk = require('chalk');
|
||||
const _ = require('lodash');
|
||||
const getFolderSize = require('./get-folder-size');
|
||||
const Bluebird = require('bluebird');
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
// output colors for the table
|
||||
const colors = {
|
||||
titles: chalk.white,
|
||||
dates: chalk.cyan,
|
||||
values: chalk.green,
|
||||
size: chalk.gray
|
||||
};
|
||||
const logCachePath = () => {
|
||||
logger.always(state.getCacheDir());
|
||||
return undefined;
|
||||
};
|
||||
const clear = () => {
|
||||
return fs.removeAsync(state.getCacheDir());
|
||||
};
|
||||
const prune = () => {
|
||||
const cacheDir = state.getCacheDir();
|
||||
const checkedInBinaryVersion = util.pkgVersion();
|
||||
let deletedBinary = false;
|
||||
return fs.readdirAsync(cacheDir).then(versions => {
|
||||
return Bluebird.all(versions.map(version => {
|
||||
if (version !== checkedInBinaryVersion) {
|
||||
deletedBinary = true;
|
||||
const versionDir = join(cacheDir, version);
|
||||
return fs.removeAsync(versionDir);
|
||||
}
|
||||
}));
|
||||
}).then(() => {
|
||||
if (deletedBinary) {
|
||||
logger.always(`Deleted all binary caches except for the ${checkedInBinaryVersion} binary cache.`);
|
||||
} else {
|
||||
logger.always(`No binary caches found to prune.`);
|
||||
}
|
||||
}).catch({
|
||||
code: 'ENOENT'
|
||||
}, () => {
|
||||
logger.always(`No Cypress cache was found at ${cacheDir}. Nothing to prune.`);
|
||||
});
|
||||
};
|
||||
const fileSizeInMB = size => {
|
||||
return `${(size / 1024 / 1024).toFixed(1)}MB`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Collects all cached versions, finds when each was used
|
||||
* and prints a table with results to the terminal
|
||||
*/
|
||||
const list = showSize => {
|
||||
return getCachedVersions(showSize).then(binaries => {
|
||||
const head = [colors.titles('version'), colors.titles('last used')];
|
||||
if (showSize) {
|
||||
head.push(colors.titles('size'));
|
||||
}
|
||||
const table = new Table({
|
||||
head
|
||||
});
|
||||
binaries.forEach(binary => {
|
||||
const versionString = colors.values(binary.version);
|
||||
const lastUsed = binary.accessed ? colors.dates(binary.accessed) : 'unknown';
|
||||
const row = [versionString, lastUsed];
|
||||
if (showSize) {
|
||||
const size = colors.size(fileSizeInMB(binary.size));
|
||||
row.push(size);
|
||||
}
|
||||
return table.push(row);
|
||||
});
|
||||
logger.always(table.toString());
|
||||
});
|
||||
};
|
||||
const getCachedVersions = showSize => {
|
||||
const cacheDir = state.getCacheDir();
|
||||
return fs.readdirAsync(cacheDir).filter(util.isSemver).map(version => {
|
||||
return {
|
||||
version,
|
||||
folderPath: join(cacheDir, version)
|
||||
};
|
||||
}).mapSeries(binary => {
|
||||
// last access time on the folder is different from last access time
|
||||
// on the Cypress binary
|
||||
const binaryDir = state.getBinaryDir(binary.version);
|
||||
const executable = state.getPathToExecutable(binaryDir);
|
||||
return fs.statAsync(executable).then(stat => {
|
||||
const lastAccessedTime = _.get(stat, 'atime');
|
||||
if (!lastAccessedTime) {
|
||||
// the test runner has never been opened
|
||||
// or could be a test simulating missing timestamp
|
||||
return binary;
|
||||
}
|
||||
const accessed = dayjs(lastAccessedTime).fromNow();
|
||||
binary.accessed = accessed;
|
||||
return binary;
|
||||
}, e => {
|
||||
// could not find the binary or gets its stats
|
||||
return binary;
|
||||
});
|
||||
}).mapSeries(binary => {
|
||||
if (showSize) {
|
||||
const binaryDir = state.getBinaryDir(binary.version);
|
||||
return getFolderSize(binaryDir).then(size => {
|
||||
return {
|
||||
...binary,
|
||||
size
|
||||
};
|
||||
});
|
||||
}
|
||||
return binary;
|
||||
});
|
||||
};
|
||||
module.exports = {
|
||||
path: logCachePath,
|
||||
clear,
|
||||
prune,
|
||||
list,
|
||||
getCachedVersions
|
||||
};
|
319
CyLukTs/lukan/node_modules/cypress/lib/tasks/download.js
generated
vendored
Normal file
319
CyLukTs/lukan/node_modules/cypress/lib/tasks/download.js
generated
vendored
Normal file
@ -0,0 +1,319 @@
|
||||
"use strict";
|
||||
|
||||
const la = require('lazy-ass');
|
||||
const is = require('check-more-types');
|
||||
const os = require('os');
|
||||
const url = require('url');
|
||||
const path = require('path');
|
||||
const debug = require('debug')('cypress:cli');
|
||||
const request = require('@cypress/request');
|
||||
const Promise = require('bluebird');
|
||||
const requestProgress = require('request-progress');
|
||||
const {
|
||||
stripIndent
|
||||
} = require('common-tags');
|
||||
const getProxyForUrl = require('proxy-from-env').getProxyForUrl;
|
||||
const {
|
||||
throwFormErrorText,
|
||||
errors
|
||||
} = require('../errors');
|
||||
const fs = require('../fs');
|
||||
const util = require('../util');
|
||||
const defaultBaseUrl = 'https://download.cypress.io/';
|
||||
const defaultMaxRedirects = 10;
|
||||
const getProxyForUrlWithNpmConfig = url => {
|
||||
return getProxyForUrl(url) || process.env.npm_config_https_proxy || process.env.npm_config_proxy || null;
|
||||
};
|
||||
const getBaseUrl = () => {
|
||||
if (util.getEnv('CYPRESS_DOWNLOAD_MIRROR')) {
|
||||
let baseUrl = util.getEnv('CYPRESS_DOWNLOAD_MIRROR');
|
||||
if (!baseUrl.endsWith('/')) {
|
||||
baseUrl += '/';
|
||||
}
|
||||
return baseUrl;
|
||||
}
|
||||
return defaultBaseUrl;
|
||||
};
|
||||
const getCA = () => {
|
||||
return new Promise(resolve => {
|
||||
if (process.env.npm_config_cafile) {
|
||||
fs.readFile(process.env.npm_config_cafile, 'utf8').then(cafileContent => {
|
||||
resolve(cafileContent);
|
||||
}).catch(() => {
|
||||
resolve();
|
||||
});
|
||||
} else if (process.env.npm_config_ca) {
|
||||
resolve(process.env.npm_config_ca);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
};
|
||||
const prepend = (arch, urlPath, version) => {
|
||||
const endpoint = url.resolve(getBaseUrl(), urlPath);
|
||||
const platform = os.platform();
|
||||
const pathTemplate = util.getEnv('CYPRESS_DOWNLOAD_PATH_TEMPLATE', true);
|
||||
return pathTemplate ? pathTemplate.replace(/\\?\$\{endpoint\}/g, endpoint).replace(/\\?\$\{platform\}/g, platform).replace(/\\?\$\{arch\}/g, arch).replace(/\\?\$\{version\}/g, version) : `${endpoint}?platform=${platform}&arch=${arch}`;
|
||||
};
|
||||
const getUrl = (arch, version) => {
|
||||
if (is.url(version)) {
|
||||
debug('version is already an url', version);
|
||||
return version;
|
||||
}
|
||||
const urlPath = version ? `desktop/${version}` : 'desktop';
|
||||
return prepend(arch, urlPath, version);
|
||||
};
|
||||
const statusMessage = err => {
|
||||
return err.statusCode ? [err.statusCode, err.statusMessage].join(' - ') : err.toString();
|
||||
};
|
||||
const prettyDownloadErr = (err, url) => {
|
||||
const msg = stripIndent`
|
||||
URL: ${url}
|
||||
${statusMessage(err)}
|
||||
`;
|
||||
debug(msg);
|
||||
return throwFormErrorText(errors.failedDownload)(msg);
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks checksum and file size for the given file. Allows both
|
||||
* values or just one of them to be checked.
|
||||
*/
|
||||
const verifyDownloadedFile = (filename, expectedSize, expectedChecksum) => {
|
||||
if (expectedSize && expectedChecksum) {
|
||||
debug('verifying checksum and file size');
|
||||
return Promise.join(util.getFileChecksum(filename), util.getFileSize(filename), (checksum, filesize) => {
|
||||
if (checksum === expectedChecksum && filesize === expectedSize) {
|
||||
debug('downloaded file has the expected checksum and size ✅');
|
||||
return;
|
||||
}
|
||||
debug('raising error: checksum or file size mismatch');
|
||||
const text = stripIndent`
|
||||
Corrupted download
|
||||
|
||||
Expected downloaded file to have checksum: ${expectedChecksum}
|
||||
Computed checksum: ${checksum}
|
||||
|
||||
Expected downloaded file to have size: ${expectedSize}
|
||||
Computed size: ${filesize}
|
||||
`;
|
||||
debug(text);
|
||||
throw new Error(text);
|
||||
});
|
||||
}
|
||||
if (expectedChecksum) {
|
||||
debug('only checking expected file checksum %d', expectedChecksum);
|
||||
return util.getFileChecksum(filename).then(checksum => {
|
||||
if (checksum === expectedChecksum) {
|
||||
debug('downloaded file has the expected checksum ✅');
|
||||
return;
|
||||
}
|
||||
debug('raising error: file checksum mismatch');
|
||||
const text = stripIndent`
|
||||
Corrupted download
|
||||
|
||||
Expected downloaded file to have checksum: ${expectedChecksum}
|
||||
Computed checksum: ${checksum}
|
||||
`;
|
||||
throw new Error(text);
|
||||
});
|
||||
}
|
||||
if (expectedSize) {
|
||||
// maybe we don't have a checksum, but at least CDN returns content length
|
||||
// which we can check against the file size
|
||||
debug('only checking expected file size %d', expectedSize);
|
||||
return util.getFileSize(filename).then(filesize => {
|
||||
if (filesize === expectedSize) {
|
||||
debug('downloaded file has the expected size ✅');
|
||||
return;
|
||||
}
|
||||
debug('raising error: file size mismatch');
|
||||
const text = stripIndent`
|
||||
Corrupted download
|
||||
|
||||
Expected downloaded file to have size: ${expectedSize}
|
||||
Computed size: ${filesize}
|
||||
`;
|
||||
throw new Error(text);
|
||||
});
|
||||
}
|
||||
debug('downloaded file lacks checksum or size to verify');
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
// downloads from given url
|
||||
// return an object with
|
||||
// {filename: ..., downloaded: true}
|
||||
const downloadFromUrl = ({
|
||||
url,
|
||||
downloadDestination,
|
||||
progress,
|
||||
ca,
|
||||
version,
|
||||
redirectTTL = defaultMaxRedirects
|
||||
}) => {
|
||||
if (redirectTTL <= 0) {
|
||||
return Promise.reject(new Error(stripIndent`
|
||||
Failed downloading the Cypress binary.
|
||||
There were too many redirects. The default allowance is ${defaultMaxRedirects}.
|
||||
Maybe you got stuck in a redirect loop?
|
||||
`));
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const proxy = getProxyForUrlWithNpmConfig(url);
|
||||
debug('Downloading package', {
|
||||
url,
|
||||
proxy,
|
||||
downloadDestination
|
||||
});
|
||||
if (ca) {
|
||||
debug('using custom CA details from npm config');
|
||||
}
|
||||
const reqOptions = {
|
||||
uri: url,
|
||||
...(proxy ? {
|
||||
proxy
|
||||
} : {}),
|
||||
...(ca ? {
|
||||
agentOptions: {
|
||||
ca
|
||||
}
|
||||
} : {}),
|
||||
method: 'GET',
|
||||
followRedirect: false
|
||||
};
|
||||
const req = request(reqOptions);
|
||||
|
||||
// closure
|
||||
let started = null;
|
||||
let expectedSize;
|
||||
let expectedChecksum;
|
||||
requestProgress(req, {
|
||||
throttle: progress.throttle
|
||||
}).on('response', response => {
|
||||
// we have computed checksum and filesize during test runner binary build
|
||||
// and have set it on the S3 object as user meta data, available via
|
||||
// these custom headers "x-amz-meta-..."
|
||||
// see https://github.com/cypress-io/cypress/pull/4092
|
||||
expectedSize = response.headers['x-amz-meta-size'] || response.headers['content-length'];
|
||||
expectedChecksum = response.headers['x-amz-meta-checksum'];
|
||||
if (expectedChecksum) {
|
||||
debug('expected checksum %s', expectedChecksum);
|
||||
}
|
||||
if (expectedSize) {
|
||||
// convert from string (all Amazon custom headers are strings)
|
||||
expectedSize = Number(expectedSize);
|
||||
debug('expected file size %d', expectedSize);
|
||||
}
|
||||
|
||||
// start counting now once we've gotten
|
||||
// response headers
|
||||
started = new Date();
|
||||
if (/^3/.test(response.statusCode)) {
|
||||
const redirectVersion = response.headers['x-version'];
|
||||
const redirectUrl = response.headers.location;
|
||||
debug('redirect version:', redirectVersion);
|
||||
debug('redirect url:', redirectUrl);
|
||||
downloadFromUrl({
|
||||
url: redirectUrl,
|
||||
progress,
|
||||
ca,
|
||||
downloadDestination,
|
||||
version: redirectVersion,
|
||||
redirectTTL: redirectTTL - 1
|
||||
}).then(resolve).catch(reject);
|
||||
|
||||
// if our status code does not start with 200
|
||||
} else if (!/^2/.test(response.statusCode)) {
|
||||
debug('response code %d', response.statusCode);
|
||||
const err = new Error(stripIndent`
|
||||
Failed downloading the Cypress binary.
|
||||
Response code: ${response.statusCode}
|
||||
Response message: ${response.statusMessage}
|
||||
`);
|
||||
reject(err);
|
||||
// status codes here are all 2xx
|
||||
} else {
|
||||
// We only enable this pipe connection when we know we've got a successful return
|
||||
// and handle the completion with verify and resolve
|
||||
// there was a possible race condition between end of request and close of writeStream
|
||||
// that is made ordered with this Promise.all
|
||||
Promise.all([new Promise(r => {
|
||||
return response.pipe(fs.createWriteStream(downloadDestination).on('close', r));
|
||||
}), new Promise(r => response.on('end', r))]).then(() => {
|
||||
debug('downloading finished');
|
||||
verifyDownloadedFile(downloadDestination, expectedSize, expectedChecksum).then(() => debug('verified')).then(() => resolve(version)).catch(reject);
|
||||
});
|
||||
}
|
||||
}).on('error', e => {
|
||||
if (e.code === 'ECONNRESET') return; // sometimes proxies give ECONNRESET but we don't care
|
||||
|
||||
reject(e);
|
||||
}).on('progress', state => {
|
||||
// total time we've elapsed
|
||||
// starting on our first progress notification
|
||||
const elapsed = new Date() - started;
|
||||
|
||||
// request-progress sends a value between 0 and 1
|
||||
const percentage = util.convertPercentToPercentage(state.percent);
|
||||
const eta = util.calculateEta(percentage, elapsed);
|
||||
|
||||
// send up our percent and seconds remaining
|
||||
progress.onProgress(percentage, util.secsRemaining(eta));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Download Cypress.zip from external versionUrl to local file.
|
||||
* @param [string] version Could be "3.3.0" or full URL
|
||||
* @param [string] downloadDestination Local filename to save as
|
||||
*/
|
||||
const start = async opts => {
|
||||
let {
|
||||
version,
|
||||
downloadDestination,
|
||||
progress,
|
||||
redirectTTL
|
||||
} = opts;
|
||||
if (!downloadDestination) {
|
||||
la(is.unemptyString(downloadDestination), 'missing download dir', opts);
|
||||
}
|
||||
if (!progress) {
|
||||
progress = {
|
||||
onProgress: () => {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
}
|
||||
const arch = await util.getRealArch();
|
||||
const versionUrl = getUrl(arch, version);
|
||||
progress.throttle = 100;
|
||||
debug('needed Cypress version: %s', version);
|
||||
debug('source url %s', versionUrl);
|
||||
debug(`downloading cypress.zip to "${downloadDestination}"`);
|
||||
|
||||
// ensure download dir exists
|
||||
return fs.ensureDirAsync(path.dirname(downloadDestination)).then(() => {
|
||||
return getCA();
|
||||
}).then(ca => {
|
||||
return downloadFromUrl({
|
||||
url: versionUrl,
|
||||
downloadDestination,
|
||||
progress,
|
||||
ca,
|
||||
version,
|
||||
...(redirectTTL ? {
|
||||
redirectTTL
|
||||
} : {})
|
||||
});
|
||||
}).catch(err => {
|
||||
return prettyDownloadErr(err, versionUrl);
|
||||
});
|
||||
};
|
||||
module.exports = {
|
||||
start,
|
||||
getUrl,
|
||||
getProxyForUrlWithNpmConfig,
|
||||
getCA
|
||||
};
|
33
CyLukTs/lukan/node_modules/cypress/lib/tasks/get-folder-size.js
generated
vendored
Normal file
33
CyLukTs/lukan/node_modules/cypress/lib/tasks/get-folder-size.js
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require('../fs');
|
||||
const {
|
||||
join
|
||||
} = require('path');
|
||||
const Bluebird = require('bluebird');
|
||||
|
||||
/**
|
||||
* Get the size of a folder or a file.
|
||||
*
|
||||
* This function returns the actual file size of the folder (size), not the allocated space on disk (size on disk).
|
||||
* For more details between the difference, check this link:
|
||||
* https://www.howtogeek.com/180369/why-is-there-a-big-difference-between-size-and-size-on-disk/
|
||||
*
|
||||
* @param {string} path path to the file or the folder.
|
||||
*/
|
||||
async function getSize(path) {
|
||||
const stat = await fs.lstat(path);
|
||||
if (stat.isDirectory()) {
|
||||
const list = await fs.readdir(path);
|
||||
return Bluebird.resolve(list).reduce(async (prev, curr) => {
|
||||
const currPath = join(path, curr);
|
||||
const s = await fs.lstat(currPath);
|
||||
if (s.isDirectory()) {
|
||||
return prev + (await getSize(currPath));
|
||||
}
|
||||
return prev + s.size;
|
||||
}, 0);
|
||||
}
|
||||
return stat.size;
|
||||
}
|
||||
module.exports = getSize;
|
360
CyLukTs/lukan/node_modules/cypress/lib/tasks/install.js
generated
vendored
Normal file
360
CyLukTs/lukan/node_modules/cypress/lib/tasks/install.js
generated
vendored
Normal file
@ -0,0 +1,360 @@
|
||||
"use strict";
|
||||
|
||||
const _ = require('lodash');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const chalk = require('chalk');
|
||||
const debug = require('debug')('cypress:cli');
|
||||
const {
|
||||
Listr
|
||||
} = require('listr2');
|
||||
const Promise = require('bluebird');
|
||||
const logSymbols = require('log-symbols');
|
||||
const {
|
||||
stripIndent
|
||||
} = require('common-tags');
|
||||
const fs = require('../fs');
|
||||
const download = require('./download');
|
||||
const util = require('../util');
|
||||
const state = require('./state');
|
||||
const unzip = require('./unzip');
|
||||
const logger = require('../logger');
|
||||
const {
|
||||
throwFormErrorText,
|
||||
errors
|
||||
} = require('../errors');
|
||||
const verbose = require('../VerboseRenderer');
|
||||
const {
|
||||
buildInfo,
|
||||
version
|
||||
} = require('../../package.json');
|
||||
function _getBinaryUrlFromBuildInfo(arch, {
|
||||
commitSha,
|
||||
commitBranch
|
||||
}) {
|
||||
return `https://cdn.cypress.io/beta/binary/${version}/${os.platform()}-${arch}/${commitBranch}-${commitSha}/cypress.zip`;
|
||||
}
|
||||
const alreadyInstalledMsg = () => {
|
||||
if (!util.isPostInstall()) {
|
||||
logger.log(stripIndent`
|
||||
Skipping installation:
|
||||
|
||||
Pass the ${chalk.yellow('--force')} option if you'd like to reinstall anyway.
|
||||
`);
|
||||
}
|
||||
};
|
||||
const displayCompletionMsg = () => {
|
||||
// check here to see if we are globally installed
|
||||
if (util.isInstalledGlobally()) {
|
||||
// if we are display a warning
|
||||
logger.log();
|
||||
logger.warn(stripIndent`
|
||||
${logSymbols.warning} Warning: It looks like you\'ve installed Cypress globally.
|
||||
|
||||
This will work, but it'\s not recommended.
|
||||
|
||||
The recommended way to install Cypress is as a devDependency per project.
|
||||
|
||||
You should probably run these commands:
|
||||
|
||||
- ${chalk.cyan('npm uninstall -g cypress')}
|
||||
- ${chalk.cyan('npm install --save-dev cypress')}
|
||||
`);
|
||||
return;
|
||||
}
|
||||
logger.log();
|
||||
logger.log('You can now open Cypress by running:', chalk.cyan(path.join('node_modules', '.bin', 'cypress'), 'open'));
|
||||
logger.log();
|
||||
logger.log(chalk.grey('https://on.cypress.io/installing-cypress'));
|
||||
logger.log();
|
||||
};
|
||||
const downloadAndUnzip = ({
|
||||
version,
|
||||
installDir,
|
||||
downloadDir
|
||||
}) => {
|
||||
const progress = {
|
||||
throttle: 100,
|
||||
onProgress: null
|
||||
};
|
||||
const downloadDestination = path.join(downloadDir, `cypress-${process.pid}.zip`);
|
||||
const rendererOptions = getRendererOptions();
|
||||
|
||||
// let the user know what version of cypress we're downloading!
|
||||
logger.log(`Installing Cypress ${chalk.gray(`(version: ${version})`)}`);
|
||||
logger.log();
|
||||
const tasks = new Listr([{
|
||||
options: {
|
||||
title: util.titleize('Downloading Cypress')
|
||||
},
|
||||
task: (ctx, task) => {
|
||||
// as our download progresses indicate the status
|
||||
progress.onProgress = progessify(task, 'Downloading Cypress');
|
||||
return download.start({
|
||||
version,
|
||||
downloadDestination,
|
||||
progress
|
||||
}).then(redirectVersion => {
|
||||
if (redirectVersion) version = redirectVersion;
|
||||
debug(`finished downloading file: ${downloadDestination}`);
|
||||
}).then(() => {
|
||||
// save the download destination for unzipping
|
||||
util.setTaskTitle(task, util.titleize(chalk.green('Downloaded Cypress')), rendererOptions.renderer);
|
||||
});
|
||||
}
|
||||
}, unzipTask({
|
||||
progress,
|
||||
zipFilePath: downloadDestination,
|
||||
installDir,
|
||||
rendererOptions
|
||||
}), {
|
||||
options: {
|
||||
title: util.titleize('Finishing Installation')
|
||||
},
|
||||
task: (ctx, task) => {
|
||||
const cleanup = () => {
|
||||
debug('removing zip file %s', downloadDestination);
|
||||
return fs.removeAsync(downloadDestination);
|
||||
};
|
||||
return cleanup().then(() => {
|
||||
debug('finished installation in', installDir);
|
||||
util.setTaskTitle(task, util.titleize(chalk.green('Finished Installation'), chalk.gray(installDir)), rendererOptions.renderer);
|
||||
});
|
||||
}
|
||||
}], {
|
||||
rendererOptions
|
||||
});
|
||||
|
||||
// start the tasks!
|
||||
return Promise.resolve(tasks.run());
|
||||
};
|
||||
const validateOS = () => {
|
||||
return util.getPlatformInfo().then(platformInfo => {
|
||||
return platformInfo.match(/(win32-x64|linux-x64|linux-arm64|darwin-x64|darwin-arm64)/);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the version to install - either a string like `1.2.3` to be fetched
|
||||
* from the download server or a file path or HTTP URL.
|
||||
*/
|
||||
function getVersionOverride({
|
||||
arch,
|
||||
envVarVersion,
|
||||
buildInfo
|
||||
}) {
|
||||
// let this environment variable reset the binary version we need
|
||||
if (envVarVersion) {
|
||||
return envVarVersion;
|
||||
}
|
||||
if (buildInfo && !buildInfo.stable) {
|
||||
logger.log(chalk.yellow(stripIndent`
|
||||
${logSymbols.warning} Warning: You are installing a pre-release build of Cypress.
|
||||
|
||||
Bugs may be present which do not exist in production builds.
|
||||
|
||||
This build was created from:
|
||||
* Commit SHA: ${buildInfo.commitSha}
|
||||
* Commit Branch: ${buildInfo.commitBranch}
|
||||
* Commit Timestamp: ${buildInfo.commitDate}
|
||||
`));
|
||||
logger.log();
|
||||
return _getBinaryUrlFromBuildInfo(arch, buildInfo);
|
||||
}
|
||||
}
|
||||
function getEnvVarVersion() {
|
||||
if (!util.getEnv('CYPRESS_INSTALL_BINARY')) return;
|
||||
|
||||
// because passed file paths are often double quoted
|
||||
// and might have extra whitespace around, be robust and trim the string
|
||||
const trimAndRemoveDoubleQuotes = true;
|
||||
const envVarVersion = util.getEnv('CYPRESS_INSTALL_BINARY', trimAndRemoveDoubleQuotes);
|
||||
debug('using environment variable CYPRESS_INSTALL_BINARY "%s"', envVarVersion);
|
||||
return envVarVersion;
|
||||
}
|
||||
const start = async (options = {}) => {
|
||||
debug('installing with options %j', options);
|
||||
const envVarVersion = getEnvVarVersion();
|
||||
if (envVarVersion === '0') {
|
||||
debug('environment variable CYPRESS_INSTALL_BINARY = 0, skipping install');
|
||||
logger.log(stripIndent`
|
||||
${chalk.yellow('Note:')} Skipping binary installation: Environment variable CYPRESS_INSTALL_BINARY = 0.`);
|
||||
logger.log();
|
||||
return;
|
||||
}
|
||||
_.defaults(options, {
|
||||
force: false,
|
||||
buildInfo
|
||||
});
|
||||
if (util.getEnv('CYPRESS_CACHE_FOLDER')) {
|
||||
const envCache = util.getEnv('CYPRESS_CACHE_FOLDER');
|
||||
logger.log(stripIndent`
|
||||
${chalk.yellow('Note:')} Overriding Cypress cache directory to: ${chalk.cyan(envCache)}
|
||||
|
||||
Previous installs of Cypress may not be found.
|
||||
`);
|
||||
logger.log();
|
||||
}
|
||||
const pkgVersion = util.pkgVersion();
|
||||
const arch = await util.getRealArch();
|
||||
const versionOverride = getVersionOverride({
|
||||
arch,
|
||||
envVarVersion,
|
||||
buildInfo: options.buildInfo
|
||||
});
|
||||
const versionToInstall = versionOverride || pkgVersion;
|
||||
debug('version in package.json is %s, version to install is %s', pkgVersion, versionToInstall);
|
||||
const installDir = state.getVersionDir(pkgVersion, options.buildInfo);
|
||||
const cacheDir = state.getCacheDir();
|
||||
const binaryDir = state.getBinaryDir(pkgVersion);
|
||||
if (!(await validateOS())) {
|
||||
return throwFormErrorText(errors.invalidOS)();
|
||||
}
|
||||
await fs.ensureDirAsync(cacheDir).catch({
|
||||
code: 'EACCES'
|
||||
}, err => {
|
||||
return throwFormErrorText(errors.invalidCacheDirectory)(stripIndent`
|
||||
Failed to access ${chalk.cyan(cacheDir)}:
|
||||
|
||||
${err.message}
|
||||
`);
|
||||
});
|
||||
const binaryPkg = await state.getBinaryPkgAsync(binaryDir);
|
||||
const binaryVersion = await state.getBinaryPkgVersion(binaryPkg);
|
||||
const shouldInstall = () => {
|
||||
if (!binaryVersion) {
|
||||
debug('no binary installed under cli version');
|
||||
return true;
|
||||
}
|
||||
logger.log();
|
||||
logger.log(stripIndent`
|
||||
Cypress ${chalk.green(binaryVersion)} is installed in ${chalk.cyan(installDir)}
|
||||
`);
|
||||
logger.log();
|
||||
if (options.force) {
|
||||
debug('performing force install over existing binary');
|
||||
return true;
|
||||
}
|
||||
if (binaryVersion === versionToInstall || !util.isSemver(versionToInstall)) {
|
||||
// our version matches, tell the user this is a noop
|
||||
alreadyInstalledMsg();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// noop if we've been told not to download
|
||||
if (!shouldInstall()) {
|
||||
return debug('Not downloading or installing binary');
|
||||
}
|
||||
if (envVarVersion) {
|
||||
logger.log(chalk.yellow(stripIndent`
|
||||
${logSymbols.warning} Warning: Forcing a binary version different than the default.
|
||||
|
||||
The CLI expected to install version: ${chalk.green(pkgVersion)}
|
||||
|
||||
Instead we will install version: ${chalk.green(versionToInstall)}
|
||||
|
||||
These versions may not work properly together.
|
||||
`));
|
||||
logger.log();
|
||||
}
|
||||
const getLocalFilePath = async () => {
|
||||
// see if version supplied is a path to a binary
|
||||
if (await fs.pathExistsAsync(versionToInstall)) {
|
||||
return path.extname(versionToInstall) === '.zip' ? versionToInstall : false;
|
||||
}
|
||||
const possibleFile = util.formAbsolutePath(versionToInstall);
|
||||
debug('checking local file', possibleFile, 'cwd', process.cwd());
|
||||
|
||||
// if this exists return the path to it
|
||||
// else false
|
||||
if ((await fs.pathExistsAsync(possibleFile)) && path.extname(possibleFile) === '.zip') {
|
||||
return possibleFile;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const pathToLocalFile = await getLocalFilePath();
|
||||
if (pathToLocalFile) {
|
||||
const absolutePath = path.resolve(versionToInstall);
|
||||
debug('found local file at', absolutePath);
|
||||
debug('skipping download');
|
||||
const rendererOptions = getRendererOptions();
|
||||
return new Listr([unzipTask({
|
||||
progress: {
|
||||
throttle: 100,
|
||||
onProgress: null
|
||||
},
|
||||
zipFilePath: absolutePath,
|
||||
installDir,
|
||||
rendererOptions
|
||||
})], {
|
||||
rendererOptions
|
||||
}).run();
|
||||
}
|
||||
if (options.force) {
|
||||
debug('Cypress already installed at', installDir);
|
||||
debug('but the installation was forced');
|
||||
}
|
||||
debug('preparing to download and unzip version ', versionToInstall, 'to path', installDir);
|
||||
const downloadDir = os.tmpdir();
|
||||
await downloadAndUnzip({
|
||||
version: versionToInstall,
|
||||
installDir,
|
||||
downloadDir
|
||||
});
|
||||
|
||||
// delay 1 sec for UX, unless we are testing
|
||||
await Promise.delay(1000);
|
||||
displayCompletionMsg();
|
||||
};
|
||||
module.exports = {
|
||||
start,
|
||||
_getBinaryUrlFromBuildInfo
|
||||
};
|
||||
const unzipTask = ({
|
||||
zipFilePath,
|
||||
installDir,
|
||||
progress,
|
||||
rendererOptions
|
||||
}) => {
|
||||
return {
|
||||
options: {
|
||||
title: util.titleize('Unzipping Cypress')
|
||||
},
|
||||
task: (ctx, task) => {
|
||||
// as our unzip progresses indicate the status
|
||||
progress.onProgress = progessify(task, 'Unzipping Cypress');
|
||||
return unzip.start({
|
||||
zipFilePath,
|
||||
installDir,
|
||||
progress
|
||||
}).then(() => {
|
||||
util.setTaskTitle(task, util.titleize(chalk.green('Unzipped Cypress')), rendererOptions.renderer);
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
const progessify = (task, title) => {
|
||||
// return higher order function
|
||||
return (percentComplete, remaining) => {
|
||||
percentComplete = chalk.white(` ${percentComplete}%`);
|
||||
|
||||
// pluralize seconds remaining
|
||||
remaining = chalk.gray(`${remaining}s`);
|
||||
util.setTaskTitle(task, util.titleize(title, percentComplete, remaining), getRendererOptions().renderer);
|
||||
};
|
||||
};
|
||||
|
||||
// if we are running in CI then use
|
||||
// the verbose renderer else use
|
||||
// the default
|
||||
const getRendererOptions = () => {
|
||||
let renderer = util.isCi() ? verbose : 'default';
|
||||
if (logger.logLevel() === 'silent') {
|
||||
renderer = 'silent';
|
||||
}
|
||||
return {
|
||||
renderer
|
||||
};
|
||||
};
|
185
CyLukTs/lukan/node_modules/cypress/lib/tasks/state.js
generated
vendored
Normal file
185
CyLukTs/lukan/node_modules/cypress/lib/tasks/state.js
generated
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
"use strict";
|
||||
|
||||
const _ = require('lodash');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const untildify = require('untildify');
|
||||
const debug = require('debug')('cypress:cli');
|
||||
const fs = require('../fs');
|
||||
const util = require('../util');
|
||||
const getPlatformExecutable = () => {
|
||||
const platform = os.platform();
|
||||
switch (platform) {
|
||||
case 'darwin':
|
||||
return 'Contents/MacOS/Cypress';
|
||||
case 'linux':
|
||||
return 'Cypress';
|
||||
case 'win32':
|
||||
return 'Cypress.exe';
|
||||
// TODO handle this error using our standard
|
||||
default:
|
||||
throw new Error(`Platform: "${platform}" is not supported.`);
|
||||
}
|
||||
};
|
||||
const getPlatFormBinaryFolder = () => {
|
||||
const platform = os.platform();
|
||||
switch (platform) {
|
||||
case 'darwin':
|
||||
return 'Cypress.app';
|
||||
case 'linux':
|
||||
return 'Cypress';
|
||||
case 'win32':
|
||||
return 'Cypress';
|
||||
// TODO handle this error using our standard
|
||||
default:
|
||||
throw new Error(`Platform: "${platform}" is not supported.`);
|
||||
}
|
||||
};
|
||||
const getBinaryPkgPath = binaryDir => {
|
||||
const platform = os.platform();
|
||||
switch (platform) {
|
||||
case 'darwin':
|
||||
return path.join(binaryDir, 'Contents', 'Resources', 'app', 'package.json');
|
||||
case 'linux':
|
||||
return path.join(binaryDir, 'resources', 'app', 'package.json');
|
||||
case 'win32':
|
||||
return path.join(binaryDir, 'resources', 'app', 'package.json');
|
||||
// TODO handle this error using our standard
|
||||
default:
|
||||
throw new Error(`Platform: "${platform}" is not supported.`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get path to binary directory
|
||||
*/
|
||||
const getBinaryDir = (version = util.pkgVersion()) => {
|
||||
return path.join(getVersionDir(version), getPlatFormBinaryFolder());
|
||||
};
|
||||
const getVersionDir = (version = util.pkgVersion(), buildInfo = util.pkgBuildInfo()) => {
|
||||
if (buildInfo && !buildInfo.stable) {
|
||||
version = ['beta', version, buildInfo.commitBranch, buildInfo.commitSha.slice(0, 8)].join('-');
|
||||
}
|
||||
return path.join(getCacheDir(), version);
|
||||
};
|
||||
|
||||
/**
|
||||
* When executing "npm postinstall" hook, the working directory is set to
|
||||
* "<current folder>/node_modules/cypress", which can be surprising when using relative paths.
|
||||
*/
|
||||
const isInstallingFromPostinstallHook = () => {
|
||||
// individual folders
|
||||
const cwdFolders = process.cwd().split(path.sep);
|
||||
const length = cwdFolders.length;
|
||||
return cwdFolders[length - 2] === 'node_modules' && cwdFolders[length - 1] === 'cypress';
|
||||
};
|
||||
const getCacheDir = () => {
|
||||
let cache_directory = util.getCacheDir();
|
||||
if (util.getEnv('CYPRESS_CACHE_FOLDER')) {
|
||||
const envVarCacheDir = untildify(util.getEnv('CYPRESS_CACHE_FOLDER'));
|
||||
debug('using environment variable CYPRESS_CACHE_FOLDER %s', envVarCacheDir);
|
||||
if (!path.isAbsolute(envVarCacheDir) && isInstallingFromPostinstallHook()) {
|
||||
const packageRootFolder = path.join('..', '..', envVarCacheDir);
|
||||
cache_directory = path.resolve(packageRootFolder);
|
||||
debug('installing from postinstall hook, original root folder is %s', packageRootFolder);
|
||||
debug('and resolved cache directory is %s', cache_directory);
|
||||
} else {
|
||||
cache_directory = path.resolve(envVarCacheDir);
|
||||
}
|
||||
}
|
||||
return cache_directory;
|
||||
};
|
||||
const parseRealPlatformBinaryFolderAsync = binaryPath => {
|
||||
return fs.realpathAsync(binaryPath).then(realPath => {
|
||||
debug('CYPRESS_RUN_BINARY has realpath:', realPath);
|
||||
if (!realPath.toString().endsWith(getPlatformExecutable())) {
|
||||
return false;
|
||||
}
|
||||
if (os.platform() === 'darwin') {
|
||||
return path.resolve(realPath, '..', '..', '..');
|
||||
}
|
||||
return path.resolve(realPath, '..');
|
||||
});
|
||||
};
|
||||
const getDistDir = () => {
|
||||
return path.join(__dirname, '..', '..', 'dist');
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns full filename to the file that keeps the Test Runner verification state as JSON text.
|
||||
* Note: the binary state file will be stored one level up from the given binary folder.
|
||||
* @param {string} binaryDir - full path to the folder holding the binary.
|
||||
*/
|
||||
const getBinaryStatePath = binaryDir => {
|
||||
return path.join(binaryDir, '..', 'binary_state.json');
|
||||
};
|
||||
const getBinaryStateContentsAsync = binaryDir => {
|
||||
const fullPath = getBinaryStatePath(binaryDir);
|
||||
return fs.readJsonAsync(fullPath).catch({
|
||||
code: 'ENOENT'
|
||||
}, SyntaxError, () => {
|
||||
debug('could not read binary_state.json file at "%s"', fullPath);
|
||||
return {};
|
||||
});
|
||||
};
|
||||
const getBinaryVerifiedAsync = binaryDir => {
|
||||
return getBinaryStateContentsAsync(binaryDir).tap(debug).get('verified');
|
||||
};
|
||||
const clearBinaryStateAsync = binaryDir => {
|
||||
return fs.removeAsync(getBinaryStatePath(binaryDir));
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes the new binary status.
|
||||
* @param {boolean} verified The new test runner state after smoke test
|
||||
* @param {string} binaryDir Folder holding the binary
|
||||
* @returns {Promise<void>} returns a promise
|
||||
*/
|
||||
const writeBinaryVerifiedAsync = (verified, binaryDir) => {
|
||||
return getBinaryStateContentsAsync(binaryDir).then(contents => {
|
||||
return fs.outputJsonAsync(getBinaryStatePath(binaryDir), _.extend(contents, {
|
||||
verified
|
||||
}), {
|
||||
spaces: 2
|
||||
});
|
||||
});
|
||||
};
|
||||
const getPathToExecutable = binaryDir => {
|
||||
return path.join(binaryDir, getPlatformExecutable());
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolves with an object read from the binary app package.json file.
|
||||
* If the file does not exist resolves with null
|
||||
*/
|
||||
const getBinaryPkgAsync = binaryDir => {
|
||||
const pathToPackageJson = getBinaryPkgPath(binaryDir);
|
||||
debug('Reading binary package.json from:', pathToPackageJson);
|
||||
return fs.pathExistsAsync(pathToPackageJson).then(exists => {
|
||||
if (!exists) {
|
||||
return null;
|
||||
}
|
||||
return fs.readJsonAsync(pathToPackageJson);
|
||||
});
|
||||
};
|
||||
const getBinaryPkgVersion = o => _.get(o, 'version', null);
|
||||
const getBinaryElectronVersion = o => _.get(o, 'electronVersion', null);
|
||||
const getBinaryElectronNodeVersion = o => _.get(o, 'electronNodeVersion', null);
|
||||
module.exports = {
|
||||
getPathToExecutable,
|
||||
getPlatformExecutable,
|
||||
// those names start to sound like Java
|
||||
getBinaryElectronNodeVersion,
|
||||
getBinaryElectronVersion,
|
||||
getBinaryPkgVersion,
|
||||
getBinaryVerifiedAsync,
|
||||
getBinaryPkgAsync,
|
||||
getBinaryPkgPath,
|
||||
getBinaryDir,
|
||||
getCacheDir,
|
||||
clearBinaryStateAsync,
|
||||
writeBinaryVerifiedAsync,
|
||||
parseRealPlatformBinaryFolderAsync,
|
||||
getDistDir,
|
||||
getVersionDir
|
||||
};
|
201
CyLukTs/lukan/node_modules/cypress/lib/tasks/unzip.js
generated
vendored
Normal file
201
CyLukTs/lukan/node_modules/cypress/lib/tasks/unzip.js
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
"use strict";
|
||||
|
||||
const _ = require('lodash');
|
||||
const la = require('lazy-ass');
|
||||
const is = require('check-more-types');
|
||||
const cp = require('child_process');
|
||||
const os = require('os');
|
||||
const yauzl = require('yauzl');
|
||||
const debug = require('debug')('cypress:cli:unzip');
|
||||
const extract = require('extract-zip');
|
||||
const Promise = require('bluebird');
|
||||
const readline = require('readline');
|
||||
const {
|
||||
throwFormErrorText,
|
||||
errors
|
||||
} = require('../errors');
|
||||
const fs = require('../fs');
|
||||
const util = require('../util');
|
||||
const unzipTools = {
|
||||
extract
|
||||
};
|
||||
|
||||
// expose this function for simple testing
|
||||
const unzip = ({
|
||||
zipFilePath,
|
||||
installDir,
|
||||
progress
|
||||
}) => {
|
||||
debug('unzipping from %s', zipFilePath);
|
||||
debug('into', installDir);
|
||||
if (!zipFilePath) {
|
||||
throw new Error('Missing zip filename');
|
||||
}
|
||||
const startTime = Date.now();
|
||||
let yauzlDoneTime = 0;
|
||||
return fs.ensureDirAsync(installDir).then(() => {
|
||||
return new Promise((resolve, reject) => {
|
||||
return yauzl.open(zipFilePath, (err, zipFile) => {
|
||||
yauzlDoneTime = Date.now();
|
||||
if (err) {
|
||||
debug('error using yauzl %s', err.message);
|
||||
return reject(err);
|
||||
}
|
||||
const total = zipFile.entryCount;
|
||||
debug('zipFile entries count', total);
|
||||
const started = new Date();
|
||||
let percent = 0;
|
||||
let count = 0;
|
||||
const notify = percent => {
|
||||
const elapsed = +new Date() - +started;
|
||||
const eta = util.calculateEta(percent, elapsed);
|
||||
progress.onProgress(percent, util.secsRemaining(eta));
|
||||
};
|
||||
const tick = () => {
|
||||
count += 1;
|
||||
percent = count / total * 100;
|
||||
const displayPercent = percent.toFixed(0);
|
||||
return notify(displayPercent);
|
||||
};
|
||||
const unzipWithNode = () => {
|
||||
debug('unzipping with node.js (slow)');
|
||||
const opts = {
|
||||
dir: installDir,
|
||||
onEntry: tick
|
||||
};
|
||||
debug('calling Node extract tool %s %o', zipFilePath, opts);
|
||||
return unzipTools.extract(zipFilePath, opts).then(() => {
|
||||
debug('node unzip finished');
|
||||
return resolve();
|
||||
}).catch(err => {
|
||||
if (err) {
|
||||
debug('error %s', err.message);
|
||||
return reject(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
const unzipFallback = _.once(unzipWithNode);
|
||||
const unzipWithUnzipTool = () => {
|
||||
debug('unzipping via `unzip`');
|
||||
const inflatingRe = /inflating:/;
|
||||
const sp = cp.spawn('unzip', ['-o', zipFilePath, '-d', installDir]);
|
||||
sp.on('error', err => {
|
||||
debug('unzip tool error: %s', err.message);
|
||||
unzipFallback();
|
||||
});
|
||||
sp.on('close', code => {
|
||||
debug('unzip tool close with code %d', code);
|
||||
if (code === 0) {
|
||||
percent = 100;
|
||||
notify(percent);
|
||||
return resolve();
|
||||
}
|
||||
debug('`unzip` failed %o', {
|
||||
code
|
||||
});
|
||||
return unzipFallback();
|
||||
});
|
||||
sp.stdout.on('data', data => {
|
||||
if (inflatingRe.test(data)) {
|
||||
return tick();
|
||||
}
|
||||
});
|
||||
sp.stderr.on('data', data => {
|
||||
debug('`unzip` stderr %s', data);
|
||||
});
|
||||
};
|
||||
|
||||
// we attempt to first unzip with the native osx
|
||||
// ditto because its less likely to have problems
|
||||
// with corruption, symlinks, or icons causing failures
|
||||
// and can handle resource forks
|
||||
// http://automatica.com.au/2011/02/unzip-mac-os-x-zip-in-terminal/
|
||||
const unzipWithOsx = () => {
|
||||
debug('unzipping via `ditto`');
|
||||
const copyingFileRe = /^copying file/;
|
||||
const sp = cp.spawn('ditto', ['-xkV', zipFilePath, installDir]);
|
||||
|
||||
// f-it just unzip with node
|
||||
sp.on('error', err => {
|
||||
debug(err.message);
|
||||
unzipFallback();
|
||||
});
|
||||
sp.on('close', code => {
|
||||
if (code === 0) {
|
||||
// make sure we get to 100% on the progress bar
|
||||
// because reading in lines is not really accurate
|
||||
percent = 100;
|
||||
notify(percent);
|
||||
return resolve();
|
||||
}
|
||||
debug('`ditto` failed %o', {
|
||||
code
|
||||
});
|
||||
return unzipFallback();
|
||||
});
|
||||
return readline.createInterface({
|
||||
input: sp.stderr
|
||||
}).on('line', line => {
|
||||
if (copyingFileRe.test(line)) {
|
||||
return tick();
|
||||
}
|
||||
});
|
||||
};
|
||||
switch (os.platform()) {
|
||||
case 'darwin':
|
||||
return unzipWithOsx();
|
||||
case 'linux':
|
||||
return unzipWithUnzipTool();
|
||||
case 'win32':
|
||||
return unzipWithNode();
|
||||
default:
|
||||
return;
|
||||
}
|
||||
});
|
||||
}).tap(() => {
|
||||
debug('unzip completed %o', {
|
||||
yauzlMs: yauzlDoneTime - startTime,
|
||||
unzipMs: Date.now() - yauzlDoneTime
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
function isMaybeWindowsMaxPathLengthError(err) {
|
||||
return os.platform() === 'win32' && err.code === 'ENOENT' && err.syscall === 'realpath';
|
||||
}
|
||||
const start = async ({
|
||||
zipFilePath,
|
||||
installDir,
|
||||
progress
|
||||
}) => {
|
||||
la(is.unemptyString(installDir), 'missing installDir');
|
||||
if (!progress) {
|
||||
progress = {
|
||||
onProgress: () => {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
}
|
||||
try {
|
||||
const installDirExists = await fs.pathExists(installDir);
|
||||
if (installDirExists) {
|
||||
debug('removing existing unzipped binary', installDir);
|
||||
await fs.removeAsync(installDir);
|
||||
}
|
||||
await unzip({
|
||||
zipFilePath,
|
||||
installDir,
|
||||
progress
|
||||
});
|
||||
} catch (err) {
|
||||
const errorTemplate = isMaybeWindowsMaxPathLengthError(err) ? errors.failedUnzipWindowsMaxPathLength : errors.failedUnzip;
|
||||
await throwFormErrorText(errorTemplate)(err);
|
||||
}
|
||||
};
|
||||
module.exports = {
|
||||
start,
|
||||
utils: {
|
||||
unzip,
|
||||
unzipTools
|
||||
}
|
||||
};
|
295
CyLukTs/lukan/node_modules/cypress/lib/tasks/verify.js
generated
vendored
Normal file
295
CyLukTs/lukan/node_modules/cypress/lib/tasks/verify.js
generated
vendored
Normal file
@ -0,0 +1,295 @@
|
||||
"use strict";
|
||||
|
||||
const _ = require('lodash');
|
||||
const chalk = require('chalk');
|
||||
const {
|
||||
Listr
|
||||
} = require('listr2');
|
||||
const debug = require('debug')('cypress:cli');
|
||||
const {
|
||||
stripIndent
|
||||
} = require('common-tags');
|
||||
const Promise = require('bluebird');
|
||||
const logSymbols = require('log-symbols');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const verbose = require('../VerboseRenderer');
|
||||
const {
|
||||
throwFormErrorText,
|
||||
errors
|
||||
} = require('../errors');
|
||||
const util = require('../util');
|
||||
const logger = require('../logger');
|
||||
const xvfb = require('../exec/xvfb');
|
||||
const state = require('./state');
|
||||
const VERIFY_TEST_RUNNER_TIMEOUT_MS = +util.getEnv('CYPRESS_VERIFY_TIMEOUT') || 30000;
|
||||
const checkExecutable = binaryDir => {
|
||||
const executable = state.getPathToExecutable(binaryDir);
|
||||
debug('checking if executable exists', executable);
|
||||
return util.isExecutableAsync(executable).then(isExecutable => {
|
||||
debug('Binary is executable? :', isExecutable);
|
||||
if (!isExecutable) {
|
||||
return throwFormErrorText(errors.binaryNotExecutable(executable))();
|
||||
}
|
||||
}).catch({
|
||||
code: 'ENOENT'
|
||||
}, () => {
|
||||
if (util.isCi()) {
|
||||
return throwFormErrorText(errors.notInstalledCI(executable))();
|
||||
}
|
||||
return throwFormErrorText(errors.missingApp(binaryDir))(stripIndent`
|
||||
Cypress executable not found at: ${chalk.cyan(executable)}
|
||||
`);
|
||||
});
|
||||
};
|
||||
const runSmokeTest = (binaryDir, options) => {
|
||||
let executable = state.getPathToExecutable(binaryDir);
|
||||
const onSmokeTestError = (smokeTestCommand, linuxWithDisplayEnv) => {
|
||||
return err => {
|
||||
debug('Smoke test failed:', err);
|
||||
let errMessage = err.stderr || err.message;
|
||||
debug('error message:', errMessage);
|
||||
if (err.timedOut) {
|
||||
debug('error timedOut is true');
|
||||
return throwFormErrorText(errors.smokeTestFailure(smokeTestCommand, true))(errMessage);
|
||||
}
|
||||
if (linuxWithDisplayEnv && util.isBrokenGtkDisplay(errMessage)) {
|
||||
util.logBrokenGtkDisplayWarning();
|
||||
return throwFormErrorText(errors.invalidSmokeTestDisplayError)(errMessage);
|
||||
}
|
||||
return throwFormErrorText(errors.missingDependency)(errMessage);
|
||||
};
|
||||
};
|
||||
const needsXvfb = xvfb.isNeeded();
|
||||
debug('needs Xvfb?', needsXvfb);
|
||||
|
||||
/**
|
||||
* Spawn Cypress running smoke test to check if all operating system
|
||||
* dependencies are good.
|
||||
*/
|
||||
const spawn = linuxWithDisplayEnv => {
|
||||
const random = _.random(0, 1000);
|
||||
const args = ['--smoke-test', `--ping=${random}`];
|
||||
if (needsSandbox()) {
|
||||
// electron requires --no-sandbox to run as root
|
||||
debug('disabling Electron sandbox');
|
||||
args.unshift('--no-sandbox');
|
||||
}
|
||||
if (options.dev) {
|
||||
executable = 'node';
|
||||
args.unshift(path.resolve(__dirname, '..', '..', '..', 'scripts', 'start.js'));
|
||||
}
|
||||
const smokeTestCommand = `${executable} ${args.join(' ')}`;
|
||||
debug('running smoke test');
|
||||
debug('using Cypress executable %s', executable);
|
||||
debug('smoke test command:', smokeTestCommand);
|
||||
debug('smoke test timeout %d ms', options.smokeTestTimeout);
|
||||
const env = _.extend({}, process.env, {
|
||||
ELECTRON_ENABLE_LOGGING: true
|
||||
});
|
||||
const stdioOptions = _.extend({}, {
|
||||
env,
|
||||
timeout: options.smokeTestTimeout
|
||||
});
|
||||
return Promise.resolve(util.exec(executable, args, stdioOptions)).catch(onSmokeTestError(smokeTestCommand, linuxWithDisplayEnv)).then(result => {
|
||||
// TODO: when execa > 1.1 is released
|
||||
// change this to `result.all` for both stderr and stdout
|
||||
// use lodash to be robust during tests against null result or missing stdout
|
||||
const smokeTestStdout = _.get(result, 'stdout', '');
|
||||
debug('smoke test stdout "%s"', smokeTestStdout);
|
||||
if (!util.stdoutLineMatches(String(random), smokeTestStdout)) {
|
||||
debug('Smoke test failed because could not find %d in:', random, result);
|
||||
const smokeTestStderr = _.get(result, 'stderr', '');
|
||||
const errorText = smokeTestStderr || smokeTestStdout;
|
||||
return throwFormErrorText(errors.smokeTestFailure(smokeTestCommand, false))(errorText);
|
||||
}
|
||||
});
|
||||
};
|
||||
const spawnInXvfb = linuxWithDisplayEnv => {
|
||||
return xvfb.start().then(() => {
|
||||
return spawn(linuxWithDisplayEnv);
|
||||
}).finally(xvfb.stop);
|
||||
};
|
||||
const userFriendlySpawn = linuxWithDisplayEnv => {
|
||||
debug('spawning, should retry on display problem?', Boolean(linuxWithDisplayEnv));
|
||||
return spawn(linuxWithDisplayEnv).catch({
|
||||
code: 'INVALID_SMOKE_TEST_DISPLAY_ERROR'
|
||||
}, () => {
|
||||
return spawnInXvfb(linuxWithDisplayEnv);
|
||||
});
|
||||
};
|
||||
if (needsXvfb) {
|
||||
return spawnInXvfb();
|
||||
}
|
||||
|
||||
// if we are on linux and there's already a DISPLAY
|
||||
// set, then we may need to rerun cypress after
|
||||
// spawning our own Xvfb server
|
||||
const linuxWithDisplayEnv = util.isPossibleLinuxWithIncorrectDisplay();
|
||||
return userFriendlySpawn(linuxWithDisplayEnv);
|
||||
};
|
||||
function testBinary(version, binaryDir, options) {
|
||||
debug('running binary verification check', version);
|
||||
|
||||
// if running from 'cypress verify', don't print this message
|
||||
if (!options.force) {
|
||||
logger.log(stripIndent`
|
||||
It looks like this is your first time using Cypress: ${chalk.cyan(version)}
|
||||
`);
|
||||
}
|
||||
logger.log();
|
||||
|
||||
// if we are running in CI then use
|
||||
// the verbose renderer else use
|
||||
// the default
|
||||
let renderer = util.isCi() ? verbose : 'default';
|
||||
if (logger.logLevel() === 'silent') renderer = 'silent';
|
||||
const rendererOptions = {
|
||||
renderer
|
||||
};
|
||||
const tasks = new Listr([{
|
||||
options: {
|
||||
title: util.titleize('Verifying Cypress can run', chalk.gray(binaryDir))
|
||||
},
|
||||
task: (ctx, task) => {
|
||||
debug('clearing out the verified version');
|
||||
return state.clearBinaryStateAsync(binaryDir).then(() => {
|
||||
return Promise.all([runSmokeTest(binaryDir, options), Promise.resolve().delay(1500) // good user experience
|
||||
]);
|
||||
}).then(() => {
|
||||
debug('write verified: true');
|
||||
return state.writeBinaryVerifiedAsync(true, binaryDir);
|
||||
}).then(() => {
|
||||
util.setTaskTitle(task, util.titleize(chalk.green('Verified Cypress!'), chalk.gray(binaryDir)), rendererOptions.renderer);
|
||||
});
|
||||
}
|
||||
}], {
|
||||
rendererOptions
|
||||
});
|
||||
return tasks.run();
|
||||
}
|
||||
const maybeVerify = (installedVersion, binaryDir, options) => {
|
||||
return state.getBinaryVerifiedAsync(binaryDir).then(isVerified => {
|
||||
debug('is Verified ?', isVerified);
|
||||
let shouldVerify = !isVerified;
|
||||
|
||||
// force verify if options.force
|
||||
if (options.force) {
|
||||
debug('force verify');
|
||||
shouldVerify = true;
|
||||
}
|
||||
if (shouldVerify) {
|
||||
return testBinary(installedVersion, binaryDir, options).then(() => {
|
||||
if (options.welcomeMessage) {
|
||||
logger.log();
|
||||
logger.log('Opening Cypress...');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
const start = (options = {}) => {
|
||||
debug('verifying Cypress app');
|
||||
const packageVersion = util.pkgVersion();
|
||||
let binaryDir = state.getBinaryDir(packageVersion);
|
||||
_.defaults(options, {
|
||||
dev: false,
|
||||
force: false,
|
||||
welcomeMessage: true,
|
||||
smokeTestTimeout: VERIFY_TEST_RUNNER_TIMEOUT_MS
|
||||
});
|
||||
if (options.dev) {
|
||||
return runSmokeTest('', options);
|
||||
}
|
||||
const parseBinaryEnvVar = () => {
|
||||
const envBinaryPath = util.getEnv('CYPRESS_RUN_BINARY');
|
||||
debug('CYPRESS_RUN_BINARY exists, =', envBinaryPath);
|
||||
logger.log(stripIndent`
|
||||
${chalk.yellow('Note:')} You have set the environment variable:
|
||||
|
||||
${chalk.white('CYPRESS_RUN_BINARY=')}${chalk.cyan(envBinaryPath)}
|
||||
|
||||
This overrides the default Cypress binary path used.
|
||||
`);
|
||||
logger.log();
|
||||
return util.isExecutableAsync(envBinaryPath).then(isExecutable => {
|
||||
debug('CYPRESS_RUN_BINARY is executable? :', isExecutable);
|
||||
if (!isExecutable) {
|
||||
return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))(stripIndent`
|
||||
The supplied binary path is not executable
|
||||
`);
|
||||
}
|
||||
}).then(() => {
|
||||
return state.parseRealPlatformBinaryFolderAsync(envBinaryPath);
|
||||
}).then(envBinaryDir => {
|
||||
if (!envBinaryDir) {
|
||||
return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))();
|
||||
}
|
||||
debug('CYPRESS_RUN_BINARY has binaryDir:', envBinaryDir);
|
||||
binaryDir = envBinaryDir;
|
||||
}).catch({
|
||||
code: 'ENOENT'
|
||||
}, err => {
|
||||
return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))(err.message);
|
||||
});
|
||||
};
|
||||
return Promise.try(() => {
|
||||
debug('checking environment variables');
|
||||
if (util.getEnv('CYPRESS_RUN_BINARY')) {
|
||||
return parseBinaryEnvVar();
|
||||
}
|
||||
}).then(() => {
|
||||
return checkExecutable(binaryDir);
|
||||
}).tap(() => {
|
||||
return debug('binaryDir is ', binaryDir);
|
||||
}).then(() => {
|
||||
return state.getBinaryPkgAsync(binaryDir);
|
||||
}).then(pkg => {
|
||||
return state.getBinaryPkgVersion(pkg);
|
||||
}).then(binaryVersion => {
|
||||
if (!binaryVersion) {
|
||||
debug('no Cypress binary found for cli version ', packageVersion);
|
||||
return throwFormErrorText(errors.missingApp(binaryDir))(`
|
||||
Cannot read binary version from: ${chalk.cyan(state.getBinaryPkgPath(binaryDir))}
|
||||
`);
|
||||
}
|
||||
debug(`Found binary version ${chalk.green(binaryVersion)} installed in: ${chalk.cyan(binaryDir)}`);
|
||||
if (binaryVersion !== packageVersion) {
|
||||
// warn if we installed with CYPRESS_INSTALL_BINARY or changed version
|
||||
// in the package.json
|
||||
logger.log(`Found binary version ${chalk.green(binaryVersion)} installed in: ${chalk.cyan(binaryDir)}`);
|
||||
logger.log();
|
||||
logger.warn(stripIndent`
|
||||
|
||||
|
||||
${logSymbols.warning} Warning: Binary version ${chalk.green(binaryVersion)} does not match the expected package version ${chalk.green(packageVersion)}
|
||||
|
||||
These versions may not work properly together.
|
||||
`);
|
||||
logger.log();
|
||||
}
|
||||
return maybeVerify(binaryVersion, binaryDir, options);
|
||||
}).catch(err => {
|
||||
if (err.known) {
|
||||
throw err;
|
||||
}
|
||||
return throwFormErrorText(errors.unexpected)(err.stack);
|
||||
});
|
||||
};
|
||||
const isLinuxLike = () => os.platform() !== 'win32';
|
||||
|
||||
/**
|
||||
* Returns true if running on a system where Electron needs "--no-sandbox" flag.
|
||||
* @see https://crbug.com/638180
|
||||
*
|
||||
* On Debian we had problems running in sandbox even for non-root users.
|
||||
* @see https://github.com/cypress-io/cypress/issues/5434
|
||||
* Seems there is a lot of discussion around this issue among Electron users
|
||||
* @see https://github.com/electron/electron/issues/17972
|
||||
*/
|
||||
const needsSandbox = () => isLinuxLike();
|
||||
module.exports = {
|
||||
start,
|
||||
VERIFY_TEST_RUNNER_TIMEOUT_MS,
|
||||
needsSandbox
|
||||
};
|
478
CyLukTs/lukan/node_modules/cypress/lib/util.js
generated
vendored
Normal file
478
CyLukTs/lukan/node_modules/cypress/lib/util.js
generated
vendored
Normal file
@ -0,0 +1,478 @@
|
||||
"use strict";
|
||||
|
||||
const _ = require('lodash');
|
||||
const arch = require('arch');
|
||||
const os = require('os');
|
||||
const ospath = require('ospath');
|
||||
const crypto = require('crypto');
|
||||
const la = require('lazy-ass');
|
||||
const is = require('check-more-types');
|
||||
const tty = require('tty');
|
||||
const path = require('path');
|
||||
const isCi = require('is-ci');
|
||||
const execa = require('execa');
|
||||
const getos = require('getos');
|
||||
const chalk = require('chalk');
|
||||
const Promise = require('bluebird');
|
||||
const cachedir = require('cachedir');
|
||||
const logSymbols = require('log-symbols');
|
||||
const executable = require('executable');
|
||||
const {
|
||||
stripIndent
|
||||
} = require('common-tags');
|
||||
const supportsColor = require('supports-color');
|
||||
const isInstalledGlobally = require('is-installed-globally');
|
||||
const logger = require('./logger');
|
||||
const debug = require('debug')('cypress:cli');
|
||||
const fs = require('./fs');
|
||||
const semver = require('semver');
|
||||
const pkg = require(path.join(__dirname, '..', 'package.json'));
|
||||
const issuesUrl = 'https://github.com/cypress-io/cypress/issues';
|
||||
const 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+)
|
||||
*/
|
||||
const getFileChecksum = filename => {
|
||||
la(is.unemptyString(filename), 'expected filename', filename);
|
||||
const hashStream = () => {
|
||||
const s = crypto.createHash('sha512');
|
||||
s.setEncoding('hex');
|
||||
return s;
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
const stream = fs.createReadStream(filename);
|
||||
stream.on('error', reject).pipe(hashStream()).on('error', reject).on('finish', function () {
|
||||
resolve(this.read());
|
||||
});
|
||||
});
|
||||
};
|
||||
const getFileSize = filename => {
|
||||
la(is.unemptyString(filename), 'expected filename', filename);
|
||||
return fs.statAsync(filename).get('size');
|
||||
};
|
||||
const isBrokenGtkDisplayRe = /Gtk: cannot open display/;
|
||||
const stringify = val => {
|
||||
return _.isObject(val) ? JSON.stringify(val) : val;
|
||||
};
|
||||
function normalizeModuleOptions(options = {}) {
|
||||
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
|
||||
*/
|
||||
const 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
|
||||
```
|
||||
*/
|
||||
const isBrokenGtkDisplay = str => {
|
||||
return isBrokenGtkDisplayRe.test(str);
|
||||
};
|
||||
const isPossibleLinuxWithIncorrectDisplay = () => {
|
||||
return isLinux() && process.env.DISPLAY;
|
||||
};
|
||||
const 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`
|
||||
|
||||
${logSymbols.warning} Warning: Cypress failed to start.
|
||||
|
||||
This is likely due to a misconfigured DISPLAY environment variable.
|
||||
|
||||
DISPLAY was set to: "${process.env.DISPLAY}"
|
||||
|
||||
Cypress will attempt to fix the problem and rerun.
|
||||
`);
|
||||
logger.warn();
|
||||
};
|
||||
function stdoutLineMatches(expectedLine, stdout) {
|
||||
const lines = stdout.split('\n').map(val => val.trim());
|
||||
return lines.some(line => line === expectedLine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms if given value is a valid CYPRESS_INTERNAL_ENV value. Undefined values
|
||||
* are valid, because the system can set the default one.
|
||||
*
|
||||
* @param {string} value
|
||||
* @example util.isValidCypressInternalEnvValue(process.env.CYPRESS_INTERNAL_ENV)
|
||||
*/
|
||||
function isValidCypressInternalEnvValue(value) {
|
||||
if (_.isUndefined(value)) {
|
||||
// will get default value
|
||||
return true;
|
||||
}
|
||||
|
||||
// names of config environments, see "packages/server/config/app.json"
|
||||
const names = ['development', 'test', 'staging', 'production'];
|
||||
return _.includes(names, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms if given value is a non-production CYPRESS_INTERNAL_ENV value.
|
||||
* Undefined values are valid, because the system can set the default one.
|
||||
*
|
||||
* @param {string} value
|
||||
* @example util.isNonProductionCypressInternalEnvValue(process.env.CYPRESS_INTERNAL_ENV)
|
||||
*/
|
||||
function isNonProductionCypressInternalEnvValue(value) {
|
||||
return !_.isUndefined(value) && value !== 'production';
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints NODE_OPTIONS using debug() module, but only
|
||||
* if DEBUG=cypress... is set
|
||||
*/
|
||||
function printNodeOptions(log = 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'
|
||||
```
|
||||
*/
|
||||
const 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;
|
||||
};
|
||||
const parseOpts = opts => {
|
||||
opts = _.pick(opts, 'autoCancelAfterFailures', 'browser', 'cachePath', 'cacheList', 'cacheClear', 'cachePrune', 'ciBuildId', 'ct', 'component', 'config', 'configFile', 'cypressVersion', 'destination', 'detached', 'dev', 'e2e', 'exit', 'env', 'force', 'global', 'group', 'headed', 'headless', 'inspect', 'inspectBrk', 'key', 'path', 'parallel', 'port', 'project', 'quiet', 'reporter', 'reporterOptions', 'record', 'runProject', 'spec', 'tag');
|
||||
if (opts.exit) {
|
||||
opts = _.omit(opts, 'exit');
|
||||
}
|
||||
|
||||
// some options might be quoted - which leads to unexpected results
|
||||
// remove double quotes from certain options
|
||||
const cleanOpts = {
|
||||
...opts
|
||||
};
|
||||
const toDequote = ['group', 'ciBuildId'];
|
||||
for (const prop of toDequote) {
|
||||
if (_.has(opts, prop)) {
|
||||
cleanOpts[prop] = dequote(opts[prop]);
|
||||
}
|
||||
}
|
||||
debug('parsed cli options %o', cleanOpts);
|
||||
return cleanOpts;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy of packages/server/lib/browsers/utils.ts
|
||||
* because we need same functionality in CLI to show the path :(
|
||||
*/
|
||||
const getApplicationDataFolder = (...paths) => {
|
||||
const {
|
||||
env
|
||||
} = process;
|
||||
|
||||
// allow overriding the app_data folder
|
||||
let folder = env.CYPRESS_CONFIG_ENV || env.CYPRESS_INTERNAL_ENV || 'development';
|
||||
const PRODUCT_NAME = pkg.productName || pkg.name;
|
||||
const OS_DATA_PATH = ospath.data();
|
||||
const ELECTRON_APP_DATA_PATH = path.join(OS_DATA_PATH, PRODUCT_NAME);
|
||||
if (process.env.CYPRESS_INTERNAL_E2E_TESTING_SELF) {
|
||||
folder = `${folder}-e2e-test`;
|
||||
}
|
||||
const p = path.join(ELECTRON_APP_DATA_PATH, 'cy', folder, ...paths);
|
||||
return p;
|
||||
};
|
||||
const util = {
|
||||
normalizeModuleOptions,
|
||||
parseOpts,
|
||||
isValidCypressInternalEnvValue,
|
||||
isNonProductionCypressInternalEnvValue,
|
||||
printNodeOptions,
|
||||
isCi() {
|
||||
return isCi;
|
||||
},
|
||||
getEnvOverrides(options = {}) {
|
||||
return _.chain({}).extend(util.getEnvColors()).extend(util.getForceTty()).omitBy(_.isUndefined) // remove undefined values
|
||||
.mapValues(value => {
|
||||
// stringify to 1 or 0
|
||||
return value ? '1' : '0';
|
||||
}).extend(util.getOriginalNodeOptions()).value();
|
||||
},
|
||||
getOriginalNodeOptions() {
|
||||
const opts = {};
|
||||
if (process.env.NODE_OPTIONS) {
|
||||
opts.ORIGINAL_NODE_OPTIONS = process.env.NODE_OPTIONS;
|
||||
}
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/18914
|
||||
// Node 17+ ships with OpenSSL 3 by default, so we may need the option
|
||||
// --openssl-legacy-provider so that webpack@4 can use the legacy MD4 hash
|
||||
// function. This option doesn't exist on Node <17 or when it is built
|
||||
// against OpenSSL 1, so we have to detect Node's major version and check
|
||||
// which version of OpenSSL it was built against before spawning the plugins
|
||||
// process.
|
||||
|
||||
// To be removed when the Cypress binary pulls in the @cypress/webpack-batteries-included-preprocessor
|
||||
// version that has been updated to webpack >= 5.61, which no longer relies on
|
||||
// Node's builtin crypto.hash function.
|
||||
if (process.versions && semver.satisfies(process.versions.node, '>=17.0.0') && semver.satisfies(process.versions.openssl, '>=3', {
|
||||
includePrerelease: true
|
||||
})) {
|
||||
opts.ORIGINAL_NODE_OPTIONS = `${opts.ORIGINAL_NODE_OPTIONS || ''} --openssl-legacy-provider`;
|
||||
}
|
||||
return opts;
|
||||
},
|
||||
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() {
|
||||
const sc = util.supportsColor();
|
||||
return {
|
||||
FORCE_COLOR: sc,
|
||||
DEBUG_COLORS: sc,
|
||||
MOCHA_COLORS: sc ? true : undefined
|
||||
};
|
||||
},
|
||||
isTty(fd) {
|
||||
return tty.isatty(fd);
|
||||
},
|
||||
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() {
|
||||
return process.cwd();
|
||||
},
|
||||
pkgBuildInfo() {
|
||||
return pkg.buildInfo;
|
||||
},
|
||||
pkgVersion() {
|
||||
return pkg.version;
|
||||
},
|
||||
exit(code) {
|
||||
process.exit(code);
|
||||
},
|
||||
logErrorExit1(err) {
|
||||
logger.error(err.message);
|
||||
process.exit(1);
|
||||
},
|
||||
dequote,
|
||||
titleize(...args) {
|
||||
// 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(...args);
|
||||
},
|
||||
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(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(eta) {
|
||||
// calculate the seconds reminaing with no decimal places
|
||||
return (_.isFinite(eta) ? eta / 1000 : 0).toFixed(0);
|
||||
},
|
||||
setTaskTitle(task, title, renderer) {
|
||||
// only update the renderer title when not running in CI
|
||||
if (renderer === 'default' && task.title !== title) {
|
||||
task.title = title;
|
||||
}
|
||||
},
|
||||
isInstalledGlobally() {
|
||||
return isInstalledGlobally;
|
||||
},
|
||||
isSemver(str) {
|
||||
return /^(\d+\.)?(\d+\.)?(\*|\d+)$/.test(str);
|
||||
},
|
||||
isExecutableAsync(filePath) {
|
||||
return Promise.resolve(executable(filePath));
|
||||
},
|
||||
isLinux,
|
||||
getOsVersionAsync() {
|
||||
return Promise.try(() => {
|
||||
if (isLinux()) {
|
||||
return getosAsync().then(osInfo => {
|
||||
return [osInfo.dist, osInfo.release].join(' - ');
|
||||
}).catch(() => {
|
||||
return os.release();
|
||||
});
|
||||
}
|
||||
return os.release();
|
||||
});
|
||||
},
|
||||
async getPlatformInfo() {
|
||||
const [version, osArch] = await Promise.all([util.getOsVersionAsync(), this.getRealArch()]);
|
||||
return stripIndent`
|
||||
Platform: ${os.platform()}-${osArch} (${version})
|
||||
Cypress Version: ${util.pkgVersion()}
|
||||
`;
|
||||
},
|
||||
_cachedArch: undefined,
|
||||
/**
|
||||
* Attempt to return the real system arch (not process.arch, which is only the Node binary's arch)
|
||||
*/
|
||||
async getRealArch() {
|
||||
if (this._cachedArch) return this._cachedArch;
|
||||
async function _getRealArch() {
|
||||
const osPlatform = os.platform();
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const osArch = os.arch();
|
||||
debug('detecting arch %o', {
|
||||
osPlatform,
|
||||
osArch
|
||||
});
|
||||
if (osArch === 'arm64') return 'arm64';
|
||||
if (osPlatform === 'darwin') {
|
||||
// could possibly be x64 node on arm64 darwin, check if we are being translated by Rosetta
|
||||
// https://stackoverflow.com/a/65347893/3474615
|
||||
const {
|
||||
stdout
|
||||
} = await execa('sysctl', ['-n', 'sysctl.proc_translated']).catch(() => '');
|
||||
debug('rosetta check result: %o', {
|
||||
stdout
|
||||
});
|
||||
if (stdout === '1') return 'arm64';
|
||||
}
|
||||
if (osPlatform === 'linux') {
|
||||
// could possibly be x64 node on arm64 linux, check the "machine hardware name"
|
||||
// list of names for reference: https://stackoverflow.com/a/45125525/3474615
|
||||
const {
|
||||
stdout
|
||||
} = await execa('uname', ['-m']).catch(() => '');
|
||||
debug('arm uname -m result: %o ', {
|
||||
stdout
|
||||
});
|
||||
if (['aarch64_be', 'aarch64', 'armv8b', 'armv8l'].includes(stdout)) return 'arm64';
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const pkgArch = arch();
|
||||
if (pkgArch === 'x86') return 'ia32';
|
||||
return pkgArch;
|
||||
}
|
||||
return this._cachedArch = await _getRealArch();
|
||||
},
|
||||
// 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(filename) {
|
||||
if (path.isAbsolute(filename)) {
|
||||
return filename;
|
||||
}
|
||||
return path.join(process.cwd(), '..', '..', filename);
|
||||
},
|
||||
getEnv(varName, trim) {
|
||||
la(is.unemptyString(varName), 'expected environment variable name, not', varName);
|
||||
const configVarName = `npm_config_${varName}`;
|
||||
const configVarNameLower = configVarName.toLowerCase();
|
||||
const packageConfigVarName = `npm_package_config_${varName}`;
|
||||
let result;
|
||||
if (process.env.hasOwnProperty(varName)) {
|
||||
debug(`Using ${varName} from environment variable`);
|
||||
result = process.env[varName];
|
||||
} else if (process.env.hasOwnProperty(configVarName)) {
|
||||
debug(`Using ${varName} from npm config`);
|
||||
result = process.env[configVarName];
|
||||
} else if (process.env.hasOwnProperty(configVarNameLower)) {
|
||||
debug(`Using ${varName.toLowerCase()} from npm config`);
|
||||
result = process.env[configVarNameLower];
|
||||
} else if (process.env.hasOwnProperty(packageConfigVarName)) {
|
||||
debug(`Using ${varName} from package.json config`);
|
||||
result = process.env[packageConfigVarName];
|
||||
}
|
||||
|
||||
// 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() {
|
||||
return cachedir('Cypress');
|
||||
},
|
||||
isPostInstall() {
|
||||
return process.env.npm_lifecycle_event === 'postinstall';
|
||||
},
|
||||
exec: execa,
|
||||
stdoutLineMatches,
|
||||
issuesUrl,
|
||||
isBrokenGtkDisplay,
|
||||
logBrokenGtkDisplayWarning,
|
||||
isPossibleLinuxWithIncorrectDisplay,
|
||||
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,
|
||||
getFileSize,
|
||||
getApplicationDataFolder
|
||||
};
|
||||
module.exports = util;
|
Reference in New Issue
Block a user