diff --git a/README.md b/README.md index 3a4879c..b79fdcd 100644 --- a/README.md +++ b/README.md @@ -179,19 +179,25 @@ jest-runner-eslint maps a lot of ESLint CLI arguments to config options. For exa |option|default|example |-----|-----|-----| +|cache|`false`|`"cache": true` |cacheLocation|`.eslintcache`|`"cacheLocation": "/path/to/cache"` |config|`null`|`"config": "/path/to/config"` |env|`null`|`"env": "mocha"` or `"env": ["mocha", "other"]` |ext|`[".js"]`|`"ext": ".jsx"` or `"ext": [".jsx", ".ts"]` |fix|`false`|`"fix": true` +|fixDryRun|`false`|`"fixDryRun": true` |format|`null`|`"format": "codeframe"` |global|`[]`|`"global": "it"` or `"global": ["it", "describe"]` |ignorePath|`null`|`"ignorePath": "/path/to/ignore"` +|ignorePattern|`[]`|`"ignorePattern": ["/path/to/ignore/*"]` +|maxWarnings|`-1`|`"maxWarnings": 0` |noEslintrc|`false`|`"noEslintrc": true` |noIgnore|`false`|`"noIgnore": true` |noInlineConfig|`false`|`"noInlineConfig": true` |parser|`espree`|`"parser": "flow"` |parserOptions|`{}`|`"parserOptions": { "myOption": true }` |plugin|`[]`|`"plugin": "prettier"` or `"plugin": ["pettier", "other"]` +|quiet|`true`|`"quiet": false` +|reportUnusedDisableDirectives|`false`|`"reportUnusedDisableDirectives": true` |rules|`null`|`"rules": {"quotes": [2, "double"]}` or `"rules": {"quotes": [2, "double"], "no-console": 2}` |rulesdir|`[]`|`"rulesdir": "/path/to/rules/dir"` or `"env": ["/path/to/rules/dir", "/path/to/other"]` diff --git a/integrationTests/__fixtures__/loud/.eslintrc.json b/integrationTests/__fixtures__/loud/.eslintrc.json new file mode 100644 index 0000000..6479217 --- /dev/null +++ b/integrationTests/__fixtures__/loud/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "no-console": "warn" + } +} diff --git a/integrationTests/__fixtures__/loud/__eslint__/file.js b/integrationTests/__fixtures__/loud/__eslint__/file.js new file mode 100644 index 0000000..7720ff4 --- /dev/null +++ b/integrationTests/__fixtures__/loud/__eslint__/file.js @@ -0,0 +1,3 @@ +const a = 1; + +console.log('a', a); diff --git a/integrationTests/__fixtures__/loud/jest-runner-eslint.config.js b/integrationTests/__fixtures__/loud/jest-runner-eslint.config.js new file mode 100644 index 0000000..eed5540 --- /dev/null +++ b/integrationTests/__fixtures__/loud/jest-runner-eslint.config.js @@ -0,0 +1,5 @@ +module.exports = { + cliOptions: { + quiet: false, + }, +}; diff --git a/integrationTests/__fixtures__/loud/jest.config.js b/integrationTests/__fixtures__/loud/jest.config.js new file mode 100644 index 0000000..94f5944 --- /dev/null +++ b/integrationTests/__fixtures__/loud/jest.config.js @@ -0,0 +1,4 @@ +module.exports = { + runner: '../../../', + testMatch: ['**/__eslint__/**/*.js'], +}; diff --git a/integrationTests/__fixtures__/max-warnings/.eslintrc.json b/integrationTests/__fixtures__/max-warnings/.eslintrc.json new file mode 100644 index 0000000..6479217 --- /dev/null +++ b/integrationTests/__fixtures__/max-warnings/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "no-console": "warn" + } +} diff --git a/integrationTests/__fixtures__/max-warnings/__eslint__/file.js b/integrationTests/__fixtures__/max-warnings/__eslint__/file.js new file mode 100644 index 0000000..a43a59c --- /dev/null +++ b/integrationTests/__fixtures__/max-warnings/__eslint__/file.js @@ -0,0 +1,5 @@ +const a = 1; + +console.log('a', a); +console.log('a', a); +console.log('a', a); diff --git a/integrationTests/__fixtures__/max-warnings/jest-runner-eslint.config.js b/integrationTests/__fixtures__/max-warnings/jest-runner-eslint.config.js new file mode 100644 index 0000000..fec1385 --- /dev/null +++ b/integrationTests/__fixtures__/max-warnings/jest-runner-eslint.config.js @@ -0,0 +1,5 @@ +module.exports = { + cliOptions: { + maxWarnings: 2, + }, +}; diff --git a/integrationTests/__fixtures__/max-warnings/jest.config.js b/integrationTests/__fixtures__/max-warnings/jest.config.js new file mode 100644 index 0000000..94f5944 --- /dev/null +++ b/integrationTests/__fixtures__/max-warnings/jest.config.js @@ -0,0 +1,4 @@ +module.exports = { + runner: '../../../', + testMatch: ['**/__eslint__/**/*.js'], +}; diff --git a/integrationTests/__snapshots__/loud.test.js.snap b/integrationTests/__snapshots__/loud.test.js.snap new file mode 100644 index 0000000..2f22b3b --- /dev/null +++ b/integrationTests/__snapshots__/loud.test.js.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Outputs warnings as console messages 1`] = ` +"PASS integrationTests/__fixtures__/loud/__eslint__/file.js + ● Console + console.warn + /mocked-path-to-jest-runner-mocha/integrationTests/__fixtures__/loud/__eslint__/file.js + 3:1 warning Unexpected console statement no-console + ✖ 1 problem (0 errors, 1 warning) + ✓ ESLint +Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +Snapshots: 0 total +Time: +Ran all test suites. +" +`; diff --git a/integrationTests/__snapshots__/max-warnings.test.js.snap b/integrationTests/__snapshots__/max-warnings.test.js.snap new file mode 100644 index 0000000..6e5f6c5 --- /dev/null +++ b/integrationTests/__snapshots__/max-warnings.test.js.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Fails if more than max warnings 1`] = ` +"FAIL integrationTests/__fixtures__/max-warnings/__eslint__/file.js +/mocked-path-to-jest-runner-mocha/integrationTests/__fixtures__/max-warnings/__eslint__/file.js + 3:1 warning Unexpected console statement no-console + 4:1 warning Unexpected console statement no-console + 5:1 warning Unexpected console statement no-console +✖ 3 problems (0 errors, 3 warnings) +ESLint found too many warnings (maximum: 2). + ✕ ESLint +Test Suites: 1 failed, 1 total +Tests: 1 failed, 1 total +Snapshots: 0 total +Time: +Ran all test suites. + +" +`; diff --git a/integrationTests/loud.test.js b/integrationTests/loud.test.js new file mode 100644 index 0000000..d79e2f8 --- /dev/null +++ b/integrationTests/loud.test.js @@ -0,0 +1,5 @@ +const runJest = require('./runJest'); + +it('Outputs warnings as console messages', () => { + return expect(runJest('loud')).resolves.toMatchSnapshot(); +}); diff --git a/integrationTests/max-warnings.test.js b/integrationTests/max-warnings.test.js new file mode 100644 index 0000000..92d7629 --- /dev/null +++ b/integrationTests/max-warnings.test.js @@ -0,0 +1,5 @@ +const runJest = require('./runJest'); + +it('Fails if more than max warnings', () => { + return expect(runJest('max-warnings')).resolves.toMatchSnapshot(); +}); diff --git a/src/runESLint.js b/src/runESLint.js index cf10ac9..1944828 100644 --- a/src/runESLint.js +++ b/src/runESLint.js @@ -12,7 +12,15 @@ const runESLint = ({ testPath, config }) => { const { CLIEngine } = getLocalESLint(config); const options = getESLintOptions(config); - const cli = new CLIEngine(options.cliOptions); + const quiet = options.cliOptions && options.cliOptions.quiet; + const cli = new CLIEngine( + Object.assign({}, options.cliOptions, { + fix: + options.cliOptions && + (options.cliOptions.fix || options.cliOptions.fixDryRun) && + (quiet ? ({ severity }) => severity === 2 : true), + }), + ); if (cli.isPathIgnored(testPath)) { const end = Date.now(); return skip({ start, end, test: { path: testPath, title: 'ESLint' } }); @@ -20,15 +28,35 @@ const runESLint = ({ testPath, config }) => { const report = cli.executeOnFiles([testPath]); - if (options.cliOptions && options.cliOptions.fix) { + if ( + options.cliOptions && + options.cliOptions.fix && + !options.cliOptions.fixDryRun + ) { CLIEngine.outputFixes(report); } const end = Date.now(); - if (report.errorCount > 0) { + const tooManyWarnings = + options.cliOptions && + options.cliOptions.maxWarnings != null && + options.cliOptions.maxWarnings >= 0 && + report.warningCount > options.cliOptions.maxWarnings; + + const format = () => { const formatter = cli.getFormatter(options.cliOptions.format); - const errorMessage = formatter(CLIEngine.getErrorResults(report.results)); + return formatter( + quiet ? CLIEngine.getErrorResults(report.results) : report.results, + ); + }; + + if (report.errorCount > 0 || tooManyWarnings) { + let errorMessage = format(); + + if (!report.errorCount && tooManyWarnings) + errorMessage += `\nESLint found too many warnings (maximum: ${options + .cliOptions.maxWarnings}).`; return fail({ start, @@ -37,7 +65,17 @@ const runESLint = ({ testPath, config }) => { }); } - return pass({ start, end, test: { path: testPath, title: 'ESLint' } }); + const result = pass({ + start, + end, + test: { path: testPath, title: 'ESLint' }, + }); + + if (!quiet && report.warningCount > 0) { + result.console = [{ message: format(), origin: '', type: 'warn' }]; + } + + return result; }; module.exports = runESLint; diff --git a/src/utils/normalizeConfig.js b/src/utils/normalizeConfig.js index 46002a5..e85924b 100644 --- a/src/utils/normalizeConfig.js +++ b/src/utils/normalizeConfig.js @@ -1,8 +1,12 @@ const identity = v => v; const negate = v => !v; const asArray = v => (typeof v === 'string' ? [v] : v); +const asInt = v => (typeof v === 'number' ? v : parseInt(v, 10)); const BASE_CONFIG = { + cache: { + default: false, + }, cacheLocation: { default: '.eslintcache', }, @@ -23,6 +27,9 @@ const BASE_CONFIG = { fix: { default: false, }, + fixDryRun: { + default: false, + }, format: { default: null, }, @@ -34,6 +41,14 @@ const BASE_CONFIG = { ignorePath: { default: null, }, + ignorePattern: { + default: [], + transform: asArray, + }, + maxWarnings: { + default: -1, + transform: asInt, + }, noEslintrc: { name: 'useEslintrc', default: false, @@ -60,6 +75,12 @@ const BASE_CONFIG = { default: [], transform: asArray, }, + quiet: { + default: false, + }, + reportUnusedDisableDirectives: { + default: false, + }, rules: { default: null, },