errors.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. 'use strict';
  2. var _templateObject = _taggedTemplateLiteral(['\n 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\n\n Otherwise, please check network connectivity and try again:'], ['\n 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\n\n Otherwise, please check network connectivity and try again:']),
  3. _templateObject2 = _taggedTemplateLiteral(['\n Search for an existing issue or open a GitHub issue at\n\n ', '\n '], ['\n Search for an existing issue or open a GitHub issue at\n\n ', '\n ']),
  4. _templateObject3 = _taggedTemplateLiteral(['\n \nPlease reinstall Cypress by running: ', '\n '], ['\n \\nPlease reinstall Cypress by running: ', '\n ']),
  5. _templateObject4 = _taggedTemplateLiteral(['\n\n Reasons this may happen:\n\n - node was installed as \'root\' or with \'sudo\'\n - the cypress npm package as \'root\' or with \'sudo\'\n\n Please check that you have the appropriate user permissions.\n '], ['\\n\n Reasons this may happen:\n\n - node was installed as \'root\' or with \'sudo\'\n - the cypress npm package as \'root\' or with \'sudo\'\n\n Please check that you have the appropriate user permissions.\n ']),
  6. _templateObject5 = _taggedTemplateLiteral(['\n\n We expected the binary to be installed here: ', '\n\n Reasons it may be missing:\n\n - You\'re caching \'node_modules\' but are not caching this path: ', '\n - You ran \'npm install\' at an earlier build step but did not persist: ', '\n\n Properly caching the binary will fix this error and avoid downloading and unzipping Cypress.\n\n Alternatively, you can run \'cypress install\' to download the binary again.\n\n ', '\n '], ['\\n\n We expected the binary to be installed here: ', '\n\n Reasons it may be missing:\n\n - You\'re caching \'node_modules\' but are not caching this path: ', '\n - You ran \'npm install\' at an earlier build step but did not persist: ', '\n\n Properly caching the binary will fix this error and avoid downloading and unzipping Cypress.\n\n Alternatively, you can run \'cypress install\' to download the binary again.\n\n ', '\n ']),
  7. _templateObject6 = _taggedTemplateLiteral(['\n There was a problem spawning Xvfb.\n\n This is likely a problem with your system, permissions, or installation of Xvfb.\n '], ['\n There was a problem spawning Xvfb.\n\n This is likely a problem with your system, permissions, or installation of Xvfb.\n ']),
  8. _templateObject7 = _taggedTemplateLiteral(['\n Install Xvfb and run Cypress again.\n\n Read our documentation on dependencies for more information:\n\n ', '\n\n If you are using Docker, we provide containers with all required dependencies installed.\n '], ['\n Install Xvfb and run Cypress again.\n\n Read our documentation on dependencies for more information:\n\n ', '\n\n If you are using Docker, we provide containers with all required dependencies installed.\n ']),
  9. _templateObject8 = _taggedTemplateLiteral(['\n This command failed with the following output:\n\n ', '\n\n '], ['\n This command failed with the following output:\n\n ', '\n\n ']),
  10. _templateObject9 = _taggedTemplateLiteral(['\n Cypress failed to start after spawning a new Xvfb server.\n\n The error logs we received were:\n\n ', '\n\n ', '\n\n ', '\n\n This is usually caused by a missing library or dependency.\n\n The error above should indicate which dependency is missing.\n\n ', '\n\n If you are using Docker, we provide containers with all required dependencies installed.\n '], ['\n Cypress failed to start after spawning a new Xvfb server.\n\n The error logs we received were:\n\n ', '\n\n ', '\n\n ', '\n\n This is usually caused by a missing library or dependency.\n\n The error above should indicate which dependency is missing.\n\n ', '\n\n If you are using Docker, we provide containers with all required dependencies installed.\n ']),
  11. _templateObject10 = _taggedTemplateLiteral(['\n This is usually caused by a missing library or dependency.\n\n The error below should indicate which dependency is missing.\n\n ', '\n\n If you are using Docker, we provide containers with all required dependencies installed.\n '], ['\n This is usually caused by a missing library or dependency.\n\n The error below should indicate which dependency is missing.\n\n ', '\n\n If you are using Docker, we provide containers with all required dependencies installed.\n ']),
  12. _templateObject11 = _taggedTemplateLiteral(['\n See discussion and possible solutions at\n ', '\n '], ['\n See discussion and possible solutions at\n ', '\n ']),
  13. _templateObject12 = _taggedTemplateLiteral(['\n Please search Cypress documentation for possible solutions:\n\n ', '\n\n Check if there is a GitHub issue describing this crash:\n\n ', '\n\n Consider opening a new issue.\n'], ['\n Please search Cypress documentation for possible solutions:\n\n ', '\n\n Check if there is a GitHub issue describing this crash:\n\n ', '\n\n Consider opening a new issue.\n']),
  14. _templateObject13 = _taggedTemplateLiteral(['\n The environment variable CYPRESS_BINARY_VERSION has been renamed to CYPRESS_INSTALL_BINARY as of version ', '\n '], ['\n The environment variable CYPRESS_BINARY_VERSION has been renamed to CYPRESS_INSTALL_BINARY as of version ', '\n ']),
  15. _templateObject14 = _taggedTemplateLiteral(['\n You should set CYPRESS_INSTALL_BINARY instead.\n '], ['\n You should set CYPRESS_INSTALL_BINARY instead.\n ']),
  16. _templateObject15 = _taggedTemplateLiteral(['\n The environment variable CYPRESS_SKIP_BINARY_INSTALL has been removed as of version ', '\n '], ['\n The environment variable CYPRESS_SKIP_BINARY_INSTALL has been removed as of version ', '\n ']),
  17. _templateObject16 = _taggedTemplateLiteral(['\n To skip the binary install, set CYPRESS_INSTALL_BINARY=0\n '], ['\n To skip the binary install, set CYPRESS_INSTALL_BINARY=0\n ']),
  18. _templateObject17 = _taggedTemplateLiteral(['\n Platform: ', ' (', ')\n Cypress Version: ', '\n '], ['\n Platform: ', ' (', ')\n Cypress Version: ', '\n ']);
  19. function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
  20. var os = require('os');
  21. var chalk = require('chalk');
  22. var _require = require('common-tags'),
  23. stripIndent = _require.stripIndent,
  24. stripIndents = _require.stripIndents;
  25. var _require2 = require('ramda'),
  26. merge = _require2.merge;
  27. var la = require('lazy-ass');
  28. var is = require('check-more-types');
  29. var util = require('./util');
  30. var state = require('./tasks/state');
  31. var docsUrl = 'https://on.cypress.io';
  32. var requiredDependenciesUrl = docsUrl + '/required-dependencies';
  33. // TODO it would be nice if all error objects could be enforced via types
  34. // to only have description + solution properties
  35. var hr = '----------';
  36. // common errors Cypress application can encounter
  37. var failedDownload = {
  38. description: 'The Cypress App could not be downloaded.',
  39. solution: stripIndent(_templateObject)
  40. };
  41. var failedUnzip = {
  42. description: 'The Cypress App could not be unzipped.',
  43. solution: stripIndent(_templateObject2, chalk.blue(util.issuesUrl))
  44. };
  45. var missingApp = function missingApp(binaryDir) {
  46. return {
  47. description: 'No version of Cypress is installed in: ' + chalk.cyan(binaryDir),
  48. solution: stripIndent(_templateObject3, chalk.cyan('cypress install'))
  49. };
  50. };
  51. var binaryNotExecutable = function binaryNotExecutable(executable) {
  52. return {
  53. description: 'Cypress cannot run because this binary file does not have executable permissions here:\n\n' + executable,
  54. solution: stripIndent(_templateObject4)
  55. };
  56. };
  57. var notInstalledCI = function notInstalledCI(executable) {
  58. return {
  59. description: 'The cypress npm package is installed, but the Cypress binary is missing.',
  60. solution: stripIndent(_templateObject5, chalk.cyan(executable), util.getCacheDir(), util.getCacheDir(), chalk.blue('https://on.cypress.io/not-installed-ci-error'))
  61. };
  62. };
  63. var nonZeroExitCodeXvfb = {
  64. description: 'Xvfb exited with a non zero exit code.',
  65. solution: stripIndent(_templateObject6)
  66. };
  67. var missingXvfb = {
  68. description: 'Your system is missing the dependency: Xvfb',
  69. solution: stripIndent(_templateObject7, chalk.blue(requiredDependenciesUrl))
  70. };
  71. var smokeTestFailure = function smokeTestFailure(smokeTestCommand, timedOut) {
  72. return {
  73. description: 'Cypress verification ' + (timedOut ? 'timed out' : 'failed') + '.',
  74. solution: stripIndent(_templateObject8, smokeTestCommand)
  75. };
  76. };
  77. var invalidSmokeTestDisplayError = {
  78. code: 'INVALID_SMOKE_TEST_DISPLAY_ERROR',
  79. description: 'Cypress verification failed.',
  80. solution: function solution(msg) {
  81. return stripIndent(_templateObject9, hr, msg, hr, chalk.blue(requiredDependenciesUrl));
  82. }
  83. };
  84. var missingDependency = {
  85. description: 'Cypress failed to start.',
  86. // this message is too Linux specific
  87. solution: stripIndent(_templateObject10, chalk.blue(requiredDependenciesUrl))
  88. };
  89. var invalidCacheDirectory = {
  90. description: 'Cypress cannot write to the cache directory due to file permissions',
  91. solution: stripIndent(_templateObject11, chalk.blue(util.getGitHubIssueUrl(1281)))
  92. };
  93. var versionMismatch = {
  94. description: 'Installed version does not match package version.',
  95. solution: 'Install Cypress and verify app again'
  96. };
  97. var incompatibleHeadlessFlags = {
  98. description: '`--headed` and `--headless` cannot both be passed.',
  99. solution: 'Either pass `--headed` or `--headless`, but not both.'
  100. };
  101. var solutionUnknown = stripIndent(_templateObject12, chalk.blue(docsUrl), chalk.blue(util.issuesUrl));
  102. var unexpected = {
  103. description: 'An unexpected error occurred while verifying the Cypress executable.',
  104. solution: solutionUnknown
  105. };
  106. var invalidCypressEnv = {
  107. description: chalk.red('The environment variable with the reserved name "CYPRESS_ENV" is set.'),
  108. solution: chalk.red('Unset the "CYPRESS_ENV" environment variable and run Cypress again.'),
  109. exitCode: 11
  110. /**
  111. * This error happens when CLI detects that the child Test Runner process
  112. * was killed with a signal, like SIGBUS
  113. * @see https://github.com/cypress-io/cypress/issues/5808
  114. * @param {'close'|'event'} eventName Child close event name
  115. * @param {string} signal Signal that closed the child process, like "SIGBUS"
  116. */
  117. };var childProcessKilled = function childProcessKilled(eventName, signal) {
  118. return {
  119. description: 'The Test Runner unexpectedly exited via a ' + chalk.cyan(eventName) + ' event with signal ' + chalk.cyan(signal),
  120. solution: solutionUnknown
  121. };
  122. };
  123. var removed = {
  124. CYPRESS_BINARY_VERSION: {
  125. description: stripIndent(_templateObject13, chalk.green('3.0.0')),
  126. solution: stripIndent(_templateObject14)
  127. },
  128. CYPRESS_SKIP_BINARY_INSTALL: {
  129. description: stripIndent(_templateObject15, chalk.green('3.0.0')),
  130. solution: stripIndent(_templateObject16)
  131. }
  132. };
  133. var CYPRESS_RUN_BINARY = {
  134. notValid: function notValid(value) {
  135. var properFormat = '**/' + state.getPlatformExecutable();
  136. return {
  137. description: 'Could not run binary set by environment variable: CYPRESS_RUN_BINARY=' + value,
  138. solution: 'Ensure the environment variable is a path to the Cypress binary, matching ' + properFormat
  139. };
  140. }
  141. };
  142. function getPlatformInfo() {
  143. return util.getOsVersionAsync().then(function (version) {
  144. return stripIndent(_templateObject17, os.platform(), version, util.pkgVersion());
  145. });
  146. }
  147. function addPlatformInformation(info) {
  148. return getPlatformInfo().then(function (platform) {
  149. return merge(info, { platform: platform });
  150. });
  151. }
  152. /**
  153. * Given an error object (see the errors above), forms error message text with details,
  154. * then resolves with Error instance you can throw or reject with.
  155. * @param {object} errorObject
  156. * @returns {Promise<Error>} resolves with an Error
  157. * @example
  158. ```js
  159. // inside a Promise with "resolve" and "reject"
  160. const errorObject = childProcessKilled('exit', 'SIGKILL')
  161. return getError(errorObject).then(reject)
  162. ```
  163. */
  164. function getError(errorObject) {
  165. return formErrorText(errorObject).then(function (errorMessage) {
  166. var err = new Error(errorMessage);
  167. err.known = true;
  168. return err;
  169. });
  170. }
  171. /**
  172. * Forms nice error message with error and platform information,
  173. * and if possible a way to solve it. Resolves with a string.
  174. */
  175. function formErrorText(info, msg, prevMessage) {
  176. return addPlatformInformation(info).then(function (obj) {
  177. var formatted = [];
  178. function add(msg) {
  179. formatted.push(stripIndents(msg));
  180. }
  181. la(is.unemptyString(obj.description), 'expected error description to be text', obj.description);
  182. // assuming that if there the solution is a function it will handle
  183. // error message and (optional previous error message)
  184. if (is.fn(obj.solution)) {
  185. var text = obj.solution(msg, prevMessage);
  186. la(is.unemptyString(text), 'expected solution to be text', text);
  187. add('\n ' + obj.description + '\n\n ' + text + '\n\n ');
  188. } else {
  189. la(is.unemptyString(obj.solution), 'expected error solution to be text', obj.solution);
  190. add('\n ' + obj.description + '\n\n ' + obj.solution + '\n\n ');
  191. if (msg) {
  192. add('\n ' + hr + '\n\n ' + msg + '\n\n ');
  193. }
  194. }
  195. add('\n ' + hr + '\n\n ' + obj.platform + '\n ');
  196. if (obj.footer) {
  197. add('\n\n ' + hr + '\n\n ' + obj.footer + '\n ');
  198. }
  199. return formatted.join('\n\n');
  200. });
  201. }
  202. var raise = function raise(info) {
  203. return function (text) {
  204. var err = new Error(text);
  205. if (info.code) {
  206. err.code = info.code;
  207. }
  208. err.known = true;
  209. throw err;
  210. };
  211. };
  212. var throwFormErrorText = function throwFormErrorText(info) {
  213. return function (msg, prevMessage) {
  214. return formErrorText(info, msg, prevMessage).then(raise(info));
  215. };
  216. };
  217. /**
  218. * Forms full error message with error and OS details, prints to the error output
  219. * and then exits the process.
  220. * @param {ErrorInformation} info Error information {description, solution}
  221. * @example return exitWithError(errors.invalidCypressEnv)('foo')
  222. */
  223. var exitWithError = function exitWithError(info) {
  224. return function (msg) {
  225. return formErrorText(info, msg).then(function (text) {
  226. // eslint-disable-next-line no-console
  227. console.error(text);
  228. process.exit(info.exitCode || 1);
  229. });
  230. };
  231. };
  232. module.exports = {
  233. raise: raise,
  234. exitWithError: exitWithError,
  235. // formError,
  236. formErrorText: formErrorText,
  237. throwFormErrorText: throwFormErrorText,
  238. getError: getError,
  239. hr: hr,
  240. errors: {
  241. nonZeroExitCodeXvfb: nonZeroExitCodeXvfb,
  242. missingXvfb: missingXvfb,
  243. missingApp: missingApp,
  244. notInstalledCI: notInstalledCI,
  245. missingDependency: missingDependency,
  246. invalidSmokeTestDisplayError: invalidSmokeTestDisplayError,
  247. versionMismatch: versionMismatch,
  248. binaryNotExecutable: binaryNotExecutable,
  249. unexpected: unexpected,
  250. failedDownload: failedDownload,
  251. failedUnzip: failedUnzip,
  252. invalidCypressEnv: invalidCypressEnv,
  253. invalidCacheDirectory: invalidCacheDirectory,
  254. removed: removed,
  255. CYPRESS_RUN_BINARY: CYPRESS_RUN_BINARY,
  256. smokeTestFailure: smokeTestFailure,
  257. childProcessKilled: childProcessKilled,
  258. incompatibleHeadlessFlags: incompatibleHeadlessFlags
  259. }
  260. };