diff --git a/packages/eslint-plugin-jest/src/rules/__tests__/valid-expect-test.js b/packages/eslint-plugin-jest/src/rules/__tests__/valid-expect-test.js index b8785bfbc18c..9529fc37e5c4 100644 --- a/packages/eslint-plugin-jest/src/rules/__tests__/valid-expect-test.js +++ b/packages/eslint-plugin-jest/src/rules/__tests__/valid-expect-test.js @@ -23,6 +23,8 @@ ruleTester.run('valid-expect', rules['valid-expect'], { 'expect(true).toBeDefined();', 'expect([1, 2, 3]).toEqual([1, 2, 3]);', 'expect(undefined).not.toBeDefined();', + 'expect(Promise.resolve(2)).resolves.toBeDefined();', + 'expect(Promise.reject(2)).rejects.toBeDefined();', ], invalid: [ @@ -77,5 +79,21 @@ ruleTester.run('valid-expect', rules['valid-expect'], { }, ], }, + { + code: 'expect(true).not.toBeDefined;', + errors: [ + { + message: '"toBeDefined" was not called.', + }, + ], + }, + { + code: 'expect(true).nope.toBeDefined;', + errors: [ + { + message: '"nope" is not a valid property of expect.', + }, + ], + }, ], }); diff --git a/packages/eslint-plugin-jest/src/rules/valid-expect.js b/packages/eslint-plugin-jest/src/rules/valid-expect.js index b325bd9282a6..b42500a3a980 100644 --- a/packages/eslint-plugin-jest/src/rules/valid-expect.js +++ b/packages/eslint-plugin-jest/src/rules/valid-expect.js @@ -16,6 +16,8 @@ import type {EslintContext, CallExpression} from './types'; +const expectProperties = ['not', 'resolves', 'rejects']; + module.exports = (context: EslintContext) => { return { CallExpression(node: CallExpression) { @@ -33,17 +35,37 @@ module.exports = (context: EslintContext) => { }); } - // matcher was not called + // something was called on `expect()` if ( node.parent && node.parent.type === 'MemberExpression' && - node.parent.parent && - node.parent.parent.type === 'ExpressionStatement' + node.parent.parent ) { - context.report({ - message: `"${node.parent.property.name}" was not called.`, - node, - }); + let propertyName = node.parent.property.name; + let grandParent = node.parent.parent; + + // a property is accessed, get the next node + if (grandParent.type === 'MemberExpression') { + // a modifier is used, just get the next one + if (expectProperties.indexOf(propertyName) > -1) { + propertyName = grandParent.property.name; + grandParent = node.parent.parent.parent; + } else { + // only a few properties are allowed + context.report({ + message: `"${propertyName}" is not a valid property of expect.`, + node, + }); + } + } + + // matcher was not called + if (grandParent.type === 'ExpressionStatement') { + context.report({ + message: `"${propertyName}" was not called.`, + node, + }); + } } } },