From 7b7a396e12c46d3087b467227887ed64854480c0 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Mon, 26 Apr 2021 12:14:23 +1200 Subject: [PATCH] fix(valid-expect): support async `expect` in ternary statements (#833) --- src/rules/__tests__/valid-expect.test.ts | 86 ++++++++++++++++++++++++ src/rules/valid-expect.ts | 15 ++++- 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/src/rules/__tests__/valid-expect.test.ts b/src/rules/__tests__/valid-expect.test.ts index 78f9cc964..10434a43b 100644 --- a/src/rules/__tests__/valid-expect.test.ts +++ b/src/rules/__tests__/valid-expect.test.ts @@ -74,6 +74,35 @@ ruleTester.run('valid-expect', rule, { return expect(functionReturningAPromise()).resolves.toEqual(1).then(() => expect(Promise.resolve(2)).resolves.toBe(1)); }); `, + dedent` + expect.extend({ + toResolve(obj) { + return this.isNot + ? expect(obj).toBe(true) + : expect(obj).resolves.not.toThrow(); + } + }); + `, + dedent` + expect.extend({ + toResolve(obj) { + return this.isNot + ? expect(obj).resolves.not.toThrow() + : expect(obj).toBe(true); + } + }); + `, + dedent` + expect.extend({ + toResolve(obj) { + return this.isNot + ? expect(obj).toBe(true) + : anotherCondition + ? expect(obj).resolves.not.toThrow() + : expect(obj).toBe(false) + } + }); + `, { code: 'expect(1).toBe(2);', options: [{ maxArgs: 2 }], @@ -369,6 +398,63 @@ ruleTester.run('valid-expect', rule, { ], }, + { + code: dedent` + expect.extend({ + toResolve(obj) { + this.isNot + ? expect(obj).toBe(true) + : expect(obj).resolves.not.toThrow(); + } + }); + `, + errors: [ + { + column: 9, + endColumn: 43, + messageId: 'asyncMustBeAwaited', + }, + ], + }, + { + code: dedent` + expect.extend({ + toResolve(obj) { + this.isNot + ? expect(obj).resolves.not.toThrow() + : expect(obj).toBe(true); + } + }); + `, + errors: [ + { + column: 9, + endColumn: 43, + messageId: 'asyncMustBeAwaited', + }, + ], + }, + { + code: dedent` + expect.extend({ + toResolve(obj) { + this.isNot + ? expect(obj).toBe(true) + : anotherCondition + ? expect(obj).resolves.not.toThrow() + : expect(obj).toBe(false) + } + }); + `, + errors: [ + { + column: 9, + endColumn: 43, + messageId: 'asyncMustBeAwaited', + }, + ], + }, + // expect().resolves { code: diff --git a/src/rules/valid-expect.ts b/src/rules/valid-expect.ts index 2869ecc64..f0118b987 100644 --- a/src/rules/valid-expect.ts +++ b/src/rules/valid-expect.ts @@ -80,14 +80,23 @@ const isAcceptableReturnNode = ( node: TSESTree.Node, allowReturn: boolean, ): node is + | TSESTree.ConditionalExpression | TSESTree.ArrowFunctionExpression | TSESTree.AwaitExpression - | TSESTree.ReturnStatement => - (allowReturn && node.type === AST_NODE_TYPES.ReturnStatement) || - [ + | TSESTree.ReturnStatement => { + if (allowReturn && node.type === AST_NODE_TYPES.ReturnStatement) { + return true; + } + + if (node.type === AST_NODE_TYPES.ConditionalExpression && node.parent) { + return isAcceptableReturnNode(node.parent, allowReturn); + } + + return [ AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.AwaitExpression, ].includes(node.type); +}; const isNoAssertionsParentNode = (node: TSESTree.Node): boolean => node.type === AST_NODE_TYPES.ExpressionStatement ||