Skip to content

Commit 944f2a3

Browse files
authored
feat(unbound-method): re-enable rule (#883)
* feat(unbound-method): re-enable rule * chore: sort rules * chore: update lockfile * docs: add unbound-method rule to docs * docs: update rule docs * revert: update rule docs
1 parent a5cfe4f commit 944f2a3

File tree

8 files changed

+36
-20
lines changed

8 files changed

+36
-20
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ export default defineConfig({
263263
| [require-test-timeout](docs/rules/require-test-timeout.md) | require tests to declare a timeout | | | 🌐 | | | | |
264264
| [require-to-throw-message](docs/rules/require-to-throw-message.md) | require toThrow() to be called with an error message | | 🌐 | | | | | |
265265
| [require-top-level-describe](docs/rules/require-top-level-describe.md) | enforce that all tests are in a top-level describe | | 🌐 | | | | | |
266+
| [unbound-method](docs/rules/unbound-method.md) | enforce unbound methods are called with their expected scope | | 🌐 | | | | 💭 | |
266267
| [valid-describe-callback](docs/rules/valid-describe-callback.md) | enforce valid describe callback || 🌐 | | | | | |
267268
| [valid-expect](docs/rules/valid-expect.md) | enforce valid `expect()` usage || 🌐 | | 🔧 | | | |
268269
| [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | require promises that have expectations in their chain to be valid || 🌐 | | | | | |

docs/rules/unbound-method.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
# Enforce unbound methods are called with their expected scope (`vitest/unbound-method`)
1+
# vitest/unbound-method
2+
3+
📝 Enforce unbound methods are called with their expected scope.
24

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

5-
💭 This rule requires type information.
7+
💭 This rule requires [type information](https://typescript-eslint.io/linting/typed-linting).
68

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

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
"vitest": "^4.0.18"
7373
},
7474
"peerDependencies": {
75+
"@typescript-eslint/eslint-plugin": "*",
7576
"eslint": ">=8.57.0",
7677
"typescript": ">=5.0.0",
7778
"vitest": "*"
@@ -82,6 +83,9 @@
8283
},
8384
"vitest": {
8485
"optional": true
86+
},
87+
"@typescript-eslint/eslint-plugin": {
88+
"optional": true
8589
}
8690
},
8791
"packageManager": "pnpm@10.18.3+sha512.bbd16e6d7286fd7e01f6b3c0b3c932cda2965c06a908328f74663f10a9aea51f1129eea615134bf992831b009eabe167ecb7008b597f40ff9bc75946aadfb08d",

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/export-rules.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,9 @@ import path from 'node:path'
88
import url from 'node:url'
99
import prettier from 'prettier'
1010

11-
const IGNORED_RULE_FILES = ['unbound-method.ts']
12-
1311
const rulesDir = path.resolve(import.meta.dirname, '../src/rules')
1412
const files = await fs.readdir(rulesDir)
15-
const ruleFiles = files.filter(
16-
(fileName) => !['index.ts', ...IGNORED_RULE_FILES].includes(fileName),
17-
)
13+
const ruleFiles = files.filter((fileName) => fileName !== 'index.ts')
1814

1915
const imports = []
2016
const rules = new Map<string, string>()

src/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ const createConfigLegacy = (rules: Record<string, string>) => ({
2323
})
2424

2525
const allRules = {
26+
'consistent-each-for': 'warn',
2627
'consistent-test-filename': 'warn',
2728
'consistent-test-it': 'warn',
28-
'consistent-each-for': 'warn',
2929
'consistent-vitest-vi': 'warn',
3030
'expect-expect': 'warn',
3131
'hoisted-apis-on-top': 'warn',
@@ -90,25 +90,26 @@ const allRules = {
9090
'prefer-to-have-length': 'warn',
9191
'prefer-todo': 'warn',
9292
'prefer-vi-mocked': 'warn',
93+
'require-awaited-expect-poll': 'warn',
9394
'require-hook': 'warn',
9495
'require-local-test-context-for-concurrent-snapshots': 'warn',
9596
'require-mock-type-parameters': 'warn',
97+
'require-test-timeout': 'off',
9698
'require-to-throw-message': 'warn',
9799
'require-top-level-describe': 'warn',
100+
'unbound-method': 'warn',
98101
'valid-describe-callback': 'warn',
99102
'valid-expect-in-promise': 'warn',
100103
'valid-expect': 'warn',
101104
'valid-title': 'warn',
102-
'require-awaited-expect-poll': 'warn',
103-
'require-test-timeout': 'off',
104105
} as const satisfies RuleList
105106

106107
const recommendedRules = {
107108
'expect-expect': 'error',
109+
'no-commented-out-tests': 'error',
108110
'no-conditional-expect': 'error',
109111
'no-disabled-tests': 'warn',
110112
'no-focused-tests': 'error',
111-
'no-commented-out-tests': 'error',
112113
'no-identical-title': 'error',
113114
'no-import-node-test': 'error',
114115
'no-interpolation-in-snapshots': 'error',

src/rules/index.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import noRestrictedViMethods from './no-restricted-vi-methods'
2828
import noStandaloneExpect from './no-standalone-expect'
2929
import noTestPrefixes from './no-test-prefixes'
3030
import noTestReturnStatement from './no-test-return-statement'
31+
import noUnneededAsyncExpectFunction from './no-unneeded-async-expect-function'
3132
import paddingAroundAfterAllBlocks from './padding-around-after-all-blocks'
3233
import paddingAroundAfterEachBlocks from './padding-around-after-each-blocks'
3334
import paddingAroundAll from './padding-around-all'
@@ -63,23 +64,23 @@ import preferToBeObject from './prefer-to-be-object'
6364
import preferToBeTruthy from './prefer-to-be-truthy'
6465
import preferToBe from './prefer-to-be'
6566
import preferToContain from './prefer-to-contain'
67+
import preferToHaveBeenCalledTimes from './prefer-to-have-been-called-times'
6668
import preferToHaveLength from './prefer-to-have-length'
6769
import preferTodo from './prefer-todo'
6870
import preferViMocked from './prefer-vi-mocked'
6971
import requireAwaitedExpectPoll from './require-awaited-expect-poll'
7072
import requireHook from './require-hook'
71-
import requireTestTimeout from './require-test-timeout'
7273
import requireLocalTestContextForConcurrentSnapshots from './require-local-test-context-for-concurrent-snapshots'
7374
import requireMockTypeParameters from './require-mock-type-parameters'
75+
import requireTestTimeout from './require-test-timeout'
7476
import requireToThrowMessage from './require-to-throw-message'
7577
import requireTopLevelDescribe from './require-top-level-describe'
78+
import unboundMethod from './unbound-method'
7679
import validDescribeCallback from './valid-describe-callback'
7780
import validExpectInPromise from './valid-expect-in-promise'
7881
import validExpect from './valid-expect'
7982
import validTitle from './valid-title'
8083
import warnTodo from './warn-todo'
81-
import noUnneededAsyncExpectFunction from './no-unneeded-async-expect-function'
82-
import preferToHaveBeenCalledTimes from './prefer-to-have-been-called-times'
8384

8485
export const rules = {
8586
'consistent-each-for': consistentEachFor,
@@ -153,12 +154,13 @@ export const rules = {
153154
'prefer-vi-mocked': preferViMocked,
154155
'require-awaited-expect-poll': requireAwaitedExpectPoll,
155156
'require-hook': requireHook,
156-
'require-test-timeout': requireTestTimeout,
157157
'require-local-test-context-for-concurrent-snapshots':
158158
requireLocalTestContextForConcurrentSnapshots,
159159
'require-mock-type-parameters': requireMockTypeParameters,
160+
'require-test-timeout': requireTestTimeout,
160161
'require-to-throw-message': requireToThrowMessage,
161162
'require-top-level-describe': requireTopLevelDescribe,
163+
'unbound-method': unboundMethod,
162164
'valid-describe-callback': validDescribeCallback,
163165
'valid-expect-in-promise': validExpectInPromise,
164166
'valid-expect': validExpect,

src/rules/unbound-method.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import { createRequire } from 'node:module'
12
import { AST_NODE_TYPES, TSESLint, TSESTree } from '@typescript-eslint/utils'
23
import { createEslintRule, getAccessorValue, isIdentifier } from '../utils'
34
import {
45
findTopMostCallExpression,
56
parseVitestFnCall,
67
} from '../utils/parse-vitest-fn-call'
78

9+
const require = createRequire(import.meta.url)
10+
811
const RULE_NAME = 'unbound-method'
912

1013
const toThrowMatchers = [
@@ -26,17 +29,21 @@ export type Options = [Config]
2629

2730
const baseRule = (() => {
2831
try {
29-
// eslint-disable-next-line @typescript-eslint/no-require-imports
3032
const TSESLintPlugin = require('@typescript-eslint/eslint-plugin')
3133

3234
return TSESLintPlugin.rules['unbound-method'] as TSESLint.RuleModule<
3335
MESSAGE_IDS,
3436
Options
3537
>
36-
} catch (e: unknown) {
37-
const error = e as { code: string }
38-
39-
if (error.code === 'MODULE_NOT_FOUND') return null
38+
} catch (error: unknown) {
39+
const errorCode =
40+
typeof error === 'object' && error !== null && 'code' in error
41+
? error.code
42+
: undefined
43+
44+
if (errorCode === 'MODULE_NOT_FOUND' || errorCode === 'ERR_REQUIRE_ESM') {
45+
return null
46+
}
4047

4148
throw error
4249
}

0 commit comments

Comments
 (0)