├── .gitignore ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── .eslintrc.json ├── LICENSE ├── package.json ├── src ├── index.js └── index.test.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .eslintrc.json 2 | .gitignore 3 | *.test.js 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 6 4 | - 8 5 | - 10 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Please visit the [Releases page](https://github.com/jest-community/jest-watch-toggle-coverage/releases) for changelogs. 2 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["standard", "prettier", "plugin:import/recommended"], 3 | "plugins": ["import", "node", "promise", "standard", "prettier"], 4 | "env": { 5 | "jest": true, 6 | "node": true 7 | }, 8 | "parserOptions": { 9 | "ecmaVersion": "latest" 10 | }, 11 | "rules": { 12 | "prettier/prettier": [ 13 | "error", 14 | { 15 | "arrowParens": "always", 16 | "semi": false, 17 | "singleQuote": true, 18 | "trailingComma": "es5" 19 | } 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Christophe Porteneuve & Delicious Insights 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jest-watch-toggle-config", 3 | "version": "3.0.0", 4 | "description": "Jest watch plugin for toggling boolean settings (e.g. verbosity, test coverage)", 5 | "main": "src/index.js", 6 | "engines": { 7 | "node": ">= 16" 8 | }, 9 | "type": "module", 10 | "scripts": { 11 | "lint": "eslint src", 12 | "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest" 13 | }, 14 | "keywords": [ 15 | "jest", 16 | "plugin", 17 | "watch", 18 | "toggle" 19 | ], 20 | "author": "Christophe Porteneuve (https://delicious-insights.com/)", 21 | "bugs": { 22 | "url": "https://github.com/jest-community/jest-watch-toggle-config/issues" 23 | }, 24 | "license": "MIT", 25 | "repository": { 26 | "type": "git", 27 | "url": "git@github.com/jest-community/jest-watch-toggle-config" 28 | }, 29 | "jest": { 30 | "transform": {} 31 | }, 32 | "devDependencies": { 33 | "cross-env": "^7.0.3", 34 | "eslint": "^8.39.0", 35 | "eslint-config-prettier": "^8.8.0", 36 | "eslint-config-standard": "^17.0.0", 37 | "eslint-plugin-import": "^2.22.0", 38 | "eslint-plugin-node": "^11.1.0", 39 | "eslint-plugin-prettier": "^4.2.1", 40 | "eslint-plugin-promise": "^6.1.1", 41 | "eslint-plugin-standard": "^5.0.0", 42 | "jest": "^29.5.0", 43 | "prettier": "^2.8.8" 44 | }, 45 | "peerDependencies": { 46 | "jest": ">= 23.4.1" 47 | }, 48 | "dependencies": { 49 | "chalk": "^5.2.0" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { ValidationError } from 'jest-validate' 2 | import chalk from 'chalk' 3 | 4 | export default class JestWatchTogglePlugin { 5 | constructor({ config } = {}) { 6 | if (!config) { 7 | errorOut( 8 | `Missing plugin configuration. Are you sure you’re using ${chalk.bold.red( 9 | 'Jest 23.3+' 10 | )}?` 11 | ) 12 | } 13 | 14 | this.setting = getConfigValue(config, 'setting') 15 | 16 | if (!this.setting) { 17 | errorOut( 18 | `${this.constructor.name} needs at least a ${chalk.bold.red( 19 | 'setting' 20 | )} configuration parameter` 21 | ) 22 | } 23 | 24 | const defaults = DEFAULT_CONFIG[this.setting] || {} 25 | this.key = 26 | getConfigValue(config, 'key', defaults) || this.setting[0].toLowerCase() 27 | this.prompt = 28 | getConfigValue(config, 'prompt', defaults) || 29 | `turn %ONOFF% ${this.setting}` 30 | } 31 | 32 | getUsageInfo(globalConfig) { 33 | const targetMode = globalConfig[this.setting] ? 'off' : 'on' 34 | return { 35 | key: this.key, 36 | prompt: this.prompt.replace(/%ONOFF%/g, targetMode), 37 | } 38 | } 39 | 40 | run(globalConfig, updateConfigAndRun) { 41 | updateConfigAndRun({ [this.setting]: !globalConfig[this.setting] }) 42 | return Promise.resolve() 43 | } 44 | } 45 | 46 | function errorOut(message) { 47 | const comment = `${chalk.bold.red( 48 | 'Configuration documentation' 49 | )}: ${chalk.underline( 50 | 'https://github.com/jest-community/jest-watch-toggle-config#readme' 51 | )} 52 | `.trim() 53 | throw new ValidationError('Watch Toggle Config Error', message, comment) 54 | } 55 | 56 | const DEFAULT_CONFIG = { 57 | bail: { key: 'b', prompt: 'turn %ONOFF% bailing at first error' }, 58 | collectCoverage: { 59 | key: 'e', 60 | prompt: 'turn %ONOFF% code coverage collection', 61 | }, 62 | notify: { key: 'n', prompt: 'turn %ONOFF% desktop notifications' }, 63 | verbose: { key: 'v', prompt: 'turn %ONOFF% test verbosity' }, 64 | } 65 | 66 | function getConfigValue(config, setting, defaults = {}) { 67 | return ( 68 | String(config[setting] || '').trim() || 69 | String(defaults[setting] || '').trim() 70 | ) 71 | } 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jest Watch Toggle Config Plugin 2 | 3 | [![Build Status](https://travis-ci.org/jest-community/jest-watch-toggle-config.svg?branch=master)](https://travis-ci.org/jest-community/jest-watch-toggle-config) [![npm version](https://badge.fury.io/js/jest-watch-toggle-config.svg)](https://badge.fury.io/js/jest-watch-toggle-config) 4 | 5 |
6 | 7 | 8 | 9 |

jest-watch-toggle-config

10 |

Toggle your Jest boolean config settings at will

11 |
12 | 13 | ## Usage 14 | 15 | ### Install 16 | 17 | Install `jest`_(it needs Jest 23.4.1+)_ and `jest-watch-toggle-config` 18 | 19 | ```bash 20 | yarn add --dev jest jest-watch-toggle-config 21 | 22 | # or with NPM 23 | 24 | npm install --save-dev jest jest-watch-toggle-config 25 | ``` 26 | 27 | ### Add it to your Jest config 28 | 29 | Since Jest 23.3, you can provide per-instance watch plugin configuration. Jest 23.4.1 opens up the list of global configuration settings that can be altered by watch plugins. Together, these evolutions let us use this same plugin in multiple ways, as along as the targeted configuration setting is boolean. 30 | 31 | There are three mandatory configuration items you need to provide: 32 | 33 | 1. `setting` is the boolean Jest configuration setting you want to toggle. Boolean settings available for configuration through watch plugins, as of Jest 23.4.1, include [`bail`](https://jestjs.io/docs/en/configuration#bail-boolean), [`collectCoverage`](https://jestjs.io/docs/en/configuration#collectcoverage-boolean), `noSCM`, [`notify`](https://jestjs.io/docs/en/configuration#notify-boolean), `onlyFailures`, [`passWithNoTests`](https://jestjs.io/docs/en/cli#passwithnotests) and [`verbose`](https://jestjs.io/docs/en/configuration#verbose-boolean). 34 | 2. `key` is the keyboard key that will be bound to this plugin instance, toggling the setting you’re interested in. We actually provide a default key for each option, trying our best not to step on Jest’s built-in keys, but they might conflict with another plugin's key. So you can tweak it. 35 | 3. `prompt` is the plugin prompt displayed in the watch menu. In this text, you can use the `%ONOFF%` placeholder, that will be dynamically replaced by either `on` or `off`, depending on the resulting setting value. We also provide good defaults for the options listed above, but feel free to tweak them. 36 | 37 | Here’s an example for toggling both test verbosity (details of passed/failed tests) and code coverage collection with this plugin. 38 | 39 | In your `package.json`: 40 | 41 | ```json 42 | { 43 | "jest": { 44 | "watchPlugins": [ 45 | ["jest-watch-toggle-config", { "setting": "verbose" }], 46 | ["jest-watch-toggle-config", { "setting": "collectCoverage" }] 47 | ] 48 | } 49 | } 50 | ``` 51 | 52 | Or in `jest.config.js` 53 | 54 | ```js 55 | module.exports = { 56 | // … 57 | watchPlugins: [ 58 | ['jest-watch-toggle-config', { setting: 'verbose' }], 59 | ['jest-watch-toggle-config', { setting: 'collectCoverage' }], 60 | ], 61 | } 62 | ``` 63 | 64 | ### Run Jest in watch mode 65 | 66 | ```bash 67 | yarn jest --watch 68 | 69 | # or with NPM 70 | 71 | npx jest --watch 72 | ``` 73 | 74 | ### List of options that have default keys and prompts 75 | 76 | As of Jest 23.4.1, the following boolean options have sane defaults you can leverage to lighten your configuration: 77 | 78 | | Option | Key | Prompt | 79 | | ------------------------------------------------------------------------------------ | ----- | ------------------------------------- | 80 | | [`bail`](https://jestjs.io/docs/en/configuration#bail-boolean) | `b` | turn %ONOFF% bailing at first error | 81 | | [`collectCoverage`](https://jestjs.io/docs/en/configuration#collectcoverage-boolean) | `e`\* | turn %ONOFF% code coverage collection | 82 | | [`notify`](https://jestjs.io/docs/en/configuration#notify-boolean) | `n` | turn %ONOFF% desktop notifications | 83 | | [`verbose`](https://jestjs.io/docs/en/configuration#verbose-boolean) | `v` | turn %ONOFF% test verbosity | 84 | 85 | _\* Jest already reserves `c`, `o` and `v`…_ 86 | -------------------------------------------------------------------------------- /src/index.test.js: -------------------------------------------------------------------------------- 1 | import { Chalk } from 'chalk' 2 | import { jest } from '@jest/globals' 3 | 4 | jest.unstable_mockModule('chalk', () => ({ default: new Chalk({ level: 0 }) })) 5 | const { default: Plugin } = await import('./index.js') 6 | 7 | describe('Jest Watch Toggle Plugin', () => { 8 | describe('at construction time', () => { 9 | it('requires a configuration object', () => { 10 | // No param at all (older Jest) 11 | expect(() => new Plugin()).toThrow(/Missing plugin configuration/) 12 | // No config at all (older Jest) 13 | expect(() => new Plugin({})).toThrow(/Missing plugin configuration/) 14 | }) 15 | 16 | it('requires the setting parameter', () => { 17 | expect(() => new Plugin({ config: {} })).toThrow( 18 | /needs at least a setting configuration parameter/ 19 | ) 20 | }) 21 | 22 | it('uses the provided key and prompt configuration, if any', () => { 23 | const config = { key: 'a', prompt: 'b', setting: 'c' } 24 | const plugin = new Plugin({ config }) 25 | for (const key of Object.keys(config)) { 26 | expect(plugin).toHaveProperty(key, config[key]) 27 | } 28 | }) 29 | 30 | describe('when predefined defaults are available, it uses them', () => { 31 | it('for `bail`', () => { 32 | const plugin = new Plugin({ config: { setting: 'bail' } }) 33 | expect(plugin).toHaveProperty('key', 'b') 34 | expect(plugin).toHaveProperty( 35 | 'prompt', 36 | 'turn %ONOFF% bailing at first error' 37 | ) 38 | }) 39 | 40 | it('for `collectCoverage`', () => { 41 | const plugin = new Plugin({ config: { setting: 'collectCoverage' } }) 42 | expect(plugin).toHaveProperty('key', 'e') 43 | expect(plugin).toHaveProperty( 44 | 'prompt', 45 | 'turn %ONOFF% code coverage collection' 46 | ) 47 | }) 48 | 49 | it('for `notify`', () => { 50 | const plugin = new Plugin({ config: { setting: 'notify' } }) 51 | expect(plugin).toHaveProperty('key', 'n') 52 | expect(plugin).toHaveProperty( 53 | 'prompt', 54 | 'turn %ONOFF% desktop notifications' 55 | ) 56 | }) 57 | 58 | it('for `verbose`', () => { 59 | const plugin = new Plugin({ config: { setting: 'verbose' } }) 60 | expect(plugin).toHaveProperty('key', 'v') 61 | expect(plugin).toHaveProperty('prompt', 'turn %ONOFF% test verbosity') 62 | }) 63 | }) 64 | 65 | it('synthetizes defaults when they are not available', () => { 66 | const plugin = new Plugin({ config: { setting: 'FooBar' } }) 67 | expect(plugin).toHaveProperty('key', 'f') 68 | expect(plugin).toHaveProperty('prompt', 'turn %ONOFF% FooBar') 69 | }) 70 | }) 71 | 72 | describe('when providing usage info', () => { 73 | const plugin = new Plugin({ 74 | config: { 75 | key: 'v', 76 | prompt: 'turn %ONOFF% tests verbosity', 77 | setting: 'verbose', 78 | }, 79 | }) 80 | 81 | it('sends the proper info when setting is enabled', () => { 82 | expect(plugin.getUsageInfo({ verbose: true })).toEqual({ 83 | key: 'v', 84 | prompt: 'turn off tests verbosity', 85 | }) 86 | }) 87 | 88 | it('sends the proper info when setting is disabled', () => { 89 | expect(plugin.getUsageInfo({ verbose: false })).toEqual({ 90 | key: 'v', 91 | prompt: 'turn on tests verbosity', 92 | }) 93 | }) 94 | }) 95 | 96 | describe('when running', () => { 97 | const plugin = new Plugin({ 98 | config: { 99 | key: 'e', 100 | prompt: 'turn %ONOFF% code coverage collection', 101 | setting: 'collectCoverage', 102 | }, 103 | }) 104 | 105 | it('returns a resolved, falsey promise', () => { 106 | expect(plugin.run({}, () => {})).toEqual(Promise.resolve()) 107 | }) 108 | 109 | it('invokes `updateConfigAndRun()` with the proper option', () => { 110 | const updateConfigAndRun = jest.fn() 111 | plugin.run({ collectCoverage: true }, updateConfigAndRun) 112 | expect(updateConfigAndRun).toHaveBeenCalledWith({ 113 | collectCoverage: false, 114 | }) 115 | 116 | updateConfigAndRun.mockReset() 117 | plugin.run({ collectCoverage: false }, updateConfigAndRun) 118 | expect(updateConfigAndRun).toHaveBeenCalledWith({ collectCoverage: true }) 119 | }) 120 | }) 121 | }) 122 | --------------------------------------------------------------------------------