Skip to content

Commit 0bbfb3a

Browse files
yatkiSimenB
authored andcommitted
fix(valid-expect): work with .then (#352)
Fixes #347
1 parent f9b6668 commit 0bbfb3a

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

src/rules/__tests__/valid-expect.test.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,35 @@ ruleTester.run('valid-expect', rule, {
4242
'test("valid-expect", async () => { await Promise.race([expect(Promise.reject(2)).not.rejects.toBeDefined(), expect(Promise.reject(2)).rejects.not.toBeDefined()]); });',
4343
'test("valid-expect", async () => { await Promise.allSettled([expect(Promise.reject(2)).not.rejects.toBeDefined(), expect(Promise.reject(2)).rejects.not.toBeDefined()]); });',
4444
'test("valid-expect", async () => { await Promise.any([expect(Promise.reject(2)).not.rejects.toBeDefined(), expect(Promise.reject(2)).rejects.not.toBeDefined()]); });',
45+
'test("valid-expect", async () => { return expect(Promise.reject(2)).not.resolves.toBeDefined().then(() => console.log("valid-case")); });',
46+
'test("valid-expect", async () => { return expect(Promise.reject(2)).not.resolves.toBeDefined().then(() => console.log("valid-case")).then(() => console.log("another valid case")); });',
47+
'test("valid-expect", async () => { return expect(Promise.reject(2)).not.resolves.toBeDefined().catch(() => console.log("valid-case")); });',
48+
'test("valid-expect", async () => { return expect(Promise.reject(2)).not.resolves.toBeDefined().then(() => console.log("valid-case")).catch(() => console.log("another valid case")); });',
49+
'test("valid-expect", async () => { return expect(Promise.reject(2)).not.resolves.toBeDefined().then(() => { expect(someMock).toHaveBeenCalledTimes(1); }); });',
50+
'test("valid-expect", async () => { await expect(Promise.reject(2)).not.resolves.toBeDefined().then(() => console.log("valid-case")); });',
51+
'test("valid-expect", async () => { await expect(Promise.reject(2)).not.resolves.toBeDefined().then(() => console.log("valid-case")).then(() => console.log("another valid case")); });',
52+
'test("valid-expect", async () => { await expect(Promise.reject(2)).not.resolves.toBeDefined().catch(() => console.log("valid-case")); });',
53+
'test("valid-expect", async () => { await expect(Promise.reject(2)).not.resolves.toBeDefined().then(() => console.log("valid-case")).catch(() => console.log("another valid case")); });',
54+
'test("valid-expect", async () => { await expect(Promise.reject(2)).not.resolves.toBeDefined().then(() => { expect(someMock).toHaveBeenCalledTimes(1); }); });',
55+
{
56+
code: `test("valid-expect", () => {
57+
return expect(functionReturningAPromise()).resolves.toEqual(1).then(() => {
58+
return expect(Promise.resolve(2)).resolves.toBe(1);
59+
});
60+
});`,
61+
},
62+
{
63+
code: `test("valid-expect", () => {
64+
return expect(functionReturningAPromise()).resolves.toEqual(1).then(async () => {
65+
await expect(Promise.resolve(2)).resolves.toBe(1);
66+
});
67+
});`,
68+
},
69+
{
70+
code: `test("valid-expect", () => {
71+
return expect(functionReturningAPromise()).resolves.toEqual(1).then(() => expect(Promise.resolve(2)).resolves.toBe(1));
72+
});`,
73+
},
4574
],
4675

4776
invalid: [
@@ -484,5 +513,40 @@ ruleTester.run('valid-expect', rule, {
484513
},
485514
],
486515
},
516+
{
517+
code: `test("valid-expect", () => {
518+
return expect(functionReturningAPromise()).resolves.toEqual(1).then(() => {
519+
expect(Promise.resolve(2)).resolves.toBe(1);
520+
});
521+
});`,
522+
errors: [
523+
{
524+
line: 3,
525+
column: 11,
526+
endLine: 3,
527+
endColumn: 54,
528+
messageId: 'asyncMustBeAwaited',
529+
data: { orReturned: ' or returned' },
530+
},
531+
],
532+
},
533+
{
534+
code: `test("valid-expect", () => {
535+
return expect(functionReturningAPromise()).resolves.toEqual(1).then(async () => {
536+
await expect(Promise.resolve(2)).resolves.toBe(1);
537+
expect(Promise.resolve(4)).resolves.toBe(4);
538+
});
539+
});`,
540+
errors: [
541+
{
542+
line: 4,
543+
column: 11,
544+
endLine: 4,
545+
endColumn: 54,
546+
messageId: 'asyncMustBeAwaited',
547+
data: { orReturned: ' or returned' },
548+
},
549+
],
550+
},
487551
],
488552
});

src/rules/valid-expect.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,24 @@ const getPromiseCallExpressionNode = node => {
6363
return null;
6464
};
6565

66+
const getParentIfThenified = node => {
67+
const grandParentNode = node.parent && node.parent.parent;
68+
69+
if (
70+
grandParentNode &&
71+
grandParentNode.type === 'CallExpression' &&
72+
grandParentNode.callee &&
73+
grandParentNode.callee.type === 'MemberExpression' &&
74+
['then', 'catch'].includes(grandParentNode.callee.property.name) &&
75+
grandParentNode.parent
76+
) {
77+
// Just in case `then`s are chained look one above.
78+
return getParentIfThenified(grandParentNode);
79+
}
80+
81+
return node;
82+
};
83+
6684
const checkIfValidReturn = (parentCallExpressionNode, allowReturn) => {
6785
const validParentNodeTypes = ['ArrowFunctionExpression', 'AwaitExpression'];
6886
if (allowReturn) {
@@ -223,6 +241,8 @@ export default {
223241
const orReturned = allowReturn ? ' or returned' : '';
224242
let messageId = 'asyncMustBeAwaited';
225243

244+
parentNode = getParentIfThenified(parentNode);
245+
226246
// Promise.x([expect()]) || Promise.x(expect())
227247
if (promiseArgumentTypes.includes(parentNode.parent.type)) {
228248
const promiseNode = getPromiseCallExpressionNode(

0 commit comments

Comments
 (0)