diff --git a/docs/rules/no-expect-resolves.md b/docs/rules/no-expect-resolves.md deleted file mode 100644 index 31cb51f43..000000000 --- a/docs/rules/no-expect-resolves.md +++ /dev/null @@ -1,47 +0,0 @@ -# Avoid using `expect().resolves` (`no-expect-resolves`) - -## Deprecated - -This rule has been deprecated in favor of -[`no-restricted-matchers`](no-restricted-matchers.md) with the following config: - -```json -{ - "rules": { - "jest/no-restricted-matchers": [ - "error", - { "resolves": "Use `expect(await promise)` instead." } - ] - } -} -``` - ---- - -Jest allows you to test a promise resolve value using `await expect().resolves`. -For consistency and readability this rule bans `expect().resolves` in favor of -`expect(await promise)`. - -## Rule details - -This rule triggers a warning if `expect().resolves` is used. - -This rule is disabled by default. - -### Default configuration - -The following patterns is considered warning: - -```js -test('some test', async () => { - await expect(Promise.resolve(1)).resolves.toBe(1); -}); -``` - -The following pattern is not considered warning: - -```js -test('some test', async () => { - expect(await Promise.resolve(1)).toBe(1); -}); -``` diff --git a/docs/rules/no-truthy-falsy.md b/docs/rules/no-truthy-falsy.md deleted file mode 100644 index aa23b1fc7..000000000 --- a/docs/rules/no-truthy-falsy.md +++ /dev/null @@ -1,53 +0,0 @@ -# Disallow using `toBeTruthy()` & `toBeFalsy()` (`no-truthy-falsy`) - -## Deprecated - -This rule has been deprecated in favor of -[`no-restricted-matchers`](no-restricted-matchers.md) with the following config: - -```json -{ - "rules": { - "jest/no-restricted-matchers": [ - "error", - { - "toBeTruthy": "Avoid `toBeTruthy`", - "toBeFalsy": "Avoid `toBeFalsy`" - } - ] - } -} -``` - ---- - -Tests against boolean values should assert true or false. Asserting `toBeTruthy` -or `toBeFalsy` matches non-boolean values as well and encourages weaker tests. - -For example, `expect(someBoolean).toBeFalsy()` passes when -`someBoolean === null`, and when `someBoolean === false`. - -Similarly, `expect(someBoolean).toBeTruthy()` passes when `someBoolean === []`, -and when `someBoolean === 'false'` (note that `'false'` is a string). - -## Rule details - -This rule triggers a warning if `toBeTruthy()` or `toBeFalsy()` are used. - -This rule is disabled by default. - -### Default configuration - -The following patterns are considered warnings: - -```js -expect(someValue).toBeTruthy(); -expect(someValue).toBeFalsy(); -``` - -The following patterns are not considered warnings: - -```js -expect(someValue).toBe(true); -expect(someValue).toBe(false); -``` diff --git a/docs/rules/no-try-expect.md b/docs/rules/no-try-expect.md deleted file mode 100644 index cba9a937a..000000000 --- a/docs/rules/no-try-expect.md +++ /dev/null @@ -1,63 +0,0 @@ -# Prevent catch assertions in tests (`no-try-expect`) - -## Deprecated - -This rule has been deprecated in favor of -[`no-conditional-expect`](no-conditional-expect.md). - ---- - -This rule prevents the use of `expect` inside `catch` blocks. - -## Rule Details - -Expectations inside a `catch` block can be silently skipped. While Jest provides -an `expect.assertions(number)` helper, it might be cumbersome to add this to -every single test. Using `toThrow` concisely guarantees that an exception was -thrown, and that its contents match expectations. - -The following patterns are warnings: - -```js -it('foo', () => { - try { - foo(); // `foo` may be refactored to not throw exceptions, yet still appears to be tested here. - } catch (err) { - expect(err).toMatch(/foo error/); - } -}); - -it('bar', async () => { - try { - await foo(); - } catch (err) { - expect(err).toMatch(/foo error/); - } -}); - -it('baz', async () => { - try { - await foo(); - } catch (err) { - expect(err).toMatchObject({ code: 'MODULE_NOT_FOUND' }); - } -}); -``` - -The following patterns are not warnings: - -```js -it('foo', () => { - expect(() => foo()).toThrow(/foo error/); -}); - -it('bar', async () => { - await expect(fooPromise).rejects.toThrow(/foo error/); -}); - -it('baz', async () => { - await expect(() => foo()).rejects.toThrow( - expect.objectContaining({ code: 'MODULE_NOT_FOUND' }), - ); -}); -``` diff --git a/docs/rules/prefer-inline-snapshots.md b/docs/rules/prefer-inline-snapshots.md deleted file mode 100644 index e01308bf6..000000000 --- a/docs/rules/prefer-inline-snapshots.md +++ /dev/null @@ -1,51 +0,0 @@ -# Suggest using inline snapshots (`prefer-inline-snapshots`) - -## Deprecated - -This rule has been deprecated in favor of -[`no-restricted-matchers`](no-restricted-matchers.md) with the following config: - -```json -{ - "rules": { - "jest/no-restricted-matchers": [ - "error", - { - "toThrowErrorMatchingSnapshot": "Use `toThrowErrorMatchingInlineSnapshot()` instead", - "toMatchSnapshot": "Use `toMatchInlineSnapshot()` instead" - } - ] - } -} -``` - ---- - -In order to make snapshot tests more manageable and reviewable -`toMatchInlineSnapshot()` and `toThrowErrorMatchingInlineSnapshot` should be -used to write the snapshots' inline in the test file. - -## Rule details - -This rule triggers a warning if `toMatchSnapshot()` or -`toThrowErrorMatchingSnapshot` is used to capture a snapshot. - -The following pattern is considered warning: - -```js -expect(obj).toMatchSnapshot(); -``` - -```js -expect(error).toThrowErrorMatchingSnapshot(); -``` - -The following pattern is not warning: - -```js -expect(obj).toMatchInlineSnapshot(); -``` - -```js -expect(error).toThrowErrorMatchingInlineSnapshot(); -``` diff --git a/src/__tests__/__snapshots__/rules.test.ts.snap b/src/__tests__/__snapshots__/rules.test.ts.snap index eb3178266..07f1f230f 100644 --- a/src/__tests__/__snapshots__/rules.test.ts.snap +++ b/src/__tests__/__snapshots__/rules.test.ts.snap @@ -77,7 +77,6 @@ Object { "jest/no-mocks-import": "error", "jest/no-standalone-expect": "error", "jest/no-test-prefixes": "error", - "jest/no-try-expect": "error", "jest/valid-describe": "error", "jest/valid-expect": "error", "jest/valid-expect-in-promise": "error", diff --git a/src/__tests__/rules.test.ts b/src/__tests__/rules.test.ts index 6703e7a13..71eb7339d 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 = 46; +const numberOfRules = 42; const ruleNames = Object.keys(plugin.rules); const deprecatedRules = Object.entries(plugin.rules) .filter(([, rule]) => rule.meta.deprecated) diff --git a/src/rules/__tests__/no-expect-resolves.test.ts b/src/rules/__tests__/no-expect-resolves.test.ts deleted file mode 100644 index 9d3e455c0..000000000 --- a/src/rules/__tests__/no-expect-resolves.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { TSESLint } from '@typescript-eslint/experimental-utils'; -import resolveFrom from 'resolve-from'; -import rule from '../no-expect-resolves'; - -const ruleTester = new TSESLint.RuleTester({ - parser: resolveFrom(require.resolve('eslint'), 'espree'), - parserOptions: { - ecmaVersion: 2017, - }, -}); - -ruleTester.run('no-expect-resolves', rule, { - valid: [ - `test('some test', async () => { - expect(await Promise.resolve(1)).toBe(1); - });`, - ], - invalid: [ - { - code: `test('some test', async () => { - await expect(Promise.resolve(1)).resolves.toBe(1); - });`, - errors: [{ endColumn: 55, column: 47, messageId: 'expectResolves' }], - }, - ], -}); diff --git a/src/rules/__tests__/no-truthy-falsy.test.ts b/src/rules/__tests__/no-truthy-falsy.test.ts deleted file mode 100644 index d1a64b567..000000000 --- a/src/rules/__tests__/no-truthy-falsy.test.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { TSESLint } from '@typescript-eslint/experimental-utils'; -import rule from '../no-truthy-falsy'; - -const ruleTester = new TSESLint.RuleTester(); - -ruleTester.run('no-truthy-falsy', rule, { - valid: [ - 'expect(true).toBe(true);', - 'expect(false).toBe(false);', - 'expect("anything").toBe(true);', - 'expect("anything").toEqual(false);', - 'expect("anything").not.toBe(true);', - 'expect("anything").not.toEqual(true);', - 'expect(Promise.resolve({})).resolves.toBe(true);', - 'expect(Promise.reject({})).rejects.toBe(true);', - 'expect(a);', - ], - - invalid: [ - { - code: 'expect(true).toBeTruthy();', - errors: [ - { - messageId: 'avoidMatcher', - data: { matcherName: 'toBeTruthy' }, - column: 14, - line: 1, - }, - ], - }, - { - code: 'expect(true)["toBeTruthy"]();', - errors: [ - { - messageId: 'avoidMatcher', - data: { matcherName: 'toBeTruthy' }, - column: 14, - line: 1, - }, - ], - }, - { - code: 'expect(false).not.toBeTruthy();', - errors: [ - { - messageId: 'avoidMatcher', - data: { matcherName: 'toBeTruthy' }, - column: 19, - line: 1, - }, - ], - }, - { - code: 'expect(Promise.resolve({})).resolves.toBeTruthy()', - errors: [ - { - messageId: 'avoidMatcher', - data: { matcherName: 'toBeTruthy' }, - column: 38, - line: 1, - }, - ], - }, - { - code: 'expect(Promise.resolve({})).rejects.toBeTruthy()', - errors: [ - { - messageId: 'avoidMatcher', - data: { matcherName: 'toBeTruthy' }, - column: 37, - line: 1, - }, - ], - }, - { - code: 'expect(false).toBeFalsy();', - errors: [ - { - messageId: 'avoidMatcher', - data: { matcherName: 'toBeFalsy' }, - column: 15, - line: 1, - }, - ], - }, - { - code: 'expect(true).not.toBeFalsy();', - errors: [ - { - messageId: 'avoidMatcher', - data: { matcherName: 'toBeFalsy' }, - column: 18, - line: 1, - }, - ], - }, - { - code: 'expect(Promise.resolve({})).resolves.toBeFalsy()', - errors: [ - { - messageId: 'avoidMatcher', - data: { matcherName: 'toBeFalsy' }, - column: 38, - line: 1, - }, - ], - }, - { - code: 'expect(Promise.resolve({})).rejects.toBeFalsy()', - errors: [ - { - messageId: 'avoidMatcher', - data: { matcherName: 'toBeFalsy' }, - column: 37, - line: 1, - }, - ], - }, - ], -}); diff --git a/src/rules/__tests__/no-try-expect.test.ts b/src/rules/__tests__/no-try-expect.test.ts deleted file mode 100644 index 008f9f230..000000000 --- a/src/rules/__tests__/no-try-expect.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { TSESLint } from '@typescript-eslint/experimental-utils'; -import resolveFrom from 'resolve-from'; -import rule from '../no-try-expect'; - -const ruleTester = new TSESLint.RuleTester({ - parser: resolveFrom(require.resolve('eslint'), 'espree'), - parserOptions: { - ecmaVersion: 2019, - }, -}); - -ruleTester.run('no-try-catch', rule, { - valid: [ - `it('foo', () => { - expect('foo').toEqual('foo'); - })`, - `it('foo', () => {}) - function myTest() { - try { - } catch { - } - }`, - `it('foo', () => { - expect('bar').toEqual('bar'); - }); - try { - } catch { - expect('foo').toEqual('foo'); - }`, - `it.skip('foo'); - try { - } catch { - expect('foo').toEqual('foo'); - }`, - `it.concurrent.skip('foo'); - try { - - } catch { - expect('foo').toEqual('foo'); - }`, - ], - invalid: [ - { - code: `it('foo', () => { - try { - - } catch (err) { - expect(err).toMatch('Error'); - } - })`, - errors: [ - { - messageId: 'noTryExpect', - }, - ], - }, - { - code: `it('foo', myTest) - function myTest() { - try { - - } catch (err) { - expect(err).toMatch('Error'); - } - } - `, - errors: [ - { - messageId: 'noTryExpect', - }, - ], - }, - { - code: `it('foo', async () => { - await wrapper('production', async () => { - try { - - } catch (err) { - expect(err).toMatch('Error'); - } - }) - })`, - errors: [ - { - messageId: 'noTryExpect', - }, - ], - }, - ], -}); diff --git a/src/rules/__tests__/prefer-inline-snapshots.test.ts b/src/rules/__tests__/prefer-inline-snapshots.test.ts deleted file mode 100644 index 77f9b2bf1..000000000 --- a/src/rules/__tests__/prefer-inline-snapshots.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { TSESLint } from '@typescript-eslint/experimental-utils'; -import rule from '../prefer-inline-snapshots'; - -const ruleTester = new TSESLint.RuleTester(); - -ruleTester.run('prefer-inline-snapshots', rule, { - valid: [ - 'expect(something).toMatchInlineSnapshot();', - 'expect(something).toThrowErrorMatchingInlineSnapshot();', - ], - invalid: [ - { - code: 'expect(something).toMatchSnapshot();', - output: 'expect(something).toMatchInlineSnapshot();', - errors: [{ messageId: 'toMatch', column: 19, line: 1 }], - }, - { - code: 'expect(something).toThrowErrorMatchingSnapshot();', - output: 'expect(something).toThrowErrorMatchingInlineSnapshot();', - errors: [{ messageId: 'toMatchError', column: 19, line: 1 }], - }, - ], -}); diff --git a/src/rules/no-expect-resolves.ts b/src/rules/no-expect-resolves.ts deleted file mode 100644 index 654e3cf8d..000000000 --- a/src/rules/no-expect-resolves.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { - ModifierName, - createRule, - isExpectCall, - isSupportedAccessor, -} from './utils'; - -export default createRule({ - name: __filename, - meta: { - docs: { - category: 'Best Practices', - description: 'Disallow expect.resolves', - recommended: false, - }, - deprecated: true, - replacedBy: ['no-restricted-matchers'], - messages: { - expectResolves: 'Use `expect(await promise)` instead.', - }, - schema: [], - type: 'suggestion', - }, - defaultOptions: [], - create: context => ({ - MemberExpression(node) { - if ( - isExpectCall(node.object) && - isSupportedAccessor(node.property, ModifierName.resolves) - ) { - context.report({ node: node.property, messageId: 'expectResolves' }); - } - }, - }), -}); diff --git a/src/rules/no-truthy-falsy.ts b/src/rules/no-truthy-falsy.ts deleted file mode 100644 index ef8b4daf6..000000000 --- a/src/rules/no-truthy-falsy.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { createRule, isExpectCall, parseExpectCall } from './utils'; - -// todo: refactor into "ban-matchers" -export default createRule({ - name: __filename, - meta: { - docs: { - category: 'Best Practices', - description: 'Disallow using `toBeTruthy()` & `toBeFalsy()`', - recommended: false, - }, - deprecated: true, - replacedBy: ['no-restricted-matchers'], - messages: { - avoidMatcher: 'Avoid {{ matcherName }}', - }, - type: 'suggestion', - schema: [], - }, - defaultOptions: [], - create(context) { - return { - CallExpression(node) { - if (!isExpectCall(node)) { - return; - } - - const { matcher } = parseExpectCall(node); - - if (!matcher || !['toBeTruthy', 'toBeFalsy'].includes(matcher.name)) { - return; - } - - context.report({ - messageId: 'avoidMatcher', - node: matcher.node.property, - data: { matcherName: matcher.name }, - }); - }, - }; - }, -}); diff --git a/src/rules/no-try-expect.ts b/src/rules/no-try-expect.ts deleted file mode 100644 index 269a0e4b8..000000000 --- a/src/rules/no-try-expect.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { TSESTree } from '@typescript-eslint/experimental-utils'; -import { - createRule, - getTestCallExpressionsFromDeclaredVariables, - isExpectCall, - isTestCaseCall, -} from './utils'; - -export default createRule({ - name: __filename, - meta: { - docs: { - description: 'Prefer using toThrow for exception tests', - category: 'Best Practices', - recommended: 'error', - }, - deprecated: true, - replacedBy: ['no-conditional-expect'], - messages: { - noTryExpect: [ - 'Tests should use Jest‘s exception helpers.', - 'Use "expect(() => yourFunction()).toThrow()" for synchronous tests,', - 'or "await expect(yourFunction()).rejects.toThrow()" for async tests', - ].join(' '), - }, - type: 'problem', - schema: [], - }, - defaultOptions: [], - create(context) { - let isTest = false; - let catchDepth = 0; - - function isThrowExpectCall(node: TSESTree.CallExpression) { - return catchDepth > 0 && isExpectCall(node); - } - - return { - CallExpression(node) { - if (isTestCaseCall(node)) { - isTest = true; - } else if (isTest && isThrowExpectCall(node)) { - context.report({ - messageId: 'noTryExpect', - node, - }); - } - }, - FunctionDeclaration(node) { - const declaredVariables = context.getDeclaredVariables(node); - const testCallExpressions = - getTestCallExpressionsFromDeclaredVariables(declaredVariables); - - if (testCallExpressions.length > 0) { - isTest = true; - } - }, - CatchClause() { - if (isTest) { - ++catchDepth; - } - }, - 'CatchClause:exit'() { - if (isTest) { - --catchDepth; - } - }, - 'CallExpression:exit'(node) { - if (isTestCaseCall(node)) { - isTest = false; - } - }, - 'FunctionDeclaration:exit'(node) { - const declaredVariables = context.getDeclaredVariables(node); - const testCallExpressions = - getTestCallExpressionsFromDeclaredVariables(declaredVariables); - - if (testCallExpressions.length > 0) { - isTest = false; - } - }, - }; - }, -}); diff --git a/src/rules/prefer-inline-snapshots.ts b/src/rules/prefer-inline-snapshots.ts deleted file mode 100644 index 55cb3af21..000000000 --- a/src/rules/prefer-inline-snapshots.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; -import { createRule } from './utils'; - -export default createRule({ - name: __filename, - meta: { - docs: { - category: 'Best Practices', - description: 'Suggest using inline snapshots', - recommended: false, - }, - deprecated: true, - replacedBy: ['no-restricted-matchers'], - messages: { - toMatch: 'Use toMatchInlineSnapshot() instead', - toMatchError: 'Use toThrowErrorMatchingInlineSnapshot() instead', - }, - fixable: 'code', - schema: [], - type: 'suggestion', - }, - defaultOptions: [], - create(context) { - return { - CallExpression(node) { - const { callee } = node; - - if ( - callee.type !== AST_NODE_TYPES.MemberExpression || - callee.property.type !== AST_NODE_TYPES.Identifier - ) { - return; - } - - if (callee.property.name === 'toMatchSnapshot') { - context.report({ - fix(fixer) { - return [ - fixer.replaceText(callee.property, 'toMatchInlineSnapshot'), - ]; - }, - messageId: 'toMatch', - node: callee.property, - }); - } else if (callee.property.name === 'toThrowErrorMatchingSnapshot') { - context.report({ - fix(fixer) { - return [ - fixer.replaceText( - callee.property, - 'toThrowErrorMatchingInlineSnapshot', - ), - ]; - }, - messageId: 'toMatchError', - node: callee.property, - }); - } - }, - }; - }, -});