From 4bf9eea3985a4855e7d3b575bd65f70fa62b9e0a Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Tue, 9 Aug 2022 07:52:35 +1200 Subject: [PATCH] fix(no-standalone-expect): only report on `expect.hasAssertions` & `expect.assertions` member calls (#1191) --- .../__tests__/no-standalone-expect.test.ts | 15 +++++++++++++++ src/rules/no-standalone-expect.ts | 18 +++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/rules/__tests__/no-standalone-expect.test.ts b/src/rules/__tests__/no-standalone-expect.test.ts index 16b38baab..439a302de 100644 --- a/src/rules/__tests__/no-standalone-expect.test.ts +++ b/src/rules/__tests__/no-standalone-expect.test.ts @@ -12,6 +12,8 @@ const ruleTester = new TSESLint.RuleTester({ ruleTester.run('no-standalone-expect', rule, { valid: [ + 'expect.any(String)', + 'expect.extend({})', 'describe("a test", () => { it("an it", () => {expect(1).toBe(1); }); });', 'describe("a test", () => { it("an it", () => { const func = () => { expect(1).toBe(1); }; }); });', 'describe("a test", () => { const func = () => { expect(1).toBe(1); }; });', @@ -65,6 +67,10 @@ ruleTester.run('no-standalone-expect', rule, { code: 'expect.hasAssertions()', errors: [{ endColumn: 23, column: 1, messageId: 'unexpectedExpect' }], }, + { + code: 'expect().hasAssertions()', + errors: [{ endColumn: 25, column: 1, messageId: 'unexpectedExpect' }], + }, { code: dedent` describe('scenario', () => { @@ -163,5 +169,14 @@ ruleTester.run('no-standalone-expect', rule, { parserOptions: { sourceType: 'module' }, errors: [{ endColumn: 51, column: 28, messageId: 'unexpectedExpect' }], }, + { + code: dedent` + import { expect as pleaseExpect } from '@jest/globals'; + + beforeEach(() => pleaseExpect.hasAssertions()); + `, + parserOptions: { sourceType: 'module' }, + errors: [{ endColumn: 46, column: 18, messageId: 'unexpectedExpect' }], + }, ], }); diff --git a/src/rules/no-standalone-expect.ts b/src/rules/no-standalone-expect.ts index 6e4b6b0d2..7ab2af026 100644 --- a/src/rules/no-standalone-expect.ts +++ b/src/rules/no-standalone-expect.ts @@ -2,6 +2,7 @@ import { AST_NODE_TYPES, TSESLint, TSESTree } from '@typescript-eslint/utils'; import { DescribeAlias, createRule, + getAccessorValue, getNodeName, isFunction, isTypeOfJestFnCall, @@ -86,9 +87,20 @@ export default createRule< return { CallExpression(node) { - const { type: jestFnCallType } = parseJestFnCall(node, context) ?? {}; + const jestFnCall = parseJestFnCall(node, context); + + if (jestFnCall?.type === 'expect') { + if ( + jestFnCall.head.node.parent?.type === + AST_NODE_TYPES.MemberExpression && + jestFnCall.members.length === 1 && + !['assertions', 'hasAssertions'].includes( + getAccessorValue(jestFnCall.members[0]), + ) + ) { + return; + } - if (jestFnCallType === 'expect') { const parent = callStack[callStack.length - 1]; if (!parent || parent === DescribeAlias.describe) { @@ -98,7 +110,7 @@ export default createRule< return; } - if (jestFnCallType === 'test' || isCustomTestBlockFunction(node)) { + if (jestFnCall?.type === 'test' || isCustomTestBlockFunction(node)) { callStack.push('test'); }