cli: better error formatting, added cypress version to errors, add footer feature

This commit is contained in:
Brian Mann
2017-09-03 23:41:52 -04:00
parent fe20323b06
commit 8ee29f7864
5 changed files with 86 additions and 50 deletions

View File

@@ -1,13 +1,18 @@
const os = require('os')
const chalk = require('chalk')
const Promise = require('bluebird')
const getos = Promise.promisify(require('getos'))
const { stripIndent, stripIndents } = require('common-tags')
const { merge } = require('ramda')
const util = require('./util')
const issuesUrl = 'https://github.com/cypress-io/cypress/issues'
const docsUrl = 'https://on.cypress.io'
const requiredDependenciesUrl = `${docsUrl}/required-dependencies`
const pkgVersion = util.pkgVersion()
// common errors Cypress application can encounter
const failedDownload = {
description: 'The Cypress App could not be downloaded.',
@@ -24,56 +29,56 @@ const failedToUnzip = {
}
const missingApp = {
description: 'No version of Cypress executable installed',
description: 'No version of Cypress executable is installed.',
solution: stripIndent`
Please reinstall Cypress and run the app again.
If the problem persists, search for an existing issue or open a GitHub issue at
${issuesUrl}
\nPlease reinstall Cypress by running: ${chalk.cyan('cypress install')}
`,
}
const missingXvfb = {
description: 'Looks like your system is missing a must have dependency: XVFB',
description: 'Your system is missing the dependency: XVFB',
solution: stripIndent`
Install XVFB and run Cypress again.
Our CI documentation provides more information how to configure dependencies
`,
footer: stripIndent`
Read our doc on CI dependencies for more information:
${requiredDependenciesUrl}
`,
`,
}
const missingDependency = {
description: 'Problem running Cypress application',
description: 'We could not run Cypress.',
// this message is too Linux specific
solution: stripIndent`
This is usually caused by a missing library or dependency.
The error below should indicate which dependency is missing.
Read our doc on CI dependencies for more information:
${requiredDependenciesUrl}
`,
}
const versionMismatch = {
description: 'Installed version does not match package version',
description: 'Installed version does not match package version.',
solution: 'Install Cypress and verify app again',
}
const unexpected = {
description: 'An unexpected error occurred while verifying the Cypress executable',
description: 'An unexpected error occurred while verifying the Cypress executable.',
solution: stripIndent`
Please search Cypress documentation for possible solutions
Please search Cypress documentation for possible solutions:
${docsUrl}
Find if there is a GitHub issue describing this crash
Check if there is a GitHub issue describing this crash:
${issuesUrl}
Consider opening a new issue, if you are the first to discover this
Consider opening a new issue.
`,
printStack: true,
}
const getOsVersion = () => {
@@ -89,8 +94,8 @@ const getOsVersion = () => {
function getPlatformInfo () {
return getOsVersion()
.then((version) => stripIndent`
Platform: ${os.platform()}
Version: ${version}
Platform: ${os.platform()} (${version})
Cypress Version: ${pkgVersion}
`)
}
@@ -99,39 +104,70 @@ function addPlatformInformation (info) {
.then((platform) => merge(info, { platform }))
}
function formError (info, error) {
return addPlatformInformation(info)
.then((info) => merge(error, info))
}
function formErrorText (info, error) {
function formErrorText (info, msg) {
const hr = '----------'
return formError(info, error)
.then((info) => stripIndents`
${hr}
${info.description}
${info.solution}
${hr}
${info.message}
${info.printStack ? info.stack : ''}
${hr}
${info.platform}
`)
return addPlatformInformation(info)
.then((obj) => {
const formatted = []
function add (msg) {
formatted.push(
stripIndents`${msg}`
)
}
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')
})
}
const raise = (text) => {
throw new Error(text)
const err = new Error(text)
err.known = true
throw err
}
const throwDetailedError = (info) => (error) =>
formErrorText(info, error)
const throwFormErrorText = (info) => (msg) => {
return formErrorText(info, msg)
.then(raise)
}
module.exports = {
formError,
raise,
// formError,
formErrorText,
throwDetailedError,
throwFormErrorText,
errors: {
missingXvfb,
missingApp,

View File

@@ -1,7 +1,7 @@
const downloadUtils = require('../download/utils')
const spawn = require('./spawn')
const debug = require('debug')('cypress:cli')
const util = require('../util')
const spawn = require('./spawn')
const { verify } = require('../tasks/verify')
module.exports = {
start (options = {}) {
@@ -30,11 +30,11 @@ module.exports = {
debug('opening from options %j', options)
debug('command line arguments %j', args)
return downloadUtils.verify()
return verify()
.then(() => {
return spawn.start(args, {
detached: Boolean(options.detached),
stdio: ['ignore', 'ignore', 'ignore'],
stdio: ['ignore', 'inherit', 'ignore'],
})
})
},

View File

@@ -1,7 +1,7 @@
const _ = require('lodash')
const debug = require('debug')('cypress:cli')
const downloadUtils = require('../download/utils')
const spawn = require('./spawn')
const { verify } = require('../tasks/verify')
const processRunOptions = (options = {}) => {
const args = ['--run-project', options.project]
@@ -86,6 +86,6 @@ module.exports = {
project: process.cwd(),
})
return downloadUtils.verify().then(run(options))
return verify().then(run(options))
},
}

View File

@@ -5,7 +5,7 @@ const debug = require('debug')('cypress:cli')
const downloadUtils = require('../download/utils')
const xvfb = require('./xvfb')
const { throwDetailedError, errors } = require('../errors')
const { throwFormErrorText, errors } = require('../errors')
module.exports = {
start (args, options = {}) {
@@ -23,7 +23,7 @@ module.exports = {
debug('spawn args %j', args)
const child = cp.spawn(cypressPath, args, options)
child.on('exit', resolve)
child.on('close', resolve)
child.on('error', reject)
if (options.detached) {
@@ -33,7 +33,7 @@ module.exports = {
}
const userFriendlySpawn = () =>
spawn().catch(throwDetailedError(errors.unexpected))
spawn().catch(throwFormErrorText(errors.unexpected))
const needsXvfb = xvfb.isNeeded()
debug('needs XVFB?', needsXvfb)

View File

@@ -3,7 +3,7 @@ const Promise = require('bluebird')
const Xvfb = require('@cypress/xvfb')
const R = require('ramda')
const debug = require('debug')('cypress:cli')
const { throwDetailedError, errors } = require('../errors')
const { throwFormErrorText, errors } = require('../errors')
const xvfb = Promise.promisifyAll(new Xvfb({ silent: true }))
@@ -13,7 +13,7 @@ module.exports = {
start () {
debug('Starting XVFB')
return xvfb.startAsync()
.catch(throwDetailedError(errors.missingXvfb))
.catch(throwFormErrorText(errors.missingXvfb))
},
stop () {