eslint-plugin-chai-friendly 1.1.1 → 1.2.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.
@@ -51,6 +51,9 @@ module.exports = {
51
51
  enforceForJSX: {
52
52
  type: "boolean",
53
53
  default: false
54
+ },
55
+ ignoreDirectives: {
56
+ type: "boolean"
54
57
  }
55
58
  },
56
59
  additionalProperties: false
@@ -66,7 +69,8 @@ module.exports = {
66
69
  allowShortCircuit = config.allowShortCircuit || false,
67
70
  allowTernary = config.allowTernary || false,
68
71
  allowTaggedTemplates = config.allowTaggedTemplates || false,
69
- enforceForJSX = config.enforceForJSX || false;
72
+ enforceForJSX = config.enforceForJSX || false,
73
+ ignoreDirectives = config.ignoreDirectives || false;
70
74
 
71
75
  /**
72
76
  * @param {ASTNode} node - any node
@@ -101,12 +105,19 @@ module.exports = {
101
105
 
102
106
  /**
103
107
  * @param {ASTNode} node - any node
104
- * @param {ASTNode[]} ancestors - the given node's ancestors
108
+ * @returns {boolean} whether the parser marked this node as a directive
109
+ */
110
+ function isParserDirective(node) {
111
+ return typeof node.directive === "string";
112
+ }
113
+
114
+ /**
115
+ * @param {ASTNode} node - any node
105
116
  * @returns {boolean} whether the given node is considered a directive in its current position
106
117
  */
107
- function isDirective(node, ancestors) {
108
- var parent = ancestors[ancestors.length - 1],
109
- grandparent = ancestors[ancestors.length - 2];
118
+ function isDirective(node) {
119
+ var parent = node.parent,
120
+ grandparent = node.parent.parent;
110
121
 
111
122
  /**
112
123
  * https://tc39.es/ecma262/#directive-prologue
@@ -137,7 +148,8 @@ module.exports = {
137
148
  ClassExpression: alwaysTrue,
138
149
  ConditionalExpression(node) {
139
150
  if (allowTernary) {
140
- return Checker.isDisallowed(node.consequent) || Checker.isDisallowed(node.alternate);
151
+ return (Checker.isDisallowed(node.consequent) && !isChaiCall(node.consequent)) ||
152
+ (Checker.isDisallowed(node.alternate) && !isChaiCall(node.alternate));
141
153
  }
142
154
  return true;
143
155
  },
@@ -152,7 +164,7 @@ module.exports = {
152
164
  },
153
165
  LogicalExpression(node) {
154
166
  if (allowShortCircuit) {
155
- return Checker.isDisallowed(node.right);
167
+ return Checker.isDisallowed(node.right) && !isChaiCall(node.right);
156
168
  }
157
169
  return true;
158
170
  },
@@ -167,22 +179,35 @@ module.exports = {
167
179
  ThisExpression: alwaysTrue,
168
180
  UnaryExpression(node) {
169
181
  return node.operator !== "void" && node.operator !== "delete";
182
+ },
183
+
184
+ // TypeScript-specific node types
185
+ TSAsExpression(node) {
186
+ return Checker.isDisallowed(node.expression);
187
+ },
188
+ TSTypeAssertion(node) {
189
+ return Checker.isDisallowed(node.expression);
190
+ },
191
+ TSNonNullExpression(node) {
192
+ return Checker.isDisallowed(node.expression);
193
+ },
194
+ TSInstantiationExpression(node) {
195
+ return Checker.isDisallowed(node.expression);
170
196
  }
171
197
  });
172
198
 
173
199
  /**
174
200
  * Determines whether or not a given node is a chai's expect statement.
175
201
  * e.g. expect(foo).to.eventually.be.true;
176
- * @param {ASTNode} node - any node
202
+ * @param {ASTNode} expressionNode - expression node
177
203
  * @returns {boolean} whether the given node is a chai expectation
178
204
  */
179
- function isChaiExpectCall(node) {
180
- let expression = node.expression;
181
- if (expression.type !== 'MemberExpression') {
205
+ function isChaiExpectCall(expressionNode) {
206
+ if (expressionNode.type !== 'MemberExpression') {
182
207
  return false;
183
208
  }
184
209
 
185
- return Boolean(findExpectCall(expression.object));
210
+ return Boolean(findExpectCall(expressionNode.object));
186
211
  }
187
212
 
188
213
  /**
@@ -214,19 +239,18 @@ module.exports = {
214
239
  /**
215
240
  * Determines whether or not a given node is a chai's should statement.
216
241
  * e.g. foo.should.eventually.be.true;
217
- * @param {ASTNode} node - any node
242
+ * @param {ASTNode} expressionNode - expression node
218
243
  * @returns {boolean} whether the given node is a chai should statement
219
244
  */
220
- function isChaiShouldCall(node) {
221
- let expression = node.expression;
222
- if (expression.type === 'ChainExpression') {
223
- expression = expression.expression
245
+ function isChaiShouldCall(expressionNode) {
246
+ if (expressionNode.type === 'ChainExpression') {
247
+ expressionNode = expressionNode.expression
224
248
  }
225
- if (expression.type !== 'MemberExpression') {
249
+ if (expressionNode.type !== 'MemberExpression') {
226
250
  return false;
227
251
  }
228
252
 
229
- return Boolean(findShouldCall(expression.object));
253
+ return Boolean(findShouldCall(expressionNode.object));
230
254
  }
231
255
 
232
256
  /**
@@ -255,18 +279,22 @@ module.exports = {
255
279
  return null;
256
280
  }
257
281
 
258
- const sourceCode = context.sourceCode ?? context.getSourceCode();
282
+ /**
283
+ * Determines whether or not a given node is a chai call.
284
+ * @param {ASTNode} expressionNode - expression node
285
+ * @returns {boolean} whether the given node is a chai call
286
+ */
287
+ function isChaiCall(expressionNode) {
288
+ return isChaiExpectCall(expressionNode) || isChaiShouldCall(expressionNode);
289
+ }
290
+
259
291
  return {
260
292
  ExpressionStatement: function(node) {
261
- var valid = !Checker.isDisallowed(node.expression)
262
- || isDirective(node,
263
- (sourceCode.getAncestors
264
- ? sourceCode.getAncestors(node)
265
- : context.getAncestors()
266
- ))
267
- || isChaiExpectCall(node)
268
- || isChaiShouldCall(node);
269
- if (!valid) {
293
+ if (Checker.isDisallowed(node.expression)
294
+ && !isParserDirective(node)
295
+ && !(ignoreDirectives && isDirective(node))
296
+ && !isChaiCall(node.expression)
297
+ ) {
270
298
  context.report({node, messageId: "unusedExpression"});
271
299
  }
272
300
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-chai-friendly",
3
- "version": "1.1.1",
3
+ "version": "1.2.1",
4
4
  "description": "This plugin makes 'no-unused-expressions' rule friendly towards chai expect statements.",
5
5
  "keywords": [
6
6
  "eslint",
@@ -49,8 +49,9 @@
49
49
  "typescript": "^5.8.3"
50
50
  },
51
51
  "overrides": {
52
- "flatted": "3.4.1",
53
- "serialize-javascript": "7.0.4",
52
+ "flatted": "3.4.2",
53
+ "serialize-javascript": "7.0.5",
54
+ "brace-expansion": "5.0.5",
54
55
  "@istanbuljs/load-nyc-config": {
55
56
  "js-yaml": "3.14.2"
56
57
  },