config-util.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. 'use strict'
  2. const arrify = require('arrify')
  3. const fs = require('fs')
  4. const path = require('path')
  5. const findUp = require('find-up')
  6. const testExclude = require('test-exclude')
  7. const Yargs = require('yargs/yargs')
  8. var Config = {}
  9. function guessCWD (cwd) {
  10. cwd = cwd || process.env.NYC_CWD || process.cwd()
  11. const pkgPath = findUp.sync('package.json', { cwd: cwd })
  12. if (pkgPath) {
  13. cwd = path.dirname(pkgPath)
  14. }
  15. return cwd
  16. }
  17. Config.loadConfig = function (argv, cwd) {
  18. const rcPath = findUp.sync([argv.nycrcPath || '.nycrc', '.nycrc.json'], { cwd: guessCWD(cwd) })
  19. let config = {}
  20. if (rcPath) {
  21. config = JSON.parse(
  22. fs.readFileSync(rcPath, 'utf-8')
  23. )
  24. }
  25. if (config.require) config.require = arrify(config.require)
  26. if (config.extension) config.extension = arrify(config.extension)
  27. if (config.exclude) config.exclude = arrify(config.exclude)
  28. if (config.include) config.include = arrify(config.include)
  29. return config
  30. }
  31. // build a yargs object, omitting any settings
  32. // that would cause the application to exit early.
  33. Config.buildYargs = function (cwd) {
  34. cwd = guessCWD(cwd)
  35. return Yargs([])
  36. .usage('$0 [command] [options]')
  37. .usage('$0 [options] [bin-to-instrument]')
  38. .option('reporter', {
  39. alias: 'r',
  40. describe: 'coverage reporter(s) to use',
  41. default: 'text',
  42. global: false
  43. })
  44. .option('report-dir', {
  45. describe: 'directory to output coverage reports in',
  46. default: 'coverage',
  47. global: false
  48. })
  49. .option('silent', {
  50. alias: 's',
  51. default: false,
  52. type: 'boolean',
  53. describe: "don't output a report after tests finish running",
  54. global: false
  55. })
  56. .option('all', {
  57. alias: 'a',
  58. default: false,
  59. type: 'boolean',
  60. describe: 'whether or not to instrument all files of the project (not just the ones touched by your test suite)',
  61. global: false
  62. })
  63. .option('exclude', {
  64. alias: 'x',
  65. default: testExclude.defaultExclude,
  66. describe: 'a list of specific files and directories that should be excluded from coverage, glob patterns are supported, node_modules is always excluded',
  67. global: false
  68. })
  69. .option('exclude-after-remap', {
  70. default: true,
  71. type: 'boolean',
  72. description: 'should exclude logic be performed after the source-map remaps filenames?',
  73. global: false
  74. })
  75. .option('include', {
  76. alias: 'n',
  77. default: [],
  78. describe: 'a list of specific files that should be covered, glob patterns are supported',
  79. global: false
  80. })
  81. .option('cwd', {
  82. describe: 'working directory used when resolving paths',
  83. default: cwd
  84. })
  85. .option('require', {
  86. alias: 'i',
  87. default: [],
  88. describe: 'a list of additional modules that nyc should attempt to require in its subprocess, e.g., @babel/register, @babel/polyfill',
  89. global: false
  90. })
  91. .option('eager', {
  92. default: false,
  93. type: 'boolean',
  94. describe: 'instantiate the instrumenter at startup (see https://git.io/vMKZ9)',
  95. global: false
  96. })
  97. .option('cache', {
  98. alias: 'c',
  99. default: true,
  100. type: 'boolean',
  101. describe: 'cache instrumentation results for improved performance',
  102. global: false
  103. })
  104. .option('cache-dir', {
  105. describe: 'explicitly set location for instrumentation cache',
  106. global: false
  107. })
  108. .option('babel-cache', {
  109. default: false,
  110. type: 'boolean',
  111. describe: 'cache babel transpilation results for improved performance',
  112. global: false
  113. })
  114. .option('es-modules', {
  115. default: true,
  116. type: 'boolean',
  117. describe: 'tell the instrumenter to treat files as ES Modules',
  118. global: false
  119. })
  120. .option('extension', {
  121. alias: 'e',
  122. default: [],
  123. describe: 'a list of extensions that nyc should handle in addition to .js',
  124. global: false
  125. })
  126. .option('check-coverage', {
  127. type: 'boolean',
  128. default: false,
  129. describe: 'check whether coverage is within thresholds provided',
  130. global: false
  131. })
  132. .option('branches', {
  133. default: 0,
  134. description: 'what % of branches must be covered?',
  135. global: false
  136. })
  137. .option('functions', {
  138. default: 0,
  139. description: 'what % of functions must be covered?',
  140. global: false
  141. })
  142. .option('lines', {
  143. default: 90,
  144. description: 'what % of lines must be covered?',
  145. global: false
  146. })
  147. .option('statements', {
  148. default: 0,
  149. description: 'what % of statements must be covered?',
  150. global: false
  151. })
  152. .option('source-map', {
  153. default: true,
  154. type: 'boolean',
  155. description: 'should nyc detect and handle source maps?',
  156. global: false
  157. })
  158. .option('per-file', {
  159. default: false,
  160. type: 'boolean',
  161. description: 'check thresholds per file',
  162. global: false
  163. })
  164. .option('produce-source-map', {
  165. default: false,
  166. type: 'boolean',
  167. description: "should nyc's instrumenter produce source maps?",
  168. global: false
  169. })
  170. .option('compact', {
  171. default: true,
  172. type: 'boolean',
  173. description: 'should the output be compacted?'
  174. })
  175. .option('preserve-comments', {
  176. default: true,
  177. type: 'boolean',
  178. description: 'should comments be preserved in the output?'
  179. })
  180. .option('instrument', {
  181. default: true,
  182. type: 'boolean',
  183. description: 'should nyc handle instrumentation?',
  184. global: false
  185. })
  186. .option('hook-require', {
  187. default: true,
  188. type: 'boolean',
  189. description: 'should nyc wrap require?',
  190. global: false
  191. })
  192. .option('hook-run-in-context', {
  193. default: false,
  194. type: 'boolean',
  195. description: 'should nyc wrap vm.runInContext?',
  196. global: false
  197. })
  198. .option('hook-run-in-this-context', {
  199. default: false,
  200. type: 'boolean',
  201. description: 'should nyc wrap vm.runInThisContext?',
  202. global: false
  203. })
  204. .option('show-process-tree', {
  205. describe: 'display the tree of spawned processes',
  206. default: false,
  207. type: 'boolean',
  208. global: false
  209. })
  210. .option('clean', {
  211. describe: 'should the .nyc_output folder be cleaned before executing tests',
  212. default: true,
  213. type: 'boolean',
  214. global: false
  215. })
  216. .option('nycrc-path', {
  217. default: '.nycrc',
  218. description: 'specify a different .nycrc path',
  219. global: false
  220. })
  221. .option('temp-dir', {
  222. alias: 't',
  223. describe: 'directory to output raw coverage information to',
  224. default: './.nyc_output',
  225. global: false
  226. })
  227. .option('temp-directory', {
  228. hidden: true,
  229. global: false
  230. })
  231. .option('skip-empty', {
  232. describe: 'don\'t show empty files (no lines of code) in report',
  233. default: false,
  234. type: 'boolean',
  235. global: false
  236. })
  237. .option('skip-full', {
  238. describe: 'don\'t show files with 100% statement, branch, and function coverage',
  239. default: false,
  240. type: 'boolean',
  241. global: false
  242. })
  243. .pkgConf('nyc', cwd)
  244. .example('$0 npm test', 'instrument your tests with coverage')
  245. .example('$0 --require @babel/register npm test', 'instrument your tests with coverage and transpile with Babel')
  246. .example('$0 report --reporter=text-lcov', 'output lcov report after running your tests')
  247. .epilog('visit https://git.io/vHysA for list of available reporters')
  248. .boolean('h')
  249. .boolean('version')
  250. .help(false)
  251. .version(false)
  252. }
  253. // we add operations that would make yargs
  254. // exit post-hoc, allowing for a multi-pass
  255. // parsing step.
  256. Config.addCommandsAndHelp = function (yargs) {
  257. return yargs
  258. .help('h')
  259. .alias('h', 'help')
  260. .version()
  261. .command(require('../lib/commands/check-coverage'))
  262. .command(require('../lib/commands/instrument'))
  263. .command(require('../lib/commands/report'))
  264. .command(require('../lib/commands/merge'))
  265. }
  266. module.exports = Config