Skip to content

Commit 600dd7e

Browse files
authoredMar 26, 2023
feat: added strict equal (#129)
1 parent 4a2591f commit 600dd7e

File tree

5 files changed

+126
-2
lines changed

5 files changed

+126
-2
lines changed
 

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ To use the all configuration, extend it in your `.eslintrc` file:
102102
| [no-test-return-statement](docs/rules/no-test-return-statement.md) | Disallow return statements in tests | 🌐 | | |
103103
| [prefer-called-with](docs/rules/prefer-called-with.md) | Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()` | 🌐 | | |
104104
| [prefer-equality-matcher](docs/rules/prefer-equality-matcher.md) | Suggest using the built-in quality matchers | 🌐 | | 💡 |
105+
| [prefer-expect-resolves](docs/rules/prefer-expect-resolves.md) | Suggest using `expect().resolves` over `expect(await ...)` syntax | 🌐 | 🔧 | |
105106
| [prefer-lowercase-title](docs/rules/prefer-lowercase-title.md) | Enforce lowercase titles | 🌐 | 🔧 | |
106107
| [prefer-strict-equal](docs/rules/prefer-strict-equal.md) | Prefer strict equal over equal | 🌐 | | 💡 |
107108
| [prefer-to-be](docs/rules/prefer-to-be.md) | Suggest using toBe() || 🔧 | |

‎docs/rules/prefer-expect-resolves.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Suggest using `expect().resolves` over `expect(await ...)` syntax (`vitest/prefer-expect-resolves`)
2+
3+
⚠️ This rule _warns_ in the 🌐 `all` config.
4+
5+
🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
6+
7+
<!-- end auto-generated rule header -->
8+
9+
```ts
10+
// bad
11+
it('passes', async () => { expect(await someValue()).toBe(true); });
12+
13+
// good
14+
it('passes', async () => { await expect(someValue()).resolves.toBe(true); });
15+
```
16+
```

‎src/index.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import preferToBeFalsy, { RULE_NAME as preferToBeFalsyName } from './rules/prefe
3333
import preferToHaveLength, { RULE_NAME as preferToHaveLengthName } from './rules/prefer-to-have-length'
3434
import preferEqualityMatcher, { RULE_NAME as preferEqualityMatcherName } from './rules/prefer-equality-matcher'
3535
import preferStrictEqual, { RULE_NAME as preferStrictEqualName } from './rules/prefer-strict-equal'
36+
import preferExpectResolves, { RULE_NAME as preferExpectResolvesName } from './rules/prefer-expect-resolves'
3637

3738
const createConfig = (rules: Record<string, string>) => ({
3839
plugins: ['vitest'],
@@ -73,7 +74,8 @@ const allRules = {
7374
[preferToBeTruthyName]: 'warn',
7475
[preferToHaveLengthName]: 'warn',
7576
[preferEqualityMatcherName]: 'warn',
76-
[preferStrictEqualName]: 'warn'
77+
[preferStrictEqualName]: 'warn',
78+
[preferExpectResolvesName]: 'warn'
7779
}
7880

7981
const recommended = {
@@ -121,7 +123,8 @@ export default {
121123
[preferToBeTruthyName]: preferToBeTruthy,
122124
[preferToHaveLengthName]: preferToHaveLength,
123125
[preferEqualityMatcherName]: preferEqualityMatcher,
124-
[preferStrictEqualName]: preferStrictEqual
126+
[preferStrictEqualName]: preferStrictEqual,
127+
[preferExpectResolvesName]: preferExpectResolves
125128
},
126129
configs: {
127130
all: createConfig(allRules),
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { it, describe } from 'vitest'
2+
import ruleTester from '../utils/tester'
3+
import rule, { RULE_NAME } from './prefer-expect-resolves'
4+
5+
const messageId = 'expectResolves'
6+
7+
describe(RULE_NAME, () => {
8+
it(RULE_NAME, () => {
9+
ruleTester.run(RULE_NAME, rule, {
10+
valid: [
11+
'expect.hasAssertions()',
12+
`it('passes', async () => {
13+
await expect(someValue()).resolves.toBe(true);
14+
});`,
15+
`it('is true', async () => {
16+
const myPromise = Promise.resolve(true);
17+
18+
await expect(myPromise).resolves.toBe(true);
19+
});
20+
`,
21+
`it('errors', async () => {
22+
await expect(Promise.reject(new Error('oh noes!'))).rejects.toThrowError(
23+
'oh noes!',
24+
);
25+
});`
26+
],
27+
invalid: [
28+
{
29+
code: 'it(\'passes\', async () => { expect(await someValue()).toBe(true); });',
30+
output: 'it(\'passes\', async () => { await expect(someValue()).resolves.toBe(true); });',
31+
errors: [{
32+
messageId
33+
}]
34+
},
35+
{
36+
code: 'it(\'is true\', async () => { const myPromise = Promise.resolve(true); expect(await myPromise).toBe(true); });',
37+
output: 'it(\'is true\', async () => { const myPromise = Promise.resolve(true); await expect(myPromise).resolves.toBe(true); });',
38+
errors: [
39+
{
40+
messageId,
41+
endColumn: 92,
42+
column: 77
43+
}
44+
]
45+
}
46+
]
47+
})
48+
})
49+
})

‎src/rules/prefer-expect-resolves.ts

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { AST_NODE_TYPES } from '@typescript-eslint/utils'
2+
import { createEslintRule } from '../utils'
3+
import { parseVitestFnCall } from '../utils/parseVitestFnCall'
4+
5+
export const RULE_NAME = 'prefer-expect-resolves'
6+
type MESSAGE_IDS = 'expectResolves'
7+
type Options = []
8+
9+
export default createEslintRule<Options, MESSAGE_IDS>({
10+
name: RULE_NAME,
11+
meta: {
12+
type: 'suggestion',
13+
docs: {
14+
description: 'Suggest using `expect().resolves` over `expect(await ...)` syntax',
15+
recommended: 'warn'
16+
},
17+
fixable: 'code',
18+
messages: {
19+
expectResolves: 'Use `expect().resolves` instead'
20+
},
21+
schema: []
22+
},
23+
defaultOptions: [],
24+
create: (context) => ({
25+
CallExpression(node) {
26+
const vitestFnCall = parseVitestFnCall(node, context)
27+
28+
if (vitestFnCall?.type !== 'expect') return
29+
30+
const { parent } = vitestFnCall.head.node
31+
32+
if (parent?.type !== AST_NODE_TYPES.CallExpression)
33+
return
34+
35+
const [awaitNode] = parent.arguments
36+
37+
if (awaitNode.type === AST_NODE_TYPES.AwaitExpression) {
38+
context.report({
39+
node: awaitNode,
40+
messageId: 'expectResolves',
41+
fix(fixer) {
42+
return [
43+
fixer.insertTextBefore(parent, 'await '),
44+
fixer.removeRange([
45+
awaitNode.range[0],
46+
awaitNode.argument.range[0]
47+
]),
48+
fixer.insertTextAfter(parent, '.resolves')
49+
]
50+
}
51+
})
52+
}
53+
}
54+
})
55+
})

0 commit comments

Comments
 (0)
Please sign in to comment.