diff --git a/src/rules/__tests__/valid-expect-in-promise.test.ts b/src/rules/__tests__/valid-expect-in-promise.test.ts index 3d4927a4f..a91cb516c 100644 --- a/src/rules/__tests__/valid-expect-in-promise.test.ts +++ b/src/rules/__tests__/valid-expect-in-promise.test.ts @@ -21,6 +21,15 @@ ruleTester.run('valid-expect-in-promise', rule, { }); })); `, + dedent` + it('it1', () => new Promise((done) => { + test() + .finally(() => { + expect(someThing).toEqual(true); + done(); + }); + })); + `, dedent` it('it1', () => { return somePromise.then(() => { @@ -28,6 +37,13 @@ ruleTester.run('valid-expect-in-promise', rule, { }); }); `, + dedent` + it('it1', () => { + return somePromise.finally(() => { + expect(someThing).toEqual(true); + }); + }); + `, dedent` it('it1', function() { return somePromise.catch(function() { @@ -234,6 +250,16 @@ ruleTester.run('valid-expect-in-promise', rule, { `, errors: [{ column: 3, endColumn: 6, messageId: 'returnPromise' }], }, + { + code: dedent` + it('it1', () => { + somePromise.finally(() => { + expect(someThing).toEqual(true); + }); + }); + `, + errors: [{ column: 3, endColumn: 6, messageId: 'returnPromise' }], + }, // { // code: ` // it('it1', () => { @@ -326,6 +352,17 @@ ruleTester.run('valid-expect-in-promise', rule, { `, errors: [{ column: 3, endColumn: 5, messageId: 'returnPromise' }], }, + { + code: dedent` + it('it1', () => { + somePromise.finally(() => { + doSomeOperation(); + expect(someThing).toEqual(true); + }) + }); + `, + errors: [{ column: 3, endColumn: 5, messageId: 'returnPromise' }], + }, { code: dedent` test('invalid return', () => { diff --git a/src/rules/valid-expect-in-promise.ts b/src/rules/valid-expect-in-promise.ts index dc30aae26..0b9bbb01e 100644 --- a/src/rules/valid-expect-in-promise.ts +++ b/src/rules/valid-expect-in-promise.ts @@ -4,7 +4,6 @@ import { TSESTree, } from '@typescript-eslint/experimental-utils'; import { - CalledKnownMemberExpression, FunctionExpression, KnownCallExpression, TestCaseName, @@ -18,15 +17,17 @@ import { type MessageIds = 'returnPromise'; type RuleContext = TSESLint.RuleContext; -type ThenOrCatchCallExpression = KnownCallExpression<'then' | 'catch'>; +type PromiseChainCallExpression = KnownCallExpression< + 'then' | 'catch' | 'finally' +>; -const isThenOrCatchCall = ( +const isPromiseChainCall = ( node: TSESTree.Node, -): node is ThenOrCatchCallExpression => +): node is PromiseChainCallExpression => node.type === AST_NODE_TYPES.CallExpression && node.callee.type === AST_NODE_TYPES.MemberExpression && isSupportedAccessor(node.callee.property) && - ['then', 'catch'].includes(getAccessorValue(node.callee.property)); + ['then', 'catch', 'finally'].includes(getAccessorValue(node.callee.property)); const isExpectCallPresentInFunction = (body: TSESTree.Node) => { if (body.type === AST_NODE_TYPES.BlockStatement) { @@ -122,7 +123,7 @@ const isParentThenOrPromiseReturned = ( const verifyExpectWithReturn = ( promiseCallbacks: Array, - node: CalledKnownMemberExpression<'then' | 'catch'>, + node: PromiseChainCallExpression['callee'], context: RuleContext, testFunctionBody: TSESTree.Statement[], ) => { @@ -167,7 +168,7 @@ export default createRule({ return { CallExpression(node) { if ( - !isThenOrCatchCall(node) || + !isPromiseChainCall(node) || (node.parent && node.parent.type === AST_NODE_TYPES.AwaitExpression) ) { return;