Skip to content

Commit

Permalink
Feat/prefer lowercase title (#121)
Browse files Browse the repository at this point in the history
* feat: updated

* feat: updated
  • Loading branch information
veritem committed Mar 25, 2023
1 parent 52bdc2b commit c68028d
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -103,6 +103,7 @@ To use the all configuration, extend it in your `.eslintrc` file:
| [prefer-called-with](docs/rules/prefer-called-with.md) | Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()` | 🌐 | | |
| [prefer-lowercase-title](docs/rules/prefer-lowercase-title.md) | Enforce lowercase titles | 🌐 | 🔧 | |
| [prefer-to-be](docs/rules/prefer-to-be.md) | Suggest using toBe() || 🔧 | |
| [prefer-to-be-false](docs/rules/prefer-to-be-false.md) | Suggest using toBeFalsy() | 🌐 | 🔧 | |
| [valid-expect](docs/rules/valid-expect.md) | Enforce valid `expect()` usage || | |
| [valid-title](docs/rules/valid-title.md) | Enforce valid titles || 🔧 | |

Expand Down
24 changes: 24 additions & 0 deletions docs/rules/prefer-to-be-false.md
@@ -0,0 +1,24 @@
# Suggest using toBeFalsy() (`vitest/prefer-to-be-false`)

⚠️ This rule _warns_ in the 🌐 `all` config.

🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).

<!-- end auto-generated rule header -->

## Rule Details

This rule aims to enforce the use of `toBeFalsy()` over `toBeFalsy()`.

Examples of **incorrect** code for this rule:

```js
expect(foo).toBe(false)
```

Examples of **correct** code for this rule:

```js
expect(foo).toBeFalsy()
```

7 changes: 5 additions & 2 deletions src/index.ts
Expand Up @@ -27,6 +27,7 @@ import noTestReturnStatement, { RULE_NAME as noTestReturnStatementName } from '.
import preferCalledWith, { RULE_NAME as preferCalledWithName } from './rules/prefer-called-with'
import validTitle, { RULE_NAME as validTitleName } from './rules/valid-title'
import validExpect, { RULE_NAME as validExpectName } from './rules/valid-expect'
import preferToBeFalse, { RULE_NAME as preferToBeFalseName } from './rules/prefer-to-be-false'

const createConfig = (rules: Record<string, string>) => ({
plugins: ['vitest'],
Expand Down Expand Up @@ -61,7 +62,8 @@ const allRules = {
[noStandaloneExpectName]: 'warn',
[noTestPrefixesName]: 'warn',
[noTestReturnStatementName]: 'warn',
[preferCalledWithName]: 'warn'
[preferCalledWithName]: 'warn',
[preferToBeFalseName]: 'warn'
}

const recommended = {
Expand Down Expand Up @@ -103,7 +105,8 @@ export default {
[noTestReturnStatementName]: noTestReturnStatement,
[preferCalledWithName]: preferCalledWith,
[validTitleName]: validTitle,
[validExpectName]: validExpect
[validExpectName]: validExpect,
[preferToBeFalseName]: preferToBeFalse
},
configs: {
all: createConfig(allRules),
Expand Down
54 changes: 54 additions & 0 deletions src/rules/prefer-to-be-false.ts
@@ -0,0 +1,54 @@
import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'
import { createEslintRule, getAccessorValue } from '../utils/index'
import { getFirstMatcherArg, parseVitestFnCall } from '../utils/parseVitestFnCall'
import { EqualityMatcher } from '../utils/types'

export const RULE_NAME = 'prefer-to-be-false'
export type MESSAGE_ID = 'preferToBeFalse';
export type Options = []

interface FalseLiteral extends TSESTree.BooleanLiteral {
value: false;
}

const isFalseLiteral = (node: TSESTree.Node): node is FalseLiteral => node.type === AST_NODE_TYPES.Literal && node.value === false

export default createEslintRule<Options, MESSAGE_ID>({
name: RULE_NAME,
meta: {
type: 'suggestion',
docs: {
description: 'Suggest using toBeFalsy()',
recommended: false
},
messages: {
preferToBeFalse: 'Prefer toBe(false) over toBeFalsy()'
},
fixable: 'code',
schema: []
},
defaultOptions: [],
create(context) {
return {
CallExpression(node) {
const vitestFnCall = parseVitestFnCall(node, context)

if (vitestFnCall?.type !== 'expect') return

if (vitestFnCall.args.length === 1 &&
isFalseLiteral(getFirstMatcherArg(vitestFnCall)) &&
// eslint-disable-next-line no-prototype-builtins
EqualityMatcher.hasOwnProperty(getAccessorValue(vitestFnCall.matcher))) {
context.report({
node: vitestFnCall.matcher,
messageId: 'preferToBeFalse',
fix: fixer => [
fixer.replaceText(vitestFnCall.matcher, 'toBeFalsy'),
fixer.remove(vitestFnCall.args[0])
]
})
}
}
}
}
})
57 changes: 57 additions & 0 deletions src/rules/prefer-to-be-false.ts.test.ts
@@ -0,0 +1,57 @@
import { RuleTester } from '@typescript-eslint/utils/dist/ts-eslint'
import { it, describe } from 'vitest'
import rule, { RULE_NAME } from './prefer-to-be-false'

const ruleTester: RuleTester = new RuleTester({
parser: require.resolve('@typescript-eslint/parser')
})

describe(RULE_NAME, () => {
it(RULE_NAME, () => {
ruleTester.run(RULE_NAME, rule, {
valid: [
'[].push(false)',
'expect("something");',
'expect(true).toBeTruthy();',
'expect(false).toBeTruthy();',
'expect(false).toBeFalsy();',
'expect(true).toBeFalsy();',
'expect(value).toEqual();',
'expect(value).not.toBeFalsy();',
'expect(value).not.toEqual();'
],
invalid: [
{
code: 'expect(true).toBe(false);',
output: 'expect(true).toBeFalsy();',
errors: [{ messageId: 'preferToBeFalse', column: 14, line: 1 }]
},
{
code: 'expect(wasSuccessful).toEqual(false);',
output: 'expect(wasSuccessful).toBeFalsy();',
errors: [{ messageId: 'preferToBeFalse', column: 23, line: 1 }]
},
{
code: 'expect(fs.existsSync(\'/path/to/file\')).toStrictEqual(false);',
output: 'expect(fs.existsSync(\'/path/to/file\')).toBeFalsy();',
errors: [{ messageId: 'preferToBeFalse', column: 40, line: 1 }]
},
{
code: 'expect("a string").not.toBe(false);',
output: 'expect("a string").not.toBeFalsy();',
errors: [{ messageId: 'preferToBeFalse', column: 24, line: 1 }]
},
{
code: 'expect("a string").not.toEqual(false);',
output: 'expect("a string").not.toBeFalsy();',
errors: [{ messageId: 'preferToBeFalse', column: 24, line: 1 }]
},
{
code: 'expect("a string").not.toStrictEqual(false);',
output: 'expect("a string").not.toBeFalsy();',
errors: [{ messageId: 'preferToBeFalse', column: 24, line: 1 }]
}
]
})
})
})

0 comments on commit c68028d

Please sign in to comment.