src/overrides/jest.ts
import {
type Dependencies,
type OverrideCreator,
type OverrideESLintConfig,
type OverrideInternalOverride,
type RulesCreator,
type SettingsCreator,
} from '../types';
import { uniqueArrayEntries } from '../utils/array';
import {
jestConfigOverrideType,
jestOverrideType,
} from '../utils/overrideType';
export const env: OverrideESLintConfig['env'] = {
jest: true,
};
export const extendsConfig = ['plugin:jest-formatting/strict'];
export const files = [
'**/__tests__/**/*.[jt]s?(x)',
'**/?(*.)+(spec|test).[jt]s?(x)',
];
export const parserOptions: OverrideESLintConfig['parserOptions'] = {
ecmaVersion: 2020,
};
export const settings = {
jest: {
version: 'detect',
},
};
export const createJestOverride: OverrideCreator = ({
rules: customRules,
files: customFiles,
parserOptions: customParserOptions,
settings: customSettings,
env: customEnv,
excludedFiles: customExcludedFiles,
extends: customExtends,
globals: customGlobals,
plugins: customPlugins,
overrides: customOverrides,
...dependencies
}) => {
if (!dependencies.hasJest) {
return null;
}
const rules: OverrideESLintConfig['rules'] = {
...createJestRules(dependencies),
...(dependencies.hasJestDom ? createJestDomRules(dependencies) : null),
...(dependencies.hasTestingLibrary
? createTestingLibraryRules(dependencies)
: null),
...createTestOverrides(dependencies),
...customRules,
};
const finalParserOptions: OverrideESLintConfig['env'] = {
...parserOptions,
...customParserOptions,
};
const finalEnv = {
...env,
...customEnv,
};
const finalFiles = customFiles ?? files;
const finalPlugins = createPlugins(dependencies, customPlugins);
const finalExtends = uniqueArrayEntries([
...extendsConfig,
...(customExtends ?? []),
]);
const finalSettings = {
...settings,
...createTestingLibrarySettings(dependencies),
...customSettings,
};
return {
env: finalEnv,
extends: finalExtends,
files: finalFiles,
parserOptions: finalParserOptions,
plugins: finalPlugins,
settings: finalSettings,
rules,
overrideType: jestOverrideType,
overrides: customOverrides,
excludedFiles: customExcludedFiles,
globals: customGlobals,
};
};
export const createPlugins = (
dependencies: Dependencies,
customPlugins?: string[]
): string[] => {
return uniqueArrayEntries([
'jest',
dependencies.hasJestDom && 'jest-dom',
dependencies.hasTestingLibrary && 'testing-library',
...(customPlugins ?? []),
]);
};
/**
* @see https://github.com/jest-community/eslint-plugin-jest
*/
export const createJestRules: RulesCreator = ({
react: { isCreateReactApp },
typescript: { hasTypeScript },
}) => {
return {
/**
* off because `test`/`it` are different things and convey meaning
* - use `test` for unit tests
* - use `it` for components
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/consistent-test-it.md
*/
'jest/consistent-test-it': 'off',
/**
* off because smoketests are fire-and-forget
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/expect-expect.md
*/
'jest/expect-expect': 'off',
/**
* enforces a maximum number assertion calls in a test body
*
* off because subjective
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/max-expects.md
*/
'jest/max-expects': 'off',
/**
* off because seems arbitrary, usually names are indeed lowercase but some tests
* might very well begin with an uppercase character
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/lowercase-name.md
*/
'jest/lowercase-name': 'off',
/**
* off because unlikely to be needed
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/max-nested-describe.md
*/
'jest/max-nested-describe': 'off',
/**
* off because if something was to change with those, jest would
* console.log or eslint would fix it
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-alias-methods.md
*/
'jest/no-alias-methods': 'off',
/**
* disallows commented out tests
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-commented-out-tests.md
*/
'jest/no-commented-out-tests': 'warn',
/**
* ensures assertions are non-conditional which leads to less complex
* tests
*
* @see jest/no-if
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-conditional-expect.md
*/
'jest/no-conditional-expect': 'error',
/**
* @see no-if
* @see https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/no-conditional-in-test.md
*/
'jest/no-conditional-in-test': 'warn',
/**
* avoids using jest debt
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-deprecated-functions.md
*/
'jest/no-deprecated-functions': 'error',
/**
* avoids having permanently disabled tests. either remove them, fix
* them or re-enable them.
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-disabled-tests.md
*/
'jest/no-disabled-tests': 'warn',
/**
* ensures `done` callback is awaited or in try/catch
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-done-callback.md
*/
'jest/no-done-callback': 'error',
/**
* ensures each hook is only called once per describe
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-duplicate-hooks.md
*/
'jest/no-duplicate-hooks': 'warn',
/**
* off because superseded by `jest/no-restricted-matchers`
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-expect-resolves.md
*/
'jest/no-expect-resolves': 'off',
/**
* tests shouldn't export something
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-export.md
*/
'jest/no-export': 'error',
/**
* avoids having accidentally skipped tests. either remove the others,
* fix them or re-enable them.
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-focused-tests.md
*/
'jest/no-focused-tests': 'error',
/**
* off because hooks are often needed
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-hooks.md
*/
'jest/no-hooks': 'off',
/**
* ensures unique test titles
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-identical-title.md
*/
'jest/no-identical-title': 'error',
/**
* ensures less complex tests
*
* @deprecated in favor of `no-conditional-in-test`
*
* @see jest/no-conditional-expect
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-if.md
*/
// 'jest/no-if': 'off',
/**
* ensures snapshots can be updated
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-interpolation-in-snapshots.md
*/
'jest/no-interpolation-in-snapshots': 'error',
/**
* prevents use of jasmine globals
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-jasmine-globals.md
*/
'jest/no-jasmine-globals': 'error',
/**
* ensures snapshots stay reasonable in size
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-large-snapshots.md
*/
'jest/no-large-snapshots': ['warn', { maxSize: 300 }],
/**
* disallows importing from `__mocks__`
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-mocks-import.md
*/
'jest/no-mocks-import': 'error',
/**
* off because workspace specific if even
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/no-restricted-jest-methods.md
*/
'jest/no-restricted-jest-methods': 'off',
/**
* off because nothing is restricted
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-restricted-matchers.md
*/
'jest/no-restricted-matchers': 'off',
/**
* ensures `expect` is used within `it`/`test` blocks
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-standalone-expect.md
*/
'jest/no-standalone-expect': 'off',
/**
* disallows `f`/`x` prefixes for `it`/`test`
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/maste`f`/`d`ocs/rules/`no`-test-prefixes.md
*/
'jest/no-test-prefixes': 'error',
/**
* ensures `return` isn't used in tests. if promises are involved, use
* async/await
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-test-return-statement.md
*/
'jest/no-test-return-statement': 'error',
/**
* disallows using jest.mock without passing a type
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-untyped-mock-factory.md
*/
'jest/no-untyped-mock-factory': hasTypeScript ? 'warn' : 'off',
/**
* off because superseded in favor of `jest/no-restricted-matchers`
*
* @see jest/no-restricted-matchers
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-truthy-falsy.md
*/
'jest/no-truthy-falsy': 'off',
/**
* off because superseded by `jest/no-conditional-expect`
*
* @see jest/no-conditional-expect
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-try-expect.md
*/
'jest/no-try-expect': 'off',
/**
* suggests `toBeCalledWith`/`toHaveBeenCalledWith` over `toBeCalled`
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-called-with.md
*/
'jest/prefer-called-with': 'error',
/**
* suggests using builtin comparison matchers
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-comparison-matcher.md
*/
'jest/prefer-comparison-matcher': 'warn',
/**
* suggests using *.each if possible
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-each.md
*/
'jest/prefer-each': 'warn',
/**
* off because should be either globally defined or not at all
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-expect-assertions.md
*/
'jest/prefer-expect-assertions': 'off',
/**
* prefer await expect().resolves over awaiting within expect
*
* can be enabled once create-react-app uses eslint-plugin-jest v24.5.0
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-expect-resolves.md
*/
...(isCreateReactApp ? null : { 'jest/prefer-expect-resolves': 'warn' }),
/**
* ensures hooks are called in the order jest calls them aswell
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-hooks-in-order.md
*/
...(isCreateReactApp ? null : { 'jest/prefer-hooks-in-order': 'warn' }),
/**
* ensures hooks are defined before tests
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-hooks-on-top.md
*/
'jest/prefer-hooks-on-top': 'error',
/**
* off because superseded in favor of `jest/no-restricted-matchers`
* *
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-inline-snapshots.md
*/
'jest/prefer-inline-snapshots': 'off',
/**
* requires adding snapshot hints for external snapshot matchers
*
* off because deemed unnecessary
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-snapshot-hint.md
*/
'jest/prefer-snapshot-hint': 'off',
/**
* prefer spying instead of copying to avoid having to cleanup
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/HEAD/docs/rules/prefer-spy-on.md
*/
'jest/prefer-spy-on': 'warn',
/**
* suggests preferring `toStrictEqual` over `toEqual`
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-strict-equal.md
*/
'jest/prefer-strict-equal': 'warn',
/**
* prefer toBe over toEqual
*
* can be enabled once create-react-app uses eslint-plugin-jest v25.0.0
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-to-be.md
*/
...(isCreateReactApp ? null : { 'jest/prefer-to-be': 'warn' }),
/**
* use `[]).toContain(foo)` instead of `[].includes(foo)).tobe(true)`
* and its variants
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-to-contain.md
*/
'jest/prefer-to-contain': 'warn',
/**
* use `[]).toHaveLength(x)` instead of `[].lenth)).toBe(x)`
* and its variants
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-to-have-length.md
*/
'jest/prefer-to-have-length': 'warn',
/**
* marks empty test cases as `test.todo`
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-todo.md
*/
'jest/prefer-todo': 'warn',
/**
* off because often it's cumbersome to inline the error message with
* the same formatting as jest expects it to be
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/require-to-throw-message.md
*/
'jest/require-to-throw-message': 'off',
/**
* requires a top level describe wrapping everything
*
* off because opinionated
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/require-top-level-describe.md
*/
'jest/require-top-level-describe': 'off',
/**
* validates callback of `describe('something', () => {})`
*
* can be enabled once create-react-app uses eslint-plugin-jest v24.5.0
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/valid-describe-callback.md
*/
...(isCreateReactApp ? null : { 'jest/valid-describe-callback': 'error' }),
/**
* validates params of `expect`
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/valid-expect.md
*/
'jest/valid-expect': 'error',
/**
* ensures promise return when not using async/await
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/valid-expect-in-promise.md
*/
'jest/valid-expect-in-promise': 'error',
/**
* ensures valid title for `describe`/`xit`/`it`/`test`/`xtest`
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/valid-title.md
*/
'jest/valid-title': hasTypeScript ? 'off' : 'warn',
};
};
/**
* @see https://github.com/testing-library/eslint-plugin-jest-dom
*/
export const createJestDomRules: RulesCreator = () => ({
/**
* prefer toBeChecked over checking attributes
*
* @see https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-checked.md
*/
'jest-dom/prefer-checked': 'warn',
/**
* prefer toBeEmpty over checking innerHTML
*
* @see https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-empty.md
*/
'jest-dom/prefer-empty': 'warn',
/**
* prefer toBeDisabled or toBeEnabled over checking attributes
*
* @see https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-enabled-disabled.md
*/
'jest-dom/prefer-enabled-disabled': 'warn',
/**
* prefer toHaveFocus over checking document.activeElement
*
* @see https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-focus.md
*/
'jest-dom/prefer-focus': 'warn',
/**
* prefer .toBeInTheDocument in favor of .toHaveLength(1)
*
* @see https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-in-document.md
*/
'jest-dom/prefer-in-document': 'warn',
/**
* prefer toBeRequired over checking properties
*
* @see https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-required.md
*/
'jest-dom/prefer-required': 'warn',
/**
* prefer toHaveAttribute over checking getAttribute/hasAttribute
*
* @see https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-to-have-attribute.md
*/
'jest-dom/prefer-to-have-attribute': 'warn',
/**
* prefer toHaveClass over checking attributes
*
* @see https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-to-have-class.md
*/
'jest-dom/prefer-to-have-class': 'warn',
/**
* prefer toHaveStyle over checking element style
*
* @see https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-to-have-attribute.md
*/
'jest-dom/prefer-to-have-style': 'warn',
/**
* prefer toHaveTextContent over checking element.textContent
*
* @see https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-to-have-text-content.md
*/
'jest-dom/prefer-to-have-text-content': 'warn',
/**
* prefer toHaveAttribute('value') over checking attributes
*
* @see https://github.com/testing-library/eslint-plugin-jest-dom/blob/master/docs/rules/prefer-to-have-value.md
*/
'jest-dom/prefer-to-have-value': 'warn',
});
/**
* @see https://github.com/testing-library/eslint-plugin-testing-library
*/
export const createTestingLibraryRules: RulesCreator = ({
react: { hasReact, isCreateReactApp },
}) => ({
/**
* enforces awaiting async queries (find*)
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/await-async-query.md
*/
'testing-library/await-async-query': 'error',
/**
* enforces awaiting async utils (waitFor)
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/await-async-utils.md
*/
'testing-library/await-async-utils': 'error',
/**
* enforces awaiting events
*
* off because not supported by @testing-library/react
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/await-fire-event.md
*/
'testing-library/await-fire-event': 'off',
/**
* enforces consistent naming based on regex pattern
*
* off because opinionated
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/consistent-data-testid.md
*/
'testing-library/consistent-data-testid': 'off',
/**
* ensures sync events are not awaited unnecessarily
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-await-sync-events.md
*/
'testing-library/no-await-sync-events': 'error',
/**
* no unecessary `await` for non-async queries
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-await-sync-query.md
*/
'testing-library/no-await-sync-query': 'error',
/**
* disallows use of `container`
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-container.md
*/
'testing-library/no-container': 'warn',
/**
* hints the use of `screen.debug()`
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-debugging-utils.md
*/
'testing-library/no-debugging-utils': 'error',
/**
* disallows direct imports from `@testing-library/dom` in react
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-dom-import.md
*/
'testing-library/no-dom-import': hasReact ? ['warn', 'react'] : 'off',
/**
* disallows /g regex flags in queries as they may lead to false positives
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-global-regexp-flag-in-query.md
*/
...(isCreateReactApp
? null
: {
'testing-library/no-global-regexp-flag-in-query': 'warn',
}),
/**
* prefer usage of `@testing-library/$framework` tools to access nodes
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-node-access.md
*/
'testing-library/no-node-access': 'warn',
/**
* hints on `cleanup` not being necessary
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-manual-cleanup.md
*/
'testing-library/no-manual-cleanup': 'error',
/**
* disalllows the use of promises passed to a `fireEvent` method
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-promise-in-fire-event.md
*/
'testing-library/no-promise-in-fire-event': 'error',
/**
* off because too opinionated
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-render-in-setup.md
*/
'testing-library/no-render-in-setup': 'off',
/**
* disallows unnecessary act() calls
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-unnecessary-act.md
*/
'testing-library/no-unnecessary-act': [
'error',
{
isStrict: true,
},
],
/**
* no empty `waitFor` or `waitForElementToBeRemoved`
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-wait-for-empty-callback.md
*/
'testing-library/no-wait-for-empty-callback': 'error',
/**
* disallows use of multiple expect inside of `waitFor`
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-wait-for-multiple-assertions.md
*/
'testing-library/no-wait-for-multiple-assertions': 'error',
/**
* disallows the use of sideeffects inside of `waitFor`
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-wait-for-side-effects.md
*/
'testing-library/no-wait-for-side-effects': 'error',
/**
* disallows snapshot generation within waitFor
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/no-wait-for-snapshot.md
*/
'testing-library/no-wait-for-snapshot': 'error',
/**
* use `expect(getByText('foo').tobeInTheDocument()` instead of
* `getByText('foo')` expecting it not to throw
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/prefer-explicit-assert.md
*/
'testing-library/prefer-explicit-assert': 'warn',
/**
* use `findBy*` instead of `waitFor` + `getBy*`
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/prefer-find-by.md
*/
'testing-library/prefer-find-by': 'warn',
/**
* ensure more specific queries to check element presence
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/prefer-presence-queries.md
*/
'testing-library/prefer-presence-queries': 'error',
/**
* prefer using queryBy* queries when waiting for disappearance
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/prefer-query-by-disappearance.md
*/
'testing-library/prefer-query-by-disappearance': 'error',
/**
* suggest using `screen` over destructured methods
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/prefer-screen-queries.md
*/
'testing-library/prefer-screen-queries': 'error',
/**
* suggest using `@testing-library/user-event` over `fireEvent` from `@testing-library/$framework`
*
* has some false positives, hence warn
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/prefer-user-event.md
*/
'testing-library/prefer-user-event': 'warn',
/**
* prefer `waitFor` instead of deprecated `wait` and similar
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/prefer-wait-for.md
*/
'testing-library/prefer-wait-for': 'warn',
/**
* enforces a valid naming for return value from render
*
* off because opinionated
*
* @see https://github.com/testing-library/eslint-plugin-testing-library/blob/main/docs/rules/render-result-naming-convention.md
*/
'testing-library/render-result-naming-convention': 'off',
});
export const createTestOverrides: RulesCreator = ({
typescript: { hasTypeScript },
react: { hasReact },
}) => ({
/**
* off to allow non-null casting e.g. querySelector or .find() results
*
* @see https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-non-null-assertion.md
*/
...(hasTypeScript
? { '@typescript-eslint/no-non-null-assertion': 'off' }
: null),
/**
* enforces unbound methods are called with their expected scope
*
* @see jest/unbound-method below
* @see https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/unbound-method.md
*/
...(hasTypeScript ? { '@typescript-eslint/unbound-method': 'warn' } : null),
/**
* off to allow silent mocks, e.g. for console
*
* @see https://eslint.org/docs/rules/no-empty-function
* @see @typescript-eslint/no-empty-function
*/
...(hasTypeScript ? { '@typescript-eslint/no-empty-function': 'off' } : null),
/**
* enforces unbound methods are called with their expected scope
*
* @see https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/unbound-method.md
*/
...(hasTypeScript ? { 'jest/unbound-method': 'warn' } : null),
/**
* off because its regularily done in tests
*
* @see https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/unified-signatures.md
*/
...(hasTypeScript ? { '@typescript-eslint/unbound-method': 'off' } : null),
/**
* off because irrelevant in tests
*
* @see https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md
*/
...(hasTypeScript
? { '@typescript-eslint/explicit-member-accessibility': 'off' }
: null),
/**
* off because irrelevant in tests and leads to false positives
*
* @see https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unsafe-argument.md
*/
...(hasTypeScript
? { '@typescript-eslint/no-unsafe-argument': 'off' }
: null),
/**
* off to allow spying on methods
*
* @see https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-namespace.md
*/
'import/no-namespace': 'off',
/**
* off to allow silent mocks, e.g. for console
*
* @see https://eslint.org/docs/rules/no-empty-function
* @see @typescript-eslint/no-empty-function
*/
'no-empty-function': 'off',
/**
* off because test names may be duplicated across different describe blocks
* @see sonarjs/no-duplicate-string
*/
'sonarjs/no-duplicate-string': 'off',
/**
* off because the same test implementation may reoccur across different describe blocks
* @see sonarjs/no-identical-function
*/
'sonarjs/no-identical-functions': 'off',
/**
* off because not too relevant in tests
*
* @see require-unicode-regexp
*/
'require-unicode-regexp': 'off',
/**
* off because may be situationally required in tests
*/
'no-param-reassign': 'off',
/**
* off because irrelevant in tests
*
* @see https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/button-has-type.md
*/
...(hasReact ? { 'react/button-has-type': 'off' } : null),
/**
* off because irrelevant in tests
*
* @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/control-has-associated-label.md
*/
...(hasReact ? { 'jsx-a11y/control-has-associated-label': 'off' } : null),
/**
* off because required for global jest.mock
*/
...(hasTypeScript
? { '@typescript-eslint/consistent-type-imports': 'off' }
: null),
});
/**
* @see https://github.com/testing-library/eslint-plugin-testing-library#testing-librarycustom-renders
*/
export const createTestingLibrarySettings: SettingsCreator = ({
hasTestingLibrary,
react: { isNext, hasReact },
}) => {
if (!hasTestingLibrary || !hasReact) {
return null;
}
return {
'testing-library/custom-renders': [
// allows usage of ReactDOM.renderToStaticMarkup in test files
'renderToStaticMarkup',
// allows usage of Document.renderDocument in test files
isNext && 'renderDocument',
].filter((maybeStr): maybeStr is string => maybeStr !== false),
};
};
const jestConfigPattern = ['jest.config.?(js|ts)'];
export const createJestConfigOverride: OverrideInternalOverride = ({
hasJest,
}) => {
if (!hasJest) {
return null;
}
return {
files: jestConfigPattern,
rules: {
'import/no-default-export': 'off',
},
overrideType: jestConfigOverrideType,
};
};