eslint 1.4.1 → 1.5.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.
Files changed (38) hide show
  1. package/README.md +1 -1
  2. package/bin/eslint.js +32 -3
  3. package/lib/ast-utils.js +17 -11
  4. package/lib/cli-engine.js +72 -11
  5. package/lib/config.js +54 -55
  6. package/lib/eslint.js +7 -56
  7. package/lib/options.js +7 -0
  8. package/lib/rules/array-bracket-spacing.js +6 -5
  9. package/lib/rules/block-spacing.js +4 -3
  10. package/lib/rules/comma-dangle.js +25 -10
  11. package/lib/rules/comma-spacing.js +4 -29
  12. package/lib/rules/computed-property-spacing.js +5 -4
  13. package/lib/rules/eol-last.js +8 -1
  14. package/lib/rules/func-style.js +29 -9
  15. package/lib/rules/id-length.js +3 -3
  16. package/lib/rules/indent.js +100 -47
  17. package/lib/rules/jsx-quotes.js +1 -1
  18. package/lib/rules/key-spacing.js +7 -1
  19. package/lib/rules/no-dupe-args.js +30 -46
  20. package/lib/rules/no-extra-semi.js +7 -1
  21. package/lib/rules/no-inline-comments.js +3 -1
  22. package/lib/rules/no-spaced-func.js +18 -5
  23. package/lib/rules/no-trailing-spaces.js +34 -6
  24. package/lib/rules/no-unused-vars.js +4 -4
  25. package/lib/rules/no-warning-comments.js +7 -0
  26. package/lib/rules/object-curly-spacing.js +7 -9
  27. package/lib/rules/semi-spacing.js +29 -4
  28. package/lib/rules/space-after-keywords.js +27 -5
  29. package/lib/rules/space-before-blocks.js +64 -7
  30. package/lib/rules/space-before-function-paren.js +19 -13
  31. package/lib/rules/space-before-keywords.js +45 -17
  32. package/lib/rules/space-infix-ops.js +22 -1
  33. package/lib/rules/space-return-throw-case.js +7 -1
  34. package/lib/testers/event-generator-tester.js +63 -0
  35. package/lib/util/comment-event-generator.js +116 -0
  36. package/lib/util/node-event-generator.js +55 -0
  37. package/lib/util/source-code.js +14 -7
  38. package/package.json +2 -2
@@ -111,10 +111,10 @@ module.exports = function(context) {
111
111
  */
112
112
  function isUsedVariable(variable, references) {
113
113
  var functionNodes = variable.defs.filter(function(def) {
114
- return def.type === "FunctionName";
115
- }).map(function(def) {
116
- return def.node;
117
- }),
114
+ return def.type === "FunctionName";
115
+ }).map(function(def) {
116
+ return def.node;
117
+ }),
118
118
  isFunctionDefinition = functionNodes.length > 0;
119
119
 
120
120
  return references.some(function(ref) {
@@ -5,6 +5,8 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ var astUtils = require("../ast-utils");
9
+
8
10
  //------------------------------------------------------------------------------
9
11
  // Rule Definition
10
12
  //------------------------------------------------------------------------------
@@ -14,6 +16,7 @@ module.exports = function(context) {
14
16
  var configuration = context.options[0] || {},
15
17
  warningTerms = configuration.terms || ["todo", "fixme", "xxx"],
16
18
  location = configuration.location || "start",
19
+ selfConfigRegEx = /\bno-warning-comments\b/,
17
20
  warningRegExps;
18
21
 
19
22
  /**
@@ -69,6 +72,10 @@ module.exports = function(context) {
69
72
  * @returns {void} undefined.
70
73
  */
71
74
  function checkComment(node) {
75
+ if (astUtils.isDirectiveComment(node) && selfConfigRegEx.test(node.value)) {
76
+ return;
77
+ }
78
+
72
79
  var matches = commentContainsWarningTerm(node.value);
73
80
 
74
81
  matches.forEach(function(matchedTerm) {
@@ -17,7 +17,8 @@ var astUtils = require("../ast-utils");
17
17
  //------------------------------------------------------------------------------
18
18
 
19
19
  module.exports = function(context) {
20
- var spaced = context.options[0] === "always";
20
+ var spaced = context.options[0] === "always",
21
+ sourceCode = context.getSourceCode();
21
22
 
22
23
  /**
23
24
  * Determines whether an option is set, relative to the spacing option.
@@ -101,7 +102,7 @@ module.exports = function(context) {
101
102
  firstSpaced, lastSpaced;
102
103
 
103
104
  if (astUtils.isTokenOnSameLine(first, second)) {
104
- firstSpaced = astUtils.isTokenSpaced(first, second);
105
+ firstSpaced = sourceCode.isSpaceBetweenTokens(first, second);
105
106
  if (options.spaced && !firstSpaced) {
106
107
  reportRequiredBeginningSpace(node, first);
107
108
  }
@@ -111,7 +112,7 @@ module.exports = function(context) {
111
112
  }
112
113
 
113
114
  if (astUtils.isTokenOnSameLine(penultimate, last)) {
114
- lastSpaced = astUtils.isTokenSpaced(penultimate, last);
115
+ lastSpaced = sourceCode.isSpaceBetweenTokens(penultimate, last);
115
116
  if (closingCurlyBraceMustBeSpaced && !lastSpaced) {
116
117
  reportRequiredEndingSpace(node, last);
117
118
  }
@@ -131,8 +132,7 @@ module.exports = function(context) {
131
132
  return;
132
133
  }
133
134
 
134
- var sourceCode = context.getSourceCode(),
135
- first = sourceCode.getFirstToken(node),
135
+ var first = sourceCode.getFirstToken(node),
136
136
  last = sourceCode.getLastToken(node),
137
137
  second = sourceCode.getTokenAfter(first),
138
138
  penultimate = sourceCode.getTokenBefore(last);
@@ -150,8 +150,7 @@ module.exports = function(context) {
150
150
  return;
151
151
  }
152
152
 
153
- var sourceCode = context.getSourceCode(),
154
- firstSpecifier = node.specifiers[0],
153
+ var firstSpecifier = node.specifiers[0],
155
154
  lastSpecifier = node.specifiers[node.specifiers.length - 1];
156
155
 
157
156
  if (lastSpecifier.type !== "ImportSpecifier") {
@@ -185,8 +184,7 @@ module.exports = function(context) {
185
184
  return;
186
185
  }
187
186
 
188
- var sourceCode = context.getSourceCode(),
189
- firstSpecifier = node.specifiers[0],
187
+ var firstSpecifier = node.specifiers[0],
190
188
  lastSpecifier = node.specifiers[node.specifiers.length - 1],
191
189
  first = sourceCode.getTokenBefore(firstSpecifier),
192
190
  last = sourceCode.getTokenAfter(lastSpecifier);
@@ -16,7 +16,8 @@ module.exports = function(context) {
16
16
 
17
17
  var config = context.options[0],
18
18
  requireSpaceBefore = false,
19
- requireSpaceAfter = true;
19
+ requireSpaceAfter = true,
20
+ sourceCode = context.getSourceCode();
20
21
 
21
22
  if (typeof config === "object") {
22
23
  if (config.hasOwnProperty("before")) {
@@ -34,7 +35,7 @@ module.exports = function(context) {
34
35
  */
35
36
  function hasLeadingSpace(token) {
36
37
  var tokenBefore = context.getTokenBefore(token);
37
- return tokenBefore && astUtils.isTokenOnSameLine(tokenBefore, token) && astUtils.isTokenSpaced(tokenBefore, token);
38
+ return tokenBefore && astUtils.isTokenOnSameLine(tokenBefore, token) && sourceCode.isSpaceBetweenTokens(tokenBefore, token);
38
39
  }
39
40
 
40
41
  /**
@@ -44,7 +45,7 @@ module.exports = function(context) {
44
45
  */
45
46
  function hasTrailingSpace(token) {
46
47
  var tokenAfter = context.getTokenAfter(token);
47
- return tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter) && astUtils.isTokenSpaced(token, tokenAfter);
48
+ return tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter) && sourceCode.isSpaceBetweenTokens(token, tokenAfter);
48
49
  }
49
50
 
50
51
  /**
@@ -57,6 +58,30 @@ module.exports = function(context) {
57
58
  return !(tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter));
58
59
  }
59
60
 
61
+ /**
62
+ * Checks if the given token is the first token in its line
63
+ * @param {Token} token The token to check.
64
+ * @returns {boolean} Whether or not the token is the first in its line.
65
+ */
66
+ function isFirstTokenInCurrentLine(token) {
67
+ var tokenBefore = context.getTokenBefore(token);
68
+ return !(tokenBefore && astUtils.isTokenOnSameLine(token, tokenBefore));
69
+ }
70
+
71
+ /**
72
+ * Checks if the next token of a given token is a closing parenthesis.
73
+ * @param {Token} token The token to check.
74
+ * @returns {boolean} Whether or not the next token of a given token is a closing parenthesis.
75
+ */
76
+ function isBeforeClosingParen(token) {
77
+ var nextToken = context.getTokenAfter(token);
78
+ return (
79
+ nextToken &&
80
+ nextToken.type === "Punctuator" &&
81
+ (nextToken.value === "}" || nextToken.value === ")")
82
+ );
83
+ }
84
+
60
85
  /**
61
86
  * Checks if the given token is a semicolon.
62
87
  * @param {Token} token The token to check.
@@ -88,7 +113,7 @@ module.exports = function(context) {
88
113
  }
89
114
  }
90
115
 
91
- if (!isLastTokenInCurrentLine(token)) {
116
+ if (!isFirstTokenInCurrentLine(token) && !isLastTokenInCurrentLine(token) && !isBeforeClosingParen(token)) {
92
117
  if (hasTrailingSpace(token)) {
93
118
  if (!requireSpaceAfter) {
94
119
  context.report(node, location, "Unexpected whitespace after semicolon.");
@@ -31,13 +31,35 @@ module.exports = function(context) {
31
31
  value = left.value;
32
32
 
33
33
  if (hasSpace !== requiresSpace) {
34
- context.report(node, "Keyword \"{{value}}\" must {{not}}be followed by whitespace.", {
35
- value: value,
36
- not: requiresSpace ? "" : "not "
34
+ context.report({
35
+ node: node,
36
+ message: "Keyword \"{{value}}\" must {{not}}be followed by whitespace.",
37
+ data: {
38
+ value: value,
39
+ not: requiresSpace ? "" : "not "
40
+ },
41
+ fix: function(fixer) {
42
+ if (requiresSpace) {
43
+ return fixer.insertTextAfter(left, " ");
44
+ } else {
45
+ return fixer.removeRange([left.range[1], right.range[0]]);
46
+ }
47
+ }
37
48
  });
38
49
  } else if (left.loc.end.line !== right.loc.start.line) {
39
- context.report(node, "Keyword \"{{value}}\" must not be followed by a newline.", {
40
- value: value
50
+ context.report({
51
+ node: node,
52
+ message: "Keyword \"{{value}}\" must not be followed by a newline.",
53
+ data: {
54
+ value: value
55
+ },
56
+ fix: function(fixer) {
57
+ var text = "";
58
+ if (requiresSpace) {
59
+ text = " ";
60
+ }
61
+ return fixer.replaceTextRange([left.range[1], right.range[0]], text);
62
+ }
41
63
  });
42
64
  }
43
65
  }
@@ -13,7 +13,28 @@ var astUtils = require("../ast-utils");
13
13
  //------------------------------------------------------------------------------
14
14
 
15
15
  module.exports = function(context) {
16
- var requireSpace = context.options[0] !== "never";
16
+ var config = context.options[0],
17
+ sourceCode = context.getSourceCode(),
18
+ checkFunctions = true,
19
+ checkKeywords = true;
20
+
21
+ if (typeof config === "object") {
22
+ checkFunctions = config.functions !== "never";
23
+ checkKeywords = config.keywords !== "never";
24
+ } else if (config === "never") {
25
+ checkFunctions = false;
26
+ checkKeywords = false;
27
+ }
28
+
29
+ /**
30
+ * Checks whether or not a given token is an arrow operator (=>).
31
+ *
32
+ * @param {Token} token - A token to check.
33
+ * @returns {boolean} `true` if the token is an arrow operator.
34
+ */
35
+ function isArrow(token) {
36
+ return token.type === "Punctuator" && token.value === "=>";
37
+ }
17
38
 
18
39
  /**
19
40
  * Checks the given BlockStatement node has a preceding space if it doesn’t start on a new line.
@@ -22,18 +43,38 @@ module.exports = function(context) {
22
43
  */
23
44
  function checkPrecedingSpace(node) {
24
45
  var precedingToken = context.getTokenBefore(node),
25
- hasSpace;
46
+ hasSpace,
47
+ parent,
48
+ requireSpace;
26
49
 
27
- if (precedingToken && astUtils.isTokenOnSameLine(precedingToken, node)) {
28
- hasSpace = astUtils.isTokenSpaced(precedingToken, node);
50
+ if (precedingToken && !isArrow(precedingToken) && astUtils.isTokenOnSameLine(precedingToken, node)) {
51
+ hasSpace = sourceCode.isSpaceBetweenTokens(precedingToken, node);
52
+ parent = context.getAncestors().pop();
53
+ if (parent.type === "FunctionExpression" || parent.type === "FunctionDeclaration") {
54
+ requireSpace = checkFunctions;
55
+ } else {
56
+ requireSpace = checkKeywords;
57
+ }
29
58
 
30
59
  if (requireSpace) {
31
60
  if (!hasSpace) {
32
- context.report(node, "Missing space before opening brace.");
61
+ context.report({
62
+ node: node,
63
+ message: "Missing space before opening brace.",
64
+ fix: function(fixer) {
65
+ return fixer.insertTextBefore(node, " ");
66
+ }
67
+ });
33
68
  }
34
69
  } else {
35
70
  if (hasSpace) {
36
- context.report(node, "Unexpected space before opening brace.");
71
+ context.report({
72
+ node: node,
73
+ message: "Unexpected space before opening brace.",
74
+ fix: function(fixer) {
75
+ return fixer.removeRange([precedingToken.range[1], node.range[0]]);
76
+ }
77
+ });
37
78
  }
38
79
  }
39
80
  }
@@ -69,6 +110,22 @@ module.exports = function(context) {
69
110
 
70
111
  module.exports.schema = [
71
112
  {
72
- "enum": ["always", "never"]
113
+ "oneOf": [
114
+ {
115
+ "enum": ["always", "never"]
116
+ },
117
+ {
118
+ "type": "object",
119
+ "properties": {
120
+ "keywords": {
121
+ "enum": ["always", "never"]
122
+ },
123
+ "functions": {
124
+ "enum": ["always", "never"]
125
+ }
126
+ },
127
+ "additionalProperties": false
128
+ }
129
+ ]
73
130
  }
74
131
  ];
@@ -2,6 +2,7 @@
2
2
  * @fileoverview Rule to validate spacing before function paren.
3
3
  * @author Mathias Schreck <https://github.com/lo1tuma>
4
4
  * @copyright 2015 Mathias Schreck
5
+ * See LICENSE in root directory for full license.
5
6
  */
6
7
  "use strict";
7
8
 
@@ -12,6 +13,7 @@
12
13
  module.exports = function(context) {
13
14
 
14
15
  var configuration = context.options[0],
16
+ sourceCode = context.getSourceCode(),
15
17
  requireAnonymousFunctionSpacing = true,
16
18
  requireNamedFunctionSpacing = true;
17
19
 
@@ -23,16 +25,6 @@ module.exports = function(context) {
23
25
  requireNamedFunctionSpacing = false;
24
26
  }
25
27
 
26
- /**
27
- * Determines whether two adjacent tokens are have whitespace between them.
28
- * @param {Object} left - The left token object.
29
- * @param {Object} right - The right token object.
30
- * @returns {boolean} Whether or not there is space between the tokens.
31
- */
32
- function isSpaced(left, right) {
33
- return left.range[1] < right.range[0];
34
- }
35
-
36
28
  /**
37
29
  * Determines whether a function has a name.
38
30
  * @param {ASTNode} node The function node.
@@ -99,13 +91,27 @@ module.exports = function(context) {
99
91
 
100
92
  location = leftToken.loc.end;
101
93
 
102
- if (isSpaced(leftToken, rightToken)) {
94
+ if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken)) {
103
95
  if ((isNamed && !requireNamedFunctionSpacing) || (!isNamed && !requireAnonymousFunctionSpacing)) {
104
- context.report(node, location, "Unexpected space before function parentheses.");
96
+ context.report({
97
+ node: node,
98
+ loc: location,
99
+ message: "Unexpected space before function parentheses.",
100
+ fix: function(fixer) {
101
+ return fixer.removeRange([leftToken.range[1], rightToken.range[0]]);
102
+ }
103
+ });
105
104
  }
106
105
  } else {
107
106
  if ((isNamed && requireNamedFunctionSpacing) || (!isNamed && requireAnonymousFunctionSpacing)) {
108
- context.report(node, location, "Missing space before function parentheses.");
107
+ context.report({
108
+ node: node,
109
+ loc: location,
110
+ message: "Missing space before function parentheses.",
111
+ fix: function(fixer) {
112
+ return fixer.insertTextAfter(leftToken, " ");
113
+ }
114
+ });
109
115
  }
110
116
  }
111
117
  }
@@ -17,12 +17,37 @@ var ERROR_MSG_NO_SPACE_EXPECTED = "Unexpected space before keyword \"{{keyword}}
17
17
 
18
18
  module.exports = function(context) {
19
19
 
20
+ var sourceCode = context.getSourceCode();
21
+
20
22
  var SPACE_REQUIRED = context.options[0] !== "never";
21
23
 
22
24
  //--------------------------------------------------------------------------
23
25
  // Helpers
24
26
  //--------------------------------------------------------------------------
25
27
 
28
+ /**
29
+ * Report the error message
30
+ * @param {ASTNode} node node to report
31
+ * @param {string} message Error message to be displayed
32
+ * @param {object} data Data object for the rule message
33
+ * @returns {void}
34
+ */
35
+ function report(node, message, data) {
36
+ context.report({
37
+ node: node,
38
+ message: message,
39
+ data: data,
40
+ fix: function(fixer) {
41
+ if (SPACE_REQUIRED) {
42
+ return fixer.insertTextBefore(node, " ");
43
+ } else {
44
+ var tokenBefore = context.getTokenBefore(node);
45
+ return fixer.removeRange([tokenBefore.range[1], node.range[0]]);
46
+ }
47
+ }
48
+ });
49
+ }
50
+
26
51
  /**
27
52
  * Check if a token meets the criteria
28
53
  *
@@ -47,10 +72,10 @@ module.exports = function(context) {
47
72
  }
48
73
 
49
74
  options = options || {};
50
- options.allowedPrecedingChars = options.allowedPrecedingChars || [];
75
+ options.allowedPrecedingChars = options.allowedPrecedingChars || [ "{" ];
51
76
  options.requireSpace = typeof options.requireSpace === "undefined" ? SPACE_REQUIRED : options.requireSpace;
52
77
 
53
- var hasSpace = astUtils.isTokenSpaced(left, right);
78
+ var hasSpace = sourceCode.isSpaceBetweenTokens(left, right);
54
79
  var spaceOk = hasSpace === options.requireSpace;
55
80
 
56
81
  if (spaceOk) {
@@ -59,13 +84,13 @@ module.exports = function(context) {
59
84
 
60
85
  if (!astUtils.isTokenOnSameLine(left, right)) {
61
86
  if (!options.requireSpace) {
62
- context.report(node, ERROR_MSG_NO_SPACE_EXPECTED, { keyword: right.value });
87
+ report(node, ERROR_MSG_NO_SPACE_EXPECTED, { keyword: right.value });
63
88
  }
64
89
  return;
65
90
  }
66
91
 
67
92
  if (!options.requireSpace) {
68
- context.report(node, ERROR_MSG_NO_SPACE_EXPECTED, { keyword: right.value });
93
+ report(node, ERROR_MSG_NO_SPACE_EXPECTED, { keyword: right.value });
69
94
  return;
70
95
  }
71
96
 
@@ -73,7 +98,7 @@ module.exports = function(context) {
73
98
  return;
74
99
  }
75
100
 
76
- context.report(node, ERROR_MSG_SPACE_EXPECTED, { keyword: right.value });
101
+ report(node, ERROR_MSG_SPACE_EXPECTED, { keyword: right.value });
77
102
 
78
103
  }
79
104
 
@@ -130,7 +155,7 @@ module.exports = function(context) {
130
155
  check(caseNode);
131
156
  });
132
157
  },
133
- ThrowStatement: check,
158
+ "ThrowStatement": check,
134
159
  "TryStatement": function(node) {
135
160
  // try
136
161
  check(node);
@@ -144,7 +169,7 @@ module.exports = function(context) {
144
169
  },
145
170
  "WithStatement": check,
146
171
  "VariableDeclaration": function(node) {
147
- check(node, { allowedPrecedingChars: [ "(" ] });
172
+ check(node, { allowedPrecedingChars: [ "(", "{" ] });
148
173
  },
149
174
  "ReturnStatement": check,
150
175
  "BreakStatement": check,
@@ -152,25 +177,28 @@ module.exports = function(context) {
152
177
  "ContinueStatement": check,
153
178
  "FunctionDeclaration": check,
154
179
  "FunctionExpression": function(node) {
155
-
156
180
  var left = context.getTokenBefore(node);
157
- var right = null;
181
+ var right = context.getFirstToken(node);
158
182
 
159
- if (left.type === "Identifier") {
160
- right = left;
161
- left = context.getTokenBefore(node, 1);
162
- } else {
163
- right = context.getFirstToken(node);
183
+ // If it's a method, a getter, or a setter, the first token is not the `function` keyword.
184
+ if (right.type !== "Keyword") {
185
+ return;
164
186
  }
165
187
 
166
- checkTokens(node, left, right, { allowedPrecedingChars: [ "(" ] });
188
+ checkTokens(node, left, right, { allowedPrecedingChars: [ "(", "{" ] });
167
189
  },
168
190
  "YieldExpression": function(node) {
169
- check(node, { allowedPrecedingChars: [ "(" ] });
191
+ check(node, { allowedPrecedingChars: [ "(", "{" ] });
170
192
  },
171
193
  "ForOfStatement": check,
172
194
  "ClassBody": function(node) {
173
- check(context.getTokenBefore(node, 1));
195
+
196
+ // Find the 'class' token
197
+ while (node.value !== "class") {
198
+ node = context.getTokenBefore(node);
199
+ }
200
+
201
+ check(node);
174
202
  },
175
203
  "Super": check
176
204
 
@@ -48,7 +48,28 @@ module.exports = function(context) {
48
48
  * @private
49
49
  */
50
50
  function report(mainNode, culpritToken) {
51
- context.report(mainNode, culpritToken.loc.start, "Infix operators must be spaced.");
51
+ context.report({
52
+ node: mainNode,
53
+ loc: culpritToken.loc.start,
54
+ message: "Infix operators must be spaced.",
55
+ fix: function(fixer) {
56
+ var previousToken = context.getTokenBefore(culpritToken);
57
+ var afterToken = context.getTokenAfter(culpritToken);
58
+ var fixString = "";
59
+
60
+ if (culpritToken.range[0] - previousToken.range[1] === 0) {
61
+ fixString = " ";
62
+ }
63
+
64
+ fixString += culpritToken.value;
65
+
66
+ if (afterToken.range[0] - culpritToken.range[1] === 0) {
67
+ fixString += " ";
68
+ }
69
+
70
+ return fixer.replaceText(culpritToken, fixString);
71
+ }
72
+ });
52
73
  }
53
74
 
54
75
  /**
@@ -21,7 +21,13 @@ module.exports = function(context) {
21
21
  value = tokens[0].value;
22
22
 
23
23
  if (tokens[0].range[1] >= tokens[1].range[0]) {
24
- context.report(node, "Keyword \"" + value + "\" must be followed by whitespace.");
24
+ context.report({
25
+ node: node,
26
+ message: "Keyword \"" + value + "\" must be followed by whitespace.",
27
+ fix: function(fixer) {
28
+ return fixer.insertTextAfterRange(tokens[0].range, " ");
29
+ }
30
+ });
25
31
  }
26
32
  }
27
33
 
@@ -0,0 +1,63 @@
1
+ /**
2
+ * @fileoverview Helpers to test EventGenerator interface.
3
+ * @author Toru Nagashima
4
+ * @copyright 2015 Toru Nagashima. All rights reserved.
5
+ * See LICENSE file in root directory for full license.
6
+ */
7
+ "use strict";
8
+
9
+ /* global describe, it */
10
+
11
+ //------------------------------------------------------------------------------
12
+ // Requirements
13
+ //------------------------------------------------------------------------------
14
+
15
+ var assert = require("assert");
16
+
17
+ //------------------------------------------------------------------------------
18
+ // Public Interface
19
+ //------------------------------------------------------------------------------
20
+
21
+ module.exports = {
22
+ /**
23
+ * Overrideable `describe` function to test.
24
+ * @param {string} text - A description.
25
+ * @param {function} method - A test logic.
26
+ * @returns {any} The returned value with the test logic.
27
+ */
28
+ describe: (typeof describe === "function") ? describe : function(text, method) {
29
+ return method.apply(this);
30
+ },
31
+
32
+ /**
33
+ * Overrideable `it` function to test.
34
+ * @param {string} text - A description.
35
+ * @param {function} method - A test logic.
36
+ * @returns {any} The returned value with the test logic.
37
+ */
38
+ it: (typeof it === "function") ? it : function(text, method) {
39
+ return method.apply(this);
40
+ },
41
+
42
+ /**
43
+ * Does some tests to check a given object implements the EventGenerator interface.
44
+ * @param {object} instance - An object to check.
45
+ * @returns {void}
46
+ */
47
+ testEventGeneratorInterface: function(instance) {
48
+ this.describe("should implement EventGenerator interface", function() {
49
+ this.it("should have `emitter` property.", function() {
50
+ assert.equal(typeof instance.emitter, "object");
51
+ assert.equal(typeof instance.emitter.emit, "function");
52
+ });
53
+
54
+ this.it("should have `enterNode` property.", function() {
55
+ assert.equal(typeof instance.enterNode, "function");
56
+ });
57
+
58
+ this.it("should have `leaveNode` property.", function() {
59
+ assert.equal(typeof instance.leaveNode, "function");
60
+ });
61
+ }.bind(this));
62
+ }
63
+ };