From f976fc8c71fc5e9f55cd5ae09092f15ee277fd2c Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Fri, 22 Mar 2024 08:28:09 +1300 Subject: [PATCH 01/23] feat: remove `no-if` rule (#1528) BREAKING CHANGE: removed `no-if` in favor of `no-conditional-in-test` --- README.md | 118 ++-- docs/rules/no-if.md | 58 -- src/__tests__/rules.test.ts | 2 +- src/rules/__tests__/no-if.test.ts | 866 ------------------------------ src/rules/no-if.ts | 121 ----- 5 files changed, 59 insertions(+), 1106 deletions(-) delete mode 100644 docs/rules/no-if.md delete mode 100644 src/rules/__tests__/no-if.test.ts delete mode 100644 src/rules/no-if.ts diff --git a/README.md b/README.md index 02d08e26b..afd0e7da6 100644 --- a/README.md +++ b/README.md @@ -318,69 +318,67 @@ set to warn in.\ 🎨 Set in the `style` [configuration](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations).\ πŸ”§ Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\ -πŸ’‘ Manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).\ -❌ Deprecated. - -| NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β  | Description | πŸ’Ό | ⚠️ | πŸ”§ | πŸ’‘ | ❌ | -| :--------------------------------------------------------------------------- | :------------------------------------------------------------------------ | :-- | :-- | :-- | :-- | :-- | -| [consistent-test-it](docs/rules/consistent-test-it.md) | Enforce `test` and `it` usage conventions | | | πŸ”§ | | | -| [expect-expect](docs/rules/expect-expect.md) | Enforce assertion to be made in a test body | | βœ… | | | | -| [max-expects](docs/rules/max-expects.md) | Enforces a maximum number assertion calls in a test body | | | | | | -| [max-nested-describe](docs/rules/max-nested-describe.md) | Enforces a maximum depth to nested describe calls | | | | | | -| [no-alias-methods](docs/rules/no-alias-methods.md) | Disallow alias methods | βœ… | 🎨 | πŸ”§ | | | -| [no-commented-out-tests](docs/rules/no-commented-out-tests.md) | Disallow commented out tests | | βœ… | | | | -| [no-conditional-expect](docs/rules/no-conditional-expect.md) | Disallow calling `expect` conditionally | βœ… | | | | | -| [no-conditional-in-test](docs/rules/no-conditional-in-test.md) | Disallow conditional logic in tests | | | | | | -| [no-confusing-set-timeout](docs/rules/no-confusing-set-timeout.md) | Disallow confusing usages of jest.setTimeout | | | | | | -| [no-deprecated-functions](docs/rules/no-deprecated-functions.md) | Disallow use of deprecated functions | βœ… | | πŸ”§ | | | -| [no-disabled-tests](docs/rules/no-disabled-tests.md) | Disallow disabled tests | | βœ… | | | | -| [no-done-callback](docs/rules/no-done-callback.md) | Disallow using a callback in asynchronous tests and hooks | βœ… | | | πŸ’‘ | | -| [no-duplicate-hooks](docs/rules/no-duplicate-hooks.md) | Disallow duplicate setup and teardown hooks | | | | | | -| [no-export](docs/rules/no-export.md) | Disallow using `exports` in files containing tests | βœ… | | | | | -| [no-focused-tests](docs/rules/no-focused-tests.md) | Disallow focused tests | βœ… | | | πŸ’‘ | | -| [no-hooks](docs/rules/no-hooks.md) | Disallow setup and teardown hooks | | | | | | -| [no-identical-title](docs/rules/no-identical-title.md) | Disallow identical titles | βœ… | | | | | -| [no-if](docs/rules/no-if.md) | Disallow conditional logic | | | | | ❌ | -| [no-interpolation-in-snapshots](docs/rules/no-interpolation-in-snapshots.md) | Disallow string interpolation inside snapshots | βœ… | | | | | -| [no-jasmine-globals](docs/rules/no-jasmine-globals.md) | Disallow Jasmine globals | βœ… | | πŸ”§ | | | -| [no-large-snapshots](docs/rules/no-large-snapshots.md) | Disallow large snapshots | | | | | | -| [no-mocks-import](docs/rules/no-mocks-import.md) | Disallow manually importing from `__mocks__` | βœ… | | | | | -| [no-restricted-jest-methods](docs/rules/no-restricted-jest-methods.md) | Disallow specific `jest.` methods | | | | | | -| [no-restricted-matchers](docs/rules/no-restricted-matchers.md) | Disallow specific matchers & modifiers | | | | | | -| [no-standalone-expect](docs/rules/no-standalone-expect.md) | Disallow using `expect` outside of `it` or `test` blocks | βœ… | | | | | -| [no-test-prefixes](docs/rules/no-test-prefixes.md) | Require using `.only` and `.skip` over `f` and `x` | βœ… | | πŸ”§ | | | -| [no-test-return-statement](docs/rules/no-test-return-statement.md) | Disallow explicitly returning from tests | | | | | | -| [no-untyped-mock-factory](docs/rules/no-untyped-mock-factory.md) | Disallow using `jest.mock()` factories without an explicit type parameter | | | πŸ”§ | | | -| [prefer-called-with](docs/rules/prefer-called-with.md) | Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()` | | | | | | -| [prefer-comparison-matcher](docs/rules/prefer-comparison-matcher.md) | Suggest using the built-in comparison matchers | | | πŸ”§ | | | -| [prefer-each](docs/rules/prefer-each.md) | Prefer using `.each` rather than manual loops | | | | | | -| [prefer-equality-matcher](docs/rules/prefer-equality-matcher.md) | Suggest using the built-in equality matchers | | | | πŸ’‘ | | -| [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using `expect.assertions()` OR `expect.hasAssertions()` | | | | πŸ’‘ | | -| [prefer-expect-resolves](docs/rules/prefer-expect-resolves.md) | Prefer `await expect(...).resolves` over `expect(await ...)` syntax | | | πŸ”§ | | | -| [prefer-hooks-in-order](docs/rules/prefer-hooks-in-order.md) | Prefer having hooks in a consistent order | | | | | | -| [prefer-hooks-on-top](docs/rules/prefer-hooks-on-top.md) | Suggest having hooks before any test cases | | | | | | -| [prefer-lowercase-title](docs/rules/prefer-lowercase-title.md) | Enforce lowercase test names | | | πŸ”§ | | | -| [prefer-mock-promise-shorthand](docs/rules/prefer-mock-promise-shorthand.md) | Prefer mock resolved/rejected shorthands for promises | | | πŸ”§ | | | -| [prefer-snapshot-hint](docs/rules/prefer-snapshot-hint.md) | Prefer including a hint with external snapshots | | | | | | -| [prefer-spy-on](docs/rules/prefer-spy-on.md) | Suggest using `jest.spyOn()` | | | πŸ”§ | | | -| [prefer-strict-equal](docs/rules/prefer-strict-equal.md) | Suggest using `toStrictEqual()` | | | | πŸ’‘ | | -| [prefer-to-be](docs/rules/prefer-to-be.md) | Suggest using `toBe()` for primitive literals | 🎨 | | πŸ”§ | | | -| [prefer-to-contain](docs/rules/prefer-to-contain.md) | Suggest using `toContain()` | 🎨 | | πŸ”§ | | | -| [prefer-to-have-length](docs/rules/prefer-to-have-length.md) | Suggest using `toHaveLength()` | 🎨 | | πŸ”§ | | | -| [prefer-todo](docs/rules/prefer-todo.md) | Suggest using `test.todo` | | | πŸ”§ | | | -| [require-hook](docs/rules/require-hook.md) | Require setup and teardown code to be within a hook | | | | | | -| [require-to-throw-message](docs/rules/require-to-throw-message.md) | Require a message for `toThrow()` | | | | | | -| [require-top-level-describe](docs/rules/require-top-level-describe.md) | Require test cases and hooks to be inside a `describe` block | | | | | | -| [valid-describe-callback](docs/rules/valid-describe-callback.md) | Enforce valid `describe()` callback | βœ… | | | | | -| [valid-expect](docs/rules/valid-expect.md) | Enforce valid `expect()` usage | βœ… | | | | | -| [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | Require promises that have expectations in their chain to be valid | βœ… | | | | | -| [valid-title](docs/rules/valid-title.md) | Enforce valid titles | βœ… | | πŸ”§ | | | +πŸ’‘ Manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions). + +| NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β  | Description | πŸ’Ό | ⚠️ | πŸ”§ | πŸ’‘ | +| :--------------------------------------------------------------------------- | :------------------------------------------------------------------------ | :-- | :-- | :-- | :-- | +| [consistent-test-it](docs/rules/consistent-test-it.md) | Enforce `test` and `it` usage conventions | | | πŸ”§ | | +| [expect-expect](docs/rules/expect-expect.md) | Enforce assertion to be made in a test body | | βœ… | | | +| [max-expects](docs/rules/max-expects.md) | Enforces a maximum number assertion calls in a test body | | | | | +| [max-nested-describe](docs/rules/max-nested-describe.md) | Enforces a maximum depth to nested describe calls | | | | | +| [no-alias-methods](docs/rules/no-alias-methods.md) | Disallow alias methods | βœ… | 🎨 | πŸ”§ | | +| [no-commented-out-tests](docs/rules/no-commented-out-tests.md) | Disallow commented out tests | | βœ… | | | +| [no-conditional-expect](docs/rules/no-conditional-expect.md) | Disallow calling `expect` conditionally | βœ… | | | | +| [no-conditional-in-test](docs/rules/no-conditional-in-test.md) | Disallow conditional logic in tests | | | | | +| [no-confusing-set-timeout](docs/rules/no-confusing-set-timeout.md) | Disallow confusing usages of jest.setTimeout | | | | | +| [no-deprecated-functions](docs/rules/no-deprecated-functions.md) | Disallow use of deprecated functions | βœ… | | πŸ”§ | | +| [no-disabled-tests](docs/rules/no-disabled-tests.md) | Disallow disabled tests | | βœ… | | | +| [no-done-callback](docs/rules/no-done-callback.md) | Disallow using a callback in asynchronous tests and hooks | βœ… | | | πŸ’‘ | +| [no-duplicate-hooks](docs/rules/no-duplicate-hooks.md) | Disallow duplicate setup and teardown hooks | | | | | +| [no-export](docs/rules/no-export.md) | Disallow using `exports` in files containing tests | βœ… | | | | +| [no-focused-tests](docs/rules/no-focused-tests.md) | Disallow focused tests | βœ… | | | πŸ’‘ | +| [no-hooks](docs/rules/no-hooks.md) | Disallow setup and teardown hooks | | | | | +| [no-identical-title](docs/rules/no-identical-title.md) | Disallow identical titles | βœ… | | | | +| [no-interpolation-in-snapshots](docs/rules/no-interpolation-in-snapshots.md) | Disallow string interpolation inside snapshots | βœ… | | | | +| [no-jasmine-globals](docs/rules/no-jasmine-globals.md) | Disallow Jasmine globals | βœ… | | πŸ”§ | | +| [no-large-snapshots](docs/rules/no-large-snapshots.md) | Disallow large snapshots | | | | | +| [no-mocks-import](docs/rules/no-mocks-import.md) | Disallow manually importing from `__mocks__` | βœ… | | | | +| [no-restricted-jest-methods](docs/rules/no-restricted-jest-methods.md) | Disallow specific `jest.` methods | | | | | +| [no-restricted-matchers](docs/rules/no-restricted-matchers.md) | Disallow specific matchers & modifiers | | | | | +| [no-standalone-expect](docs/rules/no-standalone-expect.md) | Disallow using `expect` outside of `it` or `test` blocks | βœ… | | | | +| [no-test-prefixes](docs/rules/no-test-prefixes.md) | Require using `.only` and `.skip` over `f` and `x` | βœ… | | πŸ”§ | | +| [no-test-return-statement](docs/rules/no-test-return-statement.md) | Disallow explicitly returning from tests | | | | | +| [no-untyped-mock-factory](docs/rules/no-untyped-mock-factory.md) | Disallow using `jest.mock()` factories without an explicit type parameter | | | πŸ”§ | | +| [prefer-called-with](docs/rules/prefer-called-with.md) | Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()` | | | | | +| [prefer-comparison-matcher](docs/rules/prefer-comparison-matcher.md) | Suggest using the built-in comparison matchers | | | πŸ”§ | | +| [prefer-each](docs/rules/prefer-each.md) | Prefer using `.each` rather than manual loops | | | | | +| [prefer-equality-matcher](docs/rules/prefer-equality-matcher.md) | Suggest using the built-in equality matchers | | | | πŸ’‘ | +| [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using `expect.assertions()` OR `expect.hasAssertions()` | | | | πŸ’‘ | +| [prefer-expect-resolves](docs/rules/prefer-expect-resolves.md) | Prefer `await expect(...).resolves` over `expect(await ...)` syntax | | | πŸ”§ | | +| [prefer-hooks-in-order](docs/rules/prefer-hooks-in-order.md) | Prefer having hooks in a consistent order | | | | | +| [prefer-hooks-on-top](docs/rules/prefer-hooks-on-top.md) | Suggest having hooks before any test cases | | | | | +| [prefer-lowercase-title](docs/rules/prefer-lowercase-title.md) | Enforce lowercase test names | | | πŸ”§ | | +| [prefer-mock-promise-shorthand](docs/rules/prefer-mock-promise-shorthand.md) | Prefer mock resolved/rejected shorthands for promises | | | πŸ”§ | | +| [prefer-snapshot-hint](docs/rules/prefer-snapshot-hint.md) | Prefer including a hint with external snapshots | | | | | +| [prefer-spy-on](docs/rules/prefer-spy-on.md) | Suggest using `jest.spyOn()` | | | πŸ”§ | | +| [prefer-strict-equal](docs/rules/prefer-strict-equal.md) | Suggest using `toStrictEqual()` | | | | πŸ’‘ | +| [prefer-to-be](docs/rules/prefer-to-be.md) | Suggest using `toBe()` for primitive literals | 🎨 | | πŸ”§ | | +| [prefer-to-contain](docs/rules/prefer-to-contain.md) | Suggest using `toContain()` | 🎨 | | πŸ”§ | | +| [prefer-to-have-length](docs/rules/prefer-to-have-length.md) | Suggest using `toHaveLength()` | 🎨 | | πŸ”§ | | +| [prefer-todo](docs/rules/prefer-todo.md) | Suggest using `test.todo` | | | πŸ”§ | | +| [require-hook](docs/rules/require-hook.md) | Require setup and teardown code to be within a hook | | | | | +| [require-to-throw-message](docs/rules/require-to-throw-message.md) | Require a message for `toThrow()` | | | | | +| [require-top-level-describe](docs/rules/require-top-level-describe.md) | Require test cases and hooks to be inside a `describe` block | | | | | +| [valid-describe-callback](docs/rules/valid-describe-callback.md) | Enforce valid `describe()` callback | βœ… | | | | +| [valid-expect](docs/rules/valid-expect.md) | Enforce valid `expect()` usage | βœ… | | | | +| [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | Require promises that have expectations in their chain to be valid | βœ… | | | | +| [valid-title](docs/rules/valid-title.md) | Enforce valid titles | βœ… | | πŸ”§ | | ### Requires Type Checking -| NameΒ Β Β Β Β Β Β Β Β Β  | Description | πŸ’Ό | ⚠️ | πŸ”§ | πŸ’‘ | ❌ | -| :--------------------------------------------- | :----------------------------------------------------------- | :-- | :-- | :-- | :-- | :-- | -| [unbound-method](docs/rules/unbound-method.md) | Enforce unbound methods are called with their expected scope | | | | | | +| NameΒ Β Β Β Β Β Β Β Β Β  | Description | πŸ’Ό | ⚠️ | πŸ”§ | πŸ’‘ | +| :--------------------------------------------- | :----------------------------------------------------------- | :-- | :-- | :-- | :-- | +| [unbound-method](docs/rules/unbound-method.md) | Enforce unbound methods are called with their expected scope | | | | | diff --git a/docs/rules/no-if.md b/docs/rules/no-if.md deleted file mode 100644 index c5add5524..000000000 --- a/docs/rules/no-if.md +++ /dev/null @@ -1,58 +0,0 @@ -# Disallow conditional logic (`no-if`) - -❌ This rule is deprecated. It was replaced by -[`jest/no-conditional-in-test`](no-conditional-in-test.md). - - - -Conditional logic in tests is usually an indication that a test is attempting to -cover too much, and not testing the logic it intends to. Each branch of code -executing within an if statement will usually be better served by a test devoted -to it. - -Conditionals are often used to satisfy the typescript type checker. In these -cases, using the non-null assertion operator (!) would be best. - -## Rule details - -This rule prevents the use of if/ else statements and conditional (ternary) -operations in tests. - -The following patterns are considered warnings: - -```js -it('foo', () => { - if ('bar') { - // an if statement here is invalid - // you are probably testing too much - } -}); - -it('foo', () => { - const bar = foo ? 'bar' : null; -}); -``` - -These patterns would not be considered warnings: - -```js -it('foo', () => { - // only test the 'foo' case -}); - -it('bar', () => { - // test the 'bar' case separately -}); - -it('foo', () => { - function foo(bar) { - // nested functions are valid - return foo ? bar : null; - } -}); -``` - -## When Not To Use It - -If you do not wish to prevent the use of if statements in tests, you can safely -disable this rule. diff --git a/src/__tests__/rules.test.ts b/src/__tests__/rules.test.ts index 59a6e3beb..8236727bd 100644 --- a/src/__tests__/rules.test.ts +++ b/src/__tests__/rules.test.ts @@ -2,7 +2,7 @@ import { existsSync } from 'fs'; import { resolve } from 'path'; import plugin from '../'; -const numberOfRules = 53; +const numberOfRules = 52; const ruleNames = Object.keys(plugin.rules); const deprecatedRules = Object.entries(plugin.rules) .filter(([, rule]) => rule.meta.deprecated) diff --git a/src/rules/__tests__/no-if.test.ts b/src/rules/__tests__/no-if.test.ts deleted file mode 100644 index 786ace8e5..000000000 --- a/src/rules/__tests__/no-if.test.ts +++ /dev/null @@ -1,866 +0,0 @@ -import { TSESLint } from '@typescript-eslint/utils'; -import dedent from 'dedent'; -import rule from '../no-if'; -import { espreeParser } from './test-utils'; - -const ruleTester = new TSESLint.RuleTester({ - parser: espreeParser, - parserOptions: { - ecmaVersion: 2015, - }, -}); - -ruleTester.run('conditional expressions', rule, { - valid: [ - 'const x = y ? 1 : 0', - dedent` - it('foo', () => { - const foo = function (bar) { - return foo ? bar : null; - }; - }); - `, - dedent` - it('foo', function () { - const foo = function (bar) { - return foo ? bar : null; - }; - }); - `, - dedent` - it.each()('foo', function () { - const foo = function (bar) { - return foo ? bar : null; - }; - }); - `, - ], - invalid: [ - { - code: dedent` - it('foo', () => { - expect(bar ? foo : baz).toBe(boo); - }) - `, - errors: [ - { - data: { condition: 'conditional' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it('foo', () => { - const foo = bar ? foo : baz; - }) - `, - errors: [ - { - data: { condition: 'conditional' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it('foo', () => { - const foo = bar ? foo : baz; - }) - const foo = bar ? foo : baz; - `, - errors: [ - { - data: { condition: 'conditional' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it('foo', () => { - const foo = bar ? foo : baz; - const anotherFoo = anotherBar ? anotherFoo : anotherBaz; - }) - `, - errors: [ - { - data: { condition: 'conditional' }, - messageId: 'conditionalInTest', - }, - { - data: { condition: 'conditional' }, - messageId: 'conditionalInTest', - }, - ], - }, - ], -}); - -ruleTester.run('switch statements', rule, { - valid: [ - dedent` - switch (true) { - case true: {} - } - `, - `it('foo', () => {})`, - dedent` - it('foo', () => {}); - function myTest() { - switch ('bar') { - } - } - `, - dedent` - foo('bar', () => { - switch(baz) {} - }) - `, - dedent` - describe('foo', () => { - switch('bar') {} - }) - `, - dedent` - describe.skip('foo', () => { - switch('bar') {} - }) - `, - dedent` - describe.skip.each()('foo', () => { - switch('bar') {} - }) - `, - dedent` - xdescribe('foo', () => { - switch('bar') {} - }) - `, - dedent` - fdescribe('foo', () => { - switch('bar') {} - }) - `, - dedent` - describe('foo', () => { - switch('bar') {} - }) - switch('bar') {} - `, - dedent` - describe('foo', () => { - afterEach(() => { - switch('bar') {} - }); - }); - `, - dedent` - it('valid', () => { - const values = something.map(thing => { - switch (thing.isFoo) { - case true: - return thing.foo; - default: - return thing.bar; - } - }); - - expect(values).toStrictEqual(['foo']); - }); - `, - dedent` - describe('valid', () => { - it('still valid', () => { - const values = something.map(thing => { - switch (thing.isFoo) { - case true: - return thing.foo; - default: - return thing.bar; - } - }); - - expect(values).toStrictEqual(['foo']); - }); - }); - `, - ], - invalid: [ - { - code: dedent` - it('foo', () => { - switch (true) { - case true: {} - } - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it('foo', () => { - switch('bar') {} - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it.skip('foo', () => { - switch('bar') {} - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it.only('foo', () => { - switch('bar') {} - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - xit('foo', () => { - switch('bar') {} - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - fit('foo', () => { - switch('bar') {} - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - fit.concurrent('foo', () => { - switch('bar') {} - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - test('foo', () => { - switch('bar') {} - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - test.skip('foo', () => { - switch('bar') {} - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - test.only('foo', () => { - switch('bar') {} - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - xtest('foo', () => { - switch('bar') {} - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - xtest('foo', function () { - switch('bar') {} - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - describe('foo', () => { - it('bar', () => { - - switch('bar') {} - }) - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: "it('foo', myTest); function myTest() { switch ('bar') {} }", - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - describe('foo', () => { - it('bar', () => { - switch('bar') {} - }) - it('baz', () => { - switch('qux') {} - switch('quux') {} - }) - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it('foo', () => { - callExpression() - switch ('bar') {} - }) - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - describe('valid', () => { - describe('still valid', () => { - it('really still valid', () => { - const values = something.map((thing) => { - switch (thing.isFoo) { - case true: - return thing.foo; - default: - return thing.bar; - } - }); - - switch('invalid') { - case true: - expect(values).toStrictEqual(['foo']); - } - }); - }); - }); - `, - errors: [ - { - data: { condition: 'switch' }, - messageId: 'conditionalInTest', - }, - ], - }, - ], -}); - -ruleTester.run('if statements', rule, { - valid: [ - 'if(foo) {}', - "it('foo', () => {})", - 'it("foo", function () {})', - "it('foo', () => {}); function myTest() { if('bar') {} }", - dedent` - foo('bar', () => { - if(baz) {} - }) - `, - dedent` - describe('foo', () => { - if('bar') {} - }) - `, - dedent` - describe.skip('foo', () => { - if('bar') {} - }) - `, - dedent` - xdescribe('foo', () => { - if('bar') {} - }) - `, - dedent` - fdescribe('foo', () => { - if('bar') {} - }) - `, - dedent` - describe('foo', () => { - if('bar') {} - }) - if('baz') {} - `, - dedent` - describe('foo', () => { - afterEach(() => { - if('bar') {} - }); - }) - `, - dedent` - describe.each\`\`('foo', () => { - afterEach(() => { - if('bar') {} - }); - }) - `, - dedent` - describe('foo', () => { - beforeEach(() => { - if('bar') {} - }); - }) - `, - 'const foo = bar ? foo : baz;', - dedent` - it('valid', () => { - const values = something.map((thing) => { - if (thing.isFoo) { - return thing.foo - } else { - return thing.bar; - } - }); - - expect(values).toStrictEqual(['foo']); - }); - `, - dedent` - describe('valid', () => { - it('still valid', () => { - const values = something.map((thing) => { - if (thing.isFoo) { - return thing.foo - } else { - return thing.bar; - } - }); - - expect(values).toStrictEqual(['foo']); - }); - }); - `, - dedent` - describe('valid', () => { - describe('still valid', () => { - it('really still valid', () => { - const values = something.map((thing) => { - if (thing.isFoo) { - return thing.foo - } else { - return thing.bar; - } - }); - - expect(values).toStrictEqual(['foo']); - }); - }); - }); - `, - dedent` - it('foo', () => { - const foo = function(bar) { - if (bar) { - return 1; - } else { - return 2; - } - }; - }); - `, - dedent` - it('foo', () => { - function foo(bar) { - if (bar) { - return 1; - } else { - return 2; - } - }; - }); - `, - ], - invalid: [ - { - code: dedent` - it('foo', () => { - if('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it.skip('foo', () => { - if('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it.skip('foo', function () { - if('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it.only('foo', () => { - if('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - xit('foo', () => { - if('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - fit('foo', () => { - if('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - fit.concurrent('foo', () => { - if('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - test('foo', () => { - if('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - test.skip('foo', () => { - if('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - test.only('foo', () => { - if('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - xtest('foo', () => { - if('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - describe('foo', () => { - it('bar', () => { - if('bar') {} - }) - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: "it('foo', myTest); function myTest() { if ('bar') {} }", - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - describe('foo', () => { - it('bar', () => { - if('bar') {} - }) - it('baz', () => { - if('qux') {} - if('quux') {} - }) - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it('foo', () => { - callExpression() - if ('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it.each\`\`('foo', () => { - callExpression() - if ('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it.each()('foo', () => { - callExpression() - if ('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it.only.each\`\`('foo', () => { - callExpression() - if ('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - it.only.each()('foo', () => { - callExpression() - if ('bar') {} - }) - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - { - code: dedent` - describe('valid', () => { - describe('still valid', () => { - it('really still valid', () => { - const values = something.map((thing) => { - if (thing.isFoo) { - return thing.foo - } else { - return thing.bar; - } - }); - - if('invalid') { - expect(values).toStrictEqual(['foo']); - } - }); - }); - }); - `, - errors: [ - { - data: { condition: 'if' }, - messageId: 'conditionalInTest', - }, - ], - }, - ], -}); diff --git a/src/rules/no-if.ts b/src/rules/no-if.ts deleted file mode 100644 index 880c44b1c..000000000 --- a/src/rules/no-if.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { AST_NODE_TYPES, type TSESTree } from '@typescript-eslint/utils'; -import { - TestCaseName, - createRule, - getAccessorValue, - getDeclaredVariables, - getNodeName, - getTestCallExpressionsFromDeclaredVariables, - parseJestFnCall, -} from './utils'; - -const testCaseNames = new Set([ - ...Object.keys(TestCaseName), - 'it.only', - 'it.only', - 'it.skip', - 'it.skip', - 'test.only', - 'test.only', - 'test.skip', - 'test.skip', - 'fit.concurrent', -]); - -const isTestFunctionExpression = ( - node: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression, -) => - node.parent !== undefined && - node.parent.type === AST_NODE_TYPES.CallExpression && - testCaseNames.has(getNodeName(node.parent.callee)); - -const conditionName = { - [AST_NODE_TYPES.ConditionalExpression]: 'conditional', - [AST_NODE_TYPES.SwitchStatement]: 'switch', - [AST_NODE_TYPES.IfStatement]: 'if', -}; - -export default createRule({ - name: __filename, - meta: { - docs: { - description: 'Disallow conditional logic', - category: 'Best Practices', - recommended: false, - }, - messages: { - conditionalInTest: 'Test should not contain {{ condition }} statements', - }, - deprecated: true, - replacedBy: ['no-conditional-in-test'], - schema: [], - type: 'suggestion', - }, - defaultOptions: [], - create(context) { - const stack: boolean[] = []; - - function validate( - node: - | TSESTree.ConditionalExpression - | TSESTree.SwitchStatement - | TSESTree.IfStatement, - ) { - const lastElementInStack = stack[stack.length - 1]; - - if (stack.length === 0 || !lastElementInStack) { - return; - } - - context.report({ - data: { condition: conditionName[node.type] }, - messageId: 'conditionalInTest', - node, - }); - } - - return { - CallExpression(node) { - const jestFnCall = parseJestFnCall(node, context); - - if (jestFnCall?.type === 'test') { - stack.push(true); - - if (jestFnCall.members.some(s => getAccessorValue(s) === 'each')) { - stack.push(true); - } - } - }, - FunctionExpression(node) { - stack.push(isTestFunctionExpression(node)); - }, - FunctionDeclaration(node) { - const declaredVariables = getDeclaredVariables(context, node); - const testCallExpressions = getTestCallExpressionsFromDeclaredVariables( - declaredVariables, - context, - ); - - stack.push(testCallExpressions.length > 0); - }, - ArrowFunctionExpression(node) { - stack.push(isTestFunctionExpression(node)); - }, - IfStatement: validate, - SwitchStatement: validate, - ConditionalExpression: validate, - 'CallExpression:exit'() { - stack.pop(); - }, - 'FunctionExpression:exit'() { - stack.pop(); - }, - 'FunctionDeclaration:exit'() { - stack.pop(); - }, - 'ArrowFunctionExpression:exit'() { - stack.pop(); - }, - }; - }, -}); From 732c71bc1a3a3cdaa5baab8495b8fb17f69d93b5 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 21 Mar 2024 19:31:17 +0000 Subject: [PATCH 02/23] chore(release): 28.0.0-next.1 [skip ci] # [28.0.0-next.1](https://github.com/jest-community/eslint-plugin-jest/compare/v27.9.0...v28.0.0-next.1) (2024-03-21) ### Features * remove `no-if` rule ([#1528](https://github.com/jest-community/eslint-plugin-jest/issues/1528)) ([f976fc8](https://github.com/jest-community/eslint-plugin-jest/commit/f976fc8c71fc5e9f55cd5ae09092f15ee277fd2c)) ### BREAKING CHANGES * removed `no-if` in favor of `no-conditional-in-test` --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af6657b36..d7719ac7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# [28.0.0-next.1](https://github.com/jest-community/eslint-plugin-jest/compare/v27.9.0...v28.0.0-next.1) (2024-03-21) + + +### Features + +* remove `no-if` rule ([#1528](https://github.com/jest-community/eslint-plugin-jest/issues/1528)) ([f976fc8](https://github.com/jest-community/eslint-plugin-jest/commit/f976fc8c71fc5e9f55cd5ae09092f15ee277fd2c)) + + +### BREAKING CHANGES + +* removed `no-if` in favor of `no-conditional-in-test` + # [27.9.0](https://github.com/jest-community/eslint-plugin-jest/compare/v27.8.0...v27.9.0) (2024-02-16) diff --git a/package.json b/package.json index 37fd5a354..b06126559 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-jest", - "version": "27.9.0", + "version": "28.0.0-next.1", "description": "ESLint rules for Jest", "keywords": [ "eslint", From df5e58081d1bd15fbed8bd22f6c03d5f350d73b6 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Fri, 22 Mar 2024 08:37:22 +1300 Subject: [PATCH 03/23] feat: drop support for Node v14 (#1527) BREAKING CHANGE: dropped support for Node v14 --- .github/workflows/nodejs.yml | 8 +------- package.json | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 8432c615e..7b566026f 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -71,16 +71,10 @@ jobs: strategy: fail-fast: false matrix: - node-version: [14.x, 16.x, 18.x, 19.x, 20.x, 21.x] + node-version: [16.x, 18.x, 19.x, 20.x, 21.x] eslint-version: [7, 8] ts-eslint-plugin-version: [5, 6, 7] exclude: - # ts-eslint/plugin@6 doesn't support node@14 - - node-version: 14.x - ts-eslint-plugin-version: 6 - # ts-eslint/plugin@7 doesn't support node@14 - - node-version: 14.x - ts-eslint-plugin-version: 7 # ts-eslint/plugin@7 doesn't support node@16 - node-version: 16.x ts-eslint-plugin-version: 7 diff --git a/package.json b/package.json index b06126559..cdd281f34 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ }, "packageManager": "yarn@3.8.1", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.10.0 || >=18.0.0" }, "publishConfig": { "provenance": true From c439b485ccfaa713c93867a9d5d7f18532153822 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 21 Mar 2024 19:40:40 +0000 Subject: [PATCH 04/23] chore(release): 28.0.0-next.2 [skip ci] # [28.0.0-next.2](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.1...v28.0.0-next.2) (2024-03-21) ### Features * drop support for Node v14 ([#1527](https://github.com/jest-community/eslint-plugin-jest/issues/1527)) ([df5e580](https://github.com/jest-community/eslint-plugin-jest/commit/df5e58081d1bd15fbed8bd22f6c03d5f350d73b6)) ### BREAKING CHANGES * dropped support for Node v14 --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7719ac7b..334645181 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# [28.0.0-next.2](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.1...v28.0.0-next.2) (2024-03-21) + + +### Features + +* drop support for Node v14 ([#1527](https://github.com/jest-community/eslint-plugin-jest/issues/1527)) ([df5e580](https://github.com/jest-community/eslint-plugin-jest/commit/df5e58081d1bd15fbed8bd22f6c03d5f350d73b6)) + + +### BREAKING CHANGES + +* dropped support for Node v14 + # [28.0.0-next.1](https://github.com/jest-community/eslint-plugin-jest/compare/v27.9.0...v28.0.0-next.1) (2024-03-21) diff --git a/package.json b/package.json index cdd281f34..b30de1225 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-jest", - "version": "28.0.0-next.1", + "version": "28.0.0-next.2", "description": "ESLint rules for Jest", "keywords": [ "eslint", From 8408db9dc90d8b4f2a62dd736dfb56889b3384c9 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Fri, 22 Mar 2024 13:56:30 +1300 Subject: [PATCH 05/23] chore: update TSConfig to use Node v16 defaults (#1529) --- package.json | 2 +- tsconfig.json | 6 ++---- yarn.lock | 16 ++++++++-------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index b30de1225..df85983fd 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "@schemastore/package": "^0.0.10", "@semantic-release/changelog": "^6.0.0", "@semantic-release/git": "^10.0.0", - "@tsconfig/node14": "^14.1.0", + "@tsconfig/node16": "^16.0.0", "@types/eslint": "^8.4.6", "@types/jest": "^29.0.0", "@types/node": "^14.18.26", diff --git a/tsconfig.json b/tsconfig.json index 49d5cfe4e..6993dce26 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "@tsconfig/node14/tsconfig.json", + "extends": "@tsconfig/node16/tsconfig.json", "compilerOptions": { "noEmit": true, "stripInternal": true, @@ -12,11 +12,9 @@ "noFallthroughCasesInSwitch": true, "strict": true, - "esModuleInterop": true, "resolveJsonModule": true, "isolatedModules": true, - "skipLibCheck": false, - "forceConsistentCasingInFileNames": true + "skipLibCheck": false }, "files": ["eslint-remote-tester.config.ts"], "include": ["src/**/*", "tools/**/*"], diff --git a/yarn.lock b/yarn.lock index 4fcc6f34b..5613c1364 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2711,13 +2711,6 @@ __metadata: languageName: node linkType: hard -"@tsconfig/node14@npm:^14.1.0": - version: 14.1.0 - resolution: "@tsconfig/node14@npm:14.1.0" - checksum: 8342dc30edbfaed11d1659b1a9819779bb69df210974a9e8a337b0624b1d9f5026f37e2dcc1d555adb3e4246a0ec35896b3ae5fe3fc69f3382d3bc11069cecc1 - languageName: node - linkType: hard - "@tsconfig/node16@npm:^1.0.2": version: 1.0.4 resolution: "@tsconfig/node16@npm:1.0.4" @@ -2725,6 +2718,13 @@ __metadata: languageName: node linkType: hard +"@tsconfig/node16@npm:^16.0.0": + version: 16.1.1 + resolution: "@tsconfig/node16@npm:16.1.1" + checksum: 26d83db06866083b543e73eda33585464362fd0835229b9a5b1185f0353b9b5db9ca4f66a4be53d4ec5d4c219be42b0a7582f8bcc7268f2f77b1c643375e490f + languageName: node + linkType: hard + "@tufjs/canonical-json@npm:2.0.0": version: 2.0.0 resolution: "@tufjs/canonical-json@npm:2.0.0" @@ -5142,7 +5142,7 @@ __metadata: "@schemastore/package": ^0.0.10 "@semantic-release/changelog": ^6.0.0 "@semantic-release/git": ^10.0.0 - "@tsconfig/node14": ^14.1.0 + "@tsconfig/node16": ^16.0.0 "@types/eslint": ^8.4.6 "@types/jest": ^29.0.0 "@types/node": ^14.18.26 From dc6e8cd249817de585b50e473c2146e1542dd146 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Sat, 23 Mar 2024 08:32:09 +1300 Subject: [PATCH 06/23] feat: upgrade `@typescript-eslint/utils` to v6 (#1508) * 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 --- package.json | 2 +- src/index.ts | 35 +----- src/rules/__tests__/unbound-method.test.ts | 104 +++++++++++++++-- src/rules/consistent-test-it.ts | 4 +- src/rules/expect-expect.ts | 2 - src/rules/max-expects.ts | 2 - src/rules/max-nested-describe.ts | 2 - src/rules/no-alias-methods.ts | 2 - src/rules/no-commented-out-tests.ts | 2 - src/rules/no-conditional-expect.ts | 2 - src/rules/no-conditional-in-test.ts | 2 - src/rules/no-confusing-set-timeout.ts | 2 - src/rules/no-deprecated-functions.ts | 2 - src/rules/no-disabled-tests.ts | 2 - src/rules/no-done-callback.ts | 2 - src/rules/no-duplicate-hooks.ts | 2 - src/rules/no-export.ts | 2 - src/rules/no-focused-tests.ts | 2 - src/rules/no-hooks.ts | 3 +- src/rules/no-identical-title.ts | 2 - src/rules/no-interpolation-in-snapshots.ts | 2 - src/rules/no-jasmine-globals.ts | 2 - src/rules/no-large-snapshots.ts | 2 - src/rules/no-mocks-import.ts | 2 - src/rules/no-restricted-jest-methods.ts | 2 - src/rules/no-restricted-matchers.ts | 2 - src/rules/no-standalone-expect.ts | 3 +- src/rules/no-test-prefixes.ts | 2 - src/rules/no-test-return-statement.ts | 2 - src/rules/no-untyped-mock-factory.ts | 11 +- src/rules/prefer-called-with.ts | 2 - src/rules/prefer-comparison-matcher.ts | 2 - src/rules/prefer-each.ts | 2 - src/rules/prefer-equality-matcher.ts | 2 - src/rules/prefer-expect-assertions.ts | 2 - src/rules/prefer-expect-resolves.ts | 2 - src/rules/prefer-hooks-in-order.ts | 2 - src/rules/prefer-hooks-on-top.ts | 2 - src/rules/prefer-lowercase-title.ts | 7 +- src/rules/prefer-mock-promise-shorthand.ts | 2 - src/rules/prefer-snapshot-hint.ts | 2 - src/rules/prefer-spy-on.ts | 2 - src/rules/prefer-strict-equal.ts | 2 - src/rules/prefer-to-be.ts | 2 - src/rules/prefer-to-contain.ts | 2 - src/rules/prefer-to-have-length.ts | 2 - src/rules/prefer-todo.ts | 2 - src/rules/require-hook.ts | 2 - src/rules/require-to-throw-message.ts | 2 - src/rules/require-top-level-describe.ts | 2 - src/rules/unbound-method.ts | 4 +- .../utils/__tests__/parseJestFnCall.test.ts | 2 - src/rules/utils/misc.ts | 35 ++---- src/rules/utils/parseJestFnCall.ts | 17 +-- src/rules/valid-describe-callback.ts | 2 - src/rules/valid-expect-in-promise.ts | 2 - src/rules/valid-expect.ts | 2 - src/rules/valid-title.ts | 5 +- yarn.lock | 106 +++++++++++++++--- 59 files changed, 219 insertions(+), 209 deletions(-) diff --git a/package.json b/package.json index df85983fd..218cb5ef8 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ ] }, "dependencies": { - "@typescript-eslint/utils": "^5.10.0" + "@typescript-eslint/utils": "^6.0.0" }, "devDependencies": { "@babel/cli": "^7.4.4", diff --git a/src/index.ts b/src/index.ts index 2396738e6..569ae64b8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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 & { meta: Required, '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 } => diff --git a/src/rules/__tests__/unbound-method.test.ts b/src/rules/__tests__/unbound-method.test.ts index c3484049d..1a926f1ba 100644 --- a/src/rules/__tests__/unbound-method.test.ts +++ b/src/rules/__tests__/unbound-method.test.ts @@ -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,8 +10,8 @@ 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, @@ -18,6 +19,26 @@ const ruleTester = new ESLintUtils.RuleTester({ }, }); +const fixtureFilename = path.join(rootPath, 'file.ts'); + +const withFixtureFilename = < + T extends Array< + | (TSESLint.ValidTestCase | string) + | TSESLint.InvalidTestCase + >, +>( + cases: T, +): T extends Array> + ? Array> + : Array> => { + // @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,7 +198,9 @@ 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: [], }, ); @@ -185,8 +208,8 @@ describe('error handling', () => { }); 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', + }, + ], + }, + ]), }); diff --git a/src/rules/consistent-test-it.ts b/src/rules/consistent-test-it.ts index 3fcd254e4..e0a68daaf 100644 --- a/src/rules/consistent-test-it.ts +++ b/src/rules/consistent-test-it.ts @@ -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], }, }, diff --git a/src/rules/expect-expect.ts b/src/rules/expect-expect.ts index 4bdd815cd..c4ec8198e 100644 --- a/src/rules/expect-expect.ts +++ b/src/rules/expect-expect.ts @@ -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', diff --git a/src/rules/max-expects.ts b/src/rules/max-expects.ts index 3cc20e105..ce62a2bc1 100644 --- a/src/rules/max-expects.ts +++ b/src/rules/max-expects.ts @@ -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: diff --git a/src/rules/max-nested-describe.ts b/src/rules/max-nested-describe.ts index b807a4591..31f603704 100644 --- a/src/rules/max-nested-describe.ts +++ b/src/rules/max-nested-describe.ts @@ -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: diff --git a/src/rules/no-alias-methods.ts b/src/rules/no-alias-methods.ts index dfd4a9629..e8c9f3b0f 100644 --- a/src/rules/no-alias-methods.ts +++ b/src/rules/no-alias-methods.ts @@ -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 }}()`, diff --git a/src/rules/no-commented-out-tests.ts b/src/rules/no-commented-out-tests.ts index 1949c3fc4..cf09618f6 100644 --- a/src/rules/no-commented-out-tests.ts +++ b/src/rules/no-commented-out-tests.ts @@ -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', diff --git a/src/rules/no-conditional-expect.ts b/src/rules/no-conditional-expect.ts index 519c23523..31e7d3ada 100644 --- a/src/rules/no-conditional-expect.ts +++ b/src/rules/no-conditional-expect.ts @@ -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`', diff --git a/src/rules/no-conditional-in-test.ts b/src/rules/no-conditional-in-test.ts index 6a58a4f77..0338fdf37 100644 --- a/src/rules/no-conditional-in-test.ts +++ b/src/rules/no-conditional-in-test.ts @@ -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', diff --git a/src/rules/no-confusing-set-timeout.ts b/src/rules/no-confusing-set-timeout.ts index 52bb29606..f295a36fb 100644 --- a/src/rules/no-confusing-set-timeout.ts +++ b/src/rules/no-confusing-set-timeout.ts @@ -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', diff --git a/src/rules/no-deprecated-functions.ts b/src/rules/no-deprecated-functions.ts index f41d65513..d83323d47 100644 --- a/src/rules/no-deprecated-functions.ts +++ b/src/rules/no-deprecated-functions.ts @@ -28,9 +28,7 @@ export default createRule({ name: __filename, meta: { docs: { - category: 'Best Practices', description: 'Disallow use of deprecated functions', - recommended: 'error', }, messages: { deprecatedFunction: diff --git a/src/rules/no-disabled-tests.ts b/src/rules/no-disabled-tests.ts index af0c7547e..70d3ef180 100644 --- a/src/rules/no-disabled-tests.ts +++ b/src/rules/no-disabled-tests.ts @@ -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', diff --git a/src/rules/no-done-callback.ts b/src/rules/no-done-callback.ts index a227987c4..7647ec368 100644 --- a/src/rules/no-done-callback.ts +++ b/src/rules/no-done-callback.ts @@ -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: diff --git a/src/rules/no-duplicate-hooks.ts b/src/rules/no-duplicate-hooks.ts index b47db957b..7305ad459 100644 --- a/src/rules/no-duplicate-hooks.ts +++ b/src/rules/no-duplicate-hooks.ts @@ -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', diff --git a/src/rules/no-export.ts b/src/rules/no-export.ts index bd94acfbd..c1cbe0a80 100644 --- a/src/rules/no-export.ts +++ b/src/rules/no-export.ts @@ -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`, diff --git a/src/rules/no-focused-tests.ts b/src/rules/no-focused-tests.ts index 0f740d94c..3d7d2ffd3 100644 --- a/src/rules/no-focused-tests.ts +++ b/src/rules/no-focused-tests.ts @@ -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', diff --git a/src/rules/no-hooks.ts b/src/rules/no-hooks.ts index 7b08ef71c..88ddfae4d 100644 --- a/src/rules/no-hooks.ts +++ b/src/rules/no-hooks.ts @@ -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'], }, }, diff --git a/src/rules/no-identical-title.ts b/src/rules/no-identical-title.ts index b8d6f7227..b2f26629e 100644 --- a/src/rules/no-identical-title.ts +++ b/src/rules/no-identical-title.ts @@ -21,9 +21,7 @@ export default createRule({ name: __filename, meta: { docs: { - category: 'Best Practices', description: 'Disallow identical titles', - recommended: 'error', }, messages: { multipleTestTitle: diff --git a/src/rules/no-interpolation-in-snapshots.ts b/src/rules/no-interpolation-in-snapshots.ts index 4b7d87daf..1961d0db4 100644 --- a/src/rules/no-interpolation-in-snapshots.ts +++ b/src/rules/no-interpolation-in-snapshots.ts @@ -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', diff --git a/src/rules/no-jasmine-globals.ts b/src/rules/no-jasmine-globals.ts index 89c51ba30..6d0d122dd 100644 --- a/src/rules/no-jasmine-globals.ts +++ b/src/rules/no-jasmine-globals.ts @@ -11,9 +11,7 @@ export default createRule({ name: __filename, meta: { docs: { - category: 'Best Practices', description: 'Disallow Jasmine globals', - recommended: 'error', }, messages: { illegalGlobal: diff --git a/src/rules/no-large-snapshots.ts b/src/rules/no-large-snapshots.ts index 0f28dcfba..f5bd0474a 100644 --- a/src/rules/no-large-snapshots.ts +++ b/src/rules/no-large-snapshots.ts @@ -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', diff --git a/src/rules/no-mocks-import.ts b/src/rules/no-mocks-import.ts index 5fac9172e..69e54571b 100644 --- a/src/rules/no-mocks-import.ts +++ b/src/rules/no-mocks-import.ts @@ -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`, diff --git a/src/rules/no-restricted-jest-methods.ts b/src/rules/no-restricted-jest-methods.ts index 37947fce5..b50bf40e6 100644 --- a/src/rules/no-restricted-jest-methods.ts +++ b/src/rules/no-restricted-jest-methods.ts @@ -12,9 +12,7 @@ export default createRule< name: __filename, meta: { docs: { - category: 'Best Practices', description: 'Disallow specific `jest.` methods', - recommended: false, }, type: 'suggestion', schema: [ diff --git a/src/rules/no-restricted-matchers.ts b/src/rules/no-restricted-matchers.ts index f05cd4367..528704be4 100644 --- a/src/rules/no-restricted-matchers.ts +++ b/src/rules/no-restricted-matchers.ts @@ -23,9 +23,7 @@ export default createRule< name: __filename, meta: { docs: { - category: 'Best Practices', description: 'Disallow specific matchers & modifiers', - recommended: false, }, type: 'suggestion', schema: [ diff --git a/src/rules/no-standalone-expect.ts b/src/rules/no-standalone-expect.ts index 5afcc977c..bb5c43fdc 100644 --- a/src/rules/no-standalone-expect.ts +++ b/src/rules/no-standalone-expect.ts @@ -60,9 +60,7 @@ 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', @@ -70,6 +68,7 @@ export default createRule< type: 'suggestion', schema: [ { + type: 'object', properties: { additionalTestBlockFunctions: { type: 'array', diff --git a/src/rules/no-test-prefixes.ts b/src/rules/no-test-prefixes.ts index 64b5cc03f..f0a38ef8f 100644 --- a/src/rules/no-test-prefixes.ts +++ b/src/rules/no-test-prefixes.ts @@ -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', diff --git a/src/rules/no-test-return-statement.ts b/src/rules/no-test-return-statement.ts index 252c76e67..6cde8e75d 100644 --- a/src/rules/no-test-return-statement.ts +++ b/src/rules/no-test-return-statement.ts @@ -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', diff --git a/src/rules/no-untyped-mock-factory.ts b/src/rules/no-untyped-mock-factory.ts index a3abe55cc..9dceda78a 100644 --- a/src/rules/no-untyped-mock-factory.ts +++ b/src/rules/no-untyped-mock-factory.ts @@ -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; diff --git a/src/rules/prefer-called-with.ts b/src/rules/prefer-called-with.ts index b4b6709a2..646309cd2 100644 --- a/src/rules/prefer-called-with.ts +++ b/src/rules/prefer-called-with.ts @@ -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 */)', diff --git a/src/rules/prefer-comparison-matcher.ts b/src/rules/prefer-comparison-matcher.ts index 17b87ac4a..ec356f656 100644 --- a/src/rules/prefer-comparison-matcher.ts +++ b/src/rules/prefer-comparison-matcher.ts @@ -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', diff --git a/src/rules/prefer-each.ts b/src/rules/prefer-each.ts index c337d71cc..141a9175b 100644 --- a/src/rules/prefer-each.ts +++ b/src/rules/prefer-each.ts @@ -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', diff --git a/src/rules/prefer-equality-matcher.ts b/src/rules/prefer-equality-matcher.ts index 18ed9abb1..02932692e 100644 --- a/src/rules/prefer-equality-matcher.ts +++ b/src/rules/prefer-equality-matcher.ts @@ -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', diff --git a/src/rules/prefer-expect-assertions.ts b/src/rules/prefer-expect-assertions.ts index d7d3be5a0..8ec38c92d 100644 --- a/src/rules/prefer-expect-assertions.ts +++ b/src/rules/prefer-expect-assertions.ts @@ -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: diff --git a/src/rules/prefer-expect-resolves.ts b/src/rules/prefer-expect-resolves.ts index cc9b09605..0c4719dc1 100644 --- a/src/rules/prefer-expect-resolves.ts +++ b/src/rules/prefer-expect-resolves.ts @@ -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: { diff --git a/src/rules/prefer-hooks-in-order.ts b/src/rules/prefer-hooks-in-order.ts index 3f1f626d1..a5544db90 100644 --- a/src/rules/prefer-hooks-in-order.ts +++ b/src/rules/prefer-hooks-in-order.ts @@ -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`, diff --git a/src/rules/prefer-hooks-on-top.ts b/src/rules/prefer-hooks-on-top.ts index 433e20a9b..0b68cd0ed 100644 --- a/src/rules/prefer-hooks-on-top.ts +++ b/src/rules/prefer-hooks-on-top.ts @@ -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', diff --git a/src/rules/prefer-lowercase-title.ts b/src/rules/prefer-lowercase-title.ts index cf9a4f6bf..b87b72581 100644 --- a/src/rules/prefer-lowercase-title.ts +++ b/src/rules/prefer-lowercase-title.ts @@ -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, }, diff --git a/src/rules/prefer-mock-promise-shorthand.ts b/src/rules/prefer-mock-promise-shorthand.ts index 7007d816e..c32a456b7 100644 --- a/src/rules/prefer-mock-promise-shorthand.ts +++ b/src/rules/prefer-mock-promise-shorthand.ts @@ -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 }}', diff --git a/src/rules/prefer-snapshot-hint.ts b/src/rules/prefer-snapshot-hint.ts index 67621c101..b1882e298 100644 --- a/src/rules/prefer-snapshot-hint.ts +++ b/src/rules/prefer-snapshot-hint.ts @@ -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', diff --git a/src/rules/prefer-spy-on.ts b/src/rules/prefer-spy-on.ts index ae1648bf6..c01ae1157 100644 --- a/src/rules/prefer-spy-on.ts +++ b/src/rules/prefer-spy-on.ts @@ -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', diff --git a/src/rules/prefer-strict-equal.ts b/src/rules/prefer-strict-equal.ts index 6586fddca..9fb594610 100644 --- a/src/rules/prefer-strict-equal.ts +++ b/src/rules/prefer-strict-equal.ts @@ -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', diff --git a/src/rules/prefer-to-be.ts b/src/rules/prefer-to-be.ts index f3fc235a0..7479d51e9 100644 --- a/src/rules/prefer-to-be.ts +++ b/src/rules/prefer-to-be.ts @@ -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', diff --git a/src/rules/prefer-to-contain.ts b/src/rules/prefer-to-contain.ts index 2e4f7e0ca..b062e1f8b 100644 --- a/src/rules/prefer-to-contain.ts +++ b/src/rules/prefer-to-contain.ts @@ -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', diff --git a/src/rules/prefer-to-have-length.ts b/src/rules/prefer-to-have-length.ts index a39fa47ce..683f5bb8f 100644 --- a/src/rules/prefer-to-have-length.ts +++ b/src/rules/prefer-to-have-length.ts @@ -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', diff --git a/src/rules/prefer-todo.ts b/src/rules/prefer-todo.ts index 8e675e1e0..12df97844 100644 --- a/src/rules/prefer-todo.ts +++ b/src/rules/prefer-todo.ts @@ -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', diff --git a/src/rules/require-hook.ts b/src/rules/require-hook.ts index 3eb0cbd9c..a60b8e2ee 100644 --- a/src/rules/require-hook.ts +++ b/src/rules/require-hook.ts @@ -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', diff --git a/src/rules/require-to-throw-message.ts b/src/rules/require-to-throw-message.ts index 9fdd6707c..e80c2f5c3 100644 --- a/src/rules/require-to-throw-message.ts +++ b/src/rules/require-to-throw-message.ts @@ -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 }}()', diff --git a/src/rules/require-top-level-describe.ts b/src/rules/require-top-level-describe.ts index 876881e2b..d0b30cba3 100644 --- a/src/rules/require-top-level-describe.ts +++ b/src/rules/require-top-level-describe.ts @@ -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', diff --git a/src/rules/unbound-method.ts b/src/rules/unbound-method.ts index 515c88258..eea17ccce 100644 --- a/src/rules/unbound-method.ts +++ b/src/rules/unbound-method.ts @@ -60,12 +60,12 @@ export default createRule({ 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) { diff --git a/src/rules/utils/__tests__/parseJestFnCall.test.ts b/src/rules/utils/__tests__/parseJestFnCall.test.ts index cdb3511b3..e119203f2 100644 --- a/src/rules/utils/__tests__/parseJestFnCall.test.ts +++ b/src/rules/utils/__tests__/parseJestFnCall.test.ts @@ -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 }}', diff --git a/src/rules/utils/misc.ts b/src/rules/utils/misc.ts index 9e025fcf5..e5e32a643 100644 --- a/src/rules/utils/misc.ts +++ b/src/rules/utils/misc.ts @@ -234,18 +234,14 @@ export const getFirstMatcherArg = ( export const getFilename = ( context: TSESLint.RuleContext, ) => { - return 'filename' in context - ? (context.filename as string) - : context.getFilename(); + return context.filename ?? context.getFilename(); }; /* istanbul ignore next */ export const getSourceCode = ( context: TSESLint.RuleContext, ) => { - return 'sourceCode' in context - ? (context.sourceCode as TSESLint.SourceCode) - : context.getSourceCode(); + return context.sourceCode ?? context.getSourceCode(); }; /* istanbul ignore next */ @@ -253,13 +249,7 @@ export const getScope = ( context: TSESLint.RuleContext, 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 */ @@ -267,13 +257,7 @@ export const getAncestors = ( context: TSESLint.RuleContext, 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 */ @@ -281,11 +265,8 @@ export const getDeclaredVariables = ( context: TSESLint.RuleContext, 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) + ); }; diff --git a/src/rules/utils/parseJestFnCall.ts b/src/rules/utils/parseJestFnCall.ts index d05531248..0f5d65ebf 100644 --- a/src/rules/utils/parseJestFnCall.ts +++ b/src/rules/utils/parseJestFnCall.ts @@ -183,20 +183,21 @@ const ValidJestFnCallChains = [ 'xtest.failing.each', ]; -declare module '@typescript-eslint/utils/dist/ts-eslint' { - export interface SharedConfigurationSettings { - jest?: { - globalAliases?: Record; - 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; + version?: number | string; + }; } const resolvePossibleAliasedGlobal = ( global: string, context: TSESLint.RuleContext, ) => { - const globalAliases = context.settings.jest?.globalAliases ?? {}; + const globalAliases = + (context.settings as SharedConfigurationSettings).jest?.globalAliases ?? {}; const alias = Object.entries(globalAliases).find(([, aliases]) => aliases.includes(global), diff --git a/src/rules/valid-describe-callback.ts b/src/rules/valid-describe-callback.ts index 08eb70a00..874511b4c 100644 --- a/src/rules/valid-describe-callback.ts +++ b/src/rules/valid-describe-callback.ts @@ -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', diff --git a/src/rules/valid-expect-in-promise.ts b/src/rules/valid-expect-in-promise.ts index 04bf86c8e..8570f8ed5 100644 --- a/src/rules/valid-expect-in-promise.ts +++ b/src/rules/valid-expect-in-promise.ts @@ -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: diff --git a/src/rules/valid-expect.ts b/src/rules/valid-expect.ts index 93b3ef20f..e5b30ea2f 100644 --- a/src/rules/valid-expect.ts +++ b/src/rules/valid-expect.ts @@ -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 }}', diff --git a/src/rules/valid-title.ts b/src/rules/valid-title.ts index 9ed6c7441..43dc09c95 100644 --- a/src/rules/valid-title.ts +++ b/src/rules/valid-title.ts @@ -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], diff --git a/yarn.lock b/yarn.lock index 5613c1364..b622e010f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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" From 9899ddfc00d35fbf1a0f66300b840d102f2ee82d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 22 Mar 2024 19:35:56 +0000 Subject: [PATCH 07/23] chore(release): 28.0.0-next.3 [skip ci] # [28.0.0-next.3](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.2...v28.0.0-next.3) (2024-03-22) ### Features * upgrade `@typescript-eslint/utils` to v6 ([#1508](https://github.com/jest-community/eslint-plugin-jest/issues/1508)) ([dc6e8cd](https://github.com/jest-community/eslint-plugin-jest/commit/dc6e8cd249817de585b50e473c2146e1542dd146)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 334645181..5aab277aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [28.0.0-next.3](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.2...v28.0.0-next.3) (2024-03-22) + + +### Features + +* upgrade `@typescript-eslint/utils` to v6 ([#1508](https://github.com/jest-community/eslint-plugin-jest/issues/1508)) ([dc6e8cd](https://github.com/jest-community/eslint-plugin-jest/commit/dc6e8cd249817de585b50e473c2146e1542dd146)) + # [28.0.0-next.2](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.1...v28.0.0-next.2) (2024-03-21) diff --git a/package.json b/package.json index 218cb5ef8..8b624f528 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-jest", - "version": "28.0.0-next.2", + "version": "28.0.0-next.3", "description": "ESLint rules for Jest", "keywords": [ "eslint", From 150e3558a637b49ddd76d362f88332b30f78dc5c Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Sun, 24 Mar 2024 07:27:41 +1300 Subject: [PATCH 08/23] feat: drop support for `@typescript-eslint/eslint-plugin` v5 (#1530) BREAKING CHANGE: dropped support for `@typescript-eslint/eslint-plugin` v5 --- .github/workflows/nodejs.yml | 2 +- package.json | 6 +- src/rules/__tests__/unbound-method.test.ts | 5 +- src/rules/no-untyped-mock-factory.ts | 7 +- yarn.lock | 113 ++++++++++----------- 5 files changed, 60 insertions(+), 73 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 7b566026f..4c6f0f314 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -73,7 +73,7 @@ jobs: matrix: node-version: [16.x, 18.x, 19.x, 20.x, 21.x] eslint-version: [7, 8] - ts-eslint-plugin-version: [5, 6, 7] + ts-eslint-plugin-version: [6, 7] exclude: # ts-eslint/plugin@7 doesn't support node@16 - node-version: 16.x diff --git a/package.json b/package.json index 8b624f528..0d887615a 100644 --- a/package.json +++ b/package.json @@ -111,8 +111,8 @@ "@types/eslint": "^8.4.6", "@types/jest": "^29.0.0", "@types/node": "^14.18.26", - "@typescript-eslint/eslint-plugin": "^5.0.0", - "@typescript-eslint/parser": "^5.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", "babel-jest": "^29.0.0", "babel-plugin-replace-ts-export-assignment": "^0.0.2", "dedent": "^1.5.0", @@ -142,7 +142,7 @@ "typescript": "^5.0.4" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0", "eslint": "^7.0.0 || ^8.0.0", "jest": "*" }, diff --git a/src/rules/__tests__/unbound-method.test.ts b/src/rules/__tests__/unbound-method.test.ts index 1a926f1ba..6aa494e79 100644 --- a/src/rules/__tests__/unbound-method.test.ts +++ b/src/rules/__tests__/unbound-method.test.ts @@ -1,5 +1,4 @@ import path from 'path'; -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'; @@ -253,9 +252,7 @@ ruleTester.run('unbound-method', requireRule(false), { "['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;'] - : []), + 'const x = Object.defineProperty;', ...[ 'instance.bound();', 'instance.unbound();', diff --git a/src/rules/no-untyped-mock-factory.ts b/src/rules/no-untyped-mock-factory.ts index 9dceda78a..4f0448696 100644 --- a/src/rules/no-untyped-mock-factory.ts +++ b/src/rules/no-untyped-mock-factory.ts @@ -36,12 +36,7 @@ export default createRule({ create(context) { return { CallExpression(node: TSESTree.CallExpression): void { - let { callee, typeArguments } = node; - - /* istanbul ignore next */ - if (!('typeArguments' in node)) { - typeArguments = (node as TSESTree.CallExpression).typeParameters; - } + const { callee, typeArguments } = node; if (callee.type !== AST_NODE_TYPES.MemberExpression) { return; diff --git a/yarn.lock b/yarn.lock index b622e010f..de28b53bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1661,7 +1661,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.4.0, @eslint-community/regexpp@npm:^4.6.1": +"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": version: 4.10.0 resolution: "@eslint-community/regexpp@npm:4.10.0" checksum: 2a6e345429ea8382aaaf3a61f865cae16ed44d31ca917910033c02dc00d505d939f10b81e079fa14d43b51499c640138e153b7e40743c4c094d9df97d4e56f7b @@ -2939,44 +2939,46 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^5.0.0": - version: 5.62.0 - resolution: "@typescript-eslint/eslint-plugin@npm:5.62.0" +"@typescript-eslint/eslint-plugin@npm:^6.0.0": + version: 6.21.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.21.0" dependencies: - "@eslint-community/regexpp": ^4.4.0 - "@typescript-eslint/scope-manager": 5.62.0 - "@typescript-eslint/type-utils": 5.62.0 - "@typescript-eslint/utils": 5.62.0 + "@eslint-community/regexpp": ^4.5.1 + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/type-utils": 6.21.0 + "@typescript-eslint/utils": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 debug: ^4.3.4 graphemer: ^1.4.0 - ignore: ^5.2.0 - natural-compare-lite: ^1.4.0 - semver: ^7.3.7 - tsutils: ^3.21.0 + ignore: ^5.2.4 + natural-compare: ^1.4.0 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 peerDependencies: - "@typescript-eslint/parser": ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + "@typescript-eslint/parser": ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: fc104b389c768f9fa7d45a48c86d5c1ad522c1d0512943e782a56b1e3096b2cbcc1eea3fcc590647bf0658eef61aac35120a9c6daf979bf629ad2956deb516a1 + checksum: 5ef2c502255e643e98051e87eb682c2a257e87afd8ec3b9f6274277615e1c2caf3131b352244cfb1987b8b2c415645eeacb9113fa841fc4c9b2ac46e8aed6efd languageName: node linkType: hard -"@typescript-eslint/parser@npm:^5.0.0": - version: 5.62.0 - resolution: "@typescript-eslint/parser@npm:5.62.0" +"@typescript-eslint/parser@npm:^6.0.0": + version: 6.21.0 + resolution: "@typescript-eslint/parser@npm:6.21.0" dependencies: - "@typescript-eslint/scope-manager": 5.62.0 - "@typescript-eslint/types": 5.62.0 - "@typescript-eslint/typescript-estree": 5.62.0 + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/typescript-estree": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 debug: ^4.3.4 peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: d168f4c7f21a7a63f47002e2d319bcbb6173597af5c60c1cf2de046b46c76b4930a093619e69faf2d30214c29ab27b54dcf1efc7046a6a6bd6f37f59a990e752 + checksum: 162fe3a867eeeffda7328bce32dae45b52283c68c8cb23258fb9f44971f761991af61f71b8c9fe1aa389e93dfe6386f8509c1273d870736c507d76dd40647b68 languageName: node linkType: hard @@ -3000,20 +3002,20 @@ __metadata: 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" +"@typescript-eslint/type-utils@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/type-utils@npm:6.21.0" dependencies: - "@typescript-eslint/typescript-estree": 5.62.0 - "@typescript-eslint/utils": 5.62.0 + "@typescript-eslint/typescript-estree": 6.21.0 + "@typescript-eslint/utils": 6.21.0 debug: ^4.3.4 - tsutils: ^3.21.0 + ts-api-utils: ^1.0.1 peerDependencies: - eslint: "*" + eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: fc41eece5f315dfda14320be0da78d3a971d650ea41300be7196934b9715f3fe1120a80207551eb71d39568275dbbcf359bde540d1ca1439d8be15e9885d2739 + checksum: 77025473f4d80acf1fafcce99c5c283e557686a61861febeba9c9913331f8a41e930bf5cd8b7a54db502a57b6eb8ea6d155cbd4f41349ed00e3d7aeb1f477ddc languageName: node linkType: hard @@ -3086,7 +3088,24 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.62.0, @typescript-eslint/utils@npm:^5.38.1": +"@typescript-eslint/utils@npm:6.21.0, @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/utils@npm:^5.38.1": version: 5.62.0 resolution: "@typescript-eslint/utils@npm:5.62.0" dependencies: @@ -3104,23 +3123,6 @@ __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" @@ -5209,8 +5211,8 @@ __metadata: "@types/eslint": ^8.4.6 "@types/jest": ^29.0.0 "@types/node": ^14.18.26 - "@typescript-eslint/eslint-plugin": ^5.0.0 - "@typescript-eslint/parser": ^5.0.0 + "@typescript-eslint/eslint-plugin": ^6.0.0 + "@typescript-eslint/parser": ^6.0.0 "@typescript-eslint/utils": ^6.0.0 babel-jest: ^29.0.0 babel-plugin-replace-ts-export-assignment: ^0.0.2 @@ -5240,7 +5242,7 @@ __metadata: ts-node: ^10.2.1 typescript: ^5.0.4 peerDependencies: - "@typescript-eslint/eslint-plugin": ^5.0.0 || ^6.0.0 || ^7.0.0 + "@typescript-eslint/eslint-plugin": ^6.0.0 || ^7.0.0 eslint: ^7.0.0 || ^8.0.0 jest: "*" peerDependenciesMeta: @@ -8473,13 +8475,6 @@ __metadata: languageName: node linkType: hard -"natural-compare-lite@npm:^1.4.0": - version: 1.4.0 - resolution: "natural-compare-lite@npm:1.4.0" - checksum: 5222ac3986a2b78dd6069ac62cbb52a7bf8ffc90d972ab76dfe7b01892485d229530ed20d0c62e79a6b363a663b273db3bde195a1358ce9e5f779d4453887225 - languageName: node - linkType: hard - "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" From 4d6f79a8b76eaa8a47260da021644aafcbbfaa29 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 23 Mar 2024 18:30:46 +0000 Subject: [PATCH 09/23] chore(release): 28.0.0-next.4 [skip ci] # [28.0.0-next.4](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.3...v28.0.0-next.4) (2024-03-23) ### Features * drop support for `@typescript-eslint/eslint-plugin` v5 ([#1530](https://github.com/jest-community/eslint-plugin-jest/issues/1530)) ([150e355](https://github.com/jest-community/eslint-plugin-jest/commit/150e3558a637b49ddd76d362f88332b30f78dc5c)) ### BREAKING CHANGES * dropped support for `@typescript-eslint/eslint-plugin` v5 --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5aab277aa..c2b5a5bc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# [28.0.0-next.4](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.3...v28.0.0-next.4) (2024-03-23) + + +### Features + +* drop support for `@typescript-eslint/eslint-plugin` v5 ([#1530](https://github.com/jest-community/eslint-plugin-jest/issues/1530)) ([150e355](https://github.com/jest-community/eslint-plugin-jest/commit/150e3558a637b49ddd76d362f88332b30f78dc5c)) + + +### BREAKING CHANGES + +* dropped support for `@typescript-eslint/eslint-plugin` v5 + # [28.0.0-next.3](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.2...v28.0.0-next.3) (2024-03-22) diff --git a/package.json b/package.json index 0d887615a..bf0786ab3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-jest", - "version": "28.0.0-next.3", + "version": "28.0.0-next.4", "description": "ESLint rules for Jest", "keywords": [ "eslint", From d3625813936d7bfd1c1a3ca31a362860df5007b1 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Sun, 24 Mar 2024 14:25:45 +1300 Subject: [PATCH 10/23] test(no-done-callback): add missing `suggestions` to `each` cases (#1535) --- src/rules/__tests__/no-done-callback.test.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/rules/__tests__/no-done-callback.test.ts b/src/rules/__tests__/no-done-callback.test.ts index dcb258bc0..3990ebcb8 100644 --- a/src/rules/__tests__/no-done-callback.test.ts +++ b/src/rules/__tests__/no-done-callback.test.ts @@ -477,6 +477,14 @@ ruleTester.run('no-done-callback', rule, { messageId: 'noDoneCallback', line: 1, column: 37, + suggestions: [ + { + messageId: 'suggestWrappingInPromise', + data: { callback: 'done' }, + output: + 'test.each``("something", () => {return new Promise(done => { done(); })})', + }, + ], }, ], }, @@ -487,6 +495,14 @@ ruleTester.run('no-done-callback', rule, { messageId: 'noDoneCallback', line: 1, column: 35, + suggestions: [ + { + messageId: 'suggestWrappingInPromise', + data: { callback: 'done' }, + output: + 'it.each``("something", () => {return new Promise(done => { done(); })})', + }, + ], }, ], }, From 0297a7ac177283eba3e6e14e0970d7e9cdeea74e Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Sun, 24 Mar 2024 14:28:06 +1300 Subject: [PATCH 11/23] refactor: address missed usage of deprecated `context.getFilename` in rules (#1533) --- src/rules/no-done-callback.ts | 3 ++- src/rules/no-large-snapshots.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/rules/no-done-callback.ts b/src/rules/no-done-callback.ts index 7647ec368..c7a43d34e 100644 --- a/src/rules/no-done-callback.ts +++ b/src/rules/no-done-callback.ts @@ -5,6 +5,7 @@ import { } from '@typescript-eslint/utils'; import { createRule, + getFilename, getNodeName, getSourceCode, isFunction, @@ -132,7 +133,7 @@ export default createRule({ !tokenAfterLastParam ) { throw new Error( - `Unexpected null when attempting to fix ${context.getFilename()} - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`, + `Unexpected null when attempting to fix ${getFilename(context)} - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`, ); } diff --git a/src/rules/no-large-snapshots.ts b/src/rules/no-large-snapshots.ts index f5bd0474a..2425823c0 100644 --- a/src/rules/no-large-snapshots.ts +++ b/src/rules/no-large-snapshots.ts @@ -105,7 +105,7 @@ export default createRule<[RuleOptions], MessageId>({ }, defaultOptions: [{}], create(context, [options]) { - if (context.getFilename().endsWith('.snap')) { + if (getFilename(context).endsWith('.snap')) { return { ExpressionStatement(node) { reportOnViolation(context, node, options); From a61b12d0f1f32f7c3a9652670da83c11173d0549 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Sun, 24 Mar 2024 14:40:17 +1300 Subject: [PATCH 12/23] test(prefer-expect-assertions): add missing `suggestions` to `each` cases (#1536) --- .../prefer-expect-assertions.test.ts | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/src/rules/__tests__/prefer-expect-assertions.test.ts b/src/rules/__tests__/prefer-expect-assertions.test.ts index f7d208abe..818fc6d04 100644 --- a/src/rules/__tests__/prefer-expect-assertions.test.ts +++ b/src/rules/__tests__/prefer-expect-assertions.test.ts @@ -1501,6 +1501,24 @@ ruleTester.run('.each support', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + test.each()("is not fine", () => {expect.hasAssertions(); + expect(someValue).toBe(true); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + test.each()("is not fine", () => {expect.assertions(); + expect(someValue).toBe(true); + }); + `, + }, + ], }, ], }, @@ -1517,6 +1535,28 @@ ruleTester.run('.each support', rule, { messageId: 'haveExpectAssertions', column: 3, line: 2, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + describe.each()('something', () => { + it("is not fine", () => {expect.hasAssertions(); + expect(someValue).toBe(true); + }); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + describe.each()('something', () => { + it("is not fine", () => {expect.assertions(); + expect(someValue).toBe(true); + }); + }); + `, + }, + ], }, ], }, @@ -1533,6 +1573,28 @@ ruleTester.run('.each support', rule, { messageId: 'haveExpectAssertions', column: 3, line: 2, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + describe.each()('something', () => { + test.each()("is not fine", () => {expect.hasAssertions(); + expect(someValue).toBe(true); + }); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + describe.each()('something', () => { + test.each()("is not fine", () => {expect.assertions(); + expect(someValue).toBe(true); + }); + }); + `, + }, + ], }, ], }, @@ -1548,6 +1610,24 @@ ruleTester.run('.each support', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + test.each()("is not fine", async () => {expect.hasAssertions(); + expect(someValue).toBe(true); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + test.each()("is not fine", async () => {expect.assertions(); + expect(someValue).toBe(true); + }); + `, + }, + ], }, ], }, @@ -1563,6 +1643,24 @@ ruleTester.run('.each support', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it.each()("is not fine", async () => {expect.hasAssertions(); + expect(someValue).toBe(true); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it.each()("is not fine", async () => {expect.assertions(); + expect(someValue).toBe(true); + }); + `, + }, + ], }, ], }, @@ -1580,6 +1678,28 @@ ruleTester.run('.each support', rule, { messageId: 'haveExpectAssertions', column: 3, line: 2, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + describe.each()('something', () => { + test.each()("is not fine", async () => {expect.hasAssertions(); + expect(someValue).toBe(true); + }); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + describe.each()('something', () => { + test.each()("is not fine", async () => {expect.assertions(); + expect(someValue).toBe(true); + }); + }); + `, + }, + ], }, ], }, From 98087f9bb27082f9fbda59a56c65536fb9d8a0dc Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Thu, 28 Mar 2024 07:02:20 +1300 Subject: [PATCH 13/23] feat: remove `snapshot` processor and `flat/snapshot` config (#1532) BREAKING CHANGE: removed unneeded `snapshot` processor and `flat/snapshot` config --- README.md | 29 ---------- .../__snapshots__/rules.test.ts.snap | 14 ----- src/__tests__/rules.test.ts | 2 - src/index.ts | 14 +---- .../__tests__/snapshot-processor.test.ts | 55 ------------------- src/processors/snapshot-processor.ts | 15 ----- 6 files changed, 1 insertion(+), 128 deletions(-) delete mode 100644 src/processors/__tests__/snapshot-processor.test.ts delete mode 100644 src/processors/snapshot-processor.ts diff --git a/README.md b/README.md index afd0e7da6..825ed26a8 100644 --- a/README.md +++ b/README.md @@ -275,35 +275,6 @@ While the `recommended` and `style` configurations only change in major versions the `all` configuration may change in any release and is thus unsuited for installations requiring long-term consistency. -## Snapshot processing - -> [!NOTE] -> -> This is only relevant for `eslint.config.js` - -This plugin provides a -[custom processor](https://eslint.org/docs/latest/extend/custom-processors) to -allow rules to "lint" snapshot files. - -For `.eslintrc` based configs, this is automatically enabled out of the box but -must be opted into for `eslint.config.js` using the `flat/snapshots` config: - -```js -const jest = require('eslint-plugin-jest'); - -module.exports = [ - { - ...jest.configs['flat/snapshots'], - rules: { - 'jest/no-large-snapshots': ['error', { maxSize: 1 }], - }, - }, -]; -``` - -Unlike other configs, this includes a `files` array that matches `.snap` files -meaning you can use it directly - ## Rules diff --git a/src/__tests__/__snapshots__/rules.test.ts.snap b/src/__tests__/__snapshots__/rules.test.ts.snap index 3044c709a..b0d635013 100644 --- a/src/__tests__/__snapshots__/rules.test.ts.snap +++ b/src/__tests__/__snapshots__/rules.test.ts.snap @@ -193,20 +193,6 @@ exports[`rules should export configs that refer to actual rules 1`] = ` "jest/valid-title": "error", }, }, - "flat/snapshots": { - "files": [ - "**/*.snap", - ], - "plugins": { - "jest": ObjectContaining { - "meta": { - "name": "eslint-plugin-jest", - "version": Any, - }, - }, - }, - "processor": "jest/snapshots", - }, "flat/style": { "languageOptions": { "globals": { diff --git a/src/__tests__/rules.test.ts b/src/__tests__/rules.test.ts index 8236727bd..3e06d7bbd 100644 --- a/src/__tests__/rules.test.ts +++ b/src/__tests__/rules.test.ts @@ -61,7 +61,6 @@ describe('rules', () => { 'flat/recommended': { plugins: { jest: expectJestPlugin } }, 'flat/style': { plugins: { jest: expectJestPlugin } }, 'flat/all': { plugins: { jest: expectJestPlugin } }, - 'flat/snapshots': { plugins: { jest: expectJestPlugin } }, }); expect(Object.keys(recommendedConfigs)).toEqual([ 'all', @@ -70,7 +69,6 @@ describe('rules', () => { 'flat/all', 'flat/recommended', 'flat/style', - 'flat/snapshots', ]); expect(Object.keys(recommendedConfigs.all.rules)).toHaveLength( ruleNames.length - deprecatedRules.length, diff --git a/src/index.ts b/src/index.ts index 569ae64b8..d6322697a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,7 +6,6 @@ import { version as packageVersion, } from '../package.json'; import globals from './globals.json'; -import * as snapshotProcessor from './processors/snapshot-processor'; type RuleModule = TSESLint.RuleModule & { meta: Required, 'docs'>>; @@ -76,8 +75,7 @@ const plugin = { | 'style' | 'flat/all' | 'flat/recommended' - | 'flat/style' - | 'flat/snapshots', + | 'flat/style', Pick, 'rules'> >, environments: { @@ -85,10 +83,6 @@ const plugin = { globals, }, }, - processors: { - snapshots: snapshotProcessor, - '.snap': snapshotProcessor, - }, rules, }; @@ -113,12 +107,6 @@ plugin.configs = { 'flat/all': createFlatConfig(allRules), 'flat/recommended': createFlatConfig(recommendedRules), 'flat/style': createFlatConfig(styleRules), - 'flat/snapshots': { - // @ts-expect-error this is introduced in flat config - files: ['**/*.snap'], - plugins: { jest: plugin }, - processor: 'jest/snapshots', - }, }; export = plugin; diff --git a/src/processors/__tests__/snapshot-processor.test.ts b/src/processors/__tests__/snapshot-processor.test.ts deleted file mode 100644 index 4ea625822..000000000 --- a/src/processors/__tests__/snapshot-processor.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -import * as snapshotProcessor from '../snapshot-processor'; - -describe('snapshot-processor', () => { - it('exports an object with preprocess and postprocess functions', () => { - expect(snapshotProcessor).toMatchObject({ - preprocess: expect.any(Function), - postprocess: expect.any(Function), - }); - }); - - describe('preprocess function', () => { - it('should pass on untouched source code to source array', () => { - const { preprocess } = snapshotProcessor; - const sourceCode = "const name = 'johnny bravo';"; - const result = preprocess(sourceCode, 'my-file.snap'); - - expect(result).toEqual([sourceCode]); - }); - }); - - describe('postprocess function', () => { - it('should only return messages about snapshot specific rules', () => { - const { postprocess } = snapshotProcessor; - - const result = postprocess( - [ - ['no-console', 'global-require', 'jest/no-large-snapshots'].map( - ruleId => ({ - ruleId, - column: 1, - line: 1, - source: null, - nodeType: 'Program', - message: 'something is not right about this...', - severity: 1, - }), - ), - ], - 'my-file.snap', - ); - - expect(result).toEqual([ - { - ruleId: 'jest/no-large-snapshots', - column: 1, - line: 1, - source: null, - nodeType: 'Program', - message: 'something is not right about this...', - severity: 1, - }, - ]); - }); - }); -}); diff --git a/src/processors/snapshot-processor.ts b/src/processors/snapshot-processor.ts deleted file mode 100644 index f455e3cb1..000000000 --- a/src/processors/snapshot-processor.ts +++ /dev/null @@ -1,15 +0,0 @@ -// https://eslint.org/docs/developer-guide/working-with-plugins#processors-in-plugins -// https://github.com/typescript-eslint/typescript-eslint/issues/808 -import type { TSESLint } from '@typescript-eslint/utils'; -import { - name as packageName, - version as packageVersion, -} from '../../package.json'; - -type SnapshotProcessor = Required; - -export const meta = { name: packageName, version: packageVersion }; -export const preprocess: SnapshotProcessor['preprocess'] = source => [source]; -export const postprocess: SnapshotProcessor['postprocess'] = messages => - // snapshot files should only be linted with snapshot specific rules - messages[0].filter(message => message.ruleId === 'jest/no-large-snapshots'); From 201b6e9336eaf2aac6261e2d36c057d928fda53a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 27 Mar 2024 18:06:01 +0000 Subject: [PATCH 14/23] chore(release): 28.0.0-next.5 [skip ci] # [28.0.0-next.5](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.4...v28.0.0-next.5) (2024-03-27) ### Features * remove `snapshot` processor and `flat/snapshot` config ([#1532](https://github.com/jest-community/eslint-plugin-jest/issues/1532)) ([98087f9](https://github.com/jest-community/eslint-plugin-jest/commit/98087f9bb27082f9fbda59a56c65536fb9d8a0dc)) ### BREAKING CHANGES * removed unneeded `snapshot` processor and `flat/snapshot` config --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2b5a5bc6..9fce1647a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# [28.0.0-next.5](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.4...v28.0.0-next.5) (2024-03-27) + + +### Features + +* remove `snapshot` processor and `flat/snapshot` config ([#1532](https://github.com/jest-community/eslint-plugin-jest/issues/1532)) ([98087f9](https://github.com/jest-community/eslint-plugin-jest/commit/98087f9bb27082f9fbda59a56c65536fb9d8a0dc)) + + +### BREAKING CHANGES + +* removed unneeded `snapshot` processor and `flat/snapshot` config + # [28.0.0-next.4](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.3...v28.0.0-next.4) (2024-03-23) diff --git a/package.json b/package.json index bf0786ab3..170374843 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-jest", - "version": "28.0.0-next.4", + "version": "28.0.0-next.5", "description": "ESLint rules for Jest", "keywords": [ "eslint", From fb800db09ce72757cf2cc74f0165f59be0c754a8 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Thu, 28 Mar 2024 07:08:44 +1300 Subject: [PATCH 15/23] test(prefer-expect-assertions): add missing suggestions (#1538) --- .../prefer-expect-assertions.test.ts | 1270 ++++++++++++++++- 1 file changed, 1250 insertions(+), 20 deletions(-) diff --git a/src/rules/__tests__/prefer-expect-assertions.test.ts b/src/rules/__tests__/prefer-expect-assertions.test.ts index 818fc6d04..0808608bb 100644 --- a/src/rules/__tests__/prefer-expect-assertions.test.ts +++ b/src/rules/__tests__/prefer-expect-assertions.test.ts @@ -94,7 +94,7 @@ ruleTester.run('prefer-expect-assertions', rule, { it("returns numbers that are greater than four", function() { pleaseExpect.assertions(2); - + for(let thing in things) { pleaseExpect(number).toBeGreaterThan(4); } @@ -374,6 +374,24 @@ ruleTester.run('prefer-expect-assertions', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("it1", async function() {expect.hasAssertions(); + expect(someValue).toBe(true); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("it1", async function() {expect.assertions(); + expect(someValue).toBe(true); + }); + `, + }, + ], }, ], }, @@ -391,6 +409,28 @@ ruleTester.run('prefer-expect-assertions', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("returns numbers that are greater than four", async () => {expect.hasAssertions(); + for(let thing in things) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("returns numbers that are greater than four", async () => {expect.assertions(); + for(let thing in things) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + ], }, ], }, @@ -408,6 +448,28 @@ ruleTester.run('prefer-expect-assertions', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("returns numbers that are greater than four", async () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("returns numbers that are greater than four", async () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + ], }, ], }, @@ -431,6 +493,40 @@ ruleTester.run('prefer-expect-assertions', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("returns numbers that are greater than four", async () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("returns numbers that are greater than five", () => { + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(5); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("returns numbers that are greater than four", async () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("returns numbers that are greater than five", () => { + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(5); + } + }); + `, + }, + ], }, ], }, @@ -493,6 +589,28 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('only returns numbers that are greater than six', () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(6); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('only returns numbers that are greater than six', () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(6); + } + }); + `, + }, + ], }, ], }, @@ -514,6 +632,36 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('returns numbers that are greater than two', function () {expect.hasAssertions(); + const expectNumbersToBeGreaterThan = (numbers, value) => { + for (let number of numbers) { + expect(number).toBeGreaterThan(value); + } + }; + + expectNumbersToBeGreaterThan(getNumbers(), 2); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('returns numbers that are greater than two', function () {expect.assertions(); + const expectNumbersToBeGreaterThan = (numbers, value) => { + for (let number of numbers) { + expect(number).toBeGreaterThan(value); + } + }; + + expectNumbersToBeGreaterThan(getNumbers(), 2); + }); + `, + }, + ], }, ], }, @@ -533,6 +681,32 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("only returns numbers that are greater than seven", function () {expect.hasAssertions(); + const numbers = getNumbers(); + + for (let i = 0; i < numbers.length; i++) { + expect(numbers[i]).toBeGreaterThan(7); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("only returns numbers that are greater than seven", function () {expect.assertions(); + const numbers = getNumbers(); + + for (let i = 0; i < numbers.length; i++) { + expect(numbers[i]).toBeGreaterThan(7); + } + }); + `, + }, + ], }, ], }, @@ -554,6 +728,36 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 5, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('has the number two', () => { + expect(number).toBe(2); + }); + + it('only returns numbers that are less than twenty', () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeLessThan(20); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('has the number two', () => { + expect(number).toBe(2); + }); + + it('only returns numbers that are less than twenty', () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeLessThan(20); + } + }); + `, + }, + ], }, ], }, @@ -573,6 +777,32 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 3, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("is wrong"); + + it("is a test", () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("is wrong"); + + it("is a test", () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + ], }, ], }, @@ -598,6 +828,44 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 5, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + + it("returns numbers that are greater than four", () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("returns numbers that are greater than five", () => { + expect(number).toBeGreaterThan(5); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + + it("returns numbers that are greater than four", () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("returns numbers that are greater than five", () => { + expect(number).toBeGreaterThan(5); + }); + `, + }, + ], }, ], }, @@ -619,6 +887,36 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it.each([1, 2, 3])("returns numbers that are greater than four", () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it.each([1, 2, 3])("returns numbers that are greater than four", () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + `, + }, + ], }, ], }, @@ -640,6 +938,36 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("returns numbers that are greater than four", () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("returns numbers that are greater than four", () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + `, + }, + ], }, ], }, @@ -663,6 +991,40 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("returns numbers that are greater than four", () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("is a number that is greater than four", () => { + expect.hasAssertions(); + + expect(number).toBeGreaterThan(4); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("returns numbers that are greater than four", () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("is a number that is greater than four", () => { + expect.hasAssertions(); + + expect(number).toBeGreaterThan(4); + }); + `, + }, + ], }, ], }, @@ -688,6 +1050,44 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 9, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("it1", () => { + expect.hasAssertions(); + + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(0); + } + }); + + it("it1", () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(0); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("it1", () => { + expect.hasAssertions(); + + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(0); + } + }); + + it("it1", () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(0); + } + }); + `, + }, + ], }, ], }, @@ -711,19 +1111,87 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, - }, - { - messageId: 'haveExpectAssertions', - column: 1, - line: 7, - }, - ], - }, - { - code: dedent` - it("it1", async () => { - expect.hasAssertions(); - + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("returns numbers that are greater than four", async () => {expect.hasAssertions(); + for (const number of await getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("returns numbers that are greater than five", () => { + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(5); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("returns numbers that are greater than four", async () => {expect.assertions(); + for (const number of await getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("returns numbers that are greater than five", () => { + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(5); + } + }); + `, + }, + ], + }, + { + messageId: 'haveExpectAssertions', + column: 1, + line: 7, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("returns numbers that are greater than four", async () => { + for (const number of await getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("returns numbers that are greater than five", () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(5); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("returns numbers that are greater than four", async () => { + for (const number of await getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("returns numbers that are greater than five", () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(5); + } + }); + `, + }, + ], + }, + ], + }, + { + code: dedent` + it("it1", async () => { + expect.hasAssertions(); + for (const number of getNumbers()) { expect(number).toBeGreaterThan(4); } @@ -741,6 +1209,44 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 9, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("it1", async () => { + expect.hasAssertions(); + + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("it1", () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("it1", async () => { + expect.hasAssertions(); + + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("it1", () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + ], }, ], }, @@ -766,6 +1272,44 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 9, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it.skip.each\`\`("it1", async () => { + expect.hasAssertions(); + + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("it1", () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it.skip.each\`\`("it1", async () => { + expect.hasAssertions(); + + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("it1", () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + ], }, ], }, @@ -791,6 +1335,44 @@ ruleTester.run('prefer-expect-assertions (loops)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("it1", async () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("it1", () => { + expect.hasAssertions(); + + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("it1", async () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + + it("it1", () => { + expect.hasAssertions(); + + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + ], }, ], }, @@ -927,6 +1509,32 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('sends the data as a string', () => {expect.hasAssertions(); + const stream = openStream(); + + stream.on('data', data => { + expect(data).toBe(expect.any(String)); + }); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('sends the data as a string', () => {expect.assertions(); + const stream = openStream(); + + stream.on('data', data => { + expect(data).toBe(expect.any(String)); + }); + }); + `, + }, + ], }, ], }, @@ -944,6 +1552,28 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('responds ok', function () {expect.hasAssertions(); + client.get('/user', response => { + expect(response.status).toBe(200); + }); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('responds ok', function () {expect.assertions(); + client.get('/user', response => { + expect(response.status).toBe(200); + }); + }); + `, + }, + ], }, ], }, @@ -963,6 +1593,32 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('responds ok', function () {expect.hasAssertions(); + client.get('/user', response => { + expect.assertions(1); + + expect(response.status).toBe(200); + }); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('responds ok', function () {expect.assertions(); + client.get('/user', response => { + expect.assertions(1); + + expect(response.status).toBe(200); + }); + }); + `, + }, + ], }, ], }, @@ -973,7 +1629,7 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { expect.assertions(1); expect(response.status).toBe(200); - }; + }; client.get('/user', expectOkResponse); }); @@ -984,6 +1640,36 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('responds ok', function () {expect.hasAssertions(); + const expectOkResponse = response => { + expect.assertions(1); + + expect(response.status).toBe(200); + }; + + client.get('/user', expectOkResponse); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('responds ok', function () {expect.assertions(); + const expectOkResponse = response => { + expect.assertions(1); + + expect(response.status).toBe(200); + }; + + client.get('/user', expectOkResponse); + }); + `, + }, + ], }, ], }, @@ -1003,6 +1689,32 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('returns numbers that are greater than two', function () {expect.hasAssertions(); + const expectNumberToBeGreaterThan = (number, value) => { + expect(number).toBeGreaterThan(value); + }; + + expectNumberToBeGreaterThan(1, 2); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('returns numbers that are greater than two', function () {expect.assertions(); + const expectNumberToBeGreaterThan = (number, value) => { + expect(number).toBeGreaterThan(value); + }; + + expectNumberToBeGreaterThan(1, 2); + }); + `, + }, + ], }, ], }, @@ -1024,6 +1736,36 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('returns numbers that are greater than two', function () {expect.hasAssertions(); + const expectNumbersToBeGreaterThan = (numbers, value) => { + for (let number of numbers) { + expect(number).toBeGreaterThan(value); + } + }; + + expectNumbersToBeGreaterThan(getNumbers(), 2); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('returns numbers that are greater than two', function () {expect.assertions(); + const expectNumbersToBeGreaterThan = (numbers, value) => { + for (let number of numbers) { + expect(number).toBeGreaterThan(value); + } + }; + + expectNumbersToBeGreaterThan(getNumbers(), 2); + }); + `, + }, + ], }, ], }, @@ -1041,6 +1783,28 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('only returns numbers that are greater than six', () => {expect.hasAssertions(); + getNumbers().forEach(number => { + expect(number).toBeGreaterThan(6); + }); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('only returns numbers that are greater than six', () => {expect.assertions(); + getNumbers().forEach(number => { + expect(number).toBeGreaterThan(6); + }); + }); + `, + }, + ], }, ], }, @@ -1064,6 +1828,40 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 3, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("is wrong"); + + it('responds ok', function () {expect.hasAssertions(); + const expectOkResponse = response => { + expect.assertions(1); + + expect(response.status).toBe(200); + }; + + client.get('/user', expectOkResponse); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("is wrong"); + + it('responds ok', function () {expect.assertions(); + const expectOkResponse = response => { + expect.assertions(1); + + expect(response.status).toBe(200); + }; + + client.get('/user', expectOkResponse); + }); + `, + }, + ], }, ], }, @@ -1091,10 +1889,52 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 5, - }, - ], - }, - { + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + + it('responds ok', function () {expect.hasAssertions(); + const expectOkResponse = response => { + expect(response.status).toBe(200); + }; + + client.get('/user', expectOkResponse); + }); + + it("returns numbers that are greater than five", () => { + expect(number).toBeGreaterThan(5); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + + it('responds ok', function () {expect.assertions(); + const expectOkResponse = response => { + expect(response.status).toBe(200); + }; + + client.get('/user', expectOkResponse); + }); + + it("returns numbers that are greater than five", () => { + expect(number).toBeGreaterThan(5); + }); + `, + }, + ], + }, + ], + }, + { code: dedent` it("is a number that is greater than four", () => { expect(number).toBeGreaterThan(4); @@ -1116,6 +1956,44 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 5, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + + it("returns numbers that are greater than four", () => {expect.hasAssertions(); + getNumbers().map(number => { + expect(number).toBeGreaterThan(0); + }); + }); + + it("returns numbers that are greater than five", () => { + expect(number).toBeGreaterThan(5); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + + it("returns numbers that are greater than four", () => {expect.assertions(); + getNumbers().map(number => { + expect(number).toBeGreaterThan(0); + }); + }); + + it("returns numbers that are greater than five", () => { + expect(number).toBeGreaterThan(5); + }); + `, + }, + ], }, ], }, @@ -1137,6 +2015,36 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it.each([1, 2, 3])("returns ok", id => {expect.hasAssertions(); + client.get(\`/users/$\{id}\`, response => { + expect(response.status).toBe(200); + }); + }); + + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it.each([1, 2, 3])("returns ok", id => {expect.assertions(); + client.get(\`/users/$\{id}\`, response => { + expect(response.status).toBe(200); + }); + }); + + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + `, + }, + ], }, ], }, @@ -1158,6 +2066,36 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('responds ok', function () {expect.hasAssertions(); + client.get('/user', response => { + expect(response.status).toBe(200); + }); + }); + + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('responds ok', function () {expect.assertions(); + client.get('/user', response => { + expect(response.status).toBe(200); + }); + }); + + it("is a number that is greater than four", () => { + expect(number).toBeGreaterThan(4); + }); + `, + }, + ], }, ], }, @@ -1181,6 +2119,40 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('responds ok', function () {expect.hasAssertions(); + client.get('/user', response => { + expect(response.status).toBe(200); + }); + }); + + it("is a number that is greater than four", () => { + expect.hasAssertions(); + + expect(number).toBeGreaterThan(4); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('responds ok', function () {expect.assertions(); + client.get('/user', response => { + expect(response.status).toBe(200); + }); + }); + + it("is a number that is greater than four", () => { + expect.hasAssertions(); + + expect(number).toBeGreaterThan(4); + }); + `, + }, + ], }, ], }, @@ -1206,6 +2178,44 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 9, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("it1", () => { + expect.hasAssertions(); + + getNumbers().forEach(number => { + expect(number).toBeGreaterThan(0); + }); + }); + + it("it1", () => {expect.hasAssertions(); + getNumbers().forEach(number => { + expect(number).toBeGreaterThan(0); + }); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("it1", () => { + expect.hasAssertions(); + + getNumbers().forEach(number => { + expect(number).toBeGreaterThan(0); + }); + }); + + it("it1", () => {expect.assertions(); + getNumbers().forEach(number => { + expect(number).toBeGreaterThan(0); + }); + }); + `, + }, + ], }, ], }, @@ -1231,6 +2241,44 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 9, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('responds ok', function () { + expect.hasAssertions(); + + client.get('/user', response => { + expect(response.status).toBe(200); + }); + }); + + it('responds not found', function () {expect.hasAssertions(); + client.get('/user', response => { + expect(response.status).toBe(404); + }); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('responds ok', function () { + expect.hasAssertions(); + + client.get('/user', response => { + expect(response.status).toBe(200); + }); + }); + + it('responds not found', function () {expect.assertions(); + client.get('/user', response => { + expect(response.status).toBe(404); + }); + }); + `, + }, + ], }, ], }, @@ -1256,6 +2304,44 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 9, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it.skip.each\`\`("it1", async () => { + expect.hasAssertions(); + + client.get('/user', response => { + expect(response.status).toBe(200); + }); + }); + + it("responds ok", () => {expect.hasAssertions(); + client.get('/user', response => { + expect(response.status).toBe(200); + }); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it.skip.each\`\`("it1", async () => { + expect.hasAssertions(); + + client.get('/user', response => { + expect(response.status).toBe(200); + }); + }); + + it("responds ok", () => {expect.assertions(); + client.get('/user', response => { + expect(response.status).toBe(200); + }); + }); + `, + }, + ], }, ], }, @@ -1270,7 +2356,39 @@ ruleTester.run('prefer-expect-assertions (callbacks)', rule, { }); `, parserOptions: { sourceType: 'module' }, - errors: [{ endColumn: 3, column: 1, messageId: 'haveExpectAssertions' }], + errors: [ + { + messageId: 'haveExpectAssertions', + column: 1, + endColumn: 3, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("returns numbers that are greater than four", function(expect) {expect.hasAssertions(); + expect.assertions(2); + + for(let thing in things) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("returns numbers that are greater than four", function(expect) {expect.assertions(); + expect.assertions(2); + + for(let thing in things) { + expect(number).toBeGreaterThan(4); + } + }); + `, + }, + ], + }, + ], }, ], }); @@ -1333,6 +2451,40 @@ ruleTester.run('prefer-expect-assertions (mixed)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('only returns numbers that are greater than zero', () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(0); + } + }); + + it("is zero", () => { + expect.hasAssertions(); + + expect(0).toBe(0); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('only returns numbers that are greater than zero', () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(0); + } + }); + + it("is zero", () => { + expect.hasAssertions(); + + expect(0).toBe(0); + }); + `, + }, + ], }, ], }, @@ -1358,6 +2510,44 @@ ruleTester.run('prefer-expect-assertions (mixed)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 9, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('only returns numbers that are greater than zero', () => { + expect.hasAssertions(); + + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(0); + } + }); + + it('only returns numbers that are less than 100', () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeLessThan(0); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('only returns numbers that are greater than zero', () => { + expect.hasAssertions(); + + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(0); + } + }); + + it('only returns numbers that are less than 100', () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeLessThan(0); + } + }); + `, + }, + ], }, ], }, @@ -1378,6 +2568,24 @@ ruleTester.run('prefer-expect-assertions (mixed)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it("to be true", async function() {expect.hasAssertions(); + expect(someValue).toBe(true); + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it("to be true", async function() {expect.assertions(); + expect(someValue).toBe(true); + }); + `, + }, + ], }, ], }, @@ -1400,6 +2608,28 @@ ruleTester.run('prefer-expect-assertions (mixed)', rule, { messageId: 'haveExpectAssertions', column: 1, line: 1, + suggestions: [ + { + messageId: 'suggestAddingHasAssertions', + output: dedent` + it('only returns numbers that are greater than zero', async () => {expect.hasAssertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(0); + } + }); + `, + }, + { + messageId: 'suggestAddingAssertions', + output: dedent` + it('only returns numbers that are greater than zero', async () => {expect.assertions(); + for (const number of getNumbers()) { + expect(number).toBeGreaterThan(0); + } + }); + `, + }, + ], }, ], }, From 8bba541f03475b80ac4bc10e4e2f5167b8e93511 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Sat, 30 Mar 2024 08:54:28 +1300 Subject: [PATCH 16/23] test(prefer-comparison-matcher): update names and remove duplicates (#1540) * test(prefer-comparison-matcher): update test names * test(prefer-comparison-matcher): deduplicate examples --- .../prefer-comparison-matcher.test.ts | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/rules/__tests__/prefer-comparison-matcher.test.ts b/src/rules/__tests__/prefer-comparison-matcher.test.ts index 8df6065e7..fdc693df1 100644 --- a/src/rules/__tests__/prefer-comparison-matcher.test.ts +++ b/src/rules/__tests__/prefer-comparison-matcher.test.ts @@ -205,30 +205,30 @@ const generateValidStringLiteralCases = (operator: string, matcher: string) => { ['x', "'y'"], ['x', '`y`'], ['x', '`y${z}`'], - ].reduce((cases, [a, b]) => [ - ...cases, - ...[ - `expect(${a} ${operator} ${b}).${matcher}(true)`, - `expect(${a} ${operator} ${b}).${matcher}(false)`, - `expect(${a} ${operator} ${b}).not.${matcher}(true)`, - `expect(${a} ${operator} ${b}).not.${matcher}(false)`, - `expect(${b} ${operator} ${a}).${matcher}(true)`, - `expect(${b} ${operator} ${a}).${matcher}(false)`, - `expect(${b} ${operator} ${a}).not.${matcher}(true)`, - `expect(${b} ${operator} ${a}).not.${matcher}(false)`, - `expect(${a} ${operator} ${b}).${matcher}(true)`, - `expect(${a} ${operator} ${b}).${matcher}(false)`, - `expect(${a} ${operator} ${b}).not.${matcher}(true)`, - `expect(${a} ${operator} ${b}).not.${matcher}(false)`, - `expect(${b} ${operator} ${a}).${matcher}(true)`, - `expect(${b} ${operator} ${a}).${matcher}(false)`, - `expect(${b} ${operator} ${a}).not.${matcher}(true)`, - `expect(${b} ${operator} ${a}).not.${matcher}(false)`, - `expect(${b} ${operator} ${b}).not.${matcher}(false)`, - `expect(${b} ${operator} ${b}).resolves.not.${matcher}(false)`, - `expect(${b} ${operator} ${b}).resolves.${matcher}(false)`, + ].reduce( + (cases, [a, b]) => [ + ...cases, + ...[ + `expect(${a} ${operator} ${b}).${matcher}(true)`, + `expect(${a} ${operator} ${b}).${matcher}(false)`, + `expect(${a} ${operator} ${b}).not.${matcher}(true)`, + `expect(${a} ${operator} ${b}).not.${matcher}(false)`, + `expect(${a} ${operator} ${b}).resolves.${matcher}(true)`, + `expect(${a} ${operator} ${b}).resolves.${matcher}(false)`, + `expect(${a} ${operator} ${b}).resolves.not.${matcher}(true)`, + `expect(${a} ${operator} ${b}).resolves.not.${matcher}(false)`, + `expect(${b} ${operator} ${a}).resolves.not.${matcher}(false)`, + `expect(${b} ${operator} ${a}).resolves.not.${matcher}(true)`, + `expect(${b} ${operator} ${a}).resolves.${matcher}(false)`, + `expect(${b} ${operator} ${a}).resolves.${matcher}(true)`, + `expect(${b} ${operator} ${a}).not.${matcher}(false)`, + `expect(${b} ${operator} ${a}).not.${matcher}(true)`, + `expect(${b} ${operator} ${a}).${matcher}(false)`, + `expect(${b} ${operator} ${a}).${matcher}(true)`, + ], ], - ]); + [], + ); }; const testComparisonOperator = ( @@ -236,7 +236,7 @@ const testComparisonOperator = ( preferredMatcher: string, preferredMatcherWhenNegated: string, ) => { - ruleTester.run(`prefer-to-be-comparison: ${operator}`, rule, { + ruleTester.run(`prefer-comparison-matcher: ${operator}`, rule, { valid: [ 'expect()', 'expect({}).toStrictEqual({})', @@ -274,7 +274,7 @@ testComparisonOperator('<', 'toBeLessThan', 'toBeGreaterThanOrEqual'); testComparisonOperator('>=', 'toBeGreaterThanOrEqual', 'toBeLessThan'); testComparisonOperator('<=', 'toBeLessThanOrEqual', 'toBeGreaterThan'); -ruleTester.run(`prefer-to-be-comparison`, rule, { +ruleTester.run(`prefer-comparison-matcher`, rule, { valid: [ 'expect.hasAssertions', 'expect.hasAssertions()', From 295120e009ae554fa5bf9f209a876b667dd93d80 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Sat, 30 Mar 2024 09:12:24 +1300 Subject: [PATCH 17/23] refactor: use `flatMap` instead of `reduce` (#1541) --- src/__tests__/rules.test.ts | 9 +-- .../__tests__/no-deprecated-functions.test.ts | 28 ++++---- .../prefer-comparison-matcher.test.ts | 70 +++++++------------ src/rules/utils/misc.ts | 18 ++--- 4 files changed, 49 insertions(+), 76 deletions(-) diff --git a/src/__tests__/rules.test.ts b/src/__tests__/rules.test.ts index 3e06d7bbd..db8eb4635 100644 --- a/src/__tests__/rules.test.ts +++ b/src/__tests__/rules.test.ts @@ -76,12 +76,9 @@ describe('rules', () => { expect(Object.keys(recommendedConfigs['flat/all'].rules)).toHaveLength( ruleNames.length - deprecatedRules.length, ); - const allConfigRules = Object.values(recommendedConfigs) - .map(config => Object.keys(config.rules ?? {})) - .reduce((previousValue, currentValue) => [ - ...previousValue, - ...currentValue, - ]); + const allConfigRules = Object.values(recommendedConfigs).flatMap(config => + Object.keys(config.rules ?? {}), + ); allConfigRules.forEach(rule => { const ruleNamePrefix = 'jest/'; diff --git a/src/rules/__tests__/no-deprecated-functions.test.ts b/src/rules/__tests__/no-deprecated-functions.test.ts index c4964c687..bd5153500 100644 --- a/src/rules/__tests__/no-deprecated-functions.test.ts +++ b/src/rules/__tests__/no-deprecated-functions.test.ts @@ -120,30 +120,26 @@ describe('the rule', () => { valid: [ 'jest', 'require("fs")', - ...allowedFunctions - .map(func => generateValidCases(jestVersion, func)) - .reduce((acc, arr) => acc.concat(arr), []), + ...allowedFunctions.flatMap(func => + generateValidCases(jestVersion, func), + ), ], - invalid: deprecations - .map(([, deprecation, replacement]) => - generateInvalidCases(jestVersion, deprecation, replacement), - ) - .reduce((acc, arr) => acc.concat(arr), []), + invalid: deprecations.flatMap(([, deprecation, replacement]) => + generateInvalidCases(jestVersion, deprecation, replacement), + ), }); ruleTester.run('detected jest version', rule, { valid: [ 'jest', 'require("fs")', - ...allowedFunctions - .map(func => generateValidCases(undefined, func)) - .reduce((acc, arr) => acc.concat(arr), []), + ...allowedFunctions.flatMap(func => + generateValidCases(undefined, func), + ), ], - invalid: deprecations - .map(([, deprecation, replacement]) => - generateInvalidCases(undefined, deprecation, replacement), - ) - .reduce((acc, arr) => acc.concat(arr), []), + invalid: deprecations.flatMap(([, deprecation, replacement]) => + generateInvalidCases(undefined, deprecation, replacement), + ), }); }); diff --git a/src/rules/__tests__/prefer-comparison-matcher.test.ts b/src/rules/__tests__/prefer-comparison-matcher.test.ts index fdc693df1..d0dca2dd4 100644 --- a/src/rules/__tests__/prefer-comparison-matcher.test.ts +++ b/src/rules/__tests__/prefer-comparison-matcher.test.ts @@ -205,30 +205,24 @@ const generateValidStringLiteralCases = (operator: string, matcher: string) => { ['x', "'y'"], ['x', '`y`'], ['x', '`y${z}`'], - ].reduce( - (cases, [a, b]) => [ - ...cases, - ...[ - `expect(${a} ${operator} ${b}).${matcher}(true)`, - `expect(${a} ${operator} ${b}).${matcher}(false)`, - `expect(${a} ${operator} ${b}).not.${matcher}(true)`, - `expect(${a} ${operator} ${b}).not.${matcher}(false)`, - `expect(${a} ${operator} ${b}).resolves.${matcher}(true)`, - `expect(${a} ${operator} ${b}).resolves.${matcher}(false)`, - `expect(${a} ${operator} ${b}).resolves.not.${matcher}(true)`, - `expect(${a} ${operator} ${b}).resolves.not.${matcher}(false)`, - `expect(${b} ${operator} ${a}).resolves.not.${matcher}(false)`, - `expect(${b} ${operator} ${a}).resolves.not.${matcher}(true)`, - `expect(${b} ${operator} ${a}).resolves.${matcher}(false)`, - `expect(${b} ${operator} ${a}).resolves.${matcher}(true)`, - `expect(${b} ${operator} ${a}).not.${matcher}(false)`, - `expect(${b} ${operator} ${a}).not.${matcher}(true)`, - `expect(${b} ${operator} ${a}).${matcher}(false)`, - `expect(${b} ${operator} ${a}).${matcher}(true)`, - ], - ], - [], - ); + ].flatMap(([a, b]) => [ + `expect(${a} ${operator} ${b}).${matcher}(true)`, + `expect(${a} ${operator} ${b}).${matcher}(false)`, + `expect(${a} ${operator} ${b}).not.${matcher}(true)`, + `expect(${a} ${operator} ${b}).not.${matcher}(false)`, + `expect(${a} ${operator} ${b}).resolves.${matcher}(true)`, + `expect(${a} ${operator} ${b}).resolves.${matcher}(false)`, + `expect(${a} ${operator} ${b}).resolves.not.${matcher}(true)`, + `expect(${a} ${operator} ${b}).resolves.not.${matcher}(false)`, + `expect(${b} ${operator} ${a}).resolves.not.${matcher}(false)`, + `expect(${b} ${operator} ${a}).resolves.not.${matcher}(true)`, + `expect(${b} ${operator} ${a}).resolves.${matcher}(false)`, + `expect(${b} ${operator} ${a}).resolves.${matcher}(true)`, + `expect(${b} ${operator} ${a}).not.${matcher}(false)`, + `expect(${b} ${operator} ${a}).not.${matcher}(true)`, + `expect(${b} ${operator} ${a}).${matcher}(false)`, + `expect(${b} ${operator} ${a}).${matcher}(true)`, + ]); }; const testComparisonOperator = ( @@ -244,27 +238,17 @@ const testComparisonOperator = ( `expect(value).${preferredMatcherWhenNegated}(1);`, `expect(value).not.${preferredMatcher}(1);`, `expect(value).not.${preferredMatcherWhenNegated}(1);`, - ...['toBe', 'toEqual', 'toStrictEqual'].reduce( - (cases, equalityMatcher) => [ - ...cases, - ...generateValidStringLiteralCases(operator, equalityMatcher), - ], - [], + ...['toBe', 'toEqual', 'toStrictEqual'].flatMap(equalityMatcher => + generateValidStringLiteralCases(operator, equalityMatcher), ), ], - invalid: ['toBe', 'toEqual', 'toStrictEqual'].reduce< - Array> - >( - (cases, equalityMatcher) => [ - ...cases, - ...generateInvalidCases( - operator, - equalityMatcher, - preferredMatcher, - preferredMatcherWhenNegated, - ), - ], - [], + invalid: ['toBe', 'toEqual', 'toStrictEqual'].flatMap(equalityMatcher => + generateInvalidCases( + operator, + equalityMatcher, + preferredMatcher, + preferredMatcherWhenNegated, + ), ), }); }; diff --git a/src/rules/utils/misc.ts b/src/rules/utils/misc.ts index e5e32a643..15c886487 100644 --- a/src/rules/utils/misc.ts +++ b/src/rules/utils/misc.ts @@ -137,18 +137,14 @@ export const getTestCallExpressionsFromDeclaredVariables = ( declaredVariables: readonly TSESLint.Scope.Variable[], context: TSESLint.RuleContext, ): TSESTree.CallExpression[] => { - return declaredVariables.reduce( - (acc, { references }) => - acc.concat( - references - .map(({ identifier }) => identifier.parent) - .filter( - (node): node is TSESTree.CallExpression => - node?.type === AST_NODE_TYPES.CallExpression && - isTypeOfJestFnCall(node, context, ['test']), - ), + return declaredVariables.flatMap(({ references }) => + references + .map(({ identifier }) => identifier.parent) + .filter( + (node): node is TSESTree.CallExpression => + node?.type === AST_NODE_TYPES.CallExpression && + isTypeOfJestFnCall(node, context, ['test']), ), - [], ); }; From af4a9c94d624b5db4643c994f5bec96b0cb889b8 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Sat, 30 Mar 2024 11:19:38 +1300 Subject: [PATCH 18/23] fix(no-large-snapshots): avoid `instanceof RegExp` check for ESLint v9 compatibility (#1542) --- src/rules/no-large-snapshots.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rules/no-large-snapshots.ts b/src/rules/no-large-snapshots.ts index 2425823c0..a33484628 100644 --- a/src/rules/no-large-snapshots.ts +++ b/src/rules/no-large-snapshots.ts @@ -54,11 +54,11 @@ const reportOnViolation = ( const snapshotName = getAccessorValue(node.expression.left.property); isAllowed = allowedSnapshotsInFile.some(name => { - if (name instanceof RegExp) { - return name.test(snapshotName); + if (typeof name === 'string') { + return snapshotName === name; } - return snapshotName === name; + return name.test(snapshotName); }); } } From 7bc48aad06bb763e0fccca204740e61cefb9648f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 29 Mar 2024 22:22:29 +0000 Subject: [PATCH 19/23] chore(release): 28.0.0-next.6 [skip ci] # [28.0.0-next.6](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.5...v28.0.0-next.6) (2024-03-29) ### Bug Fixes * **no-large-snapshots:** avoid `instanceof RegExp` check for ESLint v9 compatibility ([#1542](https://github.com/jest-community/eslint-plugin-jest/issues/1542)) ([af4a9c9](https://github.com/jest-community/eslint-plugin-jest/commit/af4a9c94d624b5db4643c994f5bec96b0cb889b8)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fce1647a..c83e83460 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [28.0.0-next.6](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.5...v28.0.0-next.6) (2024-03-29) + + +### Bug Fixes + +* **no-large-snapshots:** avoid `instanceof RegExp` check for ESLint v9 compatibility ([#1542](https://github.com/jest-community/eslint-plugin-jest/issues/1542)) ([af4a9c9](https://github.com/jest-community/eslint-plugin-jest/commit/af4a9c94d624b5db4643c994f5bec96b0cb889b8)) + # [28.0.0-next.5](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.4...v28.0.0-next.5) (2024-03-27) diff --git a/package.json b/package.json index 170374843..12ea23063 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-jest", - "version": "28.0.0-next.5", + "version": "28.0.0-next.6", "description": "ESLint rules for Jest", "keywords": [ "eslint", From 59d642c5d434feb314d2ece23d054044a5ce5615 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Mon, 1 Apr 2024 07:32:14 +1300 Subject: [PATCH 20/23] ci: run against upcoming next major ESLint version (#1534) * ci: run against next ESLint * test: make util * test: use a class * test: use a class (2) * test: improve compat class * refactor: make `flatCompat` util private * test: get `linter#verify` cases passing * ci: skip lint project on eslint v9 * test: ignore coverage in util class * chore: move Jest config into dedicated file * ci: handle skipping linting in Jest config * test: skip `unbound-method` when using `@typescript-eslint` v6 * ci: skip ESLint v9 on Node v16 * refactor: import `Config` from `jest` directly * refactor: address `@ts-expect-error`s * refactor: use a constant instead of a function --- .eslintrc.js | 2 +- .github/workflows/nodejs.yml | 7 +- jest.config.ts | 58 ++++++++++++++ package.json | 30 -------- .../__tests__/consistent-test-it.test.ts | 5 +- src/rules/__tests__/expect-expect.test.ts | 6 +- src/rules/__tests__/max-expects.test.ts | 5 +- .../__tests__/max-nested-describe.test.ts | 5 +- src/rules/__tests__/no-alias-methods.test.ts | 4 +- .../__tests__/no-commented-out-tests.test.ts | 5 +- .../__tests__/no-conditional-expect.test.ts | 5 +- .../__tests__/no-conditional-in-test.test.ts | 5 +- .../no-confusing-set-timeout.test.ts | 5 +- .../__tests__/no-deprecated-functions.test.ts | 17 +++- src/rules/__tests__/no-disabled-tests.test.ts | 5 +- src/rules/__tests__/no-done-callback.test.ts | 5 +- .../__tests__/no-duplicate-hooks.test.ts | 5 +- src/rules/__tests__/no-export.test.ts | 5 +- src/rules/__tests__/no-focused-tests.test.ts | 5 +- src/rules/__tests__/no-hooks.test.ts | 5 +- .../__tests__/no-identical-title.test.ts | 5 +- .../no-interpolation-in-snapshots.test.ts | 5 +- .../__tests__/no-jasmine-globals.test.ts | 4 +- .../__tests__/no-large-snapshots.test.ts | 36 ++++++++- src/rules/__tests__/no-mocks-import.test.ts | 5 +- .../no-restricted-jest-methods.test.ts | 5 +- .../__tests__/no-restricted-matchers.test.ts | 5 +- .../__tests__/no-standalone-expect.test.ts | 5 +- src/rules/__tests__/no-test-prefixes.test.ts | 4 +- .../no-test-return-statement.test.ts | 5 +- .../__tests__/no-untyped-mock-factory.test.ts | 4 +- .../__tests__/prefer-called-with.test.ts | 4 +- .../prefer-comparison-matcher.test.ts | 6 +- src/rules/__tests__/prefer-each.test.ts | 5 +- .../__tests__/prefer-equality-matcher.test.ts | 6 +- .../prefer-expect-assertions.test.ts | 5 +- .../__tests__/prefer-expect-resolves.test.ts | 5 +- .../__tests__/prefer-hooks-in-order.test.ts | 5 +- .../__tests__/prefer-hooks-on-top.test.ts | 5 +- .../__tests__/prefer-lowercase-title.test.ts | 5 +- .../prefer-mock-promise-shorthand.test.ts | 5 +- .../__tests__/prefer-snapshot-hint.test.ts | 5 +- src/rules/__tests__/prefer-spy-on.test.ts | 6 +- .../__tests__/prefer-strict-equal.test.ts | 4 +- src/rules/__tests__/prefer-to-be.test.ts | 7 +- src/rules/__tests__/prefer-to-contain.test.ts | 7 +- .../__tests__/prefer-to-have-length.test.ts | 5 +- src/rules/__tests__/prefer-todo.test.ts | 5 +- src/rules/__tests__/require-hook.test.ts | 7 +- .../require-to-throw-message.test.ts | 5 +- .../require-top-level-describe.test.ts | 5 +- src/rules/__tests__/test-utils.ts | 77 +++++++++++++++++++ src/rules/__tests__/unbound-method.test.ts | 7 +- .../__tests__/valid-describe-callback.test.ts | 5 +- .../__tests__/valid-expect-in-promise.test.ts | 5 +- src/rules/__tests__/valid-expect.test.ts | 5 +- src/rules/__tests__/valid-title.test.ts | 5 +- .../utils/__tests__/parseJestFnCall.test.ts | 6 +- 58 files changed, 303 insertions(+), 186 deletions(-) create mode 100644 jest.config.ts diff --git a/.eslintrc.js b/.eslintrc.js index 20228a5a3..f5c296ce2 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -98,7 +98,7 @@ module.exports = { globals, }, { - files: ['src/**/*', 'dangerfile.ts', 'tools/*'], + files: ['src/**/*', 'dangerfile.ts', 'tools/*', './jest.config.ts'], parserOptions: { sourceType: 'module', }, diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 4c6f0f314..115857667 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -72,12 +72,15 @@ jobs: fail-fast: false matrix: node-version: [16.x, 18.x, 19.x, 20.x, 21.x] - eslint-version: [7, 8] + eslint-version: [7, 8, next] ts-eslint-plugin-version: [6, 7] exclude: # ts-eslint/plugin@7 doesn't support node@16 - node-version: 16.x ts-eslint-plugin-version: 7 + # eslint@9 doesn't support node@16 + - node-version: 16.x + eslint-version: next # ts-eslint/plugin@7 doesn't support node@19 - node-version: 19.x ts-eslint-plugin-version: 7 @@ -103,7 +106,7 @@ jobs: yarn add --dev eslint@${{ matrix.eslint-version }} @typescript-eslint/eslint-plugin@${{ matrix.ts-eslint-plugin-version }} @typescript-eslint/parser@${{ matrix.ts-eslint-plugin-version }} - name: run tests # only collect coverage on eslint versions that support dynamic import - run: yarn test --coverage ${{ matrix.eslint-version >= 8 }} + run: yarn test --coverage ${{ matrix.eslint-version == 8 }} env: CI: true - uses: codecov/codecov-action@v3 diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 000000000..e5a6b638e --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,58 @@ +import { version as typescriptESLintPluginVersion } from '@typescript-eslint/eslint-plugin/package.json'; +import { version as eslintVersion } from 'eslint/package.json'; +import type { Config } from 'jest'; +import * as semver from 'semver'; + +const config = { + clearMocks: true, + restoreMocks: true, + resetMocks: true, + + coverageThreshold: { + global: { + branches: 100, + functions: 100, + lines: 100, + statements: 100, + }, + }, + + projects: [ + { + displayName: 'test', + testPathIgnorePatterns: [ + '/lib/.*', + '/src/rules/__tests__/fixtures/*', + '/src/rules/__tests__/test-utils.ts', + ], + coveragePathIgnorePatterns: ['/node_modules/'], + }, + { + displayName: 'lint', + runner: 'jest-runner-eslint', + testMatch: ['/**/*.{js,ts}'], + testPathIgnorePatterns: ['/lib/.*'], + coveragePathIgnorePatterns: ['/node_modules/'], + }, + ], +} satisfies Config; + +if (semver.major(eslintVersion) >= 9) { + config.projects = config.projects.filter( + ({ displayName }) => displayName !== 'lint', + ); + + // jest/unbound-method doesn't work when using @typescript-eslint v6 + if (semver.major(typescriptESLintPluginVersion) === 6) { + for (const project of config.projects) { + project.testPathIgnorePatterns.push( + '/src/rules/__tests__/unbound-method.test.ts', + ); + project.coveragePathIgnorePatterns.push( + '/src/rules/unbound-method.ts', + ); + } + } +} + +export default config; diff --git a/package.json b/package.json index 12ea23063..aff8c6ca4 100644 --- a/package.json +++ b/package.json @@ -64,36 +64,6 @@ "@semantic-release/github" ] }, - "jest": { - "coverageThreshold": { - "global": { - "branches": 100, - "functions": 100, - "lines": 100, - "statements": 100 - } - }, - "projects": [ - { - "displayName": "test", - "testPathIgnorePatterns": [ - "/lib/.*", - "/src/rules/__tests__/fixtures/*", - "/src/rules/__tests__/test-utils.ts" - ] - }, - { - "displayName": "lint", - "runner": "jest-runner-eslint", - "testMatch": [ - "/**/*.{js,ts}" - ], - "testPathIgnorePatterns": [ - "/lib/.*" - ] - } - ] - }, "dependencies": { "@typescript-eslint/utils": "^6.0.0" }, diff --git a/src/rules/__tests__/consistent-test-it.test.ts b/src/rules/__tests__/consistent-test-it.test.ts index 354629e17..c11577c22 100644 --- a/src/rules/__tests__/consistent-test-it.test.ts +++ b/src/rules/__tests__/consistent-test-it.test.ts @@ -1,10 +1,9 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../consistent-test-it'; import { TestCaseName } from '../utils'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/expect-expect.test.ts b/src/rules/__tests__/expect-expect.test.ts index edaed7a4a..59018e817 100644 --- a/src/rules/__tests__/expect-expect.test.ts +++ b/src/rules/__tests__/expect-expect.test.ts @@ -1,9 +1,9 @@ -import { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/utils'; +import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../expect-expect'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/max-expects.test.ts b/src/rules/__tests__/max-expects.test.ts index 17a2853fb..e629c5695 100644 --- a/src/rules/__tests__/max-expects.test.ts +++ b/src/rules/__tests__/max-expects.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../max-expects'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, diff --git a/src/rules/__tests__/max-nested-describe.test.ts b/src/rules/__tests__/max-nested-describe.test.ts index a23465071..54301882e 100644 --- a/src/rules/__tests__/max-nested-describe.test.ts +++ b/src/rules/__tests__/max-nested-describe.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../max-nested-describe'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, diff --git a/src/rules/__tests__/no-alias-methods.test.ts b/src/rules/__tests__/no-alias-methods.test.ts index 22b1bf954..a49717f2f 100644 --- a/src/rules/__tests__/no-alias-methods.test.ts +++ b/src/rules/__tests__/no-alias-methods.test.ts @@ -1,7 +1,7 @@ -import { TSESLint } from '@typescript-eslint/utils'; import rule from '../no-alias-methods'; +import { FlatCompatRuleTester } from './test-utils'; -const ruleTester = new TSESLint.RuleTester(); +const ruleTester = new FlatCompatRuleTester(); ruleTester.run('no-alias-methods', rule, { valid: [ diff --git a/src/rules/__tests__/no-commented-out-tests.test.ts b/src/rules/__tests__/no-commented-out-tests.test.ts index 540269919..d919a0bb7 100644 --- a/src/rules/__tests__/no-commented-out-tests.test.ts +++ b/src/rules/__tests__/no-commented-out-tests.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-commented-out-tests'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/no-conditional-expect.test.ts b/src/rules/__tests__/no-conditional-expect.test.ts index 86c9cee5d..93eddc043 100644 --- a/src/rules/__tests__/no-conditional-expect.test.ts +++ b/src/rules/__tests__/no-conditional-expect.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-conditional-expect'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2019, diff --git a/src/rules/__tests__/no-conditional-in-test.test.ts b/src/rules/__tests__/no-conditional-in-test.test.ts index f133a7647..c005cd3c1 100644 --- a/src/rules/__tests__/no-conditional-in-test.test.ts +++ b/src/rules/__tests__/no-conditional-in-test.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-conditional-in-test'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/no-confusing-set-timeout.test.ts b/src/rules/__tests__/no-confusing-set-timeout.test.ts index c7369d1ac..ec2d9a276 100644 --- a/src/rules/__tests__/no-confusing-set-timeout.test.ts +++ b/src/rules/__tests__/no-confusing-set-timeout.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-confusing-set-timeout'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2020, diff --git a/src/rules/__tests__/no-deprecated-functions.test.ts b/src/rules/__tests__/no-deprecated-functions.test.ts index bd5153500..4fd970c3a 100644 --- a/src/rules/__tests__/no-deprecated-functions.test.ts +++ b/src/rules/__tests__/no-deprecated-functions.test.ts @@ -4,6 +4,7 @@ import { type JestVersion, detectJestVersion, } from '../utils/detectJestVersion'; +import { FlatCompatRuleTester, usingFlatConfig } from './test-utils'; jest.mock('../utils/detectJestVersion'); @@ -11,7 +12,7 @@ const detectJestVersionMock = detectJestVersion as jest.MockedFunction< typeof detectJestVersion >; -const ruleTester = new TSESLint.RuleTester(); +const ruleTester = new FlatCompatRuleTester(); const generateValidCases = ( jestVersion: JestVersion | string | undefined, @@ -154,6 +155,20 @@ describe('the rule', () => { expect(() => { const linter = new TSESLint.Linter(); + /* istanbul ignore if */ + if (usingFlatConfig) { + linter.verify('jest.resetModuleRegistry()', [ + { + plugins: { + jest: { rules: { 'no-deprecated-functions': rule } }, + }, + rules: { 'jest/no-deprecated-functions': 'error' }, + }, + ]); + + return; + } + linter.defineRule('no-deprecated-functions', rule); linter.verify('jest.resetModuleRegistry()', { diff --git a/src/rules/__tests__/no-disabled-tests.test.ts b/src/rules/__tests__/no-disabled-tests.test.ts index b331767ba..0210d1a94 100644 --- a/src/rules/__tests__/no-disabled-tests.test.ts +++ b/src/rules/__tests__/no-disabled-tests.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-disabled-tests'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/no-done-callback.test.ts b/src/rules/__tests__/no-done-callback.test.ts index 3990ebcb8..0fef8cb61 100644 --- a/src/rules/__tests__/no-done-callback.test.ts +++ b/src/rules/__tests__/no-done-callback.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-done-callback'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, diff --git a/src/rules/__tests__/no-duplicate-hooks.test.ts b/src/rules/__tests__/no-duplicate-hooks.test.ts index 12e067392..48b198ea4 100644 --- a/src/rules/__tests__/no-duplicate-hooks.test.ts +++ b/src/rules/__tests__/no-duplicate-hooks.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-duplicate-hooks'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/no-export.test.ts b/src/rules/__tests__/no-export.test.ts index 2fc5dbb52..8a5f3e3a6 100644 --- a/src/rules/__tests__/no-export.test.ts +++ b/src/rules/__tests__/no-export.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-export'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/no-focused-tests.test.ts b/src/rules/__tests__/no-focused-tests.test.ts index 320610868..46946f8e7 100644 --- a/src/rules/__tests__/no-focused-tests.test.ts +++ b/src/rules/__tests__/no-focused-tests.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-focused-tests'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 6, diff --git a/src/rules/__tests__/no-hooks.test.ts b/src/rules/__tests__/no-hooks.test.ts index ffb3e1c8f..915e41f0a 100644 --- a/src/rules/__tests__/no-hooks.test.ts +++ b/src/rules/__tests__/no-hooks.test.ts @@ -1,10 +1,9 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-hooks'; import { HookName } from '../utils'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/no-identical-title.test.ts b/src/rules/__tests__/no-identical-title.test.ts index 28c1e011e..5e601ee71 100644 --- a/src/rules/__tests__/no-identical-title.test.ts +++ b/src/rules/__tests__/no-identical-title.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-identical-title'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/no-interpolation-in-snapshots.test.ts b/src/rules/__tests__/no-interpolation-in-snapshots.test.ts index e54f1f1a4..d5ab94d27 100644 --- a/src/rules/__tests__/no-interpolation-in-snapshots.test.ts +++ b/src/rules/__tests__/no-interpolation-in-snapshots.test.ts @@ -1,8 +1,7 @@ -import { TSESLint } from '@typescript-eslint/utils'; import rule from '../no-interpolation-in-snapshots'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, diff --git a/src/rules/__tests__/no-jasmine-globals.test.ts b/src/rules/__tests__/no-jasmine-globals.test.ts index e4ac33425..ba25ebe6f 100644 --- a/src/rules/__tests__/no-jasmine-globals.test.ts +++ b/src/rules/__tests__/no-jasmine-globals.test.ts @@ -1,7 +1,7 @@ -import { TSESLint } from '@typescript-eslint/utils'; import rule from '../no-jasmine-globals'; +import { FlatCompatRuleTester } from './test-utils'; -const ruleTester = new TSESLint.RuleTester(); +const ruleTester = new FlatCompatRuleTester(); ruleTester.run('no-jasmine-globals', rule, { valid: [ diff --git a/src/rules/__tests__/no-large-snapshots.test.ts b/src/rules/__tests__/no-large-snapshots.test.ts index 981f7935b..5d8fa2500 100644 --- a/src/rules/__tests__/no-large-snapshots.test.ts +++ b/src/rules/__tests__/no-large-snapshots.test.ts @@ -1,9 +1,13 @@ import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-large-snapshots'; -import { espreeParser } from './test-utils'; +import { + FlatCompatRuleTester, + espreeParser, + usingFlatConfig, +} from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, @@ -267,6 +271,34 @@ describe('no-large-snapshots', () => { expect(() => { const linter = new TSESLint.Linter(); + /* istanbul ignore if */ + if (usingFlatConfig) { + linter.verify( + 'console.log()', + [ + { + files: ['*.snap'], + plugins: { + jest: { rules: { 'no-large-snapshots': rule } }, + }, + rules: { + 'jest/no-large-snapshots': [ + 'error', + { + allowedSnapshots: { + 'mock-component.jsx.snap': [/a big component \d+/u], + }, + }, + ], + }, + }, + ], + 'mock-component.jsx.snap', + ); + + return; + } + linter.defineRule('no-large-snapshots', rule); linter.verify( diff --git a/src/rules/__tests__/no-mocks-import.test.ts b/src/rules/__tests__/no-mocks-import.test.ts index cdeb49361..de59594df 100644 --- a/src/rules/__tests__/no-mocks-import.test.ts +++ b/src/rules/__tests__/no-mocks-import.test.ts @@ -1,8 +1,7 @@ -import { TSESLint } from '@typescript-eslint/utils'; import rule from '../no-mocks-import'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/no-restricted-jest-methods.test.ts b/src/rules/__tests__/no-restricted-jest-methods.test.ts index dc60aba1d..20e0b98ed 100644 --- a/src/rules/__tests__/no-restricted-jest-methods.test.ts +++ b/src/rules/__tests__/no-restricted-jest-methods.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-restricted-jest-methods'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, diff --git a/src/rules/__tests__/no-restricted-matchers.test.ts b/src/rules/__tests__/no-restricted-matchers.test.ts index 60cfd963b..b31d2d10b 100644 --- a/src/rules/__tests__/no-restricted-matchers.test.ts +++ b/src/rules/__tests__/no-restricted-matchers.test.ts @@ -1,8 +1,7 @@ -import { TSESLint } from '@typescript-eslint/utils'; import rule from '../no-restricted-matchers'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, diff --git a/src/rules/__tests__/no-standalone-expect.test.ts b/src/rules/__tests__/no-standalone-expect.test.ts index 439a302de..342f61039 100644 --- a/src/rules/__tests__/no-standalone-expect.test.ts +++ b/src/rules/__tests__/no-standalone-expect.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-standalone-expect'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/no-test-prefixes.test.ts b/src/rules/__tests__/no-test-prefixes.test.ts index b688c883a..107bf4c3b 100644 --- a/src/rules/__tests__/no-test-prefixes.test.ts +++ b/src/rules/__tests__/no-test-prefixes.test.ts @@ -1,8 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-test-prefixes'; +import { FlatCompatRuleTester } from './test-utils'; -const ruleTester = new TSESLint.RuleTester(); +const ruleTester = new FlatCompatRuleTester(); ruleTester.run('no-test-prefixes', rule, { valid: [ diff --git a/src/rules/__tests__/no-test-return-statement.test.ts b/src/rules/__tests__/no-test-return-statement.test.ts index 9209ed00e..30314f52f 100644 --- a/src/rules/__tests__/no-test-return-statement.test.ts +++ b/src/rules/__tests__/no-test-return-statement.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-test-return-statement'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015 }, }); diff --git a/src/rules/__tests__/no-untyped-mock-factory.test.ts b/src/rules/__tests__/no-untyped-mock-factory.test.ts index 171497699..9965ca771 100644 --- a/src/rules/__tests__/no-untyped-mock-factory.test.ts +++ b/src/rules/__tests__/no-untyped-mock-factory.test.ts @@ -1,8 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../no-untyped-mock-factory'; +import { FlatCompatRuleTester } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: require.resolve('@typescript-eslint/parser'), }); diff --git a/src/rules/__tests__/prefer-called-with.test.ts b/src/rules/__tests__/prefer-called-with.test.ts index cf2832199..e41d17adc 100644 --- a/src/rules/__tests__/prefer-called-with.test.ts +++ b/src/rules/__tests__/prefer-called-with.test.ts @@ -1,7 +1,7 @@ -import { TSESLint } from '@typescript-eslint/utils'; import rule from '../prefer-called-with'; +import { FlatCompatRuleTester } from './test-utils'; -const ruleTester = new TSESLint.RuleTester(); +const ruleTester = new FlatCompatRuleTester(); ruleTester.run('prefer-called-with', rule, { valid: [ diff --git a/src/rules/__tests__/prefer-comparison-matcher.test.ts b/src/rules/__tests__/prefer-comparison-matcher.test.ts index d0dca2dd4..a72d030a0 100644 --- a/src/rules/__tests__/prefer-comparison-matcher.test.ts +++ b/src/rules/__tests__/prefer-comparison-matcher.test.ts @@ -1,8 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; +import type { TSESLint } from '@typescript-eslint/utils'; import rule from '../prefer-comparison-matcher'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/prefer-each.test.ts b/src/rules/__tests__/prefer-each.test.ts index d001ccb0c..7abde3462 100644 --- a/src/rules/__tests__/prefer-each.test.ts +++ b/src/rules/__tests__/prefer-each.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../prefer-each'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/prefer-equality-matcher.test.ts b/src/rules/__tests__/prefer-equality-matcher.test.ts index 0f18bacb2..7b266c62f 100644 --- a/src/rules/__tests__/prefer-equality-matcher.test.ts +++ b/src/rules/__tests__/prefer-equality-matcher.test.ts @@ -1,8 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; +import type { TSESLint } from '@typescript-eslint/utils'; import rule from '../prefer-equality-matcher'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/prefer-expect-assertions.test.ts b/src/rules/__tests__/prefer-expect-assertions.test.ts index 0808608bb..d83a1a056 100644 --- a/src/rules/__tests__/prefer-expect-assertions.test.ts +++ b/src/rules/__tests__/prefer-expect-assertions.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../prefer-expect-assertions'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, diff --git a/src/rules/__tests__/prefer-expect-resolves.test.ts b/src/rules/__tests__/prefer-expect-resolves.test.ts index 8f7b6589b..37176df2f 100644 --- a/src/rules/__tests__/prefer-expect-resolves.test.ts +++ b/src/rules/__tests__/prefer-expect-resolves.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../prefer-expect-resolves'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, diff --git a/src/rules/__tests__/prefer-hooks-in-order.test.ts b/src/rules/__tests__/prefer-hooks-in-order.test.ts index ca55d2e22..6dfc03219 100644 --- a/src/rules/__tests__/prefer-hooks-in-order.test.ts +++ b/src/rules/__tests__/prefer-hooks-in-order.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../prefer-hooks-in-order'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/prefer-hooks-on-top.test.ts b/src/rules/__tests__/prefer-hooks-on-top.test.ts index e8dc3f859..54e7267ec 100644 --- a/src/rules/__tests__/prefer-hooks-on-top.test.ts +++ b/src/rules/__tests__/prefer-hooks-on-top.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../prefer-hooks-on-top'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/prefer-lowercase-title.test.ts b/src/rules/__tests__/prefer-lowercase-title.test.ts index f745885d3..d8d94d11f 100644 --- a/src/rules/__tests__/prefer-lowercase-title.test.ts +++ b/src/rules/__tests__/prefer-lowercase-title.test.ts @@ -1,10 +1,9 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../prefer-lowercase-title'; import { DescribeAlias, TestCaseName } from '../utils'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/prefer-mock-promise-shorthand.test.ts b/src/rules/__tests__/prefer-mock-promise-shorthand.test.ts index c5d94af1f..d04d9a86c 100644 --- a/src/rules/__tests__/prefer-mock-promise-shorthand.test.ts +++ b/src/rules/__tests__/prefer-mock-promise-shorthand.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../prefer-mock-promise-shorthand'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 6, diff --git a/src/rules/__tests__/prefer-snapshot-hint.test.ts b/src/rules/__tests__/prefer-snapshot-hint.test.ts index dad2b6cde..e38985524 100644 --- a/src/rules/__tests__/prefer-snapshot-hint.test.ts +++ b/src/rules/__tests__/prefer-snapshot-hint.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../prefer-snapshot-hint'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/prefer-spy-on.test.ts b/src/rules/__tests__/prefer-spy-on.test.ts index fd847b100..69d4a0c75 100644 --- a/src/rules/__tests__/prefer-spy-on.test.ts +++ b/src/rules/__tests__/prefer-spy-on.test.ts @@ -1,8 +1,8 @@ -import { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/utils'; +import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import rule from '../prefer-spy-on'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/prefer-strict-equal.test.ts b/src/rules/__tests__/prefer-strict-equal.test.ts index 670a5c12b..cc245dbad 100644 --- a/src/rules/__tests__/prefer-strict-equal.test.ts +++ b/src/rules/__tests__/prefer-strict-equal.test.ts @@ -1,7 +1,7 @@ -import { TSESLint } from '@typescript-eslint/utils'; import rule from '../prefer-strict-equal'; +import { FlatCompatRuleTester } from './test-utils'; -const ruleTester = new TSESLint.RuleTester(); +const ruleTester = new FlatCompatRuleTester(); ruleTester.run('prefer-strict-equal', rule, { valid: [ diff --git a/src/rules/__tests__/prefer-to-be.test.ts b/src/rules/__tests__/prefer-to-be.test.ts index 86ac70558..5cf0b0f36 100644 --- a/src/rules/__tests__/prefer-to-be.test.ts +++ b/src/rules/__tests__/prefer-to-be.test.ts @@ -1,8 +1,7 @@ -import { TSESLint } from '@typescript-eslint/utils'; import rule from '../prefer-to-be'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, @@ -317,7 +316,7 @@ ruleTester.run('prefer-to-be: undefined vs defined', rule, { ], }); -new TSESLint.RuleTester({ +new FlatCompatRuleTester({ parser: require.resolve('@typescript-eslint/parser'), }).run('prefer-to-be: typescript edition', rule, { valid: [ diff --git a/src/rules/__tests__/prefer-to-contain.test.ts b/src/rules/__tests__/prefer-to-contain.test.ts index 458e5d62a..4ff45cd30 100644 --- a/src/rules/__tests__/prefer-to-contain.test.ts +++ b/src/rules/__tests__/prefer-to-contain.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../prefer-to-contain'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, @@ -212,7 +211,7 @@ ruleTester.run('prefer-to-contain', rule, { ], }); -new TSESLint.RuleTester({ +new FlatCompatRuleTester({ parser: require.resolve('@typescript-eslint/parser'), }).run('prefer-to-be-null: typescript edition', rule, { valid: [ diff --git a/src/rules/__tests__/prefer-to-have-length.test.ts b/src/rules/__tests__/prefer-to-have-length.test.ts index a7f0807d4..2389d3024 100644 --- a/src/rules/__tests__/prefer-to-have-length.test.ts +++ b/src/rules/__tests__/prefer-to-have-length.test.ts @@ -1,8 +1,7 @@ -import { TSESLint } from '@typescript-eslint/utils'; import rule from '../prefer-to-have-length'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2020, diff --git a/src/rules/__tests__/prefer-todo.test.ts b/src/rules/__tests__/prefer-todo.test.ts index e36b3a5b1..e5c288247 100644 --- a/src/rules/__tests__/prefer-todo.test.ts +++ b/src/rules/__tests__/prefer-todo.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../prefer-todo'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015 }, }); diff --git a/src/rules/__tests__/require-hook.test.ts b/src/rules/__tests__/require-hook.test.ts index e952739cc..49f00ec6a 100644 --- a/src/rules/__tests__/require-hook.test.ts +++ b/src/rules/__tests__/require-hook.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../require-hook'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, @@ -408,7 +407,7 @@ ruleTester.run('require-hook', rule, { ], }); -new TSESLint.RuleTester({ +new FlatCompatRuleTester({ parser: require.resolve('@typescript-eslint/parser'), }).run('require-hook: typescript edition', rule, { valid: [ diff --git a/src/rules/__tests__/require-to-throw-message.test.ts b/src/rules/__tests__/require-to-throw-message.test.ts index 39b7deba9..695f36c0c 100644 --- a/src/rules/__tests__/require-to-throw-message.test.ts +++ b/src/rules/__tests__/require-to-throw-message.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../require-to-throw-message'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, diff --git a/src/rules/__tests__/require-top-level-describe.test.ts b/src/rules/__tests__/require-top-level-describe.test.ts index be01704f7..34f80fd4a 100644 --- a/src/rules/__tests__/require-top-level-describe.test.ts +++ b/src/rules/__tests__/require-top-level-describe.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../require-top-level-describe'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, diff --git a/src/rules/__tests__/test-utils.ts b/src/rules/__tests__/test-utils.ts index f21066c16..398b502f1 100644 --- a/src/rules/__tests__/test-utils.ts +++ b/src/rules/__tests__/test-utils.ts @@ -1,6 +1,83 @@ import { createRequire } from 'module'; +import { TSESLint } from '@typescript-eslint/utils'; +import { version as eslintVersion } from 'eslint/package.json'; +import * as semver from 'semver'; const require = createRequire(__filename); const eslintRequire = createRequire(require.resolve('eslint')); export const espreeParser = eslintRequire.resolve('espree'); + +export const usingFlatConfig = semver.major(eslintVersion) >= 9; + +export class FlatCompatRuleTester extends TSESLint.RuleTester { + public constructor(testerConfig?: TSESLint.RuleTesterConfig) { + super(FlatCompatRuleTester._flatCompat(testerConfig)); + } + + public override run< + TMessageIds extends string, + TOptions extends Readonly, + >( + ruleName: string, + rule: TSESLint.RuleModule, + tests: TSESLint.RunTests, + ) { + super.run(ruleName, rule, { + valid: tests.valid.map(t => FlatCompatRuleTester._flatCompat(t)), + invalid: tests.invalid.map(t => FlatCompatRuleTester._flatCompat(t)), + }); + } + + /* istanbul ignore next */ + private static _flatCompat< + T extends + | undefined + | TSESLint.RuleTesterConfig + | string + | TSESLint.ValidTestCase + | TSESLint.InvalidTestCase, + >(config: T): T { + if (!config || !usingFlatConfig || typeof config === 'string') { + return config; + } + + const obj: TSESLint.FlatConfig.Config & { + languageOptions: TSESLint.FlatConfig.LanguageOptions & { + parserOptions: TSESLint.FlatConfig.ParserOptions; + }; + } = { + languageOptions: { parserOptions: {} }, + }; + + for (const [key, value] of Object.entries(config)) { + if (key === 'parser') { + obj.languageOptions.parser = require(value); + + continue; + } + + if (key === 'parserOptions') { + for (const [option, val] of Object.entries(value)) { + if (option === 'ecmaVersion' || option === 'sourceType') { + // @ts-expect-error: TS thinks the value could the opposite type of whatever option is + obj.languageOptions[option] = + val as TSESLint.FlatConfig.LanguageOptions[ + | 'ecmaVersion' + | 'sourceType']; + + continue; + } + + obj.languageOptions.parserOptions[option] = val; + } + + continue; + } + + obj[key as keyof typeof obj] = value; + } + + return obj as unknown as T; + } +} diff --git a/src/rules/__tests__/unbound-method.test.ts b/src/rules/__tests__/unbound-method.test.ts index 6aa494e79..934f29fa6 100644 --- a/src/rules/__tests__/unbound-method.test.ts +++ b/src/rules/__tests__/unbound-method.test.ts @@ -1,7 +1,8 @@ import path from 'path'; -import { TSESLint } from '@typescript-eslint/utils'; +import type { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import type { MessageIds, Options } from '../unbound-method'; +import { FlatCompatRuleTester } from './test-utils'; function getFixturesRootDir(): string { return path.join(__dirname, 'fixtures'); @@ -9,7 +10,7 @@ function getFixturesRootDir(): string { const rootPath = getFixturesRootDir(); -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: require.resolve('@typescript-eslint/parser'), parserOptions: { sourceType: 'module', @@ -184,7 +185,7 @@ describe('error handling', () => { }); describe('when @typescript-eslint/eslint-plugin is not available', () => { - const ruleTester = new TSESLint.RuleTester({ + const ruleTester = new FlatCompatRuleTester({ parser: require.resolve('@typescript-eslint/parser'), parserOptions: { sourceType: 'module', diff --git a/src/rules/__tests__/valid-describe-callback.test.ts b/src/rules/__tests__/valid-describe-callback.test.ts index 83526a4b7..6fb15bb16 100644 --- a/src/rules/__tests__/valid-describe-callback.test.ts +++ b/src/rules/__tests__/valid-describe-callback.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../valid-describe-callback'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, diff --git a/src/rules/__tests__/valid-expect-in-promise.test.ts b/src/rules/__tests__/valid-expect-in-promise.test.ts index 8337c88af..efab56c14 100644 --- a/src/rules/__tests__/valid-expect-in-promise.test.ts +++ b/src/rules/__tests__/valid-expect-in-promise.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../valid-expect-in-promise'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, diff --git a/src/rules/__tests__/valid-expect.test.ts b/src/rules/__tests__/valid-expect.test.ts index bb503d825..9a4b5c1a0 100644 --- a/src/rules/__tests__/valid-expect.test.ts +++ b/src/rules/__tests__/valid-expect.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../valid-expect'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, diff --git a/src/rules/__tests__/valid-title.test.ts b/src/rules/__tests__/valid-title.test.ts index 181ef8cc5..8c8f26465 100644 --- a/src/rules/__tests__/valid-title.test.ts +++ b/src/rules/__tests__/valid-title.test.ts @@ -1,9 +1,8 @@ -import { TSESLint } from '@typescript-eslint/utils'; import dedent from 'dedent'; import rule from '../valid-title'; -import { espreeParser } from './test-utils'; +import { FlatCompatRuleTester, espreeParser } from './test-utils'; -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2017, diff --git a/src/rules/utils/__tests__/parseJestFnCall.test.ts b/src/rules/utils/__tests__/parseJestFnCall.test.ts index e119203f2..28c59abe9 100644 --- a/src/rules/utils/__tests__/parseJestFnCall.test.ts +++ b/src/rules/utils/__tests__/parseJestFnCall.test.ts @@ -1,7 +1,7 @@ import type { JSONSchemaForNPMPackageJsonFiles } from '@schemastore/package'; -import { TSESLint, type TSESTree } from '@typescript-eslint/utils'; +import type { TSESTree } from '@typescript-eslint/utils'; import dedent from 'dedent'; -import { espreeParser } from '../../__tests__/test-utils'; +import { FlatCompatRuleTester, espreeParser } from '../../__tests__/test-utils'; import { type ParsedJestFnCall, type ResolvedJestFnWithNode, @@ -29,7 +29,7 @@ const findESLintVersion = (): number => { const eslintVersion = findESLintVersion(); -const ruleTester = new TSESLint.RuleTester({ +const ruleTester = new FlatCompatRuleTester({ parser: espreeParser, parserOptions: { ecmaVersion: 2015, From 3c5e1673afd02dc2c9b90d259c0452326715ae6c Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 6 Apr 2024 10:00:05 +0200 Subject: [PATCH 21/23] fix: allow ESLint 9 as peer dependency (#1547) --- .github/workflows/nodejs.yml | 4 +- package.json | 4 +- yarn.lock | 160 ++++++++++++++--------------------- 3 files changed, 67 insertions(+), 101 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 115857667..af18c6a87 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -72,7 +72,7 @@ jobs: fail-fast: false matrix: node-version: [16.x, 18.x, 19.x, 20.x, 21.x] - eslint-version: [7, 8, next] + eslint-version: [7, 8, 9] ts-eslint-plugin-version: [6, 7] exclude: # ts-eslint/plugin@7 doesn't support node@16 @@ -80,7 +80,7 @@ jobs: ts-eslint-plugin-version: 7 # eslint@9 doesn't support node@16 - node-version: 16.x - eslint-version: next + eslint-version: 9 # ts-eslint/plugin@7 doesn't support node@19 - node-version: 19.x ts-eslint-plugin-version: 7 diff --git a/package.json b/package.json index aff8c6ca4..e30b2d511 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "babel-jest": "^29.0.0", "babel-plugin-replace-ts-export-assignment": "^0.0.2", "dedent": "^1.5.0", - "eslint": "^7.0.0 || ^8.0.0", + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", "eslint-config-prettier": "^9.0.0", "eslint-doc-generator": "^1.0.0", "eslint-plugin-eslint-comments": "^3.1.2", @@ -113,7 +113,7 @@ }, "peerDependencies": { "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0", - "eslint": "^7.0.0 || ^8.0.0", + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", "jest": "*" }, "peerDependenciesMeta": { diff --git a/yarn.lock b/yarn.lock index 9733c6a58..aaa62090f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1666,38 +1666,38 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.1.4": - version: 2.1.4 - resolution: "@eslint/eslintrc@npm:2.1.4" +"@eslint/eslintrc@npm:^3.0.2": + version: 3.0.2 + resolution: "@eslint/eslintrc@npm:3.0.2" dependencies: ajv: ^6.12.4 debug: ^4.3.2 - espree: ^9.6.0 - globals: ^13.19.0 + espree: ^10.0.1 + globals: ^14.0.0 ignore: ^5.2.0 import-fresh: ^3.2.1 js-yaml: ^4.1.0 minimatch: ^3.1.2 strip-json-comments: ^3.1.1 - checksum: 10957c7592b20ca0089262d8c2a8accbad14b4f6507e35416c32ee6b4dbf9cad67dfb77096bbd405405e9ada2b107f3797fe94362e1c55e0b09d6e90dd149127 + checksum: 05bf516b60fbb1c1bdc264e081118b2172c5feb071cd665976482c5614b8e7950991175fea3ca6b1f482ced7cb0d0aa34ceab3a508d6bf1ff17b4efc0911e293 languageName: node linkType: hard -"@eslint/js@npm:8.57.0": - version: 8.57.0 - resolution: "@eslint/js@npm:8.57.0" - checksum: 315dc65b0e9893e2bff139bddace7ea601ad77ed47b4550e73da8c9c2d2766c7a575c3cddf17ef85b8fd6a36ff34f91729d0dcca56e73ca887c10df91a41b0bb +"@eslint/js@npm:9.0.0": + version: 9.0.0 + resolution: "@eslint/js@npm:9.0.0" + checksum: bd8692d68fc79306ad44999fdec9c1ab39c72c3947034f5a251a9148bc175f1d831b54cbbe522d69d88d9d4f1b9e85a1495513553b8528fd8b107d77eadb713f languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.14": - version: 0.11.14 - resolution: "@humanwhocodes/config-array@npm:0.11.14" +"@humanwhocodes/config-array@npm:^0.12.3": + version: 0.12.3 + resolution: "@humanwhocodes/config-array@npm:0.12.3" dependencies: - "@humanwhocodes/object-schema": ^2.0.2 + "@humanwhocodes/object-schema": ^2.0.3 debug: ^4.3.1 minimatch: ^3.0.5 - checksum: 861ccce9eaea5de19546653bccf75bf09fe878bc39c3aab00aeee2d2a0e654516adad38dd1098aab5e3af0145bbcbf3f309bdf4d964f8dab9dcd5834ae4c02f2 + checksum: 4212cf12567538675f45f09dae9715978fac805fbc6f194ce31e62dbbe01ca286b87478463c042883bf4451998be737012dd0882530f55ad0c0e901d963b5123 languageName: node linkType: hard @@ -1708,7 +1708,7 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^2.0.2": +"@humanwhocodes/object-schema@npm:^2.0.3": version: 2.0.3 resolution: "@humanwhocodes/object-schema@npm:2.0.3" checksum: d3b78f6c5831888c6ecc899df0d03bcc25d46f3ad26a11d7ea52944dc36a35ef543fad965322174238d677a43d5c694434f6607532cff7077062513ad7022631 @@ -3164,13 +3164,6 @@ __metadata: languageName: node linkType: hard -"@ungap/structured-clone@npm:^1.2.0": - version: 1.2.0 - resolution: "@ungap/structured-clone@npm:1.2.0" - checksum: 4f656b7b4672f2ce6e272f2427d8b0824ed11546a601d8d5412b9d7704e83db38a8d9f402ecdf2b9063fc164af842ad0ec4a55819f621ed7e7ea4d1efcc74524 - languageName: node - linkType: hard - "JSONStream@npm:^1.3.5": version: 1.3.5 resolution: "JSONStream@npm:1.3.5" @@ -3206,7 +3199,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.4.1, acorn@npm:^8.9.0": +"acorn@npm:^8.11.3, acorn@npm:^8.4.1": version: 8.11.3 resolution: "acorn@npm:8.11.3" bin: @@ -4744,15 +4737,6 @@ __metadata: languageName: node linkType: hard -"doctrine@npm:^3.0.0": - version: 3.0.0 - resolution: "doctrine@npm:3.0.0" - dependencies: - esutils: ^2.0.2 - checksum: fd7673ca77fe26cd5cba38d816bc72d641f500f1f9b25b83e8ce28827fe2da7ad583a8da26ab6af85f834138cf8dae9f69b0cd6ab925f52ddab1754db44d99ce - languageName: node - linkType: hard - "dom-serializer@npm:^2.0.0": version: 2.0.0 resolution: "dom-serializer@npm:2.0.0" @@ -5225,7 +5209,7 @@ __metadata: babel-jest: ^29.0.0 babel-plugin-replace-ts-export-assignment: ^0.0.2 dedent: ^1.5.0 - eslint: ^7.0.0 || ^8.0.0 + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 eslint-config-prettier: ^9.0.0 eslint-doc-generator: ^1.0.0 eslint-plugin-eslint-comments: ^3.1.2 @@ -5251,7 +5235,7 @@ __metadata: typescript: ^5.0.4 peerDependencies: "@typescript-eslint/eslint-plugin": ^6.0.0 || ^7.0.0 - eslint: ^7.0.0 || ^8.0.0 + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 jest: "*" peerDependenciesMeta: "@typescript-eslint/eslint-plugin": @@ -5339,13 +5323,13 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^7.2.2": - version: 7.2.2 - resolution: "eslint-scope@npm:7.2.2" +"eslint-scope@npm:^8.0.1": + version: 8.0.1 + resolution: "eslint-scope@npm:8.0.1" dependencies: esrecurse: ^4.3.0 estraverse: ^5.2.0 - checksum: ec97dbf5fb04b94e8f4c5a91a7f0a6dd3c55e46bfc7bbcd0e3138c3a76977570e02ed89a1810c778dcd72072ff0e9621ba1379b4babe53921d71e2e4486fda3e + checksum: 67a5a39312dadb8c9a677df0f2e8add8daf15280b08bfe07f898d5347ee2d7cd2a1f5c2760f34e46e8f5f13f7192f47c2c10abe676bfa4173ae5539365551940 languageName: node linkType: hard @@ -5383,47 +5367,50 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": +"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1": version: 3.4.3 resolution: "eslint-visitor-keys@npm:3.4.3" checksum: 36e9ef87fca698b6fd7ca5ca35d7b2b6eeaaf106572e2f7fd31c12d3bfdaccdb587bba6d3621067e5aece31c8c3a348b93922ab8f7b2cbc6aaab5e1d89040c60 languageName: node linkType: hard -"eslint@npm:^7.0.0 || ^8.0.0": - version: 8.57.0 - resolution: "eslint@npm:8.57.0" +"eslint-visitor-keys@npm:^4.0.0": + version: 4.0.0 + resolution: "eslint-visitor-keys@npm:4.0.0" + checksum: 5c09f89cf29d87cdbfbac38802a880d3c2e65f8cb61c689888346758f1e24a4c7f6caefeac9474dfa52058a99920623599bdb00516976a30134abeba91275aa2 + languageName: node + linkType: hard + +"eslint@npm:^7.0.0 || ^8.0.0 || ^9.0.0": + version: 9.0.0 + resolution: "eslint@npm:9.0.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.6.1 - "@eslint/eslintrc": ^2.1.4 - "@eslint/js": 8.57.0 - "@humanwhocodes/config-array": ^0.11.14 + "@eslint/eslintrc": ^3.0.2 + "@eslint/js": 9.0.0 + "@humanwhocodes/config-array": ^0.12.3 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 - "@ungap/structured-clone": ^1.2.0 ajv: ^6.12.4 chalk: ^4.0.0 cross-spawn: ^7.0.2 debug: ^4.3.2 - doctrine: ^3.0.0 escape-string-regexp: ^4.0.0 - eslint-scope: ^7.2.2 - eslint-visitor-keys: ^3.4.3 - espree: ^9.6.1 + eslint-scope: ^8.0.1 + eslint-visitor-keys: ^4.0.0 + espree: ^10.0.1 esquery: ^1.4.2 esutils: ^2.0.2 fast-deep-equal: ^3.1.3 - file-entry-cache: ^6.0.1 + file-entry-cache: ^8.0.0 find-up: ^5.0.0 glob-parent: ^6.0.2 - globals: ^13.19.0 graphemer: ^1.4.0 ignore: ^5.2.0 imurmurhash: ^0.1.4 is-glob: ^4.0.0 is-path-inside: ^3.0.3 - js-yaml: ^4.1.0 json-stable-stringify-without-jsonify: ^1.0.1 levn: ^0.4.1 lodash.merge: ^4.6.2 @@ -5434,18 +5421,18 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 3a48d7ff85ab420a8447e9810d8087aea5b1df9ef68c9151732b478de698389ee656fd895635b5f2871c89ee5a2652b3f343d11e9db6f8486880374ebc74a2d9 + checksum: 3f20468cfd0f5affadf0f307e3af5b8f9ed19feaabccc3b4ed7548d40727d3f5dea4138db1ec287ca5a6152e164a051450604d47186b5fb28bb158a40937cf60 languageName: node linkType: hard -"espree@npm:^9.6.0, espree@npm:^9.6.1": - version: 9.6.1 - resolution: "espree@npm:9.6.1" +"espree@npm:^10.0.1": + version: 10.0.1 + resolution: "espree@npm:10.0.1" dependencies: - acorn: ^8.9.0 + acorn: ^8.11.3 acorn-jsx: ^5.3.2 - eslint-visitor-keys: ^3.4.1 - checksum: eb8c149c7a2a77b3f33a5af80c10875c3abd65450f60b8af6db1bfcfa8f101e21c1e56a561c6dc13b848e18148d43469e7cd208506238554fb5395a9ea5a1ab9 + eslint-visitor-keys: ^4.0.0 + checksum: 62c9242a84c6741cebd35ede6574131d0419be7e5559566403e384087d99c4ddb2ced44e32acd44a4c3d8a8a84997cf8d78810c4e46b3fe25a804f1a92dc6b9d languageName: node linkType: hard @@ -5667,12 +5654,12 @@ __metadata: languageName: node linkType: hard -"file-entry-cache@npm:^6.0.1": - version: 6.0.1 - resolution: "file-entry-cache@npm:6.0.1" +"file-entry-cache@npm:^8.0.0": + version: 8.0.0 + resolution: "file-entry-cache@npm:8.0.0" dependencies: - flat-cache: ^3.0.4 - checksum: f49701feaa6314c8127c3c2f6173cfefff17612f5ed2daaafc6da13b5c91fd43e3b2a58fd0d63f9f94478a501b167615931e7200e31485e320f74a33885a9c74 + flat-cache: ^4.0.0 + checksum: f67802d3334809048c69b3d458f672e1b6d26daefda701761c81f203b80149c35dea04d78ea4238969dd617678e530876722a0634c43031a0957f10cc3ed190f languageName: node linkType: hard @@ -5731,14 +5718,13 @@ __metadata: languageName: node linkType: hard -"flat-cache@npm:^3.0.4": - version: 3.2.0 - resolution: "flat-cache@npm:3.2.0" +"flat-cache@npm:^4.0.0": + version: 4.0.1 + resolution: "flat-cache@npm:4.0.1" dependencies: flatted: ^3.2.9 - keyv: ^4.5.3 - rimraf: ^3.0.2 - checksum: e7e0f59801e288b54bee5cb9681e9ee21ee28ef309f886b312c9d08415b79fc0f24ac842f84356ce80f47d6a53de62197ce0e6e148dc42d5db005992e2a756ec + keyv: ^4.5.4 + checksum: 899fc86bf6df093547d76e7bfaeb900824b869d7d457d02e9b8aae24836f0a99fbad79328cfd6415ee8908f180699bf259dc7614f793447cb14f707caf5996f6 languageName: node linkType: hard @@ -6059,12 +6045,10 @@ __metadata: languageName: node linkType: hard -"globals@npm:^13.19.0": - version: 13.24.0 - resolution: "globals@npm:13.24.0" - dependencies: - type-fest: ^0.20.2 - checksum: 56066ef058f6867c04ff203b8a44c15b038346a62efbc3060052a1016be9f56f4cf0b2cd45b74b22b81e521a889fc7786c73691b0549c2f3a6e825b3d394f43c +"globals@npm:^14.0.0": + version: 14.0.0 + resolution: "globals@npm:14.0.0" + checksum: 534b8216736a5425737f59f6e6a5c7f386254560c9f41d24a9227d60ee3ad4a9e82c5b85def0e212e9d92162f83a92544be4c7fd4c902cb913736c10e08237ac languageName: node linkType: hard @@ -7646,7 +7630,7 @@ __metadata: languageName: node linkType: hard -"keyv@npm:^4.5.3": +"keyv@npm:^4.5.4": version: 4.5.4 resolution: "keyv@npm:4.5.4" dependencies: @@ -9993,17 +9977,6 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^3.0.2": - version: 3.0.2 - resolution: "rimraf@npm:3.0.2" - dependencies: - glob: ^7.1.3 - bin: - rimraf: bin.js - checksum: 87f4164e396f0171b0a3386cc1877a817f572148ee13a7e113b238e48e8a9f2f31d009a92ec38a591ff1567d9662c6b67fd8818a2dbbaed74bc26a87a2a4a9a0 - languageName: node - linkType: hard - "rimraf@npm:^5.0.0": version: 5.0.5 resolution: "rimraf@npm:5.0.5" @@ -11041,13 +11014,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^0.20.2": - version: 0.20.2 - resolution: "type-fest@npm:0.20.2" - checksum: 4fb3272df21ad1c552486f8a2f8e115c09a521ad7a8db3d56d53718d0c907b62c6e9141ba5f584af3f6830d0872c521357e512381f24f7c44acae583ad517d73 - languageName: node - linkType: hard - "type-fest@npm:^0.21.3": version: 0.21.3 resolution: "type-fest@npm:0.21.3" From c87e3887e736c40d1460af9cdbdffe30f79fdaea Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 6 Apr 2024 10:02:23 +0200 Subject: [PATCH 22/23] fix: drop support for Node 19 (#1548) BREAKING CHANGE: Node v19 is no longer supported --- .github/workflows/nodejs.yml | 5 +---- package.json | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index af18c6a87..75256d525 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -71,7 +71,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [16.x, 18.x, 19.x, 20.x, 21.x] + node-version: [16.x, 18.x, 20.x, 21.x] eslint-version: [7, 8, 9] ts-eslint-plugin-version: [6, 7] exclude: @@ -81,9 +81,6 @@ jobs: # eslint@9 doesn't support node@16 - node-version: 16.x eslint-version: 9 - # ts-eslint/plugin@7 doesn't support node@19 - - node-version: 19.x - ts-eslint-plugin-version: 7 # ts-eslint/plugin@7 doesn't support eslint@7 - eslint-version: 7 ts-eslint-plugin-version: 7 diff --git a/package.json b/package.json index e30b2d511..e4496721f 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ }, "packageManager": "yarn@3.8.1", "engines": { - "node": "^16.10.0 || >=18.0.0" + "node": "^16.10.0 || ^18.12.0 || >=20.0.0" }, "publishConfig": { "provenance": true From 37f1d6957f3418ccda78020a5a2eb8b7617e83d2 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 6 Apr 2024 08:07:19 +0000 Subject: [PATCH 23/23] chore(release): 28.0.0-next.7 [skip ci] # [28.0.0-next.7](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.6...v28.0.0-next.7) (2024-04-06) ### Bug Fixes * allow ESLint 9 as peer dependency ([#1547](https://github.com/jest-community/eslint-plugin-jest/issues/1547)) ([3c5e167](https://github.com/jest-community/eslint-plugin-jest/commit/3c5e1673afd02dc2c9b90d259c0452326715ae6c)) * drop support for Node 19 ([#1548](https://github.com/jest-community/eslint-plugin-jest/issues/1548)) ([c87e388](https://github.com/jest-community/eslint-plugin-jest/commit/c87e3887e736c40d1460af9cdbdffe30f79fdaea)) ### BREAKING CHANGES * Node v19 is no longer supported --- CHANGELOG.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c83e83460..965b9be25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# [28.0.0-next.7](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.6...v28.0.0-next.7) (2024-04-06) + + +### Bug Fixes + +* allow ESLint 9 as peer dependency ([#1547](https://github.com/jest-community/eslint-plugin-jest/issues/1547)) ([3c5e167](https://github.com/jest-community/eslint-plugin-jest/commit/3c5e1673afd02dc2c9b90d259c0452326715ae6c)) +* drop support for Node 19 ([#1548](https://github.com/jest-community/eslint-plugin-jest/issues/1548)) ([c87e388](https://github.com/jest-community/eslint-plugin-jest/commit/c87e3887e736c40d1460af9cdbdffe30f79fdaea)) + + +### BREAKING CHANGES + +* Node v19 is no longer supported + # [28.0.0-next.6](https://github.com/jest-community/eslint-plugin-jest/compare/v28.0.0-next.5...v28.0.0-next.6) (2024-03-29) diff --git a/package.json b/package.json index e4496721f..8c96ce99d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-jest", - "version": "28.0.0-next.6", + "version": "28.0.0-next.7", "description": "ESLint rules for Jest", "keywords": [ "eslint",