eslint-plugin-chai-friendly 0.4.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.editorconfig ADDED
@@ -0,0 +1,15 @@
1
+ ; EditorConfig file: https://EditorConfig.org
2
+ ; Install the "EditorConfig" plugin into your editor to use
3
+
4
+ root = true
5
+
6
+ [*]
7
+ charset = utf-8
8
+ end_of_line = lf
9
+ insert_final_newline = true
10
+ indent_style = space
11
+ indent_size = 4
12
+ trim_trailing_whitespace = true
13
+
14
+ [*.json]
15
+ indent_size = 2
package/.eslintignore ADDED
@@ -0,0 +1,2 @@
1
+ node_modules
2
+ !.eslintrc.js
package/.eslintrc.js ADDED
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ module.exports = {
4
+ extends: ['eslint:recommended'],
5
+ env: {
6
+ node: true
7
+ },
8
+ parserOptions: {
9
+ ecmaVersion: 2020
10
+ },
11
+ rules: {
12
+ strict: ['error'],
13
+ indent: ['error', 4]
14
+ }
15
+ };
@@ -0,0 +1 @@
1
+ {"/Users/user/repos/eslint-plugin-chai-friendly/lib/rules/no-unused-expressions.js":{"path":"/Users/user/repos/eslint-plugin-chai-friendly/lib/rules/no-unused-expressions.js","statementMap":{"0":{"start":{"line":17,"column":4},"end":{"line":17,"column":16}},"1":{"start":{"line":25,"column":4},"end":{"line":25,"column":17}},"2":{"start":{"line":29,"column":0},"end":{"line":266,"column":2}},"3":{"start":{"line":66,"column":21},"end":{"line":66,"column":45}},"4":{"start":{"line":67,"column":32},"end":{"line":67,"column":65}},"5":{"start":{"line":68,"column":27},"end":{"line":68,"column":55}},"6":{"start":{"line":69,"column":35},"end":{"line":69,"column":71}},"7":{"start":{"line":70,"column":28},"end":{"line":70,"column":57}},"8":{"start":{"line":77,"column":12},"end":{"line":78,"column":96}},"9":{"start":{"line":87,"column":12},"end":{"line":91,"column":13}},"10":{"start":{"line":87,"column":25},"end":{"line":87,"column":26}},"11":{"start":{"line":88,"column":16},"end":{"line":90,"column":17}},"12":{"start":{"line":89,"column":20},"end":{"line":89,"column":44}},"13":{"start":{"line":92,"column":12},"end":{"line":92,"column":32}},"14":{"start":{"line":100,"column":12},"end":{"line":100,"column":60}},"15":{"start":{"line":109,"column":25},"end":{"line":109,"column":56}},"16":{"start":{"line":110,"column":30},"end":{"line":110,"column":61}},"17":{"start":{"line":112,"column":12},"end":{"line":114,"column":58}},"18":{"start":{"line":121,"column":24},"end":{"line":166,"column":10}},"19":{"start":{"line":123,"column":16},"end":{"line":123,"column":65}},"20":{"start":{"line":130,"column":16},"end":{"line":130,"column":61}},"21":{"start":{"line":134,"column":16},"end":{"line":136,"column":17}},"22":{"start":{"line":135,"column":20},"end":{"line":135,"column":105}},"23":{"start":{"line":137,"column":16},"end":{"line":137,"column":28}},"24":{"start":{"line":143,"column":16},"end":{"line":143,"column":37}},"25":{"start":{"line":146,"column":16},"end":{"line":146,"column":37}},"26":{"start":{"line":149,"column":16},"end":{"line":151,"column":17}},"27":{"start":{"line":150,"column":20},"end":{"line":150,"column":60}},"28":{"start":{"line":152,"column":16},"end":{"line":152,"column":28}},"29":{"start":{"line":159,"column":16},"end":{"line":159,"column":45}},"30":{"start":{"line":164,"column":16},"end":{"line":164,"column":78}},"31":{"start":{"line":175,"column":29},"end":{"line":175,"column":44}},"32":{"start":{"line":176,"column":12},"end":{"line":178,"column":13}},"33":{"start":{"line":177,"column":16},"end":{"line":177,"column":29}},"34":{"start":{"line":180,"column":12},"end":{"line":180,"column":62}},"35":{"start":{"line":190,"column":12},"end":{"line":192,"column":13}},"36":{"start":{"line":191,"column":16},"end":{"line":191,"column":28}},"37":{"start":{"line":195,"column":12},"end":{"line":197,"column":13}},"38":{"start":{"line":196,"column":16},"end":{"line":196,"column":51}},"39":{"start":{"line":198,"column":12},"end":{"line":200,"column":13}},"40":{"start":{"line":199,"column":16},"end":{"line":199,"column":51}},"41":{"start":{"line":201,"column":12},"end":{"line":203,"column":13}},"42":{"start":{"line":202,"column":16},"end":{"line":202,"column":55}},"43":{"start":{"line":206,"column":12},"end":{"line":206,"column":24}},"44":{"start":{"line":216,"column":29},"end":{"line":216,"column":44}},"45":{"start":{"line":217,"column":12},"end":{"line":219,"column":13}},"46":{"start":{"line":218,"column":16},"end":{"line":218,"column":50}},"47":{"start":{"line":220,"column":12},"end":{"line":222,"column":13}},"48":{"start":{"line":221,"column":16},"end":{"line":221,"column":29}},"49":{"start":{"line":224,"column":12},"end":{"line":224,"column":62}},"50":{"start":{"line":234,"column":12},"end":{"line":236,"column":13}},"51":{"start":{"line":235,"column":16},"end":{"line":235,"column":28}},"52":{"start":{"line":239,"column":12},"end":{"line":241,"column":13}},"53":{"start":{"line":240,"column":16},"end":{"line":240,"column":51}},"54":{"start":{"line":242,"column":12},"end":{"line":244,"column":13}},"55":{"start":{"line":243,"column":16},"end":{"line":243,"column":51}},"56":{"start":{"line":245,"column":12},"end":{"line":247,"column":13}},"57":{"start":{"line":246,"column":16},"end":{"line":246,"column":55}},"58":{"start":{"line":250,"column":12},"end":{"line":250,"column":24}},"59":{"start":{"line":254,"column":8},"end":{"line":264,"column":10}},"60":{"start":{"line":256,"column":28},"end":{"line":259,"column":45}},"61":{"start":{"line":260,"column":16},"end":{"line":262,"column":17}},"62":{"start":{"line":261,"column":20},"end":{"line":261,"column":74}}},"fnMap":{"0":{"name":"alwaysTrue","decl":{"start":{"line":16,"column":9},"end":{"line":16,"column":19}},"loc":{"start":{"line":16,"column":22},"end":{"line":18,"column":1}},"line":16},"1":{"name":"alwaysFalse","decl":{"start":{"line":24,"column":9},"end":{"line":24,"column":20}},"loc":{"start":{"line":24,"column":23},"end":{"line":26,"column":1}},"line":24},"2":{"name":"(anonymous_2)","decl":{"start":{"line":65,"column":12},"end":{"line":65,"column":13}},"loc":{"start":{"line":65,"column":31},"end":{"line":265,"column":5}},"line":65},"3":{"name":"looksLikeDirective","decl":{"start":{"line":76,"column":17},"end":{"line":76,"column":35}},"loc":{"start":{"line":76,"column":42},"end":{"line":79,"column":9}},"line":76},"4":{"name":"takeWhile","decl":{"start":{"line":86,"column":17},"end":{"line":86,"column":26}},"loc":{"start":{"line":86,"column":44},"end":{"line":93,"column":9}},"line":86},"5":{"name":"directives","decl":{"start":{"line":99,"column":17},"end":{"line":99,"column":27}},"loc":{"start":{"line":99,"column":34},"end":{"line":101,"column":9}},"line":99},"6":{"name":"isDirective","decl":{"start":{"line":108,"column":17},"end":{"line":108,"column":28}},"loc":{"start":{"line":108,"column":46},"end":{"line":115,"column":9}},"line":108},"7":{"name":"(anonymous_7)","decl":{"start":{"line":122,"column":12},"end":{"line":122,"column":13}},"loc":{"start":{"line":122,"column":31},"end":{"line":124,"column":13}},"line":122},"8":{"name":"(anonymous_8)","decl":{"start":{"line":129,"column":12},"end":{"line":129,"column":13}},"loc":{"start":{"line":129,"column":34},"end":{"line":131,"column":13}},"line":129},"9":{"name":"(anonymous_9)","decl":{"start":{"line":133,"column":12},"end":{"line":133,"column":13}},"loc":{"start":{"line":133,"column":40},"end":{"line":138,"column":13}},"line":133},"10":{"name":"(anonymous_10)","decl":{"start":{"line":142,"column":12},"end":{"line":142,"column":13}},"loc":{"start":{"line":142,"column":25},"end":{"line":144,"column":13}},"line":142},"11":{"name":"(anonymous_11)","decl":{"start":{"line":145,"column":12},"end":{"line":145,"column":13}},"loc":{"start":{"line":145,"column":26},"end":{"line":147,"column":13}},"line":145},"12":{"name":"(anonymous_12)","decl":{"start":{"line":148,"column":12},"end":{"line":148,"column":13}},"loc":{"start":{"line":148,"column":36},"end":{"line":153,"column":13}},"line":148},"13":{"name":"(anonymous_13)","decl":{"start":{"line":158,"column":12},"end":{"line":158,"column":13}},"loc":{"start":{"line":158,"column":39},"end":{"line":160,"column":13}},"line":158},"14":{"name":"(anonymous_14)","decl":{"start":{"line":163,"column":12},"end":{"line":163,"column":13}},"loc":{"start":{"line":163,"column":34},"end":{"line":165,"column":13}},"line":163},"15":{"name":"isChaiExpectCall","decl":{"start":{"line":174,"column":17},"end":{"line":174,"column":33}},"loc":{"start":{"line":174,"column":40},"end":{"line":181,"column":9}},"line":174},"16":{"name":"findExpectCall","decl":{"start":{"line":188,"column":17},"end":{"line":188,"column":31}},"loc":{"start":{"line":188,"column":38},"end":{"line":207,"column":9}},"line":188},"17":{"name":"isChaiShouldCall","decl":{"start":{"line":215,"column":17},"end":{"line":215,"column":33}},"loc":{"start":{"line":215,"column":40},"end":{"line":225,"column":9}},"line":215},"18":{"name":"findShouldCall","decl":{"start":{"line":232,"column":17},"end":{"line":232,"column":31}},"loc":{"start":{"line":232,"column":38},"end":{"line":251,"column":9}},"line":232},"19":{"name":"(anonymous_19)","decl":{"start":{"line":255,"column":33},"end":{"line":255,"column":34}},"loc":{"start":{"line":255,"column":48},"end":{"line":263,"column":13}},"line":255}},"branchMap":{"0":{"loc":{"start":{"line":66,"column":21},"end":{"line":66,"column":45}},"type":"binary-expr","locations":[{"start":{"line":66,"column":21},"end":{"line":66,"column":39}},{"start":{"line":66,"column":43},"end":{"line":66,"column":45}}],"line":66},"1":{"loc":{"start":{"line":67,"column":32},"end":{"line":67,"column":65}},"type":"binary-expr","locations":[{"start":{"line":67,"column":32},"end":{"line":67,"column":56}},{"start":{"line":67,"column":60},"end":{"line":67,"column":65}}],"line":67},"2":{"loc":{"start":{"line":68,"column":27},"end":{"line":68,"column":55}},"type":"binary-expr","locations":[{"start":{"line":68,"column":27},"end":{"line":68,"column":46}},{"start":{"line":68,"column":50},"end":{"line":68,"column":55}}],"line":68},"3":{"loc":{"start":{"line":69,"column":35},"end":{"line":69,"column":71}},"type":"binary-expr","locations":[{"start":{"line":69,"column":35},"end":{"line":69,"column":62}},{"start":{"line":69,"column":66},"end":{"line":69,"column":71}}],"line":69},"4":{"loc":{"start":{"line":70,"column":28},"end":{"line":70,"column":57}},"type":"binary-expr","locations":[{"start":{"line":70,"column":28},"end":{"line":70,"column":48}},{"start":{"line":70,"column":52},"end":{"line":70,"column":57}}],"line":70},"5":{"loc":{"start":{"line":77,"column":19},"end":{"line":78,"column":95}},"type":"binary-expr","locations":[{"start":{"line":77,"column":19},"end":{"line":77,"column":54}},{"start":{"line":78,"column":16},"end":{"line":78,"column":50}},{"start":{"line":78,"column":54},"end":{"line":78,"column":95}}],"line":77},"6":{"loc":{"start":{"line":88,"column":16},"end":{"line":90,"column":17}},"type":"if","locations":[{"start":{"line":88,"column":16},"end":{"line":90,"column":17}},{"start":{"line":88,"column":16},"end":{"line":90,"column":17}}],"line":88},"7":{"loc":{"start":{"line":112,"column":19},"end":{"line":114,"column":57}},"type":"binary-expr","locations":[{"start":{"line":112,"column":20},"end":{"line":112,"column":45}},{"start":{"line":112,"column":49},"end":{"line":112,"column":81}},{"start":{"line":113,"column":21},"end":{"line":113,"column":54}},{"start":{"line":114,"column":20},"end":{"line":114,"column":57}}],"line":112},"8":{"loc":{"start":{"line":123,"column":24},"end":{"line":123,"column":57}},"type":"binary-expr","locations":[{"start":{"line":123,"column":24},"end":{"line":123,"column":42}},{"start":{"line":123,"column":46},"end":{"line":123,"column":57}}],"line":123},"9":{"loc":{"start":{"line":134,"column":16},"end":{"line":136,"column":17}},"type":"if","locations":[{"start":{"line":134,"column":16},"end":{"line":136,"column":17}},{"start":{"line":134,"column":16},"end":{"line":136,"column":17}}],"line":134},"10":{"loc":{"start":{"line":135,"column":27},"end":{"line":135,"column":104}},"type":"binary-expr","locations":[{"start":{"line":135,"column":27},"end":{"line":135,"column":64}},{"start":{"line":135,"column":68},"end":{"line":135,"column":104}}],"line":135},"11":{"loc":{"start":{"line":149,"column":16},"end":{"line":151,"column":17}},"type":"if","locations":[{"start":{"line":149,"column":16},"end":{"line":151,"column":17}},{"start":{"line":149,"column":16},"end":{"line":151,"column":17}}],"line":149},"12":{"loc":{"start":{"line":164,"column":23},"end":{"line":164,"column":77}},"type":"binary-expr","locations":[{"start":{"line":164,"column":23},"end":{"line":164,"column":47}},{"start":{"line":164,"column":51},"end":{"line":164,"column":77}}],"line":164},"13":{"loc":{"start":{"line":176,"column":12},"end":{"line":178,"column":13}},"type":"if","locations":[{"start":{"line":176,"column":12},"end":{"line":178,"column":13}},{"start":{"line":176,"column":12},"end":{"line":178,"column":13}}],"line":176},"14":{"loc":{"start":{"line":190,"column":12},"end":{"line":192,"column":13}},"type":"if","locations":[{"start":{"line":190,"column":12},"end":{"line":192,"column":13}},{"start":{"line":190,"column":12},"end":{"line":192,"column":13}}],"line":190},"15":{"loc":{"start":{"line":190,"column":16},"end":{"line":190,"column":116}},"type":"binary-expr","locations":[{"start":{"line":190,"column":16},"end":{"line":190,"column":46}},{"start":{"line":190,"column":50},"end":{"line":190,"column":83}},{"start":{"line":190,"column":87},"end":{"line":190,"column":116}}],"line":190},"16":{"loc":{"start":{"line":195,"column":12},"end":{"line":197,"column":13}},"type":"if","locations":[{"start":{"line":195,"column":12},"end":{"line":197,"column":13}},{"start":{"line":195,"column":12},"end":{"line":197,"column":13}}],"line":195},"17":{"loc":{"start":{"line":198,"column":12},"end":{"line":200,"column":13}},"type":"if","locations":[{"start":{"line":198,"column":12},"end":{"line":200,"column":13}},{"start":{"line":198,"column":12},"end":{"line":200,"column":13}}],"line":198},"18":{"loc":{"start":{"line":201,"column":12},"end":{"line":203,"column":13}},"type":"if","locations":[{"start":{"line":201,"column":12},"end":{"line":203,"column":13}},{"start":{"line":201,"column":12},"end":{"line":203,"column":13}}],"line":201},"19":{"loc":{"start":{"line":217,"column":12},"end":{"line":219,"column":13}},"type":"if","locations":[{"start":{"line":217,"column":12},"end":{"line":219,"column":13}},{"start":{"line":217,"column":12},"end":{"line":219,"column":13}}],"line":217},"20":{"loc":{"start":{"line":220,"column":12},"end":{"line":222,"column":13}},"type":"if","locations":[{"start":{"line":220,"column":12},"end":{"line":222,"column":13}},{"start":{"line":220,"column":12},"end":{"line":222,"column":13}}],"line":220},"21":{"loc":{"start":{"line":234,"column":12},"end":{"line":236,"column":13}},"type":"if","locations":[{"start":{"line":234,"column":12},"end":{"line":236,"column":13}},{"start":{"line":234,"column":12},"end":{"line":236,"column":13}}],"line":234},"22":{"loc":{"start":{"line":234,"column":16},"end":{"line":234,"column":100}},"type":"binary-expr","locations":[{"start":{"line":234,"column":16},"end":{"line":234,"column":48}},{"start":{"line":234,"column":52},"end":{"line":234,"column":65}},{"start":{"line":234,"column":69},"end":{"line":234,"column":100}}],"line":234},"23":{"loc":{"start":{"line":239,"column":12},"end":{"line":241,"column":13}},"type":"if","locations":[{"start":{"line":239,"column":12},"end":{"line":241,"column":13}},{"start":{"line":239,"column":12},"end":{"line":241,"column":13}}],"line":239},"24":{"loc":{"start":{"line":242,"column":12},"end":{"line":244,"column":13}},"type":"if","locations":[{"start":{"line":242,"column":12},"end":{"line":244,"column":13}},{"start":{"line":242,"column":12},"end":{"line":244,"column":13}}],"line":242},"25":{"loc":{"start":{"line":245,"column":12},"end":{"line":247,"column":13}},"type":"if","locations":[{"start":{"line":245,"column":12},"end":{"line":247,"column":13}},{"start":{"line":245,"column":12},"end":{"line":247,"column":13}}],"line":245},"26":{"loc":{"start":{"line":256,"column":28},"end":{"line":259,"column":45}},"type":"binary-expr","locations":[{"start":{"line":256,"column":28},"end":{"line":256,"column":66}},{"start":{"line":257,"column":23},"end":{"line":257,"column":64}},{"start":{"line":258,"column":23},"end":{"line":258,"column":45}},{"start":{"line":259,"column":23},"end":{"line":259,"column":45}}],"line":256},"27":{"loc":{"start":{"line":260,"column":16},"end":{"line":262,"column":17}},"type":"if","locations":[{"start":{"line":260,"column":16},"end":{"line":262,"column":17}},{"start":{"line":260,"column":16},"end":{"line":262,"column":17}}],"line":260}},"s":{"0":42,"1":27,"2":1,"3":79,"4":79,"5":79,"6":79,"7":79,"8":66,"9":52,"10":52,"11":66,"12":51,"13":1,"14":52,"15":54,"16":54,"17":54,"18":79,"19":106,"20":9,"21":7,"22":5,"23":2,"24":2,"25":2,"26":10,"27":6,"28":4,"29":3,"30":4,"31":45,"32":45,"33":36,"34":9,"35":38,"36":3,"37":35,"38":26,"39":9,"40":3,"41":6,"42":0,"43":6,"44":42,"45":42,"46":7,"47":42,"48":29,"49":13,"50":38,"51":5,"52":33,"53":22,"54":11,"55":3,"56":8,"57":0,"58":8,"59":79,"60":83,"61":83,"62":37},"f":{"0":42,"1":27,"2":79,"3":66,"4":52,"5":52,"6":54,"7":106,"8":9,"9":7,"10":2,"11":2,"12":10,"13":3,"14":4,"15":45,"16":38,"17":42,"18":38,"19":83},"b":{"0":[79,58],"1":[79,72],"2":[79,73],"3":[79,76],"4":[79,75],"5":[66,62,16],"6":[51,15],"7":[54,10,10,52],"8":[106,27],"9":[5,2],"10":[5,3],"11":[6,4],"12":[4,3],"13":[36,9],"14":[3,35],"15":[38,6,3],"16":[26,9],"17":[3,6],"18":[0,6],"19":[7,35],"20":[29,13],"21":[5,33],"22":[38,27,27],"23":[22,11],"24":[3,8],"25":[0,8],"26":[83,54,45,42],"27":[37,46]},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"dd374607c4c2b081d47e729c0ee6547a96d54982","contentHash":"085284c031abf8ad77a81dcf5f0e6765748fe87b8d11666b4f9fb6745e154202"}}
@@ -0,0 +1 @@
1
+ {"parent":null,"pid":33337,"argv":["/usr/local/bin/node","/Users/user/repos/eslint-plugin-chai-friendly/node_modules/.bin/mocha","tests","--recursive"],"execArgv":[],"cwd":"/Users/user/repos/eslint-plugin-chai-friendly","time":1620604159241,"ppid":33336,"coverageFilename":"/Users/user/repos/eslint-plugin-chai-friendly/.nyc_output/a9bacb87-6c71-4985-a8ed-1837b4c2d3e4.json","externalId":"","uuid":"a9bacb87-6c71-4985-a8ed-1837b4c2d3e4","files":["/Users/user/repos/eslint-plugin-chai-friendly/lib/rules/no-unused-expressions.js"]}
@@ -0,0 +1 @@
1
+ {"processes":{"a9bacb87-6c71-4985-a8ed-1837b4c2d3e4":{"parent":null,"children":[]}},"files":{"/Users/user/repos/eslint-plugin-chai-friendly/lib/rules/no-unused-expressions.js":["a9bacb87-6c71-4985-a8ed-1837b4c2d3e4"]},"externalIds":{}}
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # eslint-plugin-chai-friendly
2
2
 
3
- [![npm](https://img.shields.io/npm/v/eslint-plugin-chai-friendly.svg)](https://www.npmjs.com/package/eslint-plugin-chai-friendly) [![npm](https://img.shields.io/npm/dm/eslint-plugin-chai-friendly.svg)](https://www.npmjs.com/package/eslint-plugin-chai-friendly)
3
+ [![npm](https://img.shields.io/npm/v/eslint-plugin-chai-friendly.svg)](https://www.npmjs.com/package/eslint-plugin-chai-friendly) [![npm](https://img.shields.io/npm/dm/eslint-plugin-chai-friendly)](https://www.npmjs.com/package/eslint-plugin-chai-friendly)
4
4
 
5
5
  This plugin overrides `no-unused-expressions` to make it friendly towards chai `expect` and `should` statements.
6
6
 
@@ -32,7 +32,7 @@ npm install eslint-plugin-chai-friendly --save-dev
32
32
 
33
33
  ## Usage
34
34
 
35
- Add `chai-friendly` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix:
35
+ Add `chai-friendly` to the plugins section of your `.eslintrc.*` configuration file. You can omit the `eslint-plugin-` prefix:
36
36
 
37
37
  ```json
38
38
  {
@@ -54,6 +54,16 @@ Then disable original `no-unused-expressions` rule and configure chai-friendly r
54
54
  }
55
55
  ```
56
56
 
57
+ If you don't need to tweak the above rule settings, you can instead
58
+ just add the following to your config file's `extends` and the above
59
+ will be applied automatically:
60
+
61
+ ```json
62
+ {
63
+ "extends": ["plugin:chai-friendly/recommended"]
64
+ }
65
+ ```
66
+
57
67
  ## Options
58
68
 
59
69
  This rule, in its default state, does not require any arguments. If you would like to enable one or more of the following you may pass an object with the options set as follows:
@@ -61,6 +71,7 @@ This rule, in its default state, does not require any arguments. If you would li
61
71
  - `allowShortCircuit` set to `true` will allow you to use short circuit evaluations in your expressions (Default: `false`).
62
72
  - `allowTernary` set to `true` will enable you to use ternary operators in your expressions similarly to short circuit evaluations (Default: `false`).
63
73
  - `allowTaggedTemplates` set to `true` will enable you to use tagged template literals in your expressions (Default: `false`).
74
+ - `enforceForJSX` set to `true` will flag unused JSX element expressions (Default: `false`).
64
75
 
65
76
  These options allow unused expressions only if all of the code paths either directly change the state (for example, assignment statement) or could have side effects (for example, function call).
66
77
 
@@ -68,4 +79,4 @@ More info in the original rule's [docs](http://eslint.org/docs/rules/no-unused-e
68
79
 
69
80
  ## Supported Rules
70
81
 
71
- - chai-friendly/no-unused-expressions
82
+ - `chai-friendly/no-unused-expressions`
package/lib/index.js CHANGED
@@ -5,10 +5,16 @@
5
5
  "use strict";
6
6
 
7
7
  module.exports = {
8
- rules: {
9
- 'no-unused-expressions': require('./rules/no-unused-expressions')
10
- }
8
+ configs: {
9
+ recommended: {
10
+ plugins: ['chai-friendly'],
11
+ rules: {
12
+ 'chai-friendly/no-unused-expressions': 'error',
13
+ 'no-unused-expressions': 'off'
14
+ }
15
+ }
16
+ },
17
+ rules: {
18
+ 'no-unused-expressions': require('./rules/no-unused-expressions')
19
+ }
11
20
  };
12
-
13
-
14
-
@@ -9,8 +9,27 @@
9
9
  // Rule Definition
10
10
  //------------------------------------------------------------------------------
11
11
 
12
+ /**
13
+ * Returns `true`.
14
+ * @returns {boolean} `true`.
15
+ */
16
+ function alwaysTrue() {
17
+ return true;
18
+ }
19
+
20
+ /**
21
+ * Returns `false`.
22
+ * @returns {boolean} `false`.
23
+ */
24
+ function alwaysFalse() {
25
+ return false;
26
+ }
27
+
28
+
12
29
  module.exports = {
13
30
  meta: {
31
+ type: "suggestion",
32
+
14
33
  docs: {
15
34
  description: "disallow unused expressions",
16
35
  category: "Best Practices",
@@ -29,18 +48,26 @@ module.exports = {
29
48
  },
30
49
  allowTaggedTemplates: {
31
50
  type: "boolean"
51
+ },
52
+ enforceForJSX: {
53
+ type: "boolean",
54
+ default: false
32
55
  }
33
56
  },
34
57
  additionalProperties: false
35
58
  }
36
- ]
59
+ ],
60
+
61
+ messages: {
62
+ unusedExpression: "Expected an assignment or function call and instead saw an expression."
63
+ }
37
64
  },
38
65
  create: function (context) {
39
66
  var config = context.options[0] || {},
40
67
  allowShortCircuit = config.allowShortCircuit || false,
41
68
  allowTernary = config.allowTernary || false,
42
- allowTaggedTemplates = config.allowTaggedTemplates || false;
43
-
69
+ allowTaggedTemplates = config.allowTaggedTemplates || false,
70
+ enforceForJSX = config.enforceForJSX || false;
44
71
 
45
72
  /**
46
73
  * @param {ASTNode} node - any node
@@ -88,31 +115,55 @@ module.exports = {
88
115
  }
89
116
 
90
117
  /**
91
- * Determines whether or not a given node is a valid expression. Recurses on short circuit eval and ternary nodes if enabled by flags.
92
- * @param {ASTNode} node - any node
93
- * @returns {boolean} whether the given node is a valid expression
118
+ * The member functions return `true` if the type has no side-effects.
119
+ * Unknown nodes are handled as `false`, then this rule ignores those.
94
120
  */
95
- function isValidExpression(node) {
96
- if (allowTernary) {
121
+ const Checker = Object.assign(Object.create(null), {
122
+ isDisallowed(node) {
123
+ return (Checker[node.type] || alwaysFalse)(node);
124
+ },
97
125
 
98
- // Recursive check for ternary and logical expressions
99
- if (node.type === "ConditionalExpression") {
100
- return isValidExpression(node.consequent) && isValidExpression(node.alternate);
126
+ ArrayExpression: alwaysTrue,
127
+ ArrowFunctionExpression: alwaysTrue,
128
+ BinaryExpression: alwaysTrue,
129
+ ChainExpression(node) {
130
+ return Checker.isDisallowed(node.expression);
131
+ },
132
+ ClassExpression: alwaysTrue,
133
+ ConditionalExpression(node) {
134
+ if (allowTernary) {
135
+ return Checker.isDisallowed(node.consequent) || Checker.isDisallowed(node.alternate);
101
136
  }
102
- }
103
- if (allowShortCircuit) {
104
- if (node.type === "LogicalExpression") {
105
- return isValidExpression(node.right);
137
+ return true;
138
+ },
139
+ FunctionExpression: alwaysTrue,
140
+ Identifier: alwaysTrue,
141
+ Literal: alwaysTrue,
142
+ JSXElement() {
143
+ return enforceForJSX;
144
+ },
145
+ JSXFragment() {
146
+ return enforceForJSX;
147
+ },
148
+ LogicalExpression(node) {
149
+ if (allowShortCircuit) {
150
+ return Checker.isDisallowed(node.right);
106
151
  }
107
- }
108
-
109
- if (allowTaggedTemplates && node.type === "TaggedTemplateExpression") {
110
152
  return true;
153
+ },
154
+ MemberExpression: alwaysTrue,
155
+ MetaProperty: alwaysTrue,
156
+ ObjectExpression: alwaysTrue,
157
+ SequenceExpression: alwaysTrue,
158
+ TaggedTemplateExpression() {
159
+ return !allowTaggedTemplates;
160
+ },
161
+ TemplateLiteral: alwaysTrue,
162
+ ThisExpression: alwaysTrue,
163
+ UnaryExpression(node) {
164
+ return node.operator !== "void" && node.operator !== "delete";
111
165
  }
112
-
113
- return /^(?:Assignment|Call|New|Update|Yield|Await)Expression$/.test(node.type) ||
114
- (node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0);
115
- }
166
+ });
116
167
 
117
168
  /**
118
169
  * Determines whether or not a given node is a chai's expect statement.
@@ -121,14 +172,12 @@ module.exports = {
121
172
  * @returns {boolean} whether the given node is a chai expectation
122
173
  */
123
174
  function isChaiExpectCall(node) {
124
- var expression = node.expression;
175
+ let expression = node.expression;
125
176
  if (expression.type !== 'MemberExpression') {
126
177
  return false;
127
178
  }
128
179
 
129
- var hasExpectCall = Boolean(findExpectCall(expression.object));
130
-
131
- return hasExpectCall;
180
+ return Boolean(findExpectCall(expression.object));
132
181
  }
133
182
 
134
183
  /**
@@ -149,10 +198,13 @@ module.exports = {
149
198
  if (node.type === 'CallExpression') {
150
199
  return findExpectCall(node.callee);
151
200
  }
201
+ if (node.type === 'ChainExpression') {
202
+ return findExpectCall(node.expression);
203
+ }
152
204
 
153
205
  // Stop search, expect(...) not found
154
206
  return null;
155
- };
207
+ }
156
208
 
157
209
  /**
158
210
  * Determines whether or not a given node is a chai's should statement.
@@ -161,14 +213,15 @@ module.exports = {
161
213
  * @returns {boolean} whether the given node is a chai should statement
162
214
  */
163
215
  function isChaiShouldCall(node) {
164
- var expression = node.expression;
216
+ let expression = node.expression;
217
+ if (expression.type === 'ChainExpression') {
218
+ expression = expression.expression
219
+ }
165
220
  if (expression.type !== 'MemberExpression') {
166
221
  return false;
167
222
  }
168
223
 
169
- var hasShouldCall = Boolean(findShouldCall(expression.object));
170
-
171
- return hasShouldCall;
224
+ return Boolean(findShouldCall(expression.object));
172
225
  }
173
226
 
174
227
  /**
@@ -189,22 +242,25 @@ module.exports = {
189
242
  if (node.type === 'CallExpression') {
190
243
  return findShouldCall(node.callee);
191
244
  }
245
+ if (node.type === 'ChainExpression') {
246
+ return findShouldCall(node.expression);
247
+ }
192
248
 
193
249
  // Stop search, obj.should not found
194
250
  return null;
195
- };
251
+ }
196
252
 
197
253
 
198
254
  return {
199
255
  ExpressionStatement: function(node) {
200
- var valid = isValidExpression(node.expression)
256
+ var valid = !Checker.isDisallowed(node.expression)
201
257
  || isDirective(node, context.getAncestors())
202
258
  || isChaiExpectCall(node)
203
259
  || isChaiShouldCall(node);
204
260
  if (!valid) {
205
- context.report(node, "Expected an assignment or function call and instead saw an expression.");
261
+ context.report({node, messageId: "unusedExpression"});
206
262
  }
207
263
  }
208
264
  };
209
265
  }
210
- };
266
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-chai-friendly",
3
- "version": "0.4.1",
3
+ "version": "0.7.1",
4
4
  "description": "This plugin makes 'no-unused-expressions' rule friendly towards chai expect statements.",
5
5
  "keywords": [
6
6
  "eslint",
@@ -18,17 +18,23 @@
18
18
  "url": "https://github.com/ihordiachenko/eslint-plugin-chai-friendly/issues"
19
19
  },
20
20
  "author": "Ihor Diachenko",
21
+ "contributors": [
22
+ "Brett Zamir"
23
+ ],
21
24
  "main": "lib/index.js",
22
25
  "scripts": {
23
- "test": "mocha tests --recursive"
26
+ "lint": "eslint .",
27
+ "test": "nyc mocha tests --recursive"
24
28
  },
25
29
  "dependencies": {},
26
30
  "peerDependencies": {
27
31
  "eslint": ">=3.0.0"
28
32
  },
29
33
  "devDependencies": {
30
- "eslint": "~3.11.0",
31
- "mocha": "^3.0.2"
34
+ "babel-eslint": "^10.1.0",
35
+ "eslint": "^7.26.0",
36
+ "mocha": "^7.1.2",
37
+ "nyc": "^15.0.1"
32
38
  },
33
39
  "engines": {
34
40
  "node": ">=0.10.0"
@@ -71,12 +71,60 @@ ruleTester.run("no-unused-expressions", rule, {
71
71
  options: [{ allowTaggedTemplates: true }],
72
72
  parserOptions: { ecmaVersion: 6 }
73
73
  },
74
+ {
75
+ code: "import(\"foo\")",
76
+ parserOptions: { ecmaVersion: 11 }
77
+ },
78
+ {
79
+ code: "func?.(\"foo\")",
80
+ parserOptions: { ecmaVersion: 11 }
81
+ },
82
+ {
83
+ code: "obj?.foo(\"bar\")",
84
+ parserOptions: { ecmaVersion: 11 }
85
+ },
86
+ // JSX
87
+ {
88
+ code: "<div />",
89
+ parserOptions: { ecmaFeatures: { jsx: true } }
90
+ },
91
+ {
92
+ code: "<></>",
93
+ parserOptions: { ecmaFeatures: { jsx: true } }
94
+ },
95
+ {
96
+ code: "var partial = <div />",
97
+ parserOptions: { ecmaFeatures: { jsx: true } }
98
+ },
99
+ {
100
+ code: "var partial = <div />",
101
+ options: [{ enforceForJSX: true }],
102
+ parserOptions: { ecmaFeatures: { jsx: true } }
103
+ },
104
+ {
105
+ code: "var partial = <></>",
106
+ options: [{ enforceForJSX: true }],
107
+ parserOptions: { ecmaFeatures: { jsx: true } }
108
+ },
109
+
74
110
  // Chai statements
75
111
  "expect(foo).to.be.true;",
76
112
  "expect(foo).to.have.a.property('bar').which.is.true",
77
113
  "foo.should.be.true;",
78
114
  "foo.inner.nested.should.be.true",
79
- "foo.should.have.a.property('bar').which.is.true;"
115
+ "foo.should.have.a.property('bar').which.is.true;",
116
+ {
117
+ code: "foo?.should.be.true;",
118
+ parserOptions: { ecmaVersion: 11 }
119
+ },
120
+ {
121
+ code: "foo?.bar?.should.be.true;",
122
+ parserOptions: { ecmaVersion: 11 }
123
+ },
124
+ {
125
+ code: "expect(foo?.bar).should.be.true;",
126
+ parserOptions: { ecmaVersion: 11 }
127
+ }
80
128
  ],
81
129
  invalid: [
82
130
  { code: "0", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]},
@@ -85,11 +133,11 @@ ruleTester.run("no-unused-expressions", rule, {
85
133
  { code: "{0}", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]},
86
134
  { code: "[]", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]},
87
135
  { code: "a && b();", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]},
88
- { code: "a() || false", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }]},
89
- { code: "a || (b = c)", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }]},
90
- { code: "a ? b() || (c = d) : e", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }]},
91
- { code: "a && b()", options: [{ allowTernary: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }]},
92
- { code: "a ? b() : c()", options: [{ allowShortCircuit: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }]},
136
+ { code: "a() || false", errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]},
137
+ { code: "a || (b = c)", errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]},
138
+ { code: "a ? b() || (c = d) : e", errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]},
139
+ { code: "a && b()", options: [{ allowTernary: true }], errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]},
140
+ { code: "a ? b() : c()", options: [{ allowShortCircuit: true }], errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]},
93
141
  { code: "a || b", options: [{ allowShortCircuit: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]},
94
142
  { code: "a() && b", options: [{ allowShortCircuit: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]},
95
143
  { code: "a ? b : 0", options: [{ allowTernary: true }], errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement"}]},
@@ -106,32 +154,73 @@ ruleTester.run("no-unused-expressions", rule, {
106
154
  code: "`untagged template literal`",
107
155
  options: [{ allowTaggedTemplates: true }],
108
156
  parserOptions: { ecmaVersion: 6},
109
- errors: ["Expected an assignment or function call and instead saw an expression."]
157
+ errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
110
158
  },
111
159
  {
112
160
  code: "`untagged template literal`",
113
161
  options: [{ allowTaggedTemplates: false }],
114
162
  parserOptions: { ecmaVersion: 6},
115
- errors: ["Expected an assignment or function call and instead saw an expression."]
163
+ errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
116
164
  },
117
165
  {
118
166
  code: "tag`tagged template literal`",
119
167
  options: [{ allowTaggedTemplates: false }],
120
168
  parserOptions: { ecmaVersion: 6},
121
- errors: ["Expected an assignment or function call and instead saw an expression."]
169
+ errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
122
170
  },
123
171
  {
124
172
  code: "`untagged template literal`",
125
173
  parserOptions: { ecmaVersion: 6 },
126
- errors: ["Expected an assignment or function call and instead saw an expression."]
174
+ errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
127
175
  },
128
176
  {
129
177
  code: "tag`tagged template literal`",
130
178
  parserOptions: { ecmaVersion: 6 },
131
- errors: ["Expected an assignment or function call and instead saw an expression."]
179
+ errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
180
+ },
181
+
182
+ // Optional chaining
183
+ {
184
+ code: "obj?.foo",
185
+ parserOptions: { ecmaVersion: 2020 },
186
+ errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
187
+ },
188
+ {
189
+ code: "obj?.foo.bar",
190
+ parserOptions: { ecmaVersion: 2020 },
191
+ errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
192
+ },
193
+ {
194
+ code: "obj?.foo().bar",
195
+ parserOptions: { ecmaVersion: 2020 },
196
+ errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
197
+ },
198
+ // JSX
199
+ {
200
+ code: "<div />",
201
+ options: [{ enforceForJSX: true }],
202
+ parserOptions: { ecmaFeatures: { jsx: true } },
203
+ errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
204
+ },
205
+ {
206
+ code: "<></>",
207
+ options: [{ enforceForJSX: true }],
208
+ parserOptions: { ecmaFeatures: { jsx: true } },
209
+ errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
132
210
  },
211
+
133
212
  // Chai statements
134
- { code: "foo.expect('bar').not.to.pass;", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }]},
135
- { code: "should.not.pass;", errors: [{ message: "Expected an assignment or function call and instead saw an expression.", type: "ExpressionStatement" }] },
213
+ { code: "foo.expect('bar').not.to.pass;", errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]},
214
+ { code: "should.not.pass;", errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }] },
215
+ {
216
+ code: "foo?.expect.to.be.true;",
217
+ parserOptions: { ecmaVersion: 11 },
218
+ errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
219
+ },
220
+ {
221
+ code: "foo?.bar?.expect.to.be.true;",
222
+ parserOptions: { ecmaVersion: 11 },
223
+ errors: [{ messageId: "unusedExpression", type: "ExpressionStatement" }]
224
+ }
136
225
  ]
137
- });
226
+ });
@@ -1,126 +0,0 @@
1
- /**
2
- * @fileoverview Flag expressions in statement position that do not side effect
3
- * @author Michael Ficarra
4
- */
5
- "use strict";
6
-
7
- //------------------------------------------------------------------------------
8
- // Rule Definition
9
- //------------------------------------------------------------------------------
10
-
11
- module.exports = {
12
- meta: {
13
- docs: {
14
- description: "disallow unused expressions",
15
- category: "Best Practices",
16
- recommended: false
17
- },
18
-
19
- schema: [
20
- {
21
- type: "object",
22
- properties: {
23
- allowShortCircuit: {
24
- type: "boolean"
25
- },
26
- allowTernary: {
27
- type: "boolean"
28
- },
29
- allowTaggedTemplates: {
30
- type: "boolean"
31
- }
32
- },
33
- additionalProperties: false
34
- }
35
- ]
36
- },
37
-
38
- create(context) {
39
- const config = context.options[0] || {},
40
- allowShortCircuit = config.allowShortCircuit || false,
41
- allowTernary = config.allowTernary || false,
42
- allowTaggedTemplates = config.allowTaggedTemplates || false;
43
-
44
- /**
45
- * @param {ASTNode} node - any node
46
- * @returns {boolean} whether the given node structurally represents a directive
47
- */
48
- function looksLikeDirective(node) {
49
- return node.type === "ExpressionStatement" &&
50
- node.expression.type === "Literal" && typeof node.expression.value === "string";
51
- }
52
-
53
- /**
54
- * @param {Function} predicate - ([a] -> Boolean) the function used to make the determination
55
- * @param {a[]} list - the input list
56
- * @returns {a[]} the leading sequence of members in the given list that pass the given predicate
57
- */
58
- function takeWhile(predicate, list) {
59
- for (let i = 0; i < list.length; ++i) {
60
- if (!predicate(list[i])) {
61
- return list.slice(0, i);
62
- }
63
- }
64
- return list.slice();
65
- }
66
-
67
- /**
68
- * @param {ASTNode} node - a Program or BlockStatement node
69
- * @returns {ASTNode[]} the leading sequence of directive nodes in the given node's body
70
- */
71
- function directives(node) {
72
- return takeWhile(looksLikeDirective, node.body);
73
- }
74
-
75
- /**
76
- * @param {ASTNode} node - any node
77
- * @param {ASTNode[]} ancestors - the given node's ancestors
78
- * @returns {boolean} whether the given node is considered a directive in its current position
79
- */
80
- function isDirective(node, ancestors) {
81
- const parent = ancestors[ancestors.length - 1],
82
- grandparent = ancestors[ancestors.length - 2];
83
-
84
- return (parent.type === "Program" || parent.type === "BlockStatement" &&
85
- (/Function/.test(grandparent.type))) &&
86
- directives(parent).indexOf(node) >= 0;
87
- }
88
-
89
- /**
90
- * Determines whether or not a given node is a valid expression. Recurses on short circuit eval and ternary nodes if enabled by flags.
91
- * @param {ASTNode} node - any node
92
- * @returns {boolean} whether the given node is a valid expression
93
- */
94
- function isValidExpression(node) {
95
- if (allowTernary) {
96
-
97
- // Recursive check for ternary and logical expressions
98
- if (node.type === "ConditionalExpression") {
99
- return isValidExpression(node.consequent) && isValidExpression(node.alternate);
100
- }
101
- }
102
-
103
- if (allowShortCircuit) {
104
- if (node.type === "LogicalExpression") {
105
- return isValidExpression(node.right);
106
- }
107
- }
108
-
109
- if (allowTaggedTemplates && node.type === "TaggedTemplateExpression") {
110
- return true;
111
- }
112
-
113
- return /^(?:Assignment|Call|New|Update|Yield|Await)Expression$/.test(node.type) ||
114
- (node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0);
115
- }
116
-
117
- return {
118
- ExpressionStatement(node) {
119
- if (!isValidExpression(node.expression) && !isDirective(node, context.getAncestors())) {
120
- context.report({ node, message: "Expected an assignment or function call and instead saw an expression." });
121
- }
122
- }
123
- };
124
-
125
- }
126
- };