eslint-plugin-jest 26.7.0 → 26.8.0

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.
@@ -29,21 +29,23 @@ var _default = (0, _utils.createRule)({
29
29
  create(context) {
30
30
  return {
31
31
  CallExpression(node) {
32
- if (!(0, _utils.isExpectCall)(node)) {
32
+ const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
33
+
34
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
33
35
  return;
34
36
  }
35
37
 
36
38
  const {
37
39
  matcher
38
- } = (0, _utils.parseExpectCall)(node);
40
+ } = jestFnCall;
39
41
 
40
- if (matcher && (0, _utils.isParsedEqualityMatcherCall)(matcher, _utils.EqualityMatcher.toEqual)) {
42
+ if ((0, _utils.isSupportedAccessor)(matcher, 'toEqual')) {
41
43
  context.report({
42
44
  messageId: 'useToStrictEqual',
43
- node: matcher.node.property,
45
+ node: matcher,
44
46
  suggest: [{
45
47
  messageId: 'suggestReplaceWithStrictEqual',
46
- fix: fixer => [(0, _utils.replaceAccessorFixer)(fixer, matcher.node.property, _utils.EqualityMatcher.toStrictEqual)]
48
+ fix: fixer => [(0, _utils.replaceAccessorFixer)(fixer, matcher, _utils.EqualityMatcher.toStrictEqual)]
47
49
  }]
48
50
  });
49
51
  }
@@ -16,12 +16,12 @@ const isNullLiteral = node => node.type === _utils.AST_NODE_TYPES.Literal && nod
16
16
  */
17
17
 
18
18
 
19
- const isNullEqualityMatcher = matcher => isNullLiteral(getFirstArgument(matcher));
19
+ const isNullEqualityMatcher = expectFnCall => isNullLiteral((0, _utils2.getFirstMatcherArg)(expectFnCall));
20
20
 
21
- const isFirstArgumentIdentifier = (matcher, name) => (0, _utils2.isIdentifier)(getFirstArgument(matcher), name);
21
+ const isFirstArgumentIdentifier = (expectFnCall, name) => (0, _utils2.isIdentifier)((0, _utils2.getFirstMatcherArg)(expectFnCall), name);
22
22
 
23
- const shouldUseToBe = matcher => {
24
- const firstArg = getFirstArgument(matcher);
23
+ const shouldUseToBe = expectFnCall => {
24
+ const firstArg = (0, _utils2.getFirstMatcherArg)(expectFnCall);
25
25
 
26
26
  if (firstArg.type === _utils.AST_NODE_TYPES.Literal) {
27
27
  // regex literals are classed as literals, but they're actually objects
@@ -32,32 +32,27 @@ const shouldUseToBe = matcher => {
32
32
  return firstArg.type === _utils.AST_NODE_TYPES.TemplateLiteral;
33
33
  };
34
34
 
35
- const getFirstArgument = matcher => {
36
- return (0, _utils2.followTypeAssertionChain)(matcher.arguments[0]);
37
- };
38
-
39
- const reportPreferToBe = (context, whatToBe, matcher, modifier) => {
40
- const modifierNode = (modifier === null || modifier === void 0 ? void 0 : modifier.negation) || (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils2.ModifierName.not && (modifier === null || modifier === void 0 ? void 0 : modifier.node);
35
+ const reportPreferToBe = (context, whatToBe, expectFnCall, modifierNode) => {
41
36
  context.report({
42
37
  messageId: `useToBe${whatToBe}`,
43
38
 
44
39
  fix(fixer) {
45
- var _matcher$arguments;
40
+ var _expectFnCall$args;
46
41
 
47
- const fixes = [(0, _utils2.replaceAccessorFixer)(fixer, matcher.node.property, `toBe${whatToBe}`)];
42
+ const fixes = [(0, _utils2.replaceAccessorFixer)(fixer, expectFnCall.matcher, `toBe${whatToBe}`)];
48
43
 
49
- if ((_matcher$arguments = matcher.arguments) !== null && _matcher$arguments !== void 0 && _matcher$arguments.length && whatToBe !== '') {
50
- fixes.push(fixer.remove(matcher.arguments[0]));
44
+ if ((_expectFnCall$args = expectFnCall.args) !== null && _expectFnCall$args !== void 0 && _expectFnCall$args.length && whatToBe !== '') {
45
+ fixes.push(fixer.remove(expectFnCall.args[0]));
51
46
  }
52
47
 
53
48
  if (modifierNode) {
54
- fixes.push(fixer.removeRange([modifierNode.property.range[0] - 1, modifierNode.property.range[1]]));
49
+ fixes.push(fixer.removeRange([modifierNode.range[0] - 1, modifierNode.range[1]]));
55
50
  }
56
51
 
57
52
  return fixes;
58
53
  },
59
54
 
60
- node: matcher.node.property
55
+ node: expectFnCall.matcher
61
56
  });
62
57
  };
63
58
 
@@ -85,46 +80,42 @@ var _default = (0, _utils2.createRule)({
85
80
  create(context) {
86
81
  return {
87
82
  CallExpression(node) {
88
- if (!(0, _utils2.isExpectCall)(node)) {
89
- return;
90
- }
91
-
92
- const {
93
- matcher,
94
- modifier
95
- } = (0, _utils2.parseExpectCall)(node);
83
+ const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
96
84
 
97
- if (!matcher) {
85
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
98
86
  return;
99
87
  }
100
88
 
101
- if (((modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils2.ModifierName.not || modifier !== null && modifier !== void 0 && modifier.negation) && ['toBeUndefined', 'toBeDefined'].includes(matcher.name)) {
102
- reportPreferToBe(context, matcher.name === 'toBeDefined' ? 'Undefined' : 'Defined', matcher, modifier);
89
+ const matcherName = (0, _utils2.getAccessorValue)(jestFnCall.matcher);
90
+ const notModifier = jestFnCall.modifiers.find(nod => (0, _utils2.getAccessorValue)(nod) === 'not');
91
+
92
+ if (notModifier && ['toBeUndefined', 'toBeDefined'].includes(matcherName)) {
93
+ reportPreferToBe(context, matcherName === 'toBeDefined' ? 'Undefined' : 'Defined', jestFnCall, notModifier);
103
94
  return;
104
95
  }
105
96
 
106
- if (!(0, _utils2.isParsedEqualityMatcherCall)(matcher)) {
97
+ if (!_utils2.EqualityMatcher.hasOwnProperty(matcherName) || jestFnCall.args.length === 0) {
107
98
  return;
108
99
  }
109
100
 
110
- if (isNullEqualityMatcher(matcher)) {
111
- reportPreferToBe(context, 'Null', matcher);
101
+ if (isNullEqualityMatcher(jestFnCall)) {
102
+ reportPreferToBe(context, 'Null', jestFnCall);
112
103
  return;
113
104
  }
114
105
 
115
- if (isFirstArgumentIdentifier(matcher, 'undefined')) {
116
- const name = (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils2.ModifierName.not || modifier !== null && modifier !== void 0 && modifier.negation ? 'Defined' : 'Undefined';
117
- reportPreferToBe(context, name, matcher, modifier);
106
+ if (isFirstArgumentIdentifier(jestFnCall, 'undefined')) {
107
+ const name = notModifier ? 'Defined' : 'Undefined';
108
+ reportPreferToBe(context, name, jestFnCall, notModifier);
118
109
  return;
119
110
  }
120
111
 
121
- if (isFirstArgumentIdentifier(matcher, 'NaN')) {
122
- reportPreferToBe(context, 'NaN', matcher);
112
+ if (isFirstArgumentIdentifier(jestFnCall, 'NaN')) {
113
+ reportPreferToBe(context, 'NaN', jestFnCall);
123
114
  return;
124
115
  }
125
116
 
126
- if (shouldUseToBe(matcher) && matcher.name !== _utils2.EqualityMatcher.toBe) {
127
- reportPreferToBe(context, '', matcher);
117
+ if (shouldUseToBe(jestFnCall) && matcherName !== _utils2.EqualityMatcher.toBe) {
118
+ reportPreferToBe(context, '', jestFnCall);
128
119
  }
129
120
  }
130
121
 
@@ -9,22 +9,6 @@ var _utils = require("@typescript-eslint/utils");
9
9
 
10
10
  var _utils2 = require("./utils");
11
11
 
12
- const isBooleanLiteral = node => node.type === _utils.AST_NODE_TYPES.Literal && typeof node.value === 'boolean';
13
-
14
- /**
15
- * Checks if the given `ParsedExpectMatcher` is a call to one of the equality matchers,
16
- * with a boolean literal as the sole argument.
17
- *
18
- * @example javascript
19
- * toBe(true);
20
- * toEqual(false);
21
- *
22
- * @param {ParsedExpectMatcher} matcher
23
- *
24
- * @return {matcher is ParsedBooleanEqualityMatcher}
25
- */
26
- const isBooleanEqualityMatcher = matcher => (0, _utils2.isParsedEqualityMatcherCall)(matcher) && isBooleanLiteral((0, _utils2.followTypeAssertionChain)(matcher.arguments[0]));
27
-
28
12
  /**
29
13
  * Checks if the given `node` is a `CallExpression` representing the calling
30
14
  * of an `includes`-like method that can be 'fixed' (using `toContain`).
@@ -33,7 +17,7 @@ const isBooleanEqualityMatcher = matcher => (0, _utils2.isParsedEqualityMatcherC
33
17
  *
34
18
  * @return {node is FixableIncludesCallExpression}
35
19
  */
36
- const isFixableIncludesCallExpression = node => node.type === _utils.AST_NODE_TYPES.CallExpression && node.callee.type === _utils.AST_NODE_TYPES.MemberExpression && (0, _utils2.isSupportedAccessor)(node.callee.property, 'includes') && (0, _utils2.hasOnlyOneArgument)(node); // expect(array.includes(<value>)[not.]{toBe,toEqual}(<boolean>)
20
+ const isFixableIncludesCallExpression = node => node.type === _utils.AST_NODE_TYPES.CallExpression && node.callee.type === _utils.AST_NODE_TYPES.MemberExpression && (0, _utils2.isSupportedAccessor)(node.callee.property, 'includes') && (0, _utils2.hasOnlyOneArgument)(node) && node.arguments[0].type !== _utils.AST_NODE_TYPES.SpreadElement; // expect(array.includes(<value>)[not.]{toBe,toEqual}(<boolean>)
37
21
 
38
22
 
39
23
  var _default = (0, _utils2.createRule)({
@@ -56,37 +40,48 @@ var _default = (0, _utils2.createRule)({
56
40
  create(context) {
57
41
  return {
58
42
  CallExpression(node) {
59
- if (!(0, _utils2.isExpectCall)(node)) {
43
+ const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
44
+
45
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect' || jestFnCall.args.length === 0) {
60
46
  return;
61
47
  }
62
48
 
63
49
  const {
64
- expect: {
65
- arguments: [includesCall],
66
- range: [, expectCallEnd]
67
- },
68
- matcher,
69
- modifier
70
- } = (0, _utils2.parseExpectCall)(node);
50
+ parent: expect
51
+ } = jestFnCall.head.node;
52
+
53
+ if ((expect === null || expect === void 0 ? void 0 : expect.type) !== _utils.AST_NODE_TYPES.CallExpression) {
54
+ return;
55
+ }
56
+
57
+ const {
58
+ arguments: [includesCall],
59
+ range: [, expectCallEnd]
60
+ } = expect;
61
+ const {
62
+ matcher
63
+ } = jestFnCall;
64
+ const matcherArg = (0, _utils2.getFirstMatcherArg)(jestFnCall);
71
65
 
72
- if (!matcher || !includesCall || modifier && modifier.name !== _utils2.ModifierName.not || !isBooleanEqualityMatcher(matcher) || !isFixableIncludesCallExpression(includesCall)) {
66
+ if (!includesCall || matcherArg.type === _utils.AST_NODE_TYPES.SpreadElement || !_utils2.EqualityMatcher.hasOwnProperty((0, _utils2.getAccessorValue)(matcher)) || !(0, _utils2.isBooleanLiteral)(matcherArg) || !isFixableIncludesCallExpression(includesCall)) {
73
67
  return;
74
68
  }
75
69
 
70
+ const hasNot = jestFnCall.modifiers.some(nod => (0, _utils2.getAccessorValue)(nod) === 'not');
76
71
  context.report({
77
72
  fix(fixer) {
78
73
  const sourceCode = context.getSourceCode(); // we need to negate the expectation if the current expected
79
74
  // value is itself negated by the "not" modifier
80
75
 
81
- const addNotModifier = (0, _utils2.followTypeAssertionChain)(matcher.arguments[0]).value === !!modifier;
76
+ const addNotModifier = matcherArg.value === hasNot;
82
77
  return [// remove the "includes" call entirely
83
78
  fixer.removeRange([includesCall.callee.property.range[0] - 1, includesCall.range[1]]), // replace the current matcher with "toContain", adding "not" if needed
84
- fixer.replaceTextRange([expectCallEnd, matcher.node.range[1]], addNotModifier ? `.${_utils2.ModifierName.not}.toContain` : '.toContain'), // replace the matcher argument with the value from the "includes"
85
- fixer.replaceText(matcher.arguments[0], sourceCode.getText(includesCall.arguments[0]))];
79
+ fixer.replaceTextRange([expectCallEnd, matcher.parent.range[1]], addNotModifier ? `.${_utils2.ModifierName.not}.toContain` : '.toContain'), // replace the matcher argument with the value from the "includes"
80
+ fixer.replaceText(jestFnCall.args[0], sourceCode.getText(includesCall.arguments[0]))];
86
81
  },
87
82
 
88
83
  messageId: 'useToContain',
89
- node: matcher.node.property
84
+ node: matcher
90
85
  });
91
86
  }
92
87
 
@@ -29,18 +29,26 @@ var _default = (0, _utils2.createRule)({
29
29
  create(context) {
30
30
  return {
31
31
  CallExpression(node) {
32
- if (!(0, _utils2.isExpectCall)(node)) {
32
+ const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
33
+
34
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
33
35
  return;
34
36
  }
35
37
 
36
38
  const {
37
- expect: {
38
- arguments: [argument]
39
- },
39
+ parent: expect
40
+ } = jestFnCall.head.node;
41
+
42
+ if ((expect === null || expect === void 0 ? void 0 : expect.type) !== _utils.AST_NODE_TYPES.CallExpression) {
43
+ return;
44
+ }
45
+
46
+ const [argument] = expect.arguments;
47
+ const {
40
48
  matcher
41
- } = (0, _utils2.parseExpectCall)(node);
49
+ } = jestFnCall;
42
50
 
43
- if (!matcher || !(0, _utils2.isParsedEqualityMatcherCall)(matcher) || (argument === null || argument === void 0 ? void 0 : argument.type) !== _utils.AST_NODE_TYPES.MemberExpression || !(0, _utils2.isSupportedAccessor)(argument.property, 'length')) {
51
+ if (!_utils2.EqualityMatcher.hasOwnProperty((0, _utils2.getAccessorValue)(matcher)) || (argument === null || argument === void 0 ? void 0 : argument.type) !== _utils.AST_NODE_TYPES.MemberExpression || !(0, _utils2.isSupportedAccessor)(argument.property, 'length')) {
44
52
  return;
45
53
  }
46
54
 
@@ -48,11 +56,11 @@ var _default = (0, _utils2.createRule)({
48
56
  fix(fixer) {
49
57
  return [// remove the "length" property accessor
50
58
  fixer.removeRange([argument.property.range[0] - 1, argument.range[1]]), // replace the current matcher with "toHaveLength"
51
- fixer.replaceTextRange([matcher.node.object.range[1], matcher.node.range[1]], '.toHaveLength')];
59
+ fixer.replaceTextRange([matcher.parent.object.range[1], matcher.parent.range[1]], '.toHaveLength')];
52
60
  },
53
61
 
54
62
  messageId: 'useToHaveLength',
55
- node: matcher.node.property
63
+ node: matcher
56
64
  });
57
65
  }
58
66
 
@@ -26,25 +26,25 @@ var _default = (0, _utils.createRule)({
26
26
  create(context) {
27
27
  return {
28
28
  CallExpression(node) {
29
- var _matcher$arguments;
29
+ const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
30
30
 
31
- if (!(0, _utils.isExpectCall)(node)) {
31
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
32
32
  return;
33
33
  }
34
34
 
35
35
  const {
36
- matcher,
37
- modifier
38
- } = (0, _utils.parseExpectCall)(node);
36
+ matcher
37
+ } = jestFnCall;
38
+ const matcherName = (0, _utils.getAccessorValue)(matcher);
39
39
 
40
- if ((matcher === null || matcher === void 0 ? void 0 : (_matcher$arguments = matcher.arguments) === null || _matcher$arguments === void 0 ? void 0 : _matcher$arguments.length) === 0 && ['toThrow', 'toThrowError'].includes(matcher.name) && (!modifier || !(modifier.name === _utils.ModifierName.not || modifier.negation))) {
40
+ if (jestFnCall.args.length === 0 && ['toThrow', 'toThrowError'].includes(matcherName) && !jestFnCall.modifiers.some(nod => (0, _utils.getAccessorValue)(nod) === 'not')) {
41
41
  // Look for `toThrow` calls with no arguments.
42
42
  context.report({
43
43
  messageId: 'addErrorMessage',
44
44
  data: {
45
- matcherName: matcher.name
45
+ matcherName
46
46
  },
47
- node: matcher.node.property
47
+ node: matcher
48
48
  });
49
49
  }
50
50
  }
@@ -5,25 +5,11 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _utils = require("./utils");
8
+ var _utils = require("@typescript-eslint/utils");
9
9
 
10
- const toThrowMatchers = ['toThrow', 'toThrowError', 'toThrowErrorMatchingSnapshot', 'toThrowErrorMatchingInlineSnapshot'];
11
-
12
- const isJestExpectToThrowCall = node => {
13
- if (!(0, _utils.isExpectCall)(node)) {
14
- return false;
15
- }
16
-
17
- const {
18
- matcher
19
- } = (0, _utils.parseExpectCall)(node);
20
-
21
- if (!matcher) {
22
- return false;
23
- }
10
+ var _utils2 = require("./utils");
24
11
 
25
- return !toThrowMatchers.includes(matcher.name);
26
- };
12
+ const toThrowMatchers = ['toThrow', 'toThrowError', 'toThrowErrorMatchingSnapshot', 'toThrowErrorMatchingInlineSnapshot'];
27
13
 
28
14
  const baseRule = (() => {
29
15
  try {
@@ -52,7 +38,7 @@ const tryCreateBaseRule = context => {
52
38
 
53
39
  const DEFAULT_MESSAGE = 'This rule requires `@typescript-eslint/eslint-plugin`';
54
40
 
55
- var _default = (0, _utils.createRule)({
41
+ var _default = (0, _utils2.createRule)({
56
42
  defaultOptions: [{
57
43
  ignoreStatic: false
58
44
  }],
@@ -84,24 +70,23 @@ var _default = (0, _utils.createRule)({
84
70
  return {};
85
71
  }
86
72
 
87
- let inExpectToThrowCall = false;
88
73
  return { ...baseSelectors,
89
74
 
90
- CallExpression(node) {
91
- inExpectToThrowCall = isJestExpectToThrowCall(node);
92
- },
75
+ MemberExpression(node) {
76
+ var _node$parent, _baseSelectors$Member;
93
77
 
94
- 'CallExpression:exit'(node) {
95
- if (inExpectToThrowCall && isJestExpectToThrowCall(node)) {
96
- inExpectToThrowCall = false;
97
- }
98
- },
78
+ if (((_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.type) === _utils.AST_NODE_TYPES.CallExpression) {
79
+ const jestFnCall = (0, _utils2.parseJestFnCall)((0, _utils2.findTopMostCallExpression)(node.parent), context);
99
80
 
100
- MemberExpression(node) {
101
- var _baseSelectors$Member;
81
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'expect') {
82
+ const {
83
+ matcher
84
+ } = jestFnCall;
102
85
 
103
- if (inExpectToThrowCall) {
104
- return;
86
+ if (!toThrowMatchers.includes((0, _utils2.getAccessorValue)(matcher))) {
87
+ return;
88
+ }
89
+ }
105
90
  }
106
91
 
107
92
  (_baseSelectors$Member = baseSelectors.MemberExpression) === null || _baseSelectors$Member === void 0 ? void 0 : _baseSelectors$Member.call(baseSelectors, node);
@@ -67,17 +67,4 @@ Object.keys(_parseJestFnCall).forEach(function (key) {
67
67
  return _parseJestFnCall[key];
68
68
  }
69
69
  });
70
- });
71
-
72
- var _parseExpectCall = require("./parseExpectCall");
73
-
74
- Object.keys(_parseExpectCall).forEach(function (key) {
75
- if (key === "default" || key === "__esModule") return;
76
- if (key in exports && exports[key] === _parseExpectCall[key]) return;
77
- Object.defineProperty(exports, key, {
78
- enumerable: true,
79
- get: function () {
80
- return _parseExpectCall[key];
81
- }
82
- });
83
70
  });
@@ -3,9 +3,9 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.createRule = exports.TestCaseName = exports.HookName = exports.DescribeAlias = void 0;
6
+ exports.getFirstMatcherArg = exports.findTopMostCallExpression = exports.createRule = exports.TestCaseName = exports.ModifierName = exports.HookName = exports.EqualityMatcher = exports.DescribeAlias = void 0;
7
7
  exports.getNodeName = getNodeName;
8
- exports.replaceAccessorFixer = exports.isFunction = exports.hasOnlyOneArgument = exports.getTestCallExpressionsFromDeclaredVariables = void 0;
8
+ exports.replaceAccessorFixer = exports.isFunction = exports.isBooleanLiteral = exports.hasOnlyOneArgument = exports.getTestCallExpressionsFromDeclaredVariables = void 0;
9
9
 
10
10
  var _path = require("path");
11
11
 
@@ -15,6 +15,8 @@ var _package = require("../../../package.json");
15
15
 
16
16
  var _accessors = require("./accessors");
17
17
 
18
+ var _followTypeAssertionChain = require("./followTypeAssertionChain");
19
+
18
20
  var _parseJestFnCall = require("./parseJestFnCall");
19
21
 
20
22
  const REPO_URL = 'https://github.com/jest-community/eslint-plugin-jest';
@@ -70,6 +72,24 @@ exports.HookName = HookName;
70
72
  HookName["afterEach"] = "afterEach";
71
73
  })(HookName || (exports.HookName = HookName = {}));
72
74
 
75
+ let ModifierName;
76
+ exports.ModifierName = ModifierName;
77
+
78
+ (function (ModifierName) {
79
+ ModifierName["not"] = "not";
80
+ ModifierName["rejects"] = "rejects";
81
+ ModifierName["resolves"] = "resolves";
82
+ })(ModifierName || (exports.ModifierName = ModifierName = {}));
83
+
84
+ let EqualityMatcher;
85
+ exports.EqualityMatcher = EqualityMatcher;
86
+
87
+ (function (EqualityMatcher) {
88
+ EqualityMatcher["toBe"] = "toBe";
89
+ EqualityMatcher["toEqual"] = "toEqual";
90
+ EqualityMatcher["toStrictEqual"] = "toStrictEqual";
91
+ })(EqualityMatcher || (exports.EqualityMatcher = EqualityMatcher = {}));
92
+
73
93
  const joinNames = (a, b) => a && b ? `${a}.${b}` : null;
74
94
 
75
95
  function getNodeName(node) {
@@ -117,4 +137,45 @@ const replaceAccessorFixer = (fixer, node, text) => {
117
137
  return fixer.replaceText(node, node.type === _utils.AST_NODE_TYPES.Identifier ? text : `'${text}'`);
118
138
  };
119
139
 
120
- exports.replaceAccessorFixer = replaceAccessorFixer;
140
+ exports.replaceAccessorFixer = replaceAccessorFixer;
141
+
142
+ const findTopMostCallExpression = node => {
143
+ let topMostCallExpression = node;
144
+ let {
145
+ parent
146
+ } = node;
147
+
148
+ while (parent) {
149
+ if (parent.type === _utils.AST_NODE_TYPES.CallExpression) {
150
+ topMostCallExpression = parent;
151
+ parent = parent.parent;
152
+ continue;
153
+ }
154
+
155
+ if (parent.type !== _utils.AST_NODE_TYPES.MemberExpression) {
156
+ break;
157
+ }
158
+
159
+ parent = parent.parent;
160
+ }
161
+
162
+ return topMostCallExpression;
163
+ };
164
+
165
+ exports.findTopMostCallExpression = findTopMostCallExpression;
166
+
167
+ const isBooleanLiteral = node => node.type === _utils.AST_NODE_TYPES.Literal && typeof node.value === 'boolean';
168
+
169
+ exports.isBooleanLiteral = isBooleanLiteral;
170
+
171
+ const getFirstMatcherArg = expectFnCall => {
172
+ const [firstArg] = expectFnCall.args;
173
+
174
+ if (firstArg.type === _utils.AST_NODE_TYPES.SpreadElement) {
175
+ return firstArg;
176
+ }
177
+
178
+ return (0, _followTypeAssertionChain.followTypeAssertionChain)(firstArg);
179
+ };
180
+
181
+ exports.getFirstMatcherArg = getFirstMatcherArg;