údržba
This commit is contained in:
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
|
||||
};
|
Reference in New Issue
Block a user