UNPKG

2.65 kBJavaScriptView Raw
1'use strict';
2
3/**
4 * Responsible for loading / finding Mocha's "rc" files.
5 * This doesn't have anything to do with `mocha.opts`.
6 *
7 * @private
8 * @module
9 */
10
11const fs = require('fs');
12const path = require('path');
13const debug = require('debug')('mocha:cli:config');
14const findUp = require('find-up');
15
16/**
17 * These are the valid config files, in order of precedence;
18 * e.g., if `.mocharc.js` is present, then `.mocharc.yaml` and the rest
19 * will be ignored.
20 * The user should still be able to explicitly specify a file.
21 * @private
22 */
23exports.CONFIG_FILES = [
24 '.mocharc.cjs',
25 '.mocharc.js',
26 '.mocharc.yaml',
27 '.mocharc.yml',
28 '.mocharc.jsonc',
29 '.mocharc.json'
30];
31
32const isModuleNotFoundError = err =>
33 err.code !== 'MODULE_NOT_FOUND' ||
34 err.message.indexOf('Cannot find module') !== -1;
35
36/**
37 * Parsers for various config filetypes. Each accepts a filepath and
38 * returns an object (but could throw)
39 */
40const parsers = (exports.parsers = {
41 yaml: filepath =>
42 require('js-yaml').safeLoad(fs.readFileSync(filepath, 'utf8')),
43 js: filepath => {
44 const cwdFilepath = path.resolve(filepath);
45 try {
46 debug(`parsers: load using cwd-relative path: "${cwdFilepath}"`);
47 return require(cwdFilepath);
48 } catch (err) {
49 if (isModuleNotFoundError(err)) {
50 debug(`parsers: retry load as module-relative path: "${filepath}"`);
51 return require(filepath);
52 } else {
53 throw err; // rethrow
54 }
55 }
56 },
57 json: filepath =>
58 JSON.parse(
59 require('strip-json-comments')(fs.readFileSync(filepath, 'utf8'))
60 )
61});
62
63/**
64 * Loads and parses, based on file extension, a config file.
65 * "JSON" files may have comments.
66 *
67 * @private
68 * @param {string} filepath - Config file path to load
69 * @returns {Object} Parsed config object
70 */
71exports.loadConfig = filepath => {
72 let config = {};
73 debug(`loadConfig: "${filepath}"`);
74
75 const ext = path.extname(filepath);
76 try {
77 if (ext === '.yml' || ext === '.yaml') {
78 config = parsers.yaml(filepath);
79 } else if (ext === '.js' || ext === '.cjs') {
80 config = parsers.js(filepath);
81 } else {
82 config = parsers.json(filepath);
83 }
84 } catch (err) {
85 throw new Error(`failed to parse config "${filepath}": ${err}`);
86 }
87 return config;
88};
89
90/**
91 * Find ("find up") config file starting at `cwd`
92 *
93 * @param {string} [cwd] - Current working directory
94 * @returns {string|null} Filepath to config, if found
95 */
96exports.findConfig = (cwd = process.cwd()) => {
97 const filepath = findUp.sync(exports.CONFIG_FILES, {cwd});
98 if (filepath) {
99 debug(`findConfig: found "${filepath}"`);
100 }
101 return filepath;
102};