diff --git a/README.md b/README.md index 415f982..3eaf059 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,26 @@ module.exports = { yarn jest ``` +## Toggle `--fix` in watch mode + +`jest-eslint-runner` comes with a watch plugin that allows you to toggle the `--fix` value while in watch mode without having to update your configuration. + +![fix](https://user-images.githubusercontent.com/574806/46181271-93205080-c279-11e8-8d73-b4c5e11086c4.gif) + +To use this watch plugin simply add this to your Jest configuration. + +```js +{ + watchPlugins: ['jest-runner-eslint/watch-fix'], +} +``` + +After this run Jest in watch mode and you will see the following line in your watch usage menu + +``` + › Press F to override ESLint --fix. +``` + ## Options This project uses [cosmiconfig](https://github.com/davidtheclark/cosmiconfig), so you can provide config via: diff --git a/jest.config.js b/jest.config.js index 365ca77..caed5f7 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,6 +3,7 @@ module.exports = { 'jest-watch-typeahead/filename', 'jest-watch-typeahead/testname', 'jest-watch-select-projects', + './watch-fix', ], projects: [ { diff --git a/package.json b/package.json index d2fea78..b2ed82b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "jest-runner-eslint", "version": "0.6.0", - "main": "build/index.js", + "main": "build/runner", "author": "Rogelio Guzman ", "description": "An experimental ESLint runner for Jest", "license": "MIT", @@ -23,6 +23,7 @@ "format": "prettier --write \"**/*.js\"" }, "dependencies": { + "chalk": "^2.4.1", "cosmiconfig": "^5.0.0", "create-jest-runner": "^0.4.1", "eslint": "^5.6.0", diff --git a/src/index.js b/src/index.js deleted file mode 100644 index d258fc6..0000000 --- a/src/index.js +++ /dev/null @@ -1,5 +0,0 @@ -const { createJestRunner } = require('create-jest-runner'); - -const runner = createJestRunner(require.resolve('./runESLint')); - -module.exports = runner; diff --git a/src/__tests__/runESLint.test.js b/src/runner/__tests__/runESLint.test.js similarity index 95% rename from src/__tests__/runESLint.test.js rename to src/runner/__tests__/runESLint.test.js index bc2d443..e23910c 100644 --- a/src/__tests__/runESLint.test.js +++ b/src/runner/__tests__/runESLint.test.js @@ -3,7 +3,7 @@ const path = require('path'); const runESLintRunnerWithMockedEngine = options => { jest.resetModules(); - jest.doMock('../utils/getLocalESLint', () => () => { + jest.doMock('../../utils/getLocalESLint', () => () => { return { CLIEngine: class { isPathIgnored(file) { @@ -24,7 +24,7 @@ const runESLintRunnerWithMockedEngine = options => { }); const runESLint = require('../runESLint'); - return runESLint(options.runESLint); + return runESLint({ extraOptions: {}, ...options.runESLint }); }; it('Requires the config setupTestFrameworkScriptFile when specified', () => { diff --git a/src/runner/index.js b/src/runner/index.js new file mode 100644 index 0000000..ea66206 --- /dev/null +++ b/src/runner/index.js @@ -0,0 +1,8 @@ +const { createJestRunner } = require('create-jest-runner'); +const configOverrides = require('../utils/configOverrides'); + +const runner = createJestRunner(require.resolve('./runESLint'), { + getExtraOptions: () => ({ fix: configOverrides.getFix() }), +}); + +module.exports = runner; diff --git a/src/runESLint.js b/src/runner/runESLint.js similarity index 81% rename from src/runESLint.js rename to src/runner/runESLint.js index 5e604ea..699335f 100644 --- a/src/runESLint.js +++ b/src/runner/runESLint.js @@ -1,6 +1,6 @@ const { pass, fail, skip } = require('create-jest-runner'); -const getLocalESLint = require('./utils/getLocalESLint'); -const getESLintOptions = require('./utils/getESLintOptions'); +const getLocalESLint = require('../utils/getLocalESLint'); +const getESLintOptions = require('../utils/getESLintOptions'); const getComputedFixValue = ({ fix, quiet, fixDryRun }) => { if (fix || fixDryRun) { @@ -9,7 +9,7 @@ const getComputedFixValue = ({ fix, quiet, fixDryRun }) => { return undefined; }; -const runESLint = ({ testPath, config }) => { +const runESLint = ({ testPath, config, extraOptions }) => { const start = Date.now(); if (config.setupTestFrameworkScriptFile) { @@ -18,12 +18,14 @@ const runESLint = ({ testPath, config }) => { } const { CLIEngine } = getLocalESLint(config); - const { cliOptions } = getESLintOptions(config); - const cli = new CLIEngine( - Object.assign({}, cliOptions, { - fix: getComputedFixValue(cliOptions), - }), - ); + const { cliOptions: baseCliOptions } = getESLintOptions(config); + const cliOptions = { + ...baseCliOptions, + fix: getComputedFixValue(baseCliOptions), + ...extraOptions, + }; + + const cli = new CLIEngine(cliOptions); if (cli.isPathIgnored(testPath)) { const end = Date.now(); diff --git a/src/utils/configOverrides.js b/src/utils/configOverrides.js new file mode 100644 index 0000000..82423be --- /dev/null +++ b/src/utils/configOverrides.js @@ -0,0 +1,13 @@ +class ConfigOverrides { + setFix(fix) { + this.fix = fix; + } + + getFix() { + return this.fix; + } +} + +const configOverrides = new ConfigOverrides(); + +module.exports = configOverrides; diff --git a/src/watchFixPlugin/__tests__/index.test.js b/src/watchFixPlugin/__tests__/index.test.js new file mode 100644 index 0000000..0639dcf --- /dev/null +++ b/src/watchFixPlugin/__tests__/index.test.js @@ -0,0 +1,66 @@ +/* eslint-disable global-require */ +const chalk = require('chalk'); + +jest.doMock('chalk', () => new chalk.constructor({ enabled: false })); + +jest.useFakeTimers(); + +let WatchFixPlugin; +let configOverrides; + +describe('watchFixPlugin', () => { + beforeEach(() => { + jest.resetModules(); + configOverrides = require('../../utils/configOverrides'); + WatchFixPlugin = require('../'); + }); + + it('shows the correct prompt', async () => { + const stdout = { write: jest.fn() }; + const config = {}; + const plugin = new WatchFixPlugin({ stdout, config }); + expect(plugin.getUsageInfo()).toEqual({ + key: 'F', + prompt: 'override ESLint --fix', + }); + + await plugin.run(plugin); + + expect(plugin.getUsageInfo()).toEqual({ + key: 'F', + prompt: 'toggle ESLint --fix (enabled)', + }); + + await plugin.run(plugin); + + expect(plugin.getUsageInfo()).toEqual({ + key: 'F', + prompt: 'toggle ESLint --fix (disabled)', + }); + }); + + it('overrides the setting in configOverrides after each invocation', async () => { + const stdout = { write: jest.fn() }; + const config = {}; + const plugin = new WatchFixPlugin({ stdout, config }); + expect(configOverrides.getFix()).toBeUndefined(); + + await plugin.run(plugin); + + expect(configOverrides.getFix()).toBe(true); + + await plugin.run(plugin); + + expect(configOverrides.getFix()).toBe(false); + }); + + it('can customize the key', () => { + const stdout = { write: jest.fn() }; + const config = { key: 'z' }; + const plugin = new WatchFixPlugin({ stdout, config }); + expect(plugin.getUsageInfo()).toEqual({ + key: 'z', + prompt: 'override ESLint --fix', + }); + }); +}); diff --git a/src/watchFixPlugin/index.js b/src/watchFixPlugin/index.js new file mode 100644 index 0000000..e045cae --- /dev/null +++ b/src/watchFixPlugin/index.js @@ -0,0 +1,36 @@ +const chalk = require('chalk'); +const configOverrides = require('../utils/configOverrides'); + +class ESLintWatchFixPlugin { + constructor({ stdout, config }) { + this._stdout = stdout; + this._key = config.key || 'F'; + } + + // eslint-disable-next-line class-methods-use-this + async run() { + const fix = configOverrides.getFix(); + configOverrides.setFix(!fix); + return true; + } + + getUsageInfo() { + const getPrompt = () => { + const fix = configOverrides.getFix(); + if (fix === undefined) { + return 'override ESLint --fix'; + } + if (!fix) { + return `toggle ESLint --fix ${chalk.italic('(disabled)')}`; + } + return `toggle ESLint --fix ${chalk.italic('(enabled)')}`; + }; + + return { + key: this._key, + prompt: getPrompt(), + }; + } +} + +module.exports = ESLintWatchFixPlugin; diff --git a/watch-fix.js b/watch-fix.js new file mode 100644 index 0000000..fc85e64 --- /dev/null +++ b/watch-fix.js @@ -0,0 +1,3 @@ +const ESLintWatchFixPlugin = require('./build/watchFixPlugin'); + +module.exports = ESLintWatchFixPlugin;