Skip to content

Commit

Permalink
Additional Configuration File Support (bcoe#436)
Browse files Browse the repository at this point in the history
feat: Adding additional configuration file options
test: unit test for config file detection
test: unit test for config files pass via the cli
test: unit test case for early exit of hideInstrumenteeArgs
test: unit test for Node.js argument handling
fix: bug in spawning of c8 process that dropped coverage significantly
  • Loading branch information
mcknasty committed Jan 20, 2024
1 parent 2ee581c commit feb6dfd
Show file tree
Hide file tree
Showing 42 changed files with 1,122 additions and 33 deletions.
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,25 @@ The above example will output coverage metrics for `foo.js`.

## CLI Options / Configuration

c8 can be configured via command-line flags, a `c8` section in `package.json`, or a JSON configuration file on disk.

A configuration file can be specified by passing its path on the command line with `--config` or `-c`. If no config option is provided, c8 searches for files named `.c8rc`, `.c8rc.json`, `.nycrc`, or `.nycrc.json`, starting from
`cwd` and walking up the filesystem tree.
c8 can be configured via command-line flags, a `c8` section in `package.json`, or a configuration file on disk.

When using `package.json` configuration or a dedicated configuration file, omit the `--` prefix from the long-form of the desired command-line option.

A configuration file can be specified by passing its path on the command line with `--config` or `-c`. If no config option is provided, c8 searches for files named in the table below starting from `cwd` and walking up the filesystem tree.

A robust configuration file naming convention is available in an effort to stay compatible with nyc configuration options and ensure dynamic configuration.

| File name | File Association |
|-----------------------------------------------------------------------------------------------------|--------------------|
| `.c8rc`, `.c8rc.json` | JSON |
| `.c8rc.yml`, `.c8rc.yaml` | YAML |
| `.c8rc.js`, `.c8rc.cjs`, `.c8.config.js`, `.c8.config.cjs`, `c8.config.js`, `c8.config.cjs` | CommonJS export* |
| `.nycrc`, `.nycrc.json` | JSON |
| `.nycrc.yaml`, `.nycrc.yml` | YAML |
| `.nycrc.js`, `.nycrc.cjs`, `nyc.config.js`, `nyc.config.cjs`, `.nyc.config.js`, `.nyc.config.cjs` | CommonJS export* |

For packages written in ESM module syntax, a static configuration option is supported in JSON or YAML syntax. A dynamic configuration is also supported. These configuration files must be written in CommonJS utilizing one of the .cjs file options in the table above. At the moment ESM syntax is not supported for writing c8 configuration files. This may change in the future, but please note, C8 is written in CommonJS syntax.

Here is a list of common options. Run `c8 --help` for the full list and documentation.

| Option | Description | Type | Default |
Expand Down
58 changes: 53 additions & 5 deletions lib/parse-args.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ const { readFileSync } = require('fs')
const Yargs = require('yargs/yargs')
const { applyExtends } = require('yargs/helpers')
const parser = require('yargs-parser')
const { resolve } = require('path')
const { resolve, extname, basename } = require('path')

function buildYargs (withCommands = false) {
const yargs = Yargs([])
.usage('$0 [opts] [script] [opts]')
.options('config', {
alias: 'c',
config: true,
describe: 'path to JSON configuration file',
describe: 'path to configuration file',
configParser: (path) => {
const config = JSON.parse(readFileSync(path))
const config = loadConfigFile(path)
return applyExtends(config, process.cwd(), true)
},
default: () => findUp.sync(['.c8rc', '.c8rc.json', '.nycrc', '.nycrc.json'])
default: () => findUp.sync(getConfigFileNames())
})
.option('reporter', {
alias: 'r',
Expand Down Expand Up @@ -194,6 +194,52 @@ function buildYargs (withCommands = false) {
return yargs
}

function loadConfigFile (path) {
let config = {}
const jsExts = ['.js', '.cjs']
const ymlExts = ['.yml', '.yaml']
const fileName = basename(path)

const ext = extname(path).toLowerCase()
if (jsExts.includes(ext)) {
config = require(path)
} else if (ymlExts.includes(ext)) {
config = require('js-yaml').load(readFileSync(path, 'utf8'))
} else if (ext === '.json' || fileName.slice(-2) === 'rc') {
config = JSON.parse(readFileSync(path, 'utf8'))
}

// Should the process die if none of these filename extensions are found?
if (Object.keys(config).length === 0) {
throw new Error(`Unsupported file type ${ext} while reading file ${path}`)
}

return config
}

function getConfigFileNames () {
return [
'.c8rc',
'.c8rc.json',
'.c8rc.yml',
'.c8rc.yaml',
'.c8rc.js',
'.c8rc.cjs',
'.c8.config.js',
'.c8.config.cjs',
'c8.config.js',
'c8.config.cjs',
'.nycrc',
'.nycrc.json',
'.nycrc.yml',
'.nycrc.yaml',
'.nyc.config.js',
'.nyc.config.cjs',
'nyc.config.js',
'nyc.config.cjs'
]
}

function hideInstrumenterArgs (yargv) {
let argv = process.argv.slice(1)
argv = argv.slice(argv.indexOf(yargv._[0]))
Expand All @@ -220,5 +266,7 @@ function hideInstrumenteeArgs () {
module.exports = {
buildYargs,
hideInstrumenterArgs,
hideInstrumenteeArgs
hideInstrumenteeArgs,
getConfigFileNames,
loadConfigFile
}
33 changes: 15 additions & 18 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"istanbul-lib-coverage": "^3.2.0",
"istanbul-lib-report": "^3.0.1",
"istanbul-reports": "^3.1.6",
"js-yaml": "^4.1.0",
"test-exclude": "^6.0.0",
"v8-to-istanbul": "^9.0.0",
"yargs": "^17.7.2",
Expand Down
11 changes: 11 additions & 0 deletions test/fixtures/config/.c8.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const config = {
"reporter": [
"html",
"text"
],
"lines": 45,
"branches": "72",
"statements": "65"
}

module.exports = config
11 changes: 11 additions & 0 deletions test/fixtures/config/.c8.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const config = {
"reporter": [
"html",
"text"
],
"lines": 47,
"branches": "72",
"statements": "65"
}

module.exports = config
11 changes: 11 additions & 0 deletions test/fixtures/config/.c8.config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const config = {
"reporter": [
"html",
"text"
],
"lines": 45,
"branches": "72",
"statements": "65"
}

module.exports = config
10 changes: 10 additions & 0 deletions test/fixtures/config/.c8rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"reporter": [
"lcov",
"json"
],
"statements": 29,
"branches": 81,
"lines": 78,
"functions": 93
}
11 changes: 11 additions & 0 deletions test/fixtures/config/.c8rc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const config = {
"reporter": [
"html",
"text"
],
"lines": 32,
"branches": "72",
"statements": "65"
}

module.exports = config
11 changes: 11 additions & 0 deletions test/fixtures/config/.c8rc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const config = {
"reporter": [
"html",
"text"
],
"lines": 22,
"branches": "72",
"statements": "65"
}

module.exports = config
8 changes: 8 additions & 0 deletions test/fixtures/config/.c8rc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
reporter:
- html
- text
statements: 83
branches: 88
lines: 10
functions: 12
8 changes: 8 additions & 0 deletions test/fixtures/config/.c8rc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
reporter:
- html
- text
statements: 89
branches: 58
lines: 69
functions: 54
12 changes: 12 additions & 0 deletions test/fixtures/config/.nyc.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const config = {
"reporter": [
"html",
"text"
],
"statements": 54,
"branches": 40,
"lines": 71,
"functions": 0
}

module.exports = config
12 changes: 12 additions & 0 deletions test/fixtures/config/.nyc.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const config = {
"reporter": [
"html",
"text"
],
"statements": 54,
"branches": 40,
"lines": 85,
"functions": 0
}

module.exports = config
7 changes: 7 additions & 0 deletions test/fixtures/config/.nycrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"statements": 95,
"branches": 40,
"lines": 51,
"functions": 89
}

9 changes: 9 additions & 0 deletions test/fixtures/config/.nycrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"reporter": [
"html",
"text"
],
"lines": 96,
"branches": "82",
"statements": "95"
}
7 changes: 7 additions & 0 deletions test/fixtures/config/.nycrc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
reporter:
- html
- text
lines: 98
branches: '82'
statements: '95'
7 changes: 7 additions & 0 deletions test/fixtures/config/.nycrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
reporter:
- html
- text
lines: 99
branches: '82'
statements: '95'
12 changes: 12 additions & 0 deletions test/fixtures/config/c8.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const config = {
"reporter": [
"html",
"text"
],
"statements": 95,
"branches": 40,
"lines": 51,
"functions": 89
}

module.exports = config
12 changes: 12 additions & 0 deletions test/fixtures/config/c8.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const config = {
"reporter": [
"html",
"text"
],
"statements": 54,
"branches": 40,
"lines": 47,
"functions": 0
}

module.exports = config
Loading

0 comments on commit feb6dfd

Please sign in to comment.