├── .github ├── FUNDING.yml └── workflows │ └── main.yml ├── .eslintignore ├── commitlint.config.js ├── src ├── index.ts ├── WatchSuspendPlugin.ts └── WatchSuspendPugin.spec.ts ├── tsconfig.json ├── .editorconfig ├── .vscode └── settings.json ├── .eslintrc.json ├── .travis.yml ├── scripts └── run-on-node-version.sh ├── tsconfig.build.json ├── jest.config.js ├── .gitignore ├── LICENSE ├── wallaby.js ├── package.json ├── .circleci └── config.yml └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: unional 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist* 3 | lib 4 | out* 5 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ['@commitlint/config-conventional'] } 2 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { WatchSuspendPlugin } from './WatchSuspendPlugin' 2 | export = WatchSuspendPlugin 3 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.build.json", 3 | "compilerOptions": { 4 | "plugins": [ 5 | { 6 | "name": "tslint-language-service" 7 | } 8 | ] 9 | }, 10 | "include": [ 11 | "src", 12 | "typings" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_size = 2 11 | indent_style = space 12 | trim_trailing_whitespace = true 13 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.enable": true, 3 | "json.schemas": [ 4 | { 5 | "fileMatch": [ 6 | "tsconfig.*.json" 7 | ], 8 | "url": "http://json.schemastore.org/tsconfig" 9 | } 10 | ], 11 | "typescript.tsdk": "node_modules/typescript/lib" 12 | } 13 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "jest": true, 5 | "node": true 6 | }, 7 | "extends": "plugin:harmony/latest", 8 | "overrides": [ 9 | { 10 | "extends": "plugin:harmony/ts-recommended", 11 | "files": [ 12 | "*.ts", 13 | "*.tsx" 14 | ] 15 | } 16 | ], 17 | "root": true 18 | } 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | cache: 3 | directories: 4 | - ~/.npm 5 | notifications: 6 | email: false 7 | branches: 8 | only: 9 | - master 10 | - /^greenkeeper.*$/ 11 | script: 12 | - yarn 13 | - yarn build 14 | - yarn coverage --reporters=default --maxWorkers=2 15 | - npm install -g codacy-coverage && cat ./coverage/lcov.info | codacy-coverage 16 | - npm install -g coveralls && cat ./coverage/lcov.info | coveralls 17 | -------------------------------------------------------------------------------- /scripts/run-on-node-version.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | if [ $1 = 'latest' ]; then 3 | target_version=$(npm info node version); 4 | else 5 | target_version=$1; 6 | fi 7 | node_version=$(node -v); 8 | if [ ${node_version:1:2} = ${target_version:0:2} ]; then 9 | echo "Detected ${node_version}, satisfying ${target_version}. Executing command"; 10 | eval $2; 11 | else 12 | echo "NodeJS ${node_version} instead of latest (${target_version:0:1}) is detected. Skipping command"; 13 | fi 14 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "esModuleInterop": true, 5 | "lib": [ 6 | "es2015" 7 | ], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "newLine": "LF", 11 | "noUnusedLocals": true, 12 | "noUnusedParameters": false, 13 | "outDir": "lib", 14 | "removeComments": false, 15 | "sourceMap": true, 16 | "strict": true 17 | }, 18 | "include": [ 19 | "typings" 20 | ], 21 | "files": [ 22 | "src/index.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | const common = require('@unional/devpkg-node/simple/config/jest.common') 2 | module.exports = Object.assign(common, { 3 | 'watchPlugins': [ 4 | [ 5 | '/lib/index.js', 6 | { 7 | 'suspend-on-start': true 8 | } 9 | ], 10 | 'jest-watch-typeahead/filename', 11 | 'jest-watch-typeahead/testname', 12 | [ 13 | 'jest-watch-toggle-config', 14 | { 15 | 'setting': 'verbose' 16 | } 17 | ], 18 | [ 19 | 'jest-watch-toggle-config', 20 | { 21 | 'setting': 'collectCoverage' 22 | } 23 | ] 24 | ] 25 | }) 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | .DS_Store 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | 9 | # Runtime data 10 | pids 11 | *.pid 12 | *.seed 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | .nyc_output 20 | .progress 21 | 22 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 23 | .grunt 24 | 25 | # node-waf configuration 26 | .lock-wscript 27 | 28 | # Compiled binary addons (http://nodejs.org/api/addons.html) 29 | build/Release 30 | 31 | # Dependency directory 32 | jspm_packages 33 | node_modules 34 | 35 | # Optional npm cache directory 36 | .npm 37 | 38 | # Optional REPL history 39 | .node_repl_history 40 | 41 | # webstorm 42 | .idea 43 | 44 | # project folders 45 | dist* 46 | lib 47 | out* 48 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | jobs: 11 | node-latest: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v1 15 | - run: yarn 16 | - run: yarn commitlint-circle 17 | - run: yarn lint 18 | - run: yarn build 19 | - run: yarn depcheck 20 | - run: yarn coverage --maxWorkers=2 21 | - run: yarn codecov 22 | - run: echo release 23 | if: github.event_name == 'push' 24 | node-others: 25 | runs-on: ubuntu-latest 26 | strategy: 27 | matrix: 28 | node-version: [8.x, 10.x, 12.x] 29 | steps: 30 | - uses: actions/checkout@v1 31 | - name: Use Node.js ${{ matrix.node-version }} 32 | uses: actions/setup-node@v1 33 | with: 34 | node-version: ${{ matrix.node-version }} 35 | - run: yarn 36 | - run: yarn build 37 | - run: yarn coverage --maxWorkers=2 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Homa Wong (unional) (homawong@gmail.com) 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /wallaby.js: -------------------------------------------------------------------------------- 1 | module.exports = () => { 2 | return { 3 | 'files': [ 4 | { pattern: 'fixtures/**/*', instrument: false }, 5 | { pattern: 'scripts/*', instrument: false }, 6 | { pattern: 'package.json', instrument: false }, 7 | { pattern: 'tsconfig.*', instrument: false }, 8 | { pattern: '__komondor__/**/*', instrument: false }, 9 | 'src/**/*.ts', 10 | '!src/**/*.spec.ts' 11 | ], 12 | 'tests': [ 13 | 'src/**/*.spec.ts' 14 | ], 15 | 'env': { 16 | 'type': 'node' 17 | }, 18 | hints: { 19 | allowIgnoringCoverageInTests: true, 20 | ignoreCoverage: /istanbul ignore next/ 21 | }, 22 | setup(wallaby) { 23 | const fs = require('fs'); 24 | if (fs.patched) return; 25 | const path = require('path'); 26 | 27 | const writeFile = fs.writeFileSync; 28 | fs.writeFileSync = function(file, content) { 29 | if (/__komondor__/.test(file)) { 30 | writeFile(path.join(wallaby.localProjectDir, file.replace(wallaby.projectCacheDir, '')), content); 31 | } 32 | return writeFile.apply(this, arguments); 33 | } 34 | const mkdirSync = fs.mkdirSync; 35 | fs.mkdirSync = function (dir, mode) { 36 | if (/__komondor__/.test(dir)) { 37 | mkdirSync(path.join(wallaby.localProjectDir, dir.replace(wallaby.projectCacheDir, '')), mode); 38 | } 39 | return mkdirSync.apply(this, arguments); 40 | } 41 | fs.patched = true; 42 | }, 43 | 'testFramework': 'jest' 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/WatchSuspendPlugin.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import { unpartial } from 'unpartial' 3 | export interface Config { 4 | 'suspend-on-start': boolean, 5 | key: string, 6 | prompt: string 7 | } 8 | export type JestGlobalConfigUsed = Pick 9 | 10 | export class WatchSuspendPlugin { 11 | globalConfig: Partial = {} 12 | log = console.info 13 | config: Config 14 | suspend: boolean 15 | constructor({ config }: { config: Partial }) { 16 | this.config = unpartial({ 'suspend-on-start': false, key: 's', prompt: 'suspend watch mode' }, config) 17 | this.suspend = this.config['suspend-on-start']; 18 | } 19 | 20 | // Add hooks to Jest lifecycle events 21 | apply(jestHooks: any) { 22 | jestHooks.shouldRunTestSuite(() => { 23 | return !this.suspend 24 | }) 25 | jestHooks.onTestRunComplete(() => { 26 | if (this.suspend) { 27 | this.log(chalk.bold(`Test is suspended.`)) 28 | } 29 | }) 30 | } 31 | 32 | // Get the prompt information for interactive plugins 33 | getUsageInfo() { 34 | return { 35 | key: this.config.key, 36 | prompt: this.suspend ? 'resume watch mode' : this.config.prompt 37 | } 38 | } 39 | 40 | // Executed when the key from `getUsageInfo` is input 41 | run(globalConfig: Partial) { 42 | this.globalConfig = globalConfig 43 | this.suspend = !this.suspend 44 | if (this.suspend) { 45 | this.log(chalk.bold('\nTest is suspended.')) 46 | } 47 | return Promise.resolve(!this.suspend) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jest-watch-suspend", 3 | "version": "0.0.0-development", 4 | "description": "Suspend watch mode", 5 | "keywords": [ 6 | "jest", 7 | "jest-watch-plugins", 8 | "testing", 9 | "tooling" 10 | ], 11 | "homepage": "https://github.com/unional/jest-watch-suspend", 12 | "bugs": { 13 | "url": "https://github.com/unional/jest-watch-suspend/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/unional/jest-watch-suspend.git" 18 | }, 19 | "license": "MIT", 20 | "author": { 21 | "name": "Homa Wong (unional)", 22 | "email": "homawong@gmail.com" 23 | }, 24 | "files": [ 25 | "lib" 26 | ], 27 | "main": "lib/index.js", 28 | "typings": "lib/index.d.ts", 29 | "scripts": { 30 | "build": "tsc -p tsconfig.build.json", 31 | "clean": "rimraf lib", 32 | "codecov": "codecov", 33 | "coverage": "jest --coverage", 34 | "dc": "yarn depcheck", 35 | "depcheck": "dependency-check . --unused --no-dev -i jest && dependency-check . --missing --no-dev", 36 | "lint": "eslint --ext=js,ts .", 37 | "nuke": "yarn clean && rimraf node_modules", 38 | "semantic-release": "semantic-release", 39 | "test": "jest", 40 | "verify": "yarn lint && yarn build && yarn dc && jest --coverage", 41 | "watch": "jest --watch" 42 | }, 43 | "husky": { 44 | "hooks": { 45 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 46 | } 47 | }, 48 | "dependencies": { 49 | "chalk": "^3.0.0", 50 | "unpartial": "^0.6.3" 51 | }, 52 | "devDependencies": { 53 | "@commitlint/cli": "^8.2.0", 54 | "@commitlint/config-conventional": "^8.2.0", 55 | "@unional/devpkg-node": "^1.4.2", 56 | "assertron": "^7.1.2", 57 | "codecov": "^3.6.1", 58 | "commitlint-circle": "^1.0.0", 59 | "husky": "^3.1.0", 60 | "jest": "^24.9.0", 61 | "semantic-release": "^15.13.31" 62 | }, 63 | "peerDependencies": { 64 | "jest": ">=23" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | workflows: 3 | version: 2 4 | all: 5 | jobs: 6 | - node-latest 7 | - node12: 8 | requires: 9 | - node-latest 10 | - node10: 11 | requires: 12 | - node-latest 13 | - node8: 14 | requires: 15 | - node-latest 16 | - release: 17 | filters: 18 | branches: 19 | only: master 20 | requires: 21 | - node-latest 22 | - node12 23 | - node10 24 | - node8 25 | jobs: 26 | node-latest: 27 | docker: 28 | - image: circleci/node:13 29 | steps: 30 | - checkout 31 | - restore_cache: 32 | name: Restore node_modules cache 33 | key: node_modules-{{ checksum "yarn.lock" }} 34 | - run: 35 | name: Install Dependencies 36 | command: | 37 | if [ ! -d node_modules ]; then 38 | yarn 39 | fi 40 | - save_cache: 41 | name: Save node modules cache 42 | key: node_modules-{{ checksum "yarn.lock" }} 43 | paths: 44 | - node_modules 45 | - run: yarn commitlint-circle 46 | - run: yarn lint 47 | - run: yarn build 48 | - run: yarn dc 49 | - run: yarn coverage --maxWorkers=2 50 | - store_test_results: 51 | path: .reports/junit 52 | - persist_to_workspace: 53 | root: '.' 54 | paths: 55 | - lib 56 | - node_modules 57 | - run: yarn codecov 58 | node12: 59 | docker: 60 | - image: 'circleci/node:12' 61 | steps: 62 | - checkout 63 | - attach_workspace: 64 | at: '.' 65 | - run: yarn coverage --maxWorkers=2 66 | - store_test_results: 67 | path: .reports/junit 68 | node10: 69 | docker: 70 | - image: 'circleci/node:10' 71 | steps: 72 | - checkout 73 | - attach_workspace: 74 | at: '.' 75 | - run: yarn coverage --maxWorkers=2 76 | - store_test_results: 77 | path: .reports/junit 78 | node8: 79 | docker: 80 | - image: 'circleci/node:8' 81 | steps: 82 | - checkout 83 | - attach_workspace: 84 | at: '.' 85 | - run: yarn coverage --maxWorkers=2 86 | - store_test_results: 87 | path: .reports/junit 88 | release: 89 | docker: 90 | - image: circleci/node:13 91 | steps: 92 | - checkout 93 | - attach_workspace: 94 | at: '.' 95 | - run: yarn semantic-release 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jest-watch-suspend 2 | 3 | [![NPM version][npm-image]][npm-url] 4 | [![NPM downloads][downloads-image]][downloads-url] 5 | [![Mentioned in Awesome Jest](https://awesome.re/mentioned-badge.svg)](https://github.com/jest-community/awesome-jest) 6 | 7 | [![Circle CI][circleci-image]][circleci-url] 8 | [![Travis CI][travis-image]][travis-url] 9 | [![Codecov][codecov-image]][codecov-url] 10 | [![Coveralls Status][coveralls-image]][coveralls-url] 11 | 12 | [![Greenkeeper][greenkeeper-image]][greenkeeper-url] 13 | [![Semantic Release][semantic-release-image]][semantic-release-url] 14 | 15 | [![Visual Studio Code][vscode-image]][vscode-url] 16 | [![Wallaby.js][wallaby-image]][wallaby-url] 17 | 18 | Pausing/resuming [`jest`](https://jestjs.io/) watch mode. 19 | 20 | Requires `jest@23+`. 21 | 22 | ## Usage 23 | 24 | To use `jest-watch-suspend`, 25 | add it to the `watchPlugins` section of the Jest configuration: 26 | 27 | ```js 28 | { 29 | "jest": { 30 | "watchPlugins": [ 31 | // default 32 | "jest-watch-suspend", 33 | // configure 34 | [ 35 | "jest-watch-suspend", { 36 | // override key press 37 | "key": "s", 38 | // override prompt 39 | "prompt": "suspend watch mode", 40 | // starts in suspend mode 41 | "suspend-on-start": true 42 | } 43 | ] 44 | ] 45 | } 46 | } 47 | ``` 48 | 49 | ## Use Cases 50 | 51 | Suspend on start: 52 | 53 | - (suspended) ➣ `[p] + ` | `[t] + ` ➣ `[s]` (resume) 54 | 55 | Setup both path and name filter before running tests: 56 | 57 | - `[s]` (suspend) ➣ `[p] + ` & `[t] + ` ➣ `[s]` (resume) 58 | 59 | Change multiple files before running tests: 60 | 61 | - `[s]` (suspend) ➣ multiple changes and file saves ➣ `[s]` (resume) 62 | 63 | Run code coverage after running some `test.only()` tests: 64 | 65 | - `[s]` (suspend) ➣ change `test.only()` back to `test()` & `[e]` (with `jest-watch-toggle-config`) ➣ `[s]` (resume) 66 | 67 | [circleci-image]: https://circleci.com/gh/unional/jest-watch-suspend/tree/master.svg?style=shield 68 | [circleci-url]: https://circleci.com/gh/unional/jest-watch-suspend/tree/master 69 | [codecov-image]: https://codecov.io/gh/unional/jest-watch-suspend/branch/master/graph/badge.svg 70 | [codecov-url]: https://codecov.io/gh/unional/jest-watch-suspend 71 | [coveralls-image]: https://coveralls.io/repos/github/unional/jest-watch-suspend/badge.svg?branch=master 72 | [coveralls-url]: https://coveralls.io/github/unional/jest-watch-suspend?branch=master 73 | [downloads-image]: https://img.shields.io/npm/dm/jest-watch-suspend.svg?style=flat 74 | [downloads-url]: https://npmjs.org/package/jest-watch-suspend 75 | [greenkeeper-image]: https://badges.greenkeeper.io/unional/jest-watch-suspend.svg 76 | [greenkeeper-url]: https://greenkeeper.io/ 77 | [npm-image]: https://img.shields.io/npm/v/jest-watch-suspend.svg?style=flat 78 | [npm-url]: https://npmjs.org/package/jest-watch-suspend 79 | [semantic-release-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg 80 | [semantic-release-url]: https://github.com/semantic-release/semantic-release 81 | [travis-image]: https://img.shields.io/travis/unional/jest-watch-suspend/master.svg?style=flat 82 | [travis-url]: https://travis-ci.org/unional/jest-watch-suspend?branch=master 83 | [vscode-image]: https://img.shields.io/badge/vscode-ready-green.svg 84 | [vscode-url]: https://code.visualstudio.com/ 85 | [wallaby-image]: https://img.shields.io/badge/wallaby.js-configured-green.svg 86 | [wallaby-url]: https://wallabyjs.com 87 | -------------------------------------------------------------------------------- /src/WatchSuspendPugin.spec.ts: -------------------------------------------------------------------------------- 1 | import WatchSuspendPlugin from '.'; 2 | 3 | test('test will run on start by default', () => { 4 | const plugin = new WatchSuspendPlugin({ config: {} }) 5 | const th = testHarness() 6 | plugin.apply(th.jestHooks) 7 | 8 | expect(th.shouldRunTestSuiteCallback()).toBe(true) 9 | }) 10 | 11 | test('suspend on start = false will run test on start', () => { 12 | const plugin = new WatchSuspendPlugin({ config: { 'suspend-on-start': false } }) 13 | 14 | const th = testHarness() 15 | plugin.apply(th.jestHooks) 16 | 17 | expect(th.shouldRunTestSuiteCallback()).toBe(true) 18 | }) 19 | 20 | test('suspend on start will put watch in suspened state', () => { 21 | const plugin = new WatchSuspendPlugin({ config: { 'suspend-on-start': true } }) 22 | const th = testHarness() 23 | plugin.apply(th.jestHooks) 24 | 25 | expect(plugin.suspend).toBe(true) 26 | expect(th.shouldRunTestSuiteCallback()).toBe(false) 27 | expect(th.shouldRunTestSuiteCallback()).toBe(false) 28 | }) 29 | 30 | test('suspend on start will show resume in usageInfo', () => { 31 | const plugin = new WatchSuspendPlugin({ config: { 'suspend-on-start': true } }) 32 | const th = testHarness() 33 | plugin.apply(th.jestHooks) 34 | plugin.log = () => { } 35 | expect(th.shouldRunTestSuiteCallback()).toBe(false) 36 | const actual = plugin.getUsageInfo() 37 | expect(actual.prompt.match(/resume/)) 38 | }) 39 | 40 | test('usageInfo default to s and "suspend watch mode"', () => { 41 | const plugin = new WatchSuspendPlugin({ config: {} }) 42 | const actual = plugin.getUsageInfo() 43 | expect(actual.key).toBe('s') 44 | expect(actual.prompt).toBe('suspend watch mode') 45 | }) 46 | 47 | test('usageInfo can be customized', () => { 48 | const plugin = new WatchSuspendPlugin({ config: { key: 'x', prompt: 'pp' } }) 49 | const actual = plugin.getUsageInfo() 50 | expect(actual.key).toBe('x') 51 | expect(actual.prompt).toBe('pp') 52 | }) 53 | 54 | test('if not suspended, when test complete will not print message', () => { 55 | const plugin = new WatchSuspendPlugin({ config: {} }) 56 | const th = testHarness() 57 | plugin.apply(th.jestHooks) 58 | plugin.log = () => { throw new Error('should not call') } 59 | th.onTestRunCompleteCallback() 60 | }) 61 | 62 | test('if suspended, when test complete will print message', () => { 63 | const plugin = new WatchSuspendPlugin({ config: {} }) 64 | plugin.suspend = true 65 | const th = testHarness() 66 | plugin.apply(th.jestHooks) 67 | let called = false 68 | plugin.log = () => called = true 69 | th.onTestRunCompleteCallback() 70 | 71 | expect(called).toBe(true) 72 | }) 73 | 74 | test('if suspended, when test complete will print message when in verbose', async () => { 75 | const plugin = new WatchSuspendPlugin({ config: {} }) 76 | const th = testHarness() 77 | plugin.apply(th.jestHooks) 78 | let called = false 79 | plugin.log = () => called = true 80 | await plugin.run({ verbose: true }) 81 | th.onTestRunCompleteCallback() 82 | 83 | expect(called).toBe(true) 84 | }) 85 | 86 | test('triggering will flip suspend or resume', async () => { 87 | const plugin = new WatchSuspendPlugin({ config: {} }) 88 | plugin.log = () => { } 89 | await plugin.run({}) 90 | expect(plugin.suspend).toBe(true) 91 | await plugin.run({}) 92 | expect(plugin.suspend).toBe(false) 93 | }) 94 | 95 | test('trigger suspend will print message', async () => { 96 | const plugin = new WatchSuspendPlugin({ config: {} }) 97 | let called = false 98 | plugin.log = () => called = true 99 | await plugin.run({}) 100 | expect(called).toBe(true) 101 | }) 102 | 103 | test('if suspend, usage info prompt "resume watch mode"', () => { 104 | const plugin = new WatchSuspendPlugin({ config: {} }) 105 | plugin.suspend = true 106 | const actual = plugin.getUsageInfo() 107 | expect(actual.prompt).toBe('resume watch mode') 108 | }) 109 | 110 | function testHarness() { 111 | const th = { 112 | shouldRunTestSuiteCallback() { }, 113 | onTestRunCompleteCallback() { }, 114 | jestHooks: { 115 | shouldRunTestSuite(fn: any) { th.shouldRunTestSuiteCallback = fn }, 116 | onTestRunComplete(fn: any) { th.onTestRunCompleteCallback = fn } 117 | } 118 | } 119 | return th 120 | } 121 | --------------------------------------------------------------------------------