Skip to content

Commit

Permalink
feat: upgrade @typescript-eslint/utils to v6 (#1508)
Browse files Browse the repository at this point in the history
* feat: upgrade to `@typescript-eslint/utils` v6

* chore: remove invalid module declarations

* fix: update `docs` meta property on rules

* chore: cast `context.settings` for now

* refactor: update deprecated method calls

* fix: update types for `JSONSchema4`

* test(unbound-method): update cases and structure

* test(unbound-method): use `TSESLint.RuleTester`

* test(unbound-method): include filename for invalid cases

* test(unbound-method): don't run broken test when using `@typescript-eslint` v5

* fix: address deprecation warning
G-Rath authored Mar 22, 2024
1 parent 8408db9 commit dc6e8cd
Showing 59 changed files with 219 additions and 209 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -95,7 +95,7 @@
]
},
"dependencies": {
"@typescript-eslint/utils": "^5.10.0"
"@typescript-eslint/utils": "^6.0.0"
},
"devDependencies": {
"@babel/cli": "^7.4.4",
35 changes: 1 addition & 34 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { readdirSync } from 'fs';
import { join, parse } from 'path';
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
import type { TSESLint } from '@typescript-eslint/utils';
import {
name as packageName,
version as packageVersion,
@@ -12,39 +12,6 @@ type RuleModule = TSESLint.RuleModule<string, unknown[]> & {
meta: Required<Pick<TSESLint.RuleMetaData<string>, 'docs'>>;
};

// v5 of `@typescript-eslint/experimental-utils` removed this
declare module '@typescript-eslint/utils/dist/ts-eslint/Rule' {
export interface RuleMetaDataDocs {
category: 'Best Practices' | 'Possible Errors';
}
}

declare module '@typescript-eslint/utils/dist/ts-eslint/SourceCode' {
export interface SourceCode {
/**
* Returns the scope of the given node.
* This information can be used track references to variables.
* @since 8.37.0
*/
getScope(node: TSESTree.Node): TSESLint.Scope.Scope;
/**
* Returns an array of the ancestors of the given node, starting at
* the root of the AST and continuing through the direct parent of the current node.
* This array does not include the currently-traversed node itself.
* @since 8.38.0
*/
getAncestors(node: TSESTree.Node): TSESTree.Node[];
/**
* Returns a list of variables declared by the given node.
* This information can be used to track references to variables.
* @since 8.38.0
*/
getDeclaredVariables(
node: TSESTree.Node,
): readonly TSESLint.Scope.Variable[];
}
}

// copied from https://github.com/babel/babel/blob/d8da63c929f2d28c401571e2a43166678c555bc4/packages/babel-helpers/src/helpers.js#L602-L606
/* istanbul ignore next */
const interopRequireDefault = (obj: any): { default: any } =>
104 changes: 92 additions & 12 deletions src/rules/__tests__/unbound-method.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import path from 'path';
import { ESLintUtils, type TSESLint } from '@typescript-eslint/utils';
import { version as rawTypeScriptESLintPluginVersion } from '@typescript-eslint/eslint-plugin/package.json';
import { TSESLint } from '@typescript-eslint/utils';
import dedent from 'dedent';
import type { MessageIds, Options } from '../unbound-method';

@@ -9,15 +10,35 @@ function getFixturesRootDir(): string {

const rootPath = getFixturesRootDir();

const ruleTester = new ESLintUtils.RuleTester({
parser: '@typescript-eslint/parser',
const ruleTester = new TSESLint.RuleTester({
parser: require.resolve('@typescript-eslint/parser'),
parserOptions: {
sourceType: 'module',
tsconfigRootDir: rootPath,
project: './tsconfig.json',
},
});

const fixtureFilename = path.join(rootPath, 'file.ts');

const withFixtureFilename = <
T extends Array<
| (TSESLint.ValidTestCase<Options> | string)
| TSESLint.InvalidTestCase<MessageIds, Options>
>,
>(
cases: T,
): T extends Array<TSESLint.InvalidTestCase<MessageIds, Options>>
? Array<TSESLint.InvalidTestCase<MessageIds, Options>>
: Array<TSESLint.ValidTestCase<Options>> => {
// @ts-expect-error this is fine, and will go away later once we upgrade
return cases.map(code => {
const test = typeof code === 'string' ? { code } : code;

return { filename: fixtureFilename, ...test };
});
};

const ConsoleClassAndVariableCode = dedent`
class Console {
log(str) {
@@ -164,8 +185,8 @@ describe('error handling', () => {
});

describe('when @typescript-eslint/eslint-plugin is not available', () => {
const ruleTester = new ESLintUtils.RuleTester({
parser: '@typescript-eslint/parser',
const ruleTester = new TSESLint.RuleTester({
parser: require.resolve('@typescript-eslint/parser'),
parserOptions: {
sourceType: 'module',
tsconfigRootDir: rootPath,
@@ -177,16 +198,18 @@ describe('error handling', () => {
'unbound-method jest edition without type service',
requireRule(true),
{
valid: validTestCases.concat(invalidTestCases.map(({ code }) => code)),
valid: withFixtureFilename(
validTestCases.concat(invalidTestCases.map(({ code }) => code)),
),
invalid: [],
},
);
});
});

ruleTester.run('unbound-method jest edition', requireRule(false), {
valid: validTestCases,
invalid: invalidTestCases,
valid: withFixtureFilename(validTestCases),
invalid: withFixtureFilename(invalidTestCases),
});

function addContainsMethodsClass(code: string): string {
@@ -225,11 +248,14 @@ function addContainsMethodsClassInvalid(
}

ruleTester.run('unbound-method', requireRule(false), {
valid: [
valid: withFixtureFilename([
'Promise.resolve().then(console.log);',
"['1', '2', '3'].map(Number.parseInt);",
'[5.2, 7.1, 3.6].map(Math.floor);',
'const x = console.log;',
...(parseInt(rawTypeScriptESLintPluginVersion.split('.')[0], 10) >= 6
? ['const x = Object.defineProperty;']
: []),
...[
'instance.bound();',
'instance.unbound();',
@@ -455,8 +481,8 @@ class OtherClass extends BaseClass {
const oc = new OtherClass();
oc.superLogThis();
`,
],
invalid: [
]),
invalid: withFixtureFilename([
{
code: `
class Console {
@@ -762,5 +788,59 @@ class OtherClass extends BaseClass {
},
],
},
],
{
code: `
const values = {
a() {},
b: () => {},
};
const { a, b } = values;
`,
errors: [
{
line: 7,
column: 9,
endColumn: 10,
messageId: 'unboundWithoutThisAnnotation',
},
],
},
{
code: `
const values = {
a() {},
b: () => {},
};
const { a: c } = values;
`,
errors: [
{
line: 7,
column: 9,
endColumn: 10,
messageId: 'unboundWithoutThisAnnotation',
},
],
},
{
code: `
const values = {
a() {},
b: () => {},
};
const { b, a } = values;
`,
errors: [
{
line: 7,
column: 12,
endColumn: 13,
messageId: 'unboundWithoutThisAnnotation',
},
],
},
]),
});
4 changes: 2 additions & 2 deletions src/rules/consistent-test-it.ts
Original file line number Diff line number Diff line change
@@ -35,9 +35,7 @@ export default createRule<
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Enforce `test` and `it` usage conventions',
recommended: false,
},
fixable: 'code',
messages: {
@@ -51,9 +49,11 @@ export default createRule<
type: 'object',
properties: {
fn: {
type: 'string',
enum: [TestCaseName.it, TestCaseName.test],
},
withinDescribe: {
type: 'string',
enum: [TestCaseName.it, TestCaseName.test],
},
},
2 changes: 0 additions & 2 deletions src/rules/expect-expect.ts
Original file line number Diff line number Diff line change
@@ -54,9 +54,7 @@ export default createRule<
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Enforce assertion to be made in a test body',
recommended: 'warn',
},
messages: {
noAssertions: 'Test has no assertions',
2 changes: 0 additions & 2 deletions src/rules/max-expects.ts
Original file line number Diff line number Diff line change
@@ -10,9 +10,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Enforces a maximum number assertion calls in a test body',
recommended: false,
},
messages: {
exceededMaxAssertion:
2 changes: 0 additions & 2 deletions src/rules/max-nested-describe.ts
Original file line number Diff line number Diff line change
@@ -5,9 +5,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Enforces a maximum depth to nested describe calls',
recommended: false,
},
messages: {
exceededMaxDepth:
2 changes: 0 additions & 2 deletions src/rules/no-alias-methods.ts
Original file line number Diff line number Diff line change
@@ -9,9 +9,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow alias methods',
recommended: 'error',
},
messages: {
replaceAlias: `Replace {{ alias }}() with its canonical name of {{ canonical }}()`,
2 changes: 0 additions & 2 deletions src/rules/no-commented-out-tests.ts
Original file line number Diff line number Diff line change
@@ -11,9 +11,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow commented out tests',
recommended: 'warn',
},
messages: {
commentedTests: 'Some tests seem to be commented',
2 changes: 0 additions & 2 deletions src/rules/no-conditional-expect.ts
Original file line number Diff line number Diff line change
@@ -20,8 +20,6 @@ export default createRule({
meta: {
docs: {
description: 'Disallow calling `expect` conditionally',
category: 'Best Practices',
recommended: 'error',
},
messages: {
conditionalExpect: 'Avoid calling `expect` conditionally`',
2 changes: 0 additions & 2 deletions src/rules/no-conditional-in-test.ts
Original file line number Diff line number Diff line change
@@ -6,8 +6,6 @@ export default createRule({
meta: {
docs: {
description: 'Disallow conditional logic in tests',
category: 'Best Practices',
recommended: false,
},
messages: {
conditionalInTest: 'Avoid having conditionals in tests',
2 changes: 0 additions & 2 deletions src/rules/no-confusing-set-timeout.ts
Original file line number Diff line number Diff line change
@@ -18,9 +18,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow confusing usages of jest.setTimeout',
recommended: false,
},
messages: {
globalSetTimeout: '`jest.setTimeout` should be call in `global` scope',
2 changes: 0 additions & 2 deletions src/rules/no-deprecated-functions.ts
Original file line number Diff line number Diff line change
@@ -28,9 +28,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow use of deprecated functions',
recommended: 'error',
},
messages: {
deprecatedFunction:
2 changes: 0 additions & 2 deletions src/rules/no-disabled-tests.ts
Original file line number Diff line number Diff line change
@@ -10,9 +10,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow disabled tests',
recommended: 'warn',
},
messages: {
missingFunction: 'Test is missing function argument',
2 changes: 0 additions & 2 deletions src/rules/no-done-callback.ts
Original file line number Diff line number Diff line change
@@ -37,9 +37,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow using a callback in asynchronous tests and hooks',
recommended: 'error',
},
messages: {
noDoneCallback:
2 changes: 0 additions & 2 deletions src/rules/no-duplicate-hooks.ts
Original file line number Diff line number Diff line change
@@ -4,9 +4,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow duplicate setup and teardown hooks',
recommended: false,
},
messages: {
noDuplicateHook: 'Duplicate {{hook}} in describe block',
2 changes: 0 additions & 2 deletions src/rules/no-export.ts
Original file line number Diff line number Diff line change
@@ -5,9 +5,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow using `exports` in files containing tests',
recommended: 'error',
},
messages: {
unexpectedExport: `Do not export from a test file`,
2 changes: 0 additions & 2 deletions src/rules/no-focused-tests.ts
Original file line number Diff line number Diff line change
@@ -5,9 +5,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow focused tests',
recommended: 'error',
},
messages: {
focusedTest: 'Unexpected focused test',
3 changes: 1 addition & 2 deletions src/rules/no-hooks.ts
Original file line number Diff line number Diff line change
@@ -7,9 +7,7 @@ export default createRule<
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow setup and teardown hooks',
recommended: false,
},
messages: {
unexpectedHook: "Unexpected '{{ hookName }}' hook",
@@ -20,6 +18,7 @@ export default createRule<
properties: {
allow: {
type: 'array',
// @ts-expect-error https://github.com/eslint/eslint/discussions/17573
contains: ['beforeAll', 'beforeEach', 'afterAll', 'afterEach'],
},
},
2 changes: 0 additions & 2 deletions src/rules/no-identical-title.ts
Original file line number Diff line number Diff line change
@@ -21,9 +21,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow identical titles',
recommended: 'error',
},
messages: {
multipleTestTitle:
2 changes: 0 additions & 2 deletions src/rules/no-interpolation-in-snapshots.ts
Original file line number Diff line number Diff line change
@@ -5,9 +5,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow string interpolation inside snapshots',
recommended: 'error',
},
messages: {
noInterpolation: 'Do not use string interpolation inside of snapshots',
2 changes: 0 additions & 2 deletions src/rules/no-jasmine-globals.ts
Original file line number Diff line number Diff line change
@@ -11,9 +11,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow Jasmine globals',
recommended: 'error',
},
messages: {
illegalGlobal:
2 changes: 0 additions & 2 deletions src/rules/no-large-snapshots.ts
Original file line number Diff line number Diff line change
@@ -76,9 +76,7 @@ export default createRule<[RuleOptions], MessageId>({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow large snapshots',
recommended: false,
},
messages: {
noSnapshot: '`{{ lineCount }}`s should begin with lowercase',
2 changes: 0 additions & 2 deletions src/rules/no-mocks-import.ts
Original file line number Diff line number Diff line change
@@ -17,9 +17,7 @@ export default createRule({
meta: {
type: 'problem',
docs: {
category: 'Best Practices',
description: 'Disallow manually importing from `__mocks__`',
recommended: 'error',
},
messages: {
noManualImport: `Mocks should not be manually imported from a ${mocksDirName} directory. Instead use \`jest.mock\` and import from the original module path`,
2 changes: 0 additions & 2 deletions src/rules/no-restricted-jest-methods.ts
Original file line number Diff line number Diff line change
@@ -12,9 +12,7 @@ export default createRule<
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow specific `jest.` methods',
recommended: false,
},
type: 'suggestion',
schema: [
2 changes: 0 additions & 2 deletions src/rules/no-restricted-matchers.ts
Original file line number Diff line number Diff line change
@@ -23,9 +23,7 @@ export default createRule<
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow specific matchers & modifiers',
recommended: false,
},
type: 'suggestion',
schema: [
3 changes: 1 addition & 2 deletions src/rules/no-standalone-expect.ts
Original file line number Diff line number Diff line change
@@ -60,16 +60,15 @@ export default createRule<
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow using `expect` outside of `it` or `test` blocks',
recommended: 'error',
},
messages: {
unexpectedExpect: 'Expect must be inside of a test block',
},
type: 'suggestion',
schema: [
{
type: 'object',
properties: {
additionalTestBlockFunctions: {
type: 'array',
2 changes: 0 additions & 2 deletions src/rules/no-test-prefixes.ts
Original file line number Diff line number Diff line change
@@ -5,9 +5,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Require using `.only` and `.skip` over `f` and `x`',
recommended: 'error',
},
messages: {
usePreferredName: 'Use "{{ preferredNodeName }}" instead',
2 changes: 0 additions & 2 deletions src/rules/no-test-return-statement.ts
Original file line number Diff line number Diff line change
@@ -25,9 +25,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Disallow explicitly returning from tests',
recommended: false,
},
messages: {
noReturnValue: 'Jest tests should not return a value',
11 changes: 7 additions & 4 deletions src/rules/no-untyped-mock-factory.ts
Original file line number Diff line number Diff line change
@@ -21,10 +21,8 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description:
'Disallow using `jest.mock()` factories without an explicit type parameter',
recommended: false,
},
messages: {
addTypeParameterToModuleMock:
@@ -38,7 +36,12 @@ export default createRule({
create(context) {
return {
CallExpression(node: TSESTree.CallExpression): void {
const { callee, typeParameters } = node;
let { callee, typeArguments } = node;

/* istanbul ignore next */
if (!('typeArguments' in node)) {
typeArguments = (node as TSESTree.CallExpression).typeParameters;
}

if (callee.type !== AST_NODE_TYPES.MemberExpression) {
return;
@@ -55,7 +58,7 @@ export default createRule({
const [nameNode, factoryNode] = node.arguments;

const hasTypeParameter =
typeParameters !== undefined && typeParameters.params.length > 0;
typeArguments !== undefined && typeArguments.params.length > 0;
const hasReturnType =
isFunction(factoryNode) && factoryNode.returnType !== undefined;

2 changes: 0 additions & 2 deletions src/rules/prefer-called-with.ts
Original file line number Diff line number Diff line change
@@ -4,10 +4,8 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description:
'Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()`',
recommended: false,
},
messages: {
preferCalledWith: 'Prefer {{ matcherName }}With(/* expected args */)',
2 changes: 0 additions & 2 deletions src/rules/prefer-comparison-matcher.ts
Original file line number Diff line number Diff line change
@@ -57,9 +57,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Suggest using the built-in comparison matchers',
recommended: false,
},
messages: {
useToBeComparison: 'Prefer using `{{ preferredMatcher }}` instead',
2 changes: 0 additions & 2 deletions src/rules/prefer-each.ts
Original file line number Diff line number Diff line change
@@ -5,9 +5,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Prefer using `.each` rather than manual loops',
recommended: false,
},
messages: {
preferEach: 'prefer using `{{ fn }}.each` rather than a manual loop',
2 changes: 0 additions & 2 deletions src/rules/prefer-equality-matcher.ts
Original file line number Diff line number Diff line change
@@ -14,9 +14,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Suggest using the built-in equality matchers',
recommended: false,
},
messages: {
useEqualityMatcher: 'Prefer using one of the equality matchers instead',
2 changes: 0 additions & 2 deletions src/rules/prefer-expect-assertions.ts
Original file line number Diff line number Diff line change
@@ -64,10 +64,8 @@ export default createRule<[RuleOptions], MessageIds>({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description:
'Suggest using `expect.assertions()` OR `expect.hasAssertions()`',
recommended: false,
},
messages: {
hasAssertionsTakesNoArguments:
2 changes: 0 additions & 2 deletions src/rules/prefer-expect-resolves.ts
Original file line number Diff line number Diff line change
@@ -5,10 +5,8 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description:
'Prefer `await expect(...).resolves` over `expect(await ...)` syntax',
recommended: false,
},
fixable: 'code',
messages: {
2 changes: 0 additions & 2 deletions src/rules/prefer-hooks-in-order.ts
Original file line number Diff line number Diff line change
@@ -6,9 +6,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Prefer having hooks in a consistent order',
recommended: false,
},
messages: {
reorderHooks: `\`{{ currentHook }}\` hooks should be before any \`{{ previousHook }}\` hooks`,
2 changes: 0 additions & 2 deletions src/rules/prefer-hooks-on-top.ts
Original file line number Diff line number Diff line change
@@ -4,9 +4,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Suggest having hooks before any test cases',
recommended: false,
},
messages: {
noHookOnTop: 'Hooks should come before test cases',
7 changes: 4 additions & 3 deletions src/rules/prefer-lowercase-title.ts
Original file line number Diff line number Diff line change
@@ -56,8 +56,6 @@ export default createRule<
type: 'suggestion',
docs: {
description: 'Enforce lowercase test names',
category: 'Best Practices',
recommended: false,
},
fixable: 'code',
messages: {
@@ -70,11 +68,14 @@ export default createRule<
ignore: {
type: 'array',
items: {
type: 'string',
// for some reason TypeScript thinks this _must_ be a read-only
// array, so we have to explicitly cast it as a mutable array
enum: [
DescribeAlias.describe,
TestCaseName.test,
TestCaseName.it,
],
] as string[],
},
additionalItems: false,
},
2 changes: 0 additions & 2 deletions src/rules/prefer-mock-promise-shorthand.ts
Original file line number Diff line number Diff line change
@@ -32,9 +32,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Prefer mock resolved/rejected shorthands for promises',
recommended: false,
},
messages: {
useMockShorthand: 'Prefer {{ replacement }}',
2 changes: 0 additions & 2 deletions src/rules/prefer-snapshot-hint.ts
Original file line number Diff line number Diff line change
@@ -43,9 +43,7 @@ export default createRule<[('always' | 'multi')?], keyof typeof messages>({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Prefer including a hint with external snapshots',
recommended: false,
},
messages,
type: 'suggestion',
2 changes: 0 additions & 2 deletions src/rules/prefer-spy-on.ts
Original file line number Diff line number Diff line change
@@ -68,9 +68,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Suggest using `jest.spyOn()`',
recommended: false,
},
messages: {
useJestSpyOn: 'Use jest.spyOn() instead',
2 changes: 0 additions & 2 deletions src/rules/prefer-strict-equal.ts
Original file line number Diff line number Diff line change
@@ -10,9 +10,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Suggest using `toStrictEqual()`',
recommended: false,
},
messages: {
useToStrictEqual: 'Use `toStrictEqual()` instead',
2 changes: 0 additions & 2 deletions src/rules/prefer-to-be.ts
Original file line number Diff line number Diff line change
@@ -93,9 +93,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Suggest using `toBe()` for primitive literals',
recommended: false,
},
messages: {
useToBe: 'Use `toBe` when expecting primitive literals',
2 changes: 0 additions & 2 deletions src/rules/prefer-to-contain.ts
Original file line number Diff line number Diff line change
@@ -39,9 +39,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Suggest using `toContain()`',
recommended: false,
},
messages: {
useToContain: 'Use toContain() instead',
2 changes: 0 additions & 2 deletions src/rules/prefer-to-have-length.ts
Original file line number Diff line number Diff line change
@@ -11,9 +11,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Suggest using `toHaveLength()`',
recommended: false,
},
messages: {
useToHaveLength: 'Use toHaveLength() instead',
2 changes: 0 additions & 2 deletions src/rules/prefer-todo.ts
Original file line number Diff line number Diff line change
@@ -55,9 +55,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Suggest using `test.todo`',
recommended: false,
},
messages: {
emptyTest: 'Prefer todo test case over empty test case',
2 changes: 0 additions & 2 deletions src/rules/require-hook.ts
Original file line number Diff line number Diff line change
@@ -65,9 +65,7 @@ export default createRule<
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Require setup and teardown code to be within a hook',
recommended: false,
},
messages: {
useHook: 'This should be done within a hook',
2 changes: 0 additions & 2 deletions src/rules/require-to-throw-message.ts
Original file line number Diff line number Diff line change
@@ -4,9 +4,7 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Require a message for `toThrow()`',
recommended: false,
},
messages: {
addErrorMessage: 'Add an error message to {{ matcherName }}()',
2 changes: 0 additions & 2 deletions src/rules/require-top-level-describe.ts
Original file line number Diff line number Diff line change
@@ -15,10 +15,8 @@ export default createRule<
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description:
'Require test cases and hooks to be inside a `describe` block',
recommended: false,
},
messages,
type: 'suggestion',
4 changes: 2 additions & 2 deletions src/rules/unbound-method.ts
Original file line number Diff line number Diff line change
@@ -60,12 +60,12 @@ export default createRule<Options, MessageIds>({
type: 'problem',
...baseRule?.meta,
docs: {
category: 'Best Practices',
description:
'Enforce unbound methods are called with their expected scope',
requiresTypeChecking: true,
...baseRule?.meta.docs,
recommended: false,
// mark this as not recommended
recommended: undefined,
},
},
create(context) {
2 changes: 0 additions & 2 deletions src/rules/utils/__tests__/parseJestFnCall.test.ts
Original file line number Diff line number Diff line change
@@ -48,9 +48,7 @@ const rule = createRule({
name: __filename,
meta: {
docs: {
category: 'Possible Errors',
description: 'Fake rule for testing parseJestFnCall',
recommended: false,
},
messages: {
details: '{{ data }}',
35 changes: 8 additions & 27 deletions src/rules/utils/misc.ts
Original file line number Diff line number Diff line change
@@ -234,58 +234,39 @@ export const getFirstMatcherArg = (
export const getFilename = (
context: TSESLint.RuleContext<string, unknown[]>,
) => {
return 'filename' in context
? (context.filename as string)
: context.getFilename();
return context.filename ?? context.getFilename();
};

/* istanbul ignore next */
export const getSourceCode = (
context: TSESLint.RuleContext<string, unknown[]>,
) => {
return 'sourceCode' in context
? (context.sourceCode as TSESLint.SourceCode)
: context.getSourceCode();
return context.sourceCode ?? context.getSourceCode();
};

/* istanbul ignore next */
export const getScope = (
context: TSESLint.RuleContext<string, unknown[]>,
node: TSESTree.Node,
) => {
const sourceCode = getSourceCode(context);

if ('getScope' in sourceCode) {
return sourceCode.getScope(node);
}

return context.getScope();
return getSourceCode(context).getScope?.(node) ?? context.getScope();
};

/* istanbul ignore next */
export const getAncestors = (
context: TSESLint.RuleContext<string, unknown[]>,
node: TSESTree.Node,
) => {
const sourceCode = getSourceCode(context);

if ('getAncestors' in sourceCode) {
return sourceCode.getAncestors(node);
}

return context.getAncestors();
return getSourceCode(context).getAncestors?.(node) ?? context.getAncestors();
};

/* istanbul ignore next */
export const getDeclaredVariables = (
context: TSESLint.RuleContext<string, unknown[]>,
node: TSESTree.Node,
) => {
const sourceCode = getSourceCode(context);

if ('getDeclaredVariables' in sourceCode) {
return sourceCode.getDeclaredVariables(node);
}

return context.getDeclaredVariables(node);
return (
getSourceCode(context).getDeclaredVariables?.(node) ??
context.getDeclaredVariables(node)
);
};
17 changes: 9 additions & 8 deletions src/rules/utils/parseJestFnCall.ts
Original file line number Diff line number Diff line change
@@ -183,20 +183,21 @@ const ValidJestFnCallChains = [
'xtest.failing.each',
];

declare module '@typescript-eslint/utils/dist/ts-eslint' {
export interface SharedConfigurationSettings {
jest?: {
globalAliases?: Record<string, string[]>;
version?: number | string;
};
}
// todo: switch back to using declaration merging once https://github.com/typescript-eslint/typescript-eslint/pull/8485
// is landed
interface SharedConfigurationSettings {
jest?: {
globalAliases?: Record<string, string[]>;
version?: number | string;
};
}

const resolvePossibleAliasedGlobal = (
global: string,
context: TSESLint.RuleContext<string, unknown[]>,
) => {
const globalAliases = context.settings.jest?.globalAliases ?? {};
const globalAliases =
(context.settings as SharedConfigurationSettings).jest?.globalAliases ?? {};

const alias = Object.entries(globalAliases).find(([, aliases]) =>
aliases.includes(global),
2 changes: 0 additions & 2 deletions src/rules/valid-describe-callback.ts
Original file line number Diff line number Diff line change
@@ -23,9 +23,7 @@ export default createRule({
meta: {
type: 'problem',
docs: {
category: 'Possible Errors',
description: 'Enforce valid `describe()` callback',
recommended: 'error',
},
messages: {
nameAndCallback: 'Describe requires name and callback arguments',
2 changes: 0 additions & 2 deletions src/rules/valid-expect-in-promise.ts
Original file line number Diff line number Diff line change
@@ -344,10 +344,8 @@ export default createRule({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description:
'Require promises that have expectations in their chain to be valid',
recommended: 'error',
},
messages: {
expectInFloatingPromise:
2 changes: 0 additions & 2 deletions src/rules/valid-expect.ts
Original file line number Diff line number Diff line change
@@ -115,9 +115,7 @@ export default createRule<[Options], MessageIds>({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Enforce valid `expect()` usage',
recommended: 'error',
},
messages: {
tooManyArgs: 'Expect takes at most {{ amount }} argument{{ s }}',
5 changes: 2 additions & 3 deletions src/rules/valid-title.ts
Original file line number Diff line number Diff line change
@@ -74,7 +74,7 @@ const compileMatcherPatterns = (
type CompiledMatcherAndMessage = [matcher: RegExp, message?: string];
type MatcherAndMessage = [matcher: string, message?: string];

const MatcherAndMessageSchema: JSONSchema.JSONSchema7 = {
const MatcherAndMessageSchema: JSONSchema.JSONSchema4 = {
type: 'array',
items: { type: 'string' },
minItems: 1,
@@ -114,9 +114,7 @@ export default createRule<[Options], MessageIds>({
name: __filename,
meta: {
docs: {
category: 'Best Practices',
description: 'Enforce valid titles',
recommended: 'error',
},
messages: {
titleMustBeString: 'Title must be a string',
@@ -158,6 +156,7 @@ export default createRule<[Options], MessageIds>({
MatcherAndMessageSchema,
{
type: 'object',
// @ts-expect-error https://github.com/eslint/eslint/discussions/17573
propertyNames: { enum: ['describe', 'test', 'it'] },
additionalProperties: {
oneOf: [{ type: 'string' }, MatcherAndMessageSchema],
106 changes: 89 additions & 17 deletions yarn.lock
Original file line number Diff line number Diff line change
@@ -1650,7 +1650,7 @@ __metadata:
languageName: node
linkType: hard

"@eslint-community/eslint-utils@npm:^4.2.0":
"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0":
version: 4.4.0
resolution: "@eslint-community/eslint-utils@npm:4.4.0"
dependencies:
@@ -2844,7 +2844,7 @@ __metadata:
languageName: node
linkType: hard

"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.9":
"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.9":
version: 7.0.15
resolution: "@types/json-schema@npm:7.0.15"
checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98
@@ -2902,10 +2902,10 @@ __metadata:
languageName: node
linkType: hard

"@types/semver@npm:^7.3.12":
version: 7.5.8
resolution: "@types/semver@npm:7.5.8"
checksum: ea6f5276f5b84c55921785a3a27a3cd37afee0111dfe2bcb3e03c31819c197c782598f17f0b150a69d453c9584cd14c4c4d7b9a55d2c5e6cacd4d66fdb3b3663
"@types/semver@npm:^7.3.12, @types/semver@npm:^7.5.0":
version: 7.5.7
resolution: "@types/semver@npm:7.5.7"
checksum: 5af9b13e3d74d86d4b618f6506ccbded801fb35dbc28608cd5a7bfb8bcac0021dd35ef305a72a0c2a8def0cff60acd706bfee16a9ed1c39a893d2a175e778ea7
languageName: node
linkType: hard

@@ -2990,6 +2990,16 @@ __metadata:
languageName: node
linkType: hard

"@typescript-eslint/scope-manager@npm:6.21.0":
version: 6.21.0
resolution: "@typescript-eslint/scope-manager@npm:6.21.0"
dependencies:
"@typescript-eslint/types": 6.21.0
"@typescript-eslint/visitor-keys": 6.21.0
checksum: 71028b757da9694528c4c3294a96cc80bc7d396e383a405eab3bc224cda7341b88e0fc292120b35d3f31f47beac69f7083196c70616434072fbcd3d3e62d3376
languageName: node
linkType: hard

"@typescript-eslint/type-utils@npm:5.62.0":
version: 5.62.0
resolution: "@typescript-eslint/type-utils@npm:5.62.0"
@@ -3014,6 +3024,32 @@ __metadata:
languageName: node
linkType: hard

"@typescript-eslint/types@npm:6.21.0":
version: 6.21.0
resolution: "@typescript-eslint/types@npm:6.21.0"
checksum: 9501b47d7403417af95fc1fb72b2038c5ac46feac0e1598a46bcb43e56a606c387e9dcd8a2a0abe174c91b509f2d2a8078b093786219eb9a01ab2fbf9ee7b684
languageName: node
linkType: hard

"@typescript-eslint/typescript-estree@npm:6.21.0":
version: 6.21.0
resolution: "@typescript-eslint/typescript-estree@npm:6.21.0"
dependencies:
"@typescript-eslint/types": 6.21.0
"@typescript-eslint/visitor-keys": 6.21.0
debug: ^4.3.4
globby: ^11.1.0
is-glob: ^4.0.3
minimatch: 9.0.3
semver: ^7.5.4
ts-api-utils: ^1.0.1
peerDependenciesMeta:
typescript:
optional: true
checksum: dec02dc107c4a541e14fb0c96148f3764b92117c3b635db3a577b5a56fc48df7a556fa853fb82b07c0663b4bf2c484c9f245c28ba3e17e5cb0918ea4cab2ea21
languageName: node
linkType: hard

"@typescript-eslint/typescript-estree@npm:^5.62.0":
version: 5.62.0
resolution: "@typescript-eslint/typescript-estree@npm:5.62.0"
@@ -3050,7 +3086,7 @@ __metadata:
languageName: node
linkType: hard

"@typescript-eslint/utils@npm:5.62.0, @typescript-eslint/utils@npm:^5.10.0, @typescript-eslint/utils@npm:^5.38.1":
"@typescript-eslint/utils@npm:5.62.0, @typescript-eslint/utils@npm:^5.38.1":
version: 5.62.0
resolution: "@typescript-eslint/utils@npm:5.62.0"
dependencies:
@@ -3068,6 +3104,23 @@ __metadata:
languageName: node
linkType: hard

"@typescript-eslint/utils@npm:^6.0.0":
version: 6.21.0
resolution: "@typescript-eslint/utils@npm:6.21.0"
dependencies:
"@eslint-community/eslint-utils": ^4.4.0
"@types/json-schema": ^7.0.12
"@types/semver": ^7.5.0
"@typescript-eslint/scope-manager": 6.21.0
"@typescript-eslint/types": 6.21.0
"@typescript-eslint/typescript-estree": 6.21.0
semver: ^7.5.4
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
checksum: b129b3a4aebec8468259f4589985cb59ea808afbfdb9c54f02fad11e17d185e2bf72bb332f7c36ec3c09b31f18fc41368678b076323e6e019d06f74ee93f7bf2
languageName: node
linkType: hard

"@typescript-eslint/visitor-keys@npm:5.62.0":
version: 5.62.0
resolution: "@typescript-eslint/visitor-keys@npm:5.62.0"
@@ -3078,6 +3131,16 @@ __metadata:
languageName: node
linkType: hard

"@typescript-eslint/visitor-keys@npm:6.21.0":
version: 6.21.0
resolution: "@typescript-eslint/visitor-keys@npm:6.21.0"
dependencies:
"@typescript-eslint/types": 6.21.0
eslint-visitor-keys: ^3.4.1
checksum: 67c7e6003d5af042d8703d11538fca9d76899f0119130b373402819ae43f0bc90d18656aa7add25a24427ccf1a0efd0804157ba83b0d4e145f06107d7d1b7433
languageName: node
linkType: hard

"@ungap/structured-clone@npm:^1.2.0":
version: 1.2.0
resolution: "@ungap/structured-clone@npm:1.2.0"
@@ -5148,7 +5211,7 @@ __metadata:
"@types/node": ^14.18.26
"@typescript-eslint/eslint-plugin": ^5.0.0
"@typescript-eslint/parser": ^5.0.0
"@typescript-eslint/utils": ^5.10.0
"@typescript-eslint/utils": ^6.0.0
babel-jest: ^29.0.0
babel-plugin-replace-ts-export-assignment: ^0.0.2
dedent: ^1.5.0
@@ -8239,6 +8302,15 @@ __metadata:
languageName: node
linkType: hard

"minimatch@npm:9.0.3, minimatch@npm:^9.0.0, minimatch@npm:^9.0.1, minimatch@npm:^9.0.3":
version: 9.0.3
resolution: "minimatch@npm:9.0.3"
dependencies:
brace-expansion: ^2.0.1
checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5
languageName: node
linkType: hard

"minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2":
version: 3.1.2
resolution: "minimatch@npm:3.1.2"
@@ -8248,15 +8320,6 @@ __metadata:
languageName: node
linkType: hard

"minimatch@npm:^9.0.0, minimatch@npm:^9.0.1, minimatch@npm:^9.0.3":
version: 9.0.3
resolution: "minimatch@npm:9.0.3"
dependencies:
brace-expansion: ^2.0.1
checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5
languageName: node
linkType: hard

"minimist-options@npm:4.1.0":
version: 4.1.0
resolution: "minimist-options@npm:4.1.0"
@@ -10822,6 +10885,15 @@ __metadata:
languageName: node
linkType: hard

"ts-api-utils@npm:^1.0.1":
version: 1.2.1
resolution: "ts-api-utils@npm:1.2.1"
peerDependencies:
typescript: ">=4.2.0"
checksum: 17a2a4454d65a6765b9351304cfd516fcda3098f49d72bba90cb7f22b6a09a573b4a1993fd7de7d6b8046c408960c5f21a25e64ccb969d484b32ea3b3e19d6e4
languageName: node
linkType: hard

"ts-node@npm:^10.2.1, ts-node@npm:^10.8.1":
version: 10.9.2
resolution: "ts-node@npm:10.9.2"

0 comments on commit dc6e8cd

Please sign in to comment.