Run Jest Watch Mode by default locally with is-ci-cli

In CI, we don’t want to start the tests in watch mode, but locally we normally want to run the tests in watch mode. We can have separate scripts, but it’d be great to not have to remember which script to run locally. Let’s use is-ci-cli to run the right script in the right environment when running the test script.

install:

  1. npm i -D is-ci-cli

scripts:

  1. "test": "is-ci \"test:coverage\" \"test:watch\"",
  2. "test:coverage": "jest --coverage",
  3. "test:watch": "jest --watch",
  4. "test:debug": "node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand --watch",

So when we run:

  1. npm t

It will check our enviorment, if it is running in CI mode, it will run coverage, otherwise it running in node, it runs watch mode.

Filter which Tests are Run with Typeahead Support in Jest Watch Mode

Jest’s watch mode is pluggable and jest-watch-typeahead is one plugin that you definitely don’t want to live without. It enhances the watch mode experience to help you know which tests will be run based on your filter. Making it even easier to run only the tests you’re concerned with running as you develop your codebase.

Install:

  1. npm install --save-dev jest-watch-typeahead

jest.config.js:

  1. const path = require('path');
  2.  
  3. module.exports = {
  4. testEnvironment: 'jest-environment-jsdom', //'jest-environment-node',
  5. moduleDirectories: [
  6. 'node_modules',
  7. path.join(__dirname, 'src'),
  8. 'shared',
  9. path.join(__dirname, 'test'),
  10. ],
  11. moduleNameMapper: {
  12. '\\.module\\.css$': 'identity-obj-proxy',
  13. '\\.css$': require.resolve('./test/style-mock.js')
  14. },
  15. snapshotSerializers: ['jest-serializer-path'],
  16. // after jest is loaded
  17. setupTestFrameworkScriptFile: require.resolve('./test/setup-tests.js'),
  18. collectCoverageFrom: ['**/src/**/*.js'],
  19. coverageThreshold: {
  20. global: {
  21. statements: 80,
  22. branchs: 80,
  23. lines: 80,
  24. functions: 80,
  25. },
  26. './src/shared/utils.js': {
  27. statements: 100,
  28. branchs: 80,
  29. lines: 100,
  30. functions: 100,
  31. }
  32. },
  33. watchPlugins: [
  34. 'jest-watch-typeahead/filename',
  35. 'jest-watch-typeahead/testname',
  36. ]
  37. }

Run tests with a different configuration using Jest’s --config flag and testMatch option

Sometimes you may have situations where configuration needs to be different for certain tests. In this lesson we’ll take a look at how we could create a custom configuration for tests that are intended to run in a node environment.

We might want to test server side rendering code, which doesn't need DOM, and some other configurations for client side. For that we need to split current jest config, to need the requirements.

test/jest-common.js:

  1. const path = require('path');
  2.  
  3. module.exports = {
  4. rootDir: path.join(__dirname, '..'), // find tests in src folder
  5. moduleDirectories: [
  6. 'node_modules',
  7. path.join(__dirname, '../src'),
  8. 'shared',
  9. __dirname,
  10. ],
  11. moduleNameMapper: {
  12. '\\.module\\.css$': 'identity-obj-proxy',
  13. '\\.css$': require.resolve('./style-mock.js')
  14. },
  15. snapshotSerializers: ['jest-serializer-path'],
  16. collectCoverageFrom: ['**/src/**/*.js'],
  17. }

test/jest-client.js

  1. module.exports = {
  2. ...require('./jest-common'),
  3. testEnvironment: 'jest-environment-jsdom', //'jest-environment-node',
  4. // after jest is loaded
  5. setupTestFrameworkScriptFile: require.resolve('./setup-tests.js'),
  6. coverageThreshold: {
  7. global: {
  8. statements: 80,
  9. branchs: 80,
  10. lines: 80,
  11. functions: 80,
  12. },
  13. './src/shared/utils.js': {
  14. statements: 100,
  15. branchs: 80,
  16. lines: 100,
  17. functions: 100,
  18. }
  19. },
  20. watchPlugins: [
  21. 'jest-watch-typeahead/filename',
  22. 'jest-watch-typeahead/testname',
  23. ]
  24. }

test/jest-server.js

  1. const path = require('path')
  2.  
  3. module.exports = {
  4. ...require('./jest-common'),
  5. coverageDirectory: path.join(__dirname, '../coverage/server'),
  6. testEnvironment: 'jest-environment-node',
  7. testMatch: ['**/__server_tests__/**/*.js']
  8. }

With that we can create new script for running the jest:

  1. "test": "is-ci \"test:coverage\" \"test:watch:client\" # CI=1 npm t run in ci mode",
  2. "test:coverage": "npm run test:coverage:client && npm run test:coverage:server",
  3. "test:coverage:client": "jest --config test/jest-client.js --coverage",
  4. "test:coverage:server": "jest --config test/jest-server.js --coverage",
  5. "test:watch:client": "jest --config test/jest-client.js --watch",
  6. "test:watch:server": "jest --config test/jest-server.js --watch",
  7. "test:debug:client": "node --inspect-brk ./node_modules/jest/bin/jest.js --config test/jest-client.js --runInBand --watch",
  8. "test:debug:server": "node --inspect-brk ./node_modules/jest/bin/jest.js --config test/jest-server.js --runInBand --watch",

The hightlighted code in script is how we run jest with the configuration file.

Support Running Multiple Configurations with Jest’s Projects Feature

Sometimes you may find it useful to have more than one configuration in a project (for example, running some tests in a node environment and others in the jsdom environment). In this lesson we’ll learn about Jest’s projects feature to have jest run both of these configurations at once.

Now we have lots of scripts for client and server:

  1. "test": "is-ci \"test:coverage\" \"test:watch:client\" # CI=1 npm t run in ci mode",
  2. "test:coverage": "npm run test:coverage:client && npm run test:coverage:server",
  3. "test:coverage:client": "jest --config test/jest-client.js --coverage",
  4. "test:coverage:server": "jest --config test/jest-server.js --coverage",
  5. "test:watch:client": "jest --config test/jest-client.js --watch",
  6. "test:watch:server": "jest --config test/jest-server.js --watch",
  7. "test:debug:client": "node --inspect-brk ./node_modules/jest/bin/jest.js --config test/jest-client.js --runInBand --watch",
  8. "test:debug:server": "node --inspect-brk ./node_modules/jest/bin/jest.js --config test/jest-server.js --runInBand --watch",

Those are not ideal, in fact we prefer:

  1. "test": "is-ci \"test:coverage\" \"test:watch\"",
  2. "test:coverage": "jest --coverage",
  3. "test:watch": "jest --watch",
  4. "test:debug": "node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand --watch",

Jest provides '--projects' options we can use to run mutiplue scripts:

  1. npx jest --projects ./test/jest-client.js ./test/jest-server.js

It runs based on both client config and server config.

Now we can config '--projects' inside jest.config.js:

  1. /*Mainly for global jest config*/
  2. // npx jest --showConifg --config ./test/jest-client.js
  3. module.exports = {
  4. ...require('./test/jest-common'),
  5. projects: ['./test/jest-client.js', './test/jest-server.js'],
  6. coverageThreshold: {
  7. global: {
  8. statements: 80,
  9. branchs: 80,
  10. lines: 80,
  11. functions: 80,
  12. },
  13. './src/shared/utils.js': {
  14. statements: 100,
  15. branchs: 80,
  16. lines: 100,
  17. functions: 100,
  18. }
  19. },
  20. collectCoverageFrom: ['**/src/**/*.js'],
  21. }

Coverage reports will be combine by jest automaticlly for both client and server side.

./test/jest-clinet.js

  1. module.exports = {
  2. ...require('./jest-common'),
  3. displayName: 'dom',
  4. testEnvironment: 'jest-environment-jsdom', //'jest-environment-node',
  5. // after jest is loaded
  6. setupTestFrameworkScriptFile: require.resolve('./setup-tests.js'),
  7. watchPlugins: [
  8. 'jest-watch-typeahead/filename',
  9. 'jest-watch-typeahead/testname',
  10. ]
  11. }

./test/jest-server.js:

  1. const path = require('path')
  2.  
  3. module.exports = {
  4. ...require('./jest-common'),
  5. displayName: 'server',
  6. testEnvironment: 'jest-environment-node',
  7. testMatch: ['**/__server_tests__/**/*.js']
  8. }

./test/jest-common.js:

  1. const path = require('path');
  2.  
  3. module.exports = {
  4. rootDir: path.join(__dirname, '..'), // find tests in src folder
  5. moduleDirectories: [
  6. 'node_modules',
  7. path.join(__dirname, '../src'),
  8. 'shared',
  9. __dirname,
  10. ],
  11. moduleNameMapper: {
  12. '\\.module\\.css$': 'identity-obj-proxy',
  13. '\\.css$': require.resolve('./style-mock.js')
  14. },
  15. snapshotSerializers: ['jest-serializer-path'],
  16. }

We added 'displayName':

So it is clear, tests are from which part.

If you just want run client test, you still can do:

  1. npx jest --config ./test/jest-client.js --watch

Test specific projects in Jest Watch Mode with jest-watch-select-projects

It’s great that we can run multiple projects in our watch mode and that we can scope the tests down to specific tests, but sometimes it’s nice to be able to quickly switch between projects in watch mode. Let’s see how this works with jest-watch-select-projects.

After we refactor our scripts, now if we want to just run client tests, we need to do:

  1. npx jest --config ./test/jest-client.js --watch

It is not so good approach.

Install:

  1. npm i -D jest-watch-select-projects

In the 'watchPlugins':

  1. watchPlugins: [
  2. 'jest-watch-typeahead/filename',
  3. 'jest-watch-typeahead/testname',
  4. 'jest-watch-select-projects',
  5. ],

Now, if we run:

  1. jest--watch

It will give a new options, which is 'P', we can select the project we want to run against.

Run ESLint with Jest using jest-runner-eslint

Jest is more than a testing framework. It’s a highly optimized, blazing fast platform with incredible parallelization for running tasks across many files in our project. It has a capability to run more than just tests. We can bring these features to our linting as well. Let’s see how we can bring our favorite Jest features (like watch mode) to ESLint with jest-runner-eslint.

Idea is using jest to run eslint as well though jest-runner

Install:

  1. npm i -D jest-runner-eslint

Create test/jest-lint.js

  1. const {rootDir} = require('./jest-common')
  2.  
  3. module.exports = {
  4. rootDir,
  5. displayName: 'lint',
  6. runner: 'jest-runner-eslint',
  7. testMatch: ['<rootDir>/**/*.js'],
  8. testPathIgnorePatterns: ['/node_modules/', '/coverage/', '/dist/', '/other/']
  9. }

To run the lint, we can do:

  1. npx jest --config test/jest-lint.js

We want to include 'lint' into the default tests runner:

jest.config.js:

  1. module.exports = {
  2. ...require('./test/jest-common'),
  3. projects: ['./test/jest-lint.js', './test/jest-client.js', './test/jest-server.js'],
  4. coverageThreshold: {
  5. global: {
  6. statements: 80,
  7. branchs: 80,
  8. lines: 80,
  9. functions: 80,
  10. },
  11. './src/shared/utils.js': {
  12. statements: 100,
  13. branchs: 80,
  14. lines: 100,
  15. functions: 100,
  16. }
  17. },
  18. collectCoverageFrom: ['**/src/**/*.js'],
  19. }

Now everytime, we run test, the lint will be also running.

Last, we can update our scripts to run the lint:

  1. "lint": "jest --config test/jest-lint.js",

Run only relevant Jest tests on git commit to avoid breakages

Running the project tests on commit is a great way to avoid breaking the application accidentally and leverage the mechanism for confidence you have from your testbase. However, as the testbase grows this can take a very long time and slow productivity down. Let’s see how Jest is capable of running only the tests and linting only the files that are affected by the files we’re committing with husky and lint-staged to speed up our local test runs as well as help us avoid accidentally committing code that breaks our application.

You can target one file to run all the tests which are related:

  1. npx jest --findRelatedTests src/shared/util.js

Install:

  1. npm i -D husky lint-staged

Add lint-staged.config.js file:

  1. module.exports = {
  2. linters: {
  3. '**/*.js': ['jest --findRelatedTests'] // any file which jest find related tests found will be added to the lint-staged
  4. }
  5. }

In package.json:

  1. "precommit": "lint-staged",

Then if we were going to change one file and break the tests, then after we do git commit, husky will kick in and run the tests which are related to the file we have changed. If the tests faild, we are not able to commit the code.

[Testing] Config jest to test Javascript Application -- Part 3的更多相关文章

  1. [Testing] Config jest to test Javascript Application -- Part 1

    Transpile Modules with Babel in Jest Tests Jest automatically loads and applies our babel configurat ...

  2. [Testing] Config jest to test Javascript Application -- Part 2

    Setup an afterEach Test Hook for all tests with Jest setupTestFrameworkScriptFile With our current t ...

  3. Web.config Transformation Syntax for Web Application Project Deployment

    Web.config Transformation Syntax for Web Application Project Deployment Other Versions   Updated: Ma ...

  4. JavaScript Application Architecture On The Road To 2015

    JavaScript Application Architecture On The Road To 2015 I once told someone I was an architect. It’s ...

  5. 转:Transform Web.Config when Deploying a Web Application Project

    Introduction One of the really cool features that are integrated with Visual Studio 2010 is Web.Conf ...

  6. spring cloud config的bootstrap.yml与application.proterties的区别

    bootstrap.yml  和application.yml  都可以用来配置参数 bootstrap.yml可以理解成系统级别的一些参数配置,这些参数一般是不会变动的 application.ym ...

  7. Unit Testing a zend-mvc application

    Unit Testing a zend-mvc application A solid unit test suite is essential for ongoing development in ...

  8. JavaScript Web Application summary

    Widget/ HTML DOM (CORE) (local dom) DOM, BOM, Event(Framework, UI, Widget) function(closure) DATA (c ...

  9. JavaScript Libraries In A TypeScript Application, Revisited

    If you haven’t already gotten involved with it, you’ll probably know that TypeScript is becoming inc ...

随机推荐

  1. leepcode作业解析 - 5-19

    18.两数之和II -输入有序数组 给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数. 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 ...

  2. Python的第3堂课

    20181119笔记 一.内存管理相关 ①Cpython解释器的垃圾回收机制 什么是垃圾:当一个值没有被绑定任何变量名(即该值的引用计数为零时),该值就是垃圾. 垃圾回收是收回值占用的内存空间. 引用 ...

  3. selenium之定位以及切换frame

    总有人看不明白,以防万一,先在开头大写加粗说明一下: frameset不用切,frame需层层切! 很多人在用selenium定位页面元素的时候会遇到定位不到的问题,明明元素就在那儿,用firebug ...

  4. 【LeetCode】Design Linked List(设计链表)

    这道题是LeetCode里的第707到题.这是在学习链表时碰见的. 题目要求: 设计链表的实现.您可以选择使用单链表或双链表.单链表中的节点应该具有两个属性:val 和 next.val 是当前节点的 ...

  5. Clickomania(区间DP)

    描述 Clickomania is a puzzle in which one starts with a rectangular grid of cells of different colours ...

  6. PAT天梯赛练习题——L3-005. 垃圾箱分布(暴力SPFA)

    L3-005. 垃圾箱分布 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 大家倒垃圾的时候,都希望垃圾箱距离自己比较近,但是谁 ...

  7. SPOJ GSS1 Can you answer these queries I ——线段树

    [题目分析] 线段树裸题. 注意update的操作,写结构体里好方便. 嗯,没了. [代码] #include <cstdio> #include <cstring> #inc ...

  8. leetcode 349 map

    只需要用map来标记1,今儿通过map的值来得到重叠的部分 class Solution { public: vector<int> intersection(vector<int& ...

  9. Modular Production Line

     Modular Production Line 时空限制: 1000ms /65536K   An automobile factory has a car production line. Now ...

  10. Find that single one.(linear runtime complexity0

    public class Solution { public int singleNumber(int[] nums) { int temp = 0; for (int i=0;i<nums.l ...