diff --git a/.eslintrc.json b/.eslintrc.json index f2555e8d..1a7ed2d4 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -6,6 +6,7 @@ "jest/globals": true }, "extends": [ + "kentcdodds", "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", "prettier", @@ -22,8 +23,35 @@ "project": "./tsconfig.eslint.json" }, "rules": { - "no-var": "error", + // TS "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }] + "@typescript-eslint/no-unused-vars": [ + "warn", + { "argsIgnorePattern": "^_" } + ], + "@typescript-eslint/no-use-before-define": "off", + + // ESLint + "max-lines-per-function": "off", + "no-restricted-imports": [ + "error", + { + "patterns": ["@typescript-eslint/experimental-utils/dist/*"] + } + ], + + // Import + "import/no-import-module-exports": "off", + "import/order": [ + "warn", + { + "groups": ["builtin", "external", "parent", "sibling", "index"], + "newlines-between": "always", + "alphabetize": { + "order": "asc", + "caseInsensitive": false + } + } + ] } } diff --git a/lib/configs/index.ts b/lib/configs/index.ts index 15b63782..42c3916a 100644 --- a/lib/configs/index.ts +++ b/lib/configs/index.ts @@ -1,13 +1,13 @@ import { join } from 'path'; -import type { TSESLint } from '@typescript-eslint/experimental-utils'; - import { importDefault, SUPPORTED_TESTING_FRAMEWORKS, SupportedTestingFramework, } from '../utils'; +import type { TSESLint } from '@typescript-eslint/experimental-utils'; + export type LinterConfigRules = Record; const configsDir = __dirname; diff --git a/lib/create-testing-library-rule/detect-testing-library-utils.ts b/lib/create-testing-library-rule/detect-testing-library-utils.ts index 62e5e54d..c62b9578 100644 --- a/lib/create-testing-library-rule/detect-testing-library-utils.ts +++ b/lib/create-testing-library-rule/detect-testing-library-utils.ts @@ -89,9 +89,9 @@ type IsAbsenceAssertFn = (node: TSESTree.MemberExpression) => boolean; type CanReportErrorsFn = () => boolean; type FindImportedTestingLibraryUtilSpecifierFn = ( specifierName: string -) => TSESTree.ImportClause | TSESTree.Identifier | undefined; +) => TSESTree.Identifier | TSESTree.ImportClause | undefined; type IsNodeComingFromTestingLibraryFn = ( - node: TSESTree.MemberExpression | TSESTree.Identifier + node: TSESTree.Identifier | TSESTree.MemberExpression ) => boolean; export interface DetectionHelpers { @@ -181,7 +181,7 @@ export function detectTestingLibraryUtils< * reporting) */ function isPotentialTestingLibraryFunction( - node: TSESTree.Identifier, + node: TSESTree.Identifier | null | undefined, isPotentialFunctionCallback: ( identifierNodeName: string, originalNodeName?: string @@ -472,9 +472,8 @@ export function detectTestingLibraryUtils< * Determines whether a given node is fireEvent method or not */ const isFireEventMethod: IsFireEventMethodFn = (node) => { - const fireEventUtil = findImportedTestingLibraryUtilSpecifier( - FIRE_EVENT_NAME - ); + const fireEventUtil = + findImportedTestingLibraryUtilSpecifier(FIRE_EVENT_NAME); let fireEventUtilName: string | undefined; if (fireEventUtil) { @@ -655,9 +654,8 @@ export function detectTestingLibraryUtils< return false; } const referenceNode = getReferenceNode(node); - const referenceNodeIdentifier = getPropertyIdentifierNode( - referenceNode - ); + const referenceNodeIdentifier = + getPropertyIdentifierNode(referenceNode); if (!referenceNodeIdentifier) { return false; } @@ -759,54 +757,58 @@ export function detectTestingLibraryUtils< /** * Finds the import util specifier related to Testing Library for a given name. */ - const findImportedTestingLibraryUtilSpecifier: FindImportedTestingLibraryUtilSpecifierFn = ( - specifierName - ): TSESTree.ImportClause | TSESTree.Identifier | undefined => { - const node = getCustomModuleImportNode() ?? getTestingLibraryImportNode(); + const findImportedTestingLibraryUtilSpecifier: FindImportedTestingLibraryUtilSpecifierFn = + ( + specifierName + ): TSESTree.Identifier | TSESTree.ImportClause | undefined => { + const node = + getCustomModuleImportNode() ?? getTestingLibraryImportNode(); + + if (!node) { + return undefined; + } - if (!node) { - return undefined; - } + return findImportSpecifier(specifierName, node); + }; - return findImportSpecifier(specifierName, node); - }; + const findImportedUserEventSpecifier: () => TSESTree.Identifier | null = + () => { + if (!importedUserEventLibraryNode) { + return null; + } - const findImportedUserEventSpecifier: () => TSESTree.Identifier | null = () => { - if (!importedUserEventLibraryNode) { - return null; - } + if (isImportDeclaration(importedUserEventLibraryNode)) { + const userEventIdentifier = + importedUserEventLibraryNode.specifiers.find((specifier) => + isImportDefaultSpecifier(specifier) + ); - if (isImportDeclaration(importedUserEventLibraryNode)) { - const userEventIdentifier = importedUserEventLibraryNode.specifiers.find( - (specifier) => isImportDefaultSpecifier(specifier) - ); + if (userEventIdentifier) { + return userEventIdentifier.local; + } + } else { + if ( + !ASTUtils.isVariableDeclarator(importedUserEventLibraryNode.parent) + ) { + return null; + } - if (userEventIdentifier) { - return userEventIdentifier.local; - } - } else { - if ( - !ASTUtils.isVariableDeclarator(importedUserEventLibraryNode.parent) - ) { - return null; - } + const requireNode = importedUserEventLibraryNode.parent; + if (!ASTUtils.isIdentifier(requireNode.id)) { + return null; + } - const requireNode = importedUserEventLibraryNode.parent; - if (!ASTUtils.isIdentifier(requireNode.id)) { - return null; + return requireNode.id; } - return requireNode.id; - } - - return null; - }; + return null; + }; const getTestingLibraryImportedUtilSpecifier = ( - node: TSESTree.MemberExpression | TSESTree.Identifier - ): TSESTree.ImportClause | TSESTree.Identifier | undefined => { - const identifierName: string | undefined = getPropertyIdentifierNode(node) - ?.name; + node: TSESTree.Identifier | TSESTree.MemberExpression + ): TSESTree.Identifier | TSESTree.ImportClause | undefined => { + const identifierName: string | undefined = + getPropertyIdentifierNode(node)?.name; if (!identifierName) { return undefined; @@ -848,9 +850,8 @@ export function detectTestingLibraryUtils< return importNode.parent; } - const variableDeclarator = findClosestVariableDeclaratorNode( - importNode - ); + const variableDeclarator = + findClosestVariableDeclaratorNode(importNode); if (isCallExpression(variableDeclarator?.init)) { return variableDeclarator?.init; @@ -868,8 +869,8 @@ export function detectTestingLibraryUtils< return false; } - const identifierName: string | undefined = getPropertyIdentifierNode(node) - ?.name; + const identifierName: string | undefined = + getPropertyIdentifierNode(node)?.name; if (!identifierName) { return false; @@ -1045,6 +1046,8 @@ export function detectTestingLibraryUtils< if (canReportErrors() && ruleInstructions[instruction]) { return ruleInstructions[instruction]?.(node); } + + return undefined; }; }); diff --git a/lib/create-testing-library-rule/index.ts b/lib/create-testing-library-rule/index.ts index 9ec86214..df46b06d 100644 --- a/lib/create-testing-library-rule/index.ts +++ b/lib/create-testing-library-rule/index.ts @@ -24,6 +24,7 @@ export function createTestingLibraryRule< detectionOptions?: Partial; create: EnhancedRuleCreate; }>): TSESLint.RuleModule { + // eslint-disable-next-line @babel/new-cap return ESLintUtils.RuleCreator(getDocsUrl)({ ...remainingConfig, create: detectTestingLibraryUtils( diff --git a/lib/node-utils/index.ts b/lib/node-utils/index.ts index 62e7dc3d..d1718f01 100644 --- a/lib/node-utils/index.ts +++ b/lib/node-utils/index.ts @@ -5,7 +5,6 @@ import { TSESLintScope, TSESTree, } from '@typescript-eslint/experimental-utils'; -import { RuleContext } from '@typescript-eslint/experimental-utils/dist/ts-eslint'; import { isArrayExpression, @@ -61,7 +60,7 @@ const ValidLeftHandSideExpressions = [ * @param shouldRestrictInnerScope - If true, CallExpression must belong to innermost scope of given node */ export function findClosestCallExpressionNode( - node: TSESTree.Node, + node: TSESTree.Node | null | undefined, shouldRestrictInnerScope = false ): TSESTree.CallExpression | null { if (isCallExpression(node)) { @@ -235,25 +234,26 @@ export function isPromiseHandled(nodeIdentifier: TSESTree.Identifier): boolean { } export function getVariableReferences( - context: RuleContext, + context: TSESLint.RuleContext, node: TSESTree.Node ): TSESLint.Scope.Reference[] { - return ( - (ASTUtils.isVariableDeclarator(node) && - context.getDeclaredVariables(node)[0]?.references?.slice(1)) || - [] - ); + if (ASTUtils.isVariableDeclarator(node)) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + return context.getDeclaredVariables(node)[0]?.references?.slice(1) ?? []; + } + + return []; } interface InnermostFunctionScope extends TSESLintScope.FunctionScope { block: + | TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclaration - | TSESTree.FunctionExpression - | TSESTree.ArrowFunctionExpression; + | TSESTree.FunctionExpression; } export function getInnermostFunctionScope( - context: RuleContext, + context: TSESLint.RuleContext, asyncQueryNode: TSESTree.Identifier ): InnermostFunctionScope | null { const innermostScope = ASTUtils.getInnermostScope( @@ -262,10 +262,10 @@ export function getInnermostFunctionScope( ); if ( - innermostScope?.type === 'function' && + innermostScope.type === 'function' && ASTUtils.isFunction(innermostScope.block) ) { - return (innermostScope as unknown) as InnermostFunctionScope; + return innermostScope as unknown as InnermostFunctionScope; } return null; @@ -273,9 +273,9 @@ export function getInnermostFunctionScope( export function getFunctionReturnStatementNode( functionNode: + | TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression - | TSESTree.ArrowFunctionExpression ): TSESTree.Node | null { if (isBlockStatement(functionNode.body)) { // regular function or arrow function with block @@ -372,9 +372,9 @@ export function getDeepestIdentifierNode( export function getReferenceNode( node: | TSESTree.CallExpression - | TSESTree.MemberExpression | TSESTree.Identifier -): TSESTree.CallExpression | TSESTree.MemberExpression | TSESTree.Identifier { + | TSESTree.MemberExpression +): TSESTree.CallExpression | TSESTree.Identifier | TSESTree.MemberExpression { if ( node.parent && (isMemberExpression(node.parent) || isCallExpression(node.parent)) @@ -387,9 +387,9 @@ export function getReferenceNode( export function getFunctionName( node: + | TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression - | TSESTree.ArrowFunctionExpression ): string { return ( ASTUtils.getFunctionNameWithKind(node) @@ -400,11 +400,11 @@ export function getFunctionName( // TODO: extract into types file? export type ImportModuleNode = - | TSESTree.ImportDeclaration - | TSESTree.CallExpression; + | TSESTree.CallExpression + | TSESTree.ImportDeclaration; export function getImportModuleName( - node: ImportModuleNode | undefined | null + node: ImportModuleNode | null | undefined ): string | undefined { // import node of shape: import { foo } from 'bar' if (isImportDeclaration(node) && typeof node.source.value === 'string') { @@ -419,6 +419,8 @@ export function getImportModuleName( ) { return node.arguments[0].value; } + + return undefined; } type AssertNodeInfo = { @@ -491,17 +493,17 @@ export function hasClosestExpectResolvesRejects(node: TSESTree.Node): boolean { * Gets the Function node which returns the given Identifier. */ export function getInnermostReturningFunction( - context: RuleContext, + context: TSESLint.RuleContext, node: TSESTree.Identifier ): + | TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression - | TSESTree.ArrowFunctionExpression | undefined { const functionScope = getInnermostFunctionScope(context, node); if (!functionScope) { - return; + return undefined; } const returnStatementNode = getFunctionReturnStatementNode( @@ -509,22 +511,21 @@ export function getInnermostReturningFunction( ); if (!returnStatementNode) { - return; + return undefined; } - const returnStatementIdentifier = getDeepestIdentifierNode( - returnStatementNode - ); + const returnStatementIdentifier = + getDeepestIdentifierNode(returnStatementNode); if (returnStatementIdentifier?.name !== node.name) { - return; + return undefined; } return functionScope.block; } export function hasImportMatch( - importNode: TSESTree.ImportClause | TSESTree.Identifier, + importNode: TSESTree.Identifier | TSESTree.ImportClause, identifierName: string ): boolean { if (ASTUtils.isIdentifier(importNode)) { @@ -601,7 +602,7 @@ export function isEmptyFunction(node: TSESTree.Node): boolean | undefined { export function findImportSpecifier( specifierName: string, node: ImportModuleNode -): TSESTree.ImportClause | TSESTree.Identifier | undefined { +): TSESTree.Identifier | TSESTree.ImportClause | undefined { if (isImportDeclaration(node)) { const namedExport = node.specifiers.find((n) => { return ( diff --git a/lib/node-utils/is-node-of-type.ts b/lib/node-utils/is-node-of-type.ts index ac8dbb5f..f227d8e3 100644 --- a/lib/node-utils/is-node-of-type.ts +++ b/lib/node-utils/is-node-of-type.ts @@ -3,9 +3,12 @@ import { TSESTree, } from '@typescript-eslint/experimental-utils'; -const isNodeOfType = (nodeType: NodeType) => ( - node: TSESTree.Node | null | undefined -): node is TSESTree.Node & { type: NodeType } => node?.type === nodeType; +const isNodeOfType = + (nodeType: NodeType) => + ( + node: TSESTree.Node | null | undefined + ): node is TSESTree.Node & { type: NodeType } => + node?.type === nodeType; export const isArrayExpression = isNodeOfType(AST_NODE_TYPES.ArrayExpression); export const isArrowFunctionExpression = isNodeOfType( diff --git a/lib/rules/await-async-query.ts b/lib/rules/await-async-query.ts index 138e449b..c3860452 100644 --- a/lib/rules/await-async-query.ts +++ b/lib/rules/await-async-query.ts @@ -1,4 +1,6 @@ import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils'; + +import { createTestingLibraryRule } from '../create-testing-library-rule'; import { findClosestCallExpressionNode, getDeepestIdentifierNode, @@ -7,10 +9,9 @@ import { getVariableReferences, isPromiseHandled, } from '../node-utils'; -import { createTestingLibraryRule } from '../create-testing-library-rule'; export const RULE_NAME = 'await-async-query'; -export type MessageIds = 'awaitAsyncQuery' | 'asyncQueryWrapper'; +export type MessageIds = 'asyncQueryWrapper' | 'awaitAsyncQuery'; type Options = []; export default createTestingLibraryRule({ @@ -74,14 +75,15 @@ export default createTestingLibraryRule({ ); // check direct usage of async query: - // const element = await findByRole('button') - if (references && references.length === 0) { + // const element = await findByRole('button') + if (references.length === 0) { if (!isPromiseHandled(identifierNode)) { - return context.report({ + context.report({ node: identifierNode, messageId: 'awaitAsyncQuery', data: { name: identifierNode.name }, }); + return; } } @@ -93,22 +95,24 @@ export default createTestingLibraryRule({ ASTUtils.isIdentifier(reference.identifier) && !isPromiseHandled(reference.identifier) ) { - return context.report({ + context.report({ node: identifierNode, messageId: 'awaitAsyncQuery', data: { name: identifierNode.name }, }); + return; } } - } else if (functionWrappersNames.includes(identifierNode.name)) { + } else if ( + functionWrappersNames.includes(identifierNode.name) && + !isPromiseHandled(identifierNode) + ) { // check async queries used within a wrapper previously detected - if (!isPromiseHandled(identifierNode)) { - return context.report({ - node: identifierNode, - messageId: 'asyncQueryWrapper', - data: { name: identifierNode.name }, - }); - } + context.report({ + node: identifierNode, + messageId: 'asyncQueryWrapper', + data: { name: identifierNode.name }, + }); } }, }; diff --git a/lib/rules/await-async-utils.ts b/lib/rules/await-async-utils.ts index a220fe90..230f3dbc 100644 --- a/lib/rules/await-async-utils.ts +++ b/lib/rules/await-async-utils.ts @@ -1,4 +1,6 @@ import { TSESTree } from '@typescript-eslint/experimental-utils'; + +import { createTestingLibraryRule } from '../create-testing-library-rule'; import { findClosestCallExpressionNode, getFunctionName, @@ -6,10 +8,9 @@ import { getVariableReferences, isPromiseHandled, } from '../node-utils'; -import { createTestingLibraryRule } from '../create-testing-library-rule'; export const RULE_NAME = 'await-async-utils'; -export type MessageIds = 'awaitAsyncUtil' | 'asyncUtilWrapper'; +export type MessageIds = 'asyncUtilWrapper' | 'awaitAsyncUtil'; type Options = []; export default createTestingLibraryRule({ @@ -66,9 +67,9 @@ export default createTestingLibraryRule({ closestCallExpression.parent ); - if (references && references.length === 0) { + if (references.length === 0) { if (!isPromiseHandled(node)) { - return context.report({ + context.report({ node, messageId: 'awaitAsyncUtil', data: { @@ -80,20 +81,21 @@ export default createTestingLibraryRule({ for (const reference of references) { const referenceNode = reference.identifier as TSESTree.Identifier; if (!isPromiseHandled(referenceNode)) { - return context.report({ + context.report({ node, messageId: 'awaitAsyncUtil', data: { name: node.name, }, }); + return; } } } } else if (functionWrappersNames.includes(node.name)) { // check async queries used within a wrapper previously detected if (!isPromiseHandled(node)) { - return context.report({ + context.report({ node, messageId: 'asyncUtilWrapper', data: { name: node.name }, diff --git a/lib/rules/await-fire-event.ts b/lib/rules/await-fire-event.ts index f5ff5f61..5fdaa794 100644 --- a/lib/rules/await-fire-event.ts +++ b/lib/rules/await-fire-event.ts @@ -1,4 +1,6 @@ -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils'; + +import { createTestingLibraryRule } from '../create-testing-library-rule'; import { findClosestCallExpressionNode, getFunctionName, @@ -6,7 +8,6 @@ import { getVariableReferences, isPromiseHandled, } from '../node-utils'; -import { createTestingLibraryRule } from '../create-testing-library-rule'; export const RULE_NAME = 'await-fire-event'; export type MessageIds = 'awaitFireEvent' | 'fireEventWrapper'; @@ -36,7 +37,7 @@ export default createTestingLibraryRule({ }, defaultOptions: [], - create: function (context, _, helpers) { + create(context, _, helpers) { const functionWrappersNames: string[] = []; function reportUnhandledNode( @@ -81,11 +82,15 @@ export default createTestingLibraryRule({ ); if (references.length === 0) { - return reportUnhandledNode(node, closestCallExpression); + reportUnhandledNode(node, closestCallExpression); } else { for (const reference of references) { - const referenceNode = reference.identifier as TSESTree.Identifier; - return reportUnhandledNode(referenceNode, closestCallExpression); + if (ASTUtils.isIdentifier(reference.identifier)) { + reportUnhandledNode( + reference.identifier, + closestCallExpression + ); + } } } } else if (functionWrappersNames.includes(node.name)) { @@ -100,11 +105,7 @@ export default createTestingLibraryRule({ return; } - return reportUnhandledNode( - node, - closestCallExpression, - 'fireEventWrapper' - ); + reportUnhandledNode(node, closestCallExpression, 'fireEventWrapper'); } }, }; diff --git a/lib/rules/consistent-data-testid.ts b/lib/rules/consistent-data-testid.ts index 6b17ad5b..e799acd0 100644 --- a/lib/rules/consistent-data-testid.ts +++ b/lib/rules/consistent-data-testid.ts @@ -5,7 +5,7 @@ export const RULE_NAME = 'consistent-data-testid'; export type MessageIds = 'consistentDataTestId'; export type Options = [ { - testIdAttribute?: string | string[]; + testIdAttribute?: string[] | string; testIdPattern: string; } ]; diff --git a/lib/rules/no-await-sync-events.ts b/lib/rules/no-await-sync-events.ts index 1080336a..bdb407ab 100644 --- a/lib/rules/no-await-sync-events.ts +++ b/lib/rules/no-await-sync-events.ts @@ -1,4 +1,6 @@ import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils'; + +import { createTestingLibraryRule } from '../create-testing-library-rule'; import { getDeepestIdentifierNode, getPropertyIdentifierNode, @@ -6,7 +8,6 @@ import { isObjectExpression, isProperty, } from '../node-utils'; -import { createTestingLibraryRule } from '../create-testing-library-rule'; export const RULE_NAME = 'no-await-sync-events'; export type MessageIds = 'noAwaitSyncEvents'; @@ -64,12 +65,12 @@ export default createTestingLibraryRule({ isObjectExpression(lastArg) && lastArg.properties.some( (property) => - (isProperty(property) && - ASTUtils.isIdentifier(property.key) && - property.key.name === 'delay' && - isLiteral(property.value) && - property.value.value) ?? - 0 > 0 + isProperty(property) && + ASTUtils.isIdentifier(property.key) && + property.key.name === 'delay' && + isLiteral(property.value) && + !!property.value.value && + property.value.value > 0 ); const simulateEventFunctionName = simulateEventFunctionIdentifier.name; diff --git a/lib/rules/no-await-sync-query.ts b/lib/rules/no-await-sync-query.ts index ce484159..5e71c9fc 100644 --- a/lib/rules/no-await-sync-query.ts +++ b/lib/rules/no-await-sync-query.ts @@ -1,4 +1,5 @@ import { TSESTree } from '@typescript-eslint/experimental-utils'; + import { createTestingLibraryRule } from '../create-testing-library-rule'; import { getDeepestIdentifierNode } from '../node-utils'; diff --git a/lib/rules/no-container.ts b/lib/rules/no-container.ts index 09d63524..1f79c3eb 100644 --- a/lib/rules/no-container.ts +++ b/lib/rules/no-container.ts @@ -1,4 +1,6 @@ import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils'; + +import { createTestingLibraryRule } from '../create-testing-library-rule'; import { getDeepestIdentifierNode, getFunctionName, @@ -7,7 +9,6 @@ import { isObjectPattern, isProperty, } from '../node-utils'; -import { createTestingLibraryRule } from '../create-testing-library-rule'; export const RULE_NAME = 'no-container'; export type MessageIds = 'noContainer'; @@ -35,7 +36,7 @@ export default createTestingLibraryRule({ }, defaultOptions: [], - create(context, [], helpers) { + create(context, _, helpers) { const destructuredContainerPropNames: string[] = []; const renderWrapperNames: string[] = []; let renderResultVarName: string | null = null; @@ -99,17 +100,18 @@ export default createTestingLibraryRule({ if (isMemberExpression(node.callee)) { showErrorIfChainedContainerMethod(node.callee); - } else { + } else if ( ASTUtils.isIdentifier(node.callee) && - destructuredContainerPropNames.includes(node.callee.name) && - context.report({ - node, - messageId: 'noContainer', - }); + destructuredContainerPropNames.includes(node.callee.name) + ) { + context.report({ + node, + messageId: 'noContainer', + }); } }, - VariableDeclarator: function (node) { + VariableDeclarator(node) { if (!node.init) { return; } @@ -119,9 +121,9 @@ export default createTestingLibraryRule({ return; } - const isRenderWrapperVariableDeclarator = initIdentifierNode - ? renderWrapperNames.includes(initIdentifierNode.name) - : false; + const isRenderWrapperVariableDeclarator = renderWrapperNames.includes( + initIdentifierNode.name + ); if ( !helpers.isRenderVariableDeclarator(node) && @@ -147,14 +149,13 @@ export default createTestingLibraryRule({ if (ASTUtils.isIdentifier(nodeValue)) { containerName = nodeValue.name; - } else { - isObjectPattern(nodeValue) && - nodeValue.properties.forEach( - (property) => - isProperty(property) && - ASTUtils.isIdentifier(property.key) && - destructuredContainerPropNames.push(property.key.name) - ); + } else if (isObjectPattern(nodeValue)) { + nodeValue.properties.forEach( + (property) => + isProperty(property) && + ASTUtils.isIdentifier(property.key) && + destructuredContainerPropNames.push(property.key.name) + ); } } else if (ASTUtils.isIdentifier(node.id)) { renderResultVarName = node.id.name; diff --git a/lib/rules/no-debug.ts b/lib/rules/no-debug.ts index 39d2829a..a0808154 100644 --- a/lib/rules/no-debug.ts +++ b/lib/rules/no-debug.ts @@ -1,3 +1,10 @@ +import { + ASTUtils, + TSESTree, + JSONSchema, +} from '@typescript-eslint/experimental-utils'; + +import { createTestingLibraryRule } from '../create-testing-library-rule'; import { getDeepestIdentifierNode, getFunctionName, @@ -9,12 +16,6 @@ import { isProperty, } from '../node-utils'; import { DEBUG_UTILS } from '../utils'; -import { createTestingLibraryRule } from '../create-testing-library-rule'; -import { - ASTUtils, - TSESTree, - JSONSchema, -} from '@typescript-eslint/experimental-utils'; type DebugUtilsToCheckFor = Partial< Record @@ -101,9 +102,9 @@ export default createTestingLibraryRule({ return; } - const isRenderWrapperVariableDeclarator = initIdentifierNode - ? renderWrapperNames.includes(initIdentifierNode.name) - : false; + const isRenderWrapperVariableDeclarator = renderWrapperNames.includes( + initIdentifierNode.name + ); if ( !helpers.isRenderVariableDeclarator(node) && diff --git a/lib/rules/no-dom-import.ts b/lib/rules/no-dom-import.ts index f294dd8c..5298eea2 100644 --- a/lib/rules/no-dom-import.ts +++ b/lib/rules/no-dom-import.ts @@ -1,4 +1,5 @@ import { TSESTree } from '@typescript-eslint/experimental-utils'; + import { createTestingLibraryRule } from '../create-testing-library-rule'; import { isCallExpression } from '../node-utils'; @@ -42,7 +43,7 @@ export default createTestingLibraryRule({ create(context, [framework], helpers) { function report( - node: TSESTree.ImportDeclaration | TSESTree.CallExpression, + node: TSESTree.CallExpression | TSESTree.ImportDeclaration, moduleName: string ) { if (framework) { diff --git a/lib/rules/no-manual-cleanup.ts b/lib/rules/no-manual-cleanup.ts index 7fdad94d..506dc9c8 100644 --- a/lib/rules/no-manual-cleanup.ts +++ b/lib/rules/no-manual-cleanup.ts @@ -3,6 +3,8 @@ import { TSESTree, TSESLint, } from '@typescript-eslint/experimental-utils'; + +import { createTestingLibraryRule } from '../create-testing-library-rule'; import { getVariableReferences, isImportDefaultSpecifier, @@ -13,13 +15,13 @@ import { ImportModuleNode, isImportDeclaration, } from '../node-utils'; -import { createTestingLibraryRule } from '../create-testing-library-rule'; export const RULE_NAME = 'no-manual-cleanup'; export type MessageIds = 'noManualCleanup'; type Options = []; -const CLEANUP_LIBRARY_REGEXP = /(@testing-library\/(preact|react|svelte|vue))|@marko\/testing-library/; +const CLEANUP_LIBRARY_REGEXP = + /(@testing-library\/(preact|react|svelte|vue))|@marko\/testing-library/; export default createTestingLibraryRule({ name: RULE_NAME, diff --git a/lib/rules/no-node-access.ts b/lib/rules/no-node-access.ts index 5827298b..a9e4ce4e 100644 --- a/lib/rules/no-node-access.ts +++ b/lib/rules/no-node-access.ts @@ -1,6 +1,7 @@ import { TSESTree, ASTUtils } from '@typescript-eslint/experimental-utils'; -import { ALL_RETURNING_NODES } from '../utils'; + import { createTestingLibraryRule } from '../create-testing-library-rule'; +import { ALL_RETURNING_NODES } from '../utils'; export const RULE_NAME = 'no-node-access'; export type MessageIds = 'noNodeAccess'; @@ -37,18 +38,21 @@ export default createTestingLibraryRule({ return; } - ASTUtils.isIdentifier(node.property) && - ALL_RETURNING_NODES.includes(node.property.name) && + if ( + ASTUtils.isIdentifier(node.property) && + ALL_RETURNING_NODES.includes(node.property.name) + ) { context.report({ - node: node, + node, loc: node.property.loc.start, messageId: 'noNodeAccess', }); + } } return { - ['ExpressionStatement MemberExpression']: showErrorForNodeAccess, - ['VariableDeclarator MemberExpression']: showErrorForNodeAccess, + 'ExpressionStatement MemberExpression': showErrorForNodeAccess, + 'VariableDeclarator MemberExpression': showErrorForNodeAccess, }; }, }); diff --git a/lib/rules/no-promise-in-fire-event.ts b/lib/rules/no-promise-in-fire-event.ts index ac731719..ea1c6f8b 100644 --- a/lib/rules/no-promise-in-fire-event.ts +++ b/lib/rules/no-promise-in-fire-event.ts @@ -1,4 +1,5 @@ import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils'; + import { createTestingLibraryRule } from '../create-testing-library-rule'; import { findClosestCallExpressionNode, @@ -46,10 +47,11 @@ export default createTestingLibraryRule({ if (isNewExpression(node)) { if (isPromiseIdentifier(node.callee)) { - return context.report({ + context.report({ node: originalNode ?? node, messageId: 'noPromiseInFireEvent', }); + return; } } @@ -64,10 +66,11 @@ export default createTestingLibraryRule({ helpers.isAsyncQuery(domElementIdentifier) || isPromiseIdentifier(domElementIdentifier) ) { - return context.report({ + context.report({ node: originalNode ?? node, messageId: 'noPromiseInFireEvent', }); + return; } } @@ -76,12 +79,13 @@ export default createTestingLibraryRule({ context.getScope(), node.name ); - if (!nodeVariable || !nodeVariable.defs) { + if (!nodeVariable) { return; } for (const definition of nodeVariable.defs) { - const variableDeclarator = definition.node as TSESTree.VariableDeclarator; + const variableDeclarator = + definition.node as TSESTree.VariableDeclarator; if (variableDeclarator.init) { checkSuspiciousNode(variableDeclarator.init, node); } diff --git a/lib/rules/no-render-in-setup.ts b/lib/rules/no-render-in-setup.ts index c445e53e..e5c7f437 100644 --- a/lib/rules/no-render-in-setup.ts +++ b/lib/rules/no-render-in-setup.ts @@ -1,12 +1,13 @@ import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils'; -import { TESTING_FRAMEWORK_SETUP_HOOKS } from '../utils'; + +import { createTestingLibraryRule } from '../create-testing-library-rule'; import { getDeepestIdentifierNode, getFunctionName, getInnermostReturningFunction, isCallExpression, } from '../node-utils'; -import { createTestingLibraryRule } from '../create-testing-library-rule'; +import { TESTING_FRAMEWORK_SETUP_HOOKS } from '../utils'; export const RULE_NAME = 'no-render-in-setup'; export type MessageIds = 'noRenderInSetup'; @@ -17,7 +18,7 @@ type Options = [ ]; export function findClosestBeforeHook( - node: TSESTree.Node, + node: TSESTree.Node | null, testingFrameworkSetupHooksToFilter: string[] ): TSESTree.Identifier | null { if (node === null) { @@ -91,9 +92,10 @@ export default createTestingLibraryRule({ return { CallExpression(node) { - const testingFrameworkSetupHooksToFilter = TESTING_FRAMEWORK_SETUP_HOOKS.filter( - (hook) => hook !== allowTestingFrameworkSetupHook - ); + const testingFrameworkSetupHooksToFilter = + TESTING_FRAMEWORK_SETUP_HOOKS.filter( + (hook) => hook !== allowTestingFrameworkSetupHook + ); const callExpressionIdentifier = getDeepestIdentifierNode(node); if (!callExpressionIdentifier) { diff --git a/lib/rules/no-unnecessary-act.ts b/lib/rules/no-unnecessary-act.ts index 152dd226..6bdfeb33 100644 --- a/lib/rules/no-unnecessary-act.ts +++ b/lib/rules/no-unnecessary-act.ts @@ -1,4 +1,5 @@ import { TSESTree } from '@typescript-eslint/experimental-utils'; + import { createTestingLibraryRule } from '../create-testing-library-rule'; import { getDeepestIdentifierNode, @@ -8,8 +9,8 @@ import { export const RULE_NAME = 'no-unnecessary-act'; export type MessageIds = - | 'noUnnecessaryActTestingLibraryUtil' - | 'noUnnecessaryActEmptyFunction'; + | 'noUnnecessaryActEmptyFunction' + | 'noUnnecessaryActTestingLibraryUtil'; export default createTestingLibraryRule<[], MessageIds>({ name: RULE_NAME, @@ -62,9 +63,9 @@ export default createTestingLibraryRule<[], MessageIds>({ function checkNoUnnecessaryActFromBlockStatement( blockStatementNode: TSESTree.BlockStatement ) { - const functionNode = blockStatementNode?.parent as - | TSESTree.FunctionExpression + const functionNode = blockStatementNode.parent as | TSESTree.ArrowFunctionExpression + | TSESTree.FunctionExpression | undefined; const callExpressionNode = functionNode?.parent as | TSESTree.CallExpression @@ -105,7 +106,7 @@ export default createTestingLibraryRule<[], MessageIds>({ return; } - const parentCallExpression = node?.parent?.parent as + const parentCallExpression = node.parent?.parent as | TSESTree.CallExpression | undefined; @@ -133,9 +134,12 @@ export default createTestingLibraryRule<[], MessageIds>({ } return { - 'CallExpression > ArrowFunctionExpression > BlockStatement': checkNoUnnecessaryActFromBlockStatement, - 'CallExpression > FunctionExpression > BlockStatement': checkNoUnnecessaryActFromBlockStatement, - 'CallExpression > ArrowFunctionExpression > CallExpression': checkNoUnnecessaryActFromImplicitReturn, + 'CallExpression > ArrowFunctionExpression > BlockStatement': + checkNoUnnecessaryActFromBlockStatement, + 'CallExpression > FunctionExpression > BlockStatement': + checkNoUnnecessaryActFromBlockStatement, + 'CallExpression > ArrowFunctionExpression > CallExpression': + checkNoUnnecessaryActFromImplicitReturn, }; }, }); diff --git a/lib/rules/no-wait-for-empty-callback.ts b/lib/rules/no-wait-for-empty-callback.ts index 0ca71193..fd95da58 100644 --- a/lib/rules/no-wait-for-empty-callback.ts +++ b/lib/rules/no-wait-for-empty-callback.ts @@ -1,10 +1,11 @@ import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils'; + +import { createTestingLibraryRule } from '../create-testing-library-rule'; import { getPropertyIdentifierNode, isCallExpression, isEmptyFunction, } from '../node-utils'; -import { createTestingLibraryRule } from '../create-testing-library-rule'; export const RULE_NAME = 'no-wait-for-empty-callback'; export type MessageIds = 'noWaitForEmptyCallback'; diff --git a/lib/rules/no-wait-for-multiple-assertions.ts b/lib/rules/no-wait-for-multiple-assertions.ts index e540c428..a5be1c08 100644 --- a/lib/rules/no-wait-for-multiple-assertions.ts +++ b/lib/rules/no-wait-for-multiple-assertions.ts @@ -1,9 +1,10 @@ import { TSESTree } from '@typescript-eslint/experimental-utils'; + +import { createTestingLibraryRule } from '../create-testing-library-rule'; import { getPropertyIdentifierNode, isExpressionStatement, } from '../node-utils'; -import { createTestingLibraryRule } from '../create-testing-library-rule'; export const RULE_NAME = 'no-wait-for-multiple-assertions'; export type MessageIds = 'noWaitForMultipleAssertion'; @@ -30,7 +31,7 @@ export default createTestingLibraryRule({ schema: [], }, defaultOptions: [], - create: function (context, _, helpers) { + create(context, _, helpers) { function getExpectNodes( body: Array ): Array { @@ -53,9 +54,8 @@ export default createTestingLibraryRule({ return; } const callExpressionNode = node.parent.parent as TSESTree.CallExpression; - const callExpressionIdentifier = getPropertyIdentifierNode( - callExpressionNode - ); + const callExpressionIdentifier = + getPropertyIdentifierNode(callExpressionNode); if (!callExpressionIdentifier) { return; @@ -82,8 +82,10 @@ export default createTestingLibraryRule({ } return { - 'CallExpression > ArrowFunctionExpression > BlockStatement': reportMultipleAssertion, - 'CallExpression > FunctionExpression > BlockStatement': reportMultipleAssertion, + 'CallExpression > ArrowFunctionExpression > BlockStatement': + reportMultipleAssertion, + 'CallExpression > FunctionExpression > BlockStatement': + reportMultipleAssertion, }; }, }); diff --git a/lib/rules/no-wait-for-side-effects.ts b/lib/rules/no-wait-for-side-effects.ts index 240b509a..b038e365 100644 --- a/lib/rules/no-wait-for-side-effects.ts +++ b/lib/rules/no-wait-for-side-effects.ts @@ -1,4 +1,6 @@ import { TSESTree } from '@typescript-eslint/experimental-utils'; + +import { createTestingLibraryRule } from '../create-testing-library-rule'; import { getPropertyIdentifierNode, isExpressionStatement, @@ -7,7 +9,6 @@ import { isCallExpression, isSequenceExpression, } from '../node-utils'; -import { createTestingLibraryRule } from '../create-testing-library-rule'; export const RULE_NAME = 'no-wait-for-side-effects'; export type MessageIds = 'noSideEffectsWaitFor'; @@ -34,21 +35,20 @@ export default createTestingLibraryRule({ schema: [], }, defaultOptions: [], - create: function (context, _, helpers) { + create(context, _, helpers) { function isCallerWaitFor( node: + | TSESTree.AssignmentExpression | TSESTree.BlockStatement | TSESTree.CallExpression - | TSESTree.AssignmentExpression | TSESTree.SequenceExpression ): boolean { if (!node.parent) { return false; } const callExpressionNode = node.parent.parent as TSESTree.CallExpression; - const callExpressionIdentifier = getPropertyIdentifierNode( - callExpressionNode - ); + const callExpressionIdentifier = + getPropertyIdentifierNode(callExpressionNode); return ( !!callExpressionIdentifier && @@ -147,8 +147,8 @@ export default createTestingLibraryRule({ function reportImplicitReturnSideEffect( node: - | TSESTree.CallExpression | TSESTree.AssignmentExpression + | TSESTree.CallExpression | TSESTree.SequenceExpression ) { if (!isCallerWaitFor(node)) { @@ -183,10 +183,14 @@ export default createTestingLibraryRule({ } return { - 'CallExpression > ArrowFunctionExpression > BlockStatement': reportSideEffects, - 'CallExpression > ArrowFunctionExpression > CallExpression': reportImplicitReturnSideEffect, - 'CallExpression > ArrowFunctionExpression > AssignmentExpression': reportImplicitReturnSideEffect, - 'CallExpression > ArrowFunctionExpression > SequenceExpression': reportImplicitReturnSideEffect, + 'CallExpression > ArrowFunctionExpression > BlockStatement': + reportSideEffects, + 'CallExpression > ArrowFunctionExpression > CallExpression': + reportImplicitReturnSideEffect, + 'CallExpression > ArrowFunctionExpression > AssignmentExpression': + reportImplicitReturnSideEffect, + 'CallExpression > ArrowFunctionExpression > SequenceExpression': + reportImplicitReturnSideEffect, 'CallExpression > FunctionExpression > BlockStatement': reportSideEffects, }; }, diff --git a/lib/rules/no-wait-for-snapshot.ts b/lib/rules/no-wait-for-snapshot.ts index 2da611c4..0c78f30d 100644 --- a/lib/rules/no-wait-for-snapshot.ts +++ b/lib/rules/no-wait-for-snapshot.ts @@ -1,4 +1,5 @@ import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils'; + import { createTestingLibraryRule } from '../create-testing-library-rule'; import { findClosestCallExpressionNode, diff --git a/lib/rules/prefer-explicit-assert.ts b/lib/rules/prefer-explicit-assert.ts index f70d3cfb..98c23b5d 100644 --- a/lib/rules/prefer-explicit-assert.ts +++ b/lib/rules/prefer-explicit-assert.ts @@ -1,8 +1,8 @@ import { TSESTree, ASTUtils } from '@typescript-eslint/experimental-utils'; -import { PRESENCE_MATCHERS, ABSENCE_MATCHERS } from '../utils'; -import { findClosestCallNode, isMemberExpression } from '../node-utils'; import { createTestingLibraryRule } from '../create-testing-library-rule'; +import { findClosestCallNode, isMemberExpression } from '../node-utils'; +import { PRESENCE_MATCHERS, ABSENCE_MATCHERS } from '../utils'; export const RULE_NAME = 'prefer-explicit-assert'; export type MessageIds = @@ -15,7 +15,7 @@ type Options = [ ]; const isAtTopLevel = (node: TSESTree.Node) => - !!node?.parent?.parent && node.parent.parent.type === 'ExpressionStatement'; + !!node.parent?.parent && node.parent.parent.type === 'ExpressionStatement'; export default createTestingLibraryRule({ name: RULE_NAME, @@ -79,7 +79,8 @@ export default createTestingLibraryRule({ const expectCallNode = findClosestCallNode(node, 'expect'); if (!expectCallNode) return; - const expectStatement = expectCallNode.parent as TSESTree.MemberExpression; + const expectStatement = + expectCallNode.parent as TSESTree.MemberExpression; const property = expectStatement.property as TSESTree.Identifier; let matcher = property.name; let isNegatedMatcher = false; diff --git a/lib/rules/prefer-find-by.ts b/lib/rules/prefer-find-by.ts index 5d3b6f5d..90568bce 100644 --- a/lib/rules/prefer-find-by.ts +++ b/lib/rules/prefer-find-by.ts @@ -3,6 +3,8 @@ import { ASTUtils, TSESLint, } from '@typescript-eslint/experimental-utils'; + +import { createTestingLibraryRule } from '../create-testing-library-rule'; import { isArrowFunctionExpression, isCallExpression, @@ -10,7 +12,6 @@ import { isObjectPattern, isProperty, } from '../node-utils'; -import { createTestingLibraryRule } from '../create-testing-library-rule'; export const RULE_NAME = 'prefer-find-by'; export type MessageIds = 'preferFindBy'; @@ -88,20 +89,15 @@ export default createTestingLibraryRule({ function reportInvalidUsage( node: TSESTree.CallExpression, replacementParams: { - queryVariant: 'findBy' | 'findAllBy'; + queryVariant: 'findAllBy' | 'findBy'; queryMethod: string; prevQuery: string; waitForMethodName: string; fix: TSESLint.ReportFixFunction; } ) { - const { - queryMethod, - queryVariant, - prevQuery, - waitForMethodName, - fix, - } = replacementParams; + const { queryMethod, queryVariant, prevQuery, waitForMethodName, fix } = + replacementParams; context.report({ node, messageId: 'preferFindBy', @@ -155,13 +151,15 @@ export default createTestingLibraryRule({ prevQuery: fullQueryMethod, waitForMethodName, fix(fixer) { - const property = ((argument.body as TSESTree.CallExpression) - .callee as TSESTree.MemberExpression).property; + const property = ( + (argument.body as TSESTree.CallExpression) + .callee as TSESTree.MemberExpression + ).property; if (helpers.isCustomQuery(property as TSESTree.Identifier)) { return null; } const newCode = `${caller}.${queryVariant}${queryMethod}(${callArguments - .map((node) => sourceCode.getText(node)) + .map((callArgNode) => sourceCode.getText(callArgNode)) .join(', ')})`; return fixer.replaceText(node, newCode); }, @@ -199,7 +197,7 @@ export default createTestingLibraryRule({ const allFixes: TSESLint.RuleFix[] = []; // this updates waitFor with findBy* const newCode = `${findByMethod}(${callArguments - .map((node) => sourceCode.getText(node)) + .map((callArgNode) => sourceCode.getText(callArgNode)) .join(', ')})`; allFixes.push(fixer.replaceText(node, newCode)); @@ -233,9 +231,10 @@ export default createTestingLibraryRule({ const textDestructuring = sourceCode.getText( allVariableDeclarations ); - const text = - textDestructuring.substring(0, textDestructuring.length - 2) + - `, ${findByMethod} }`; + const text = `${textDestructuring.substring( + 0, + textDestructuring.length - 2 + )}, ${findByMethod} }`; allFixes.push(fixer.replaceText(allVariableDeclarations, text)); } diff --git a/lib/rules/prefer-presence-queries.ts b/lib/rules/prefer-presence-queries.ts index a343b085..9e19677c 100644 --- a/lib/rules/prefer-presence-queries.ts +++ b/lib/rules/prefer-presence-queries.ts @@ -1,9 +1,10 @@ import { TSESTree } from '@typescript-eslint/experimental-utils'; -import { findClosestCallNode, isMemberExpression } from '../node-utils'; + import { createTestingLibraryRule } from '../create-testing-library-rule'; +import { findClosestCallNode, isMemberExpression } from '../node-utils'; export const RULE_NAME = 'prefer-presence-queries'; -export type MessageIds = 'wrongPresenceQuery' | 'wrongAbsenceQuery'; +export type MessageIds = 'wrongAbsenceQuery' | 'wrongPresenceQuery'; type Options = []; export default createTestingLibraryRule({ @@ -56,11 +57,9 @@ export default createTestingLibraryRule({ } if (isPresenceAssert && !isPresenceQuery) { - return context.report({ node, messageId: 'wrongPresenceQuery' }); - } - - if (isAbsenceAssert && isPresenceQuery) { - return context.report({ node, messageId: 'wrongAbsenceQuery' }); + context.report({ node, messageId: 'wrongPresenceQuery' }); + } else if (isAbsenceAssert && isPresenceQuery) { + context.report({ node, messageId: 'wrongAbsenceQuery' }); } }, }; diff --git a/lib/rules/prefer-screen-queries.ts b/lib/rules/prefer-screen-queries.ts index f51b1aa1..eb649f72 100644 --- a/lib/rules/prefer-screen-queries.ts +++ b/lib/rules/prefer-screen-queries.ts @@ -1,4 +1,6 @@ import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils'; + +import { createTestingLibraryRule } from '../create-testing-library-rule'; import { isCallExpression, isMemberExpression, @@ -6,7 +8,6 @@ import { isObjectPattern, isProperty, } from '../node-utils'; -import { createTestingLibraryRule } from '../create-testing-library-rule'; export const RULE_NAME = 'prefer-screen-queries'; export type MessageIds = 'preferScreenQueries'; diff --git a/lib/rules/prefer-user-event.ts b/lib/rules/prefer-user-event.ts index a836c8e9..b6b82543 100644 --- a/lib/rules/prefer-user-event.ts +++ b/lib/rules/prefer-user-event.ts @@ -1,4 +1,5 @@ import { TSESTree } from '@typescript-eslint/experimental-utils'; + import { createTestingLibraryRule } from '../create-testing-library-rule'; import { findClosestCallExpressionNode } from '../node-utils'; diff --git a/lib/rules/prefer-wait-for.ts b/lib/rules/prefer-wait-for.ts index 08f7d6ed..fc8f654b 100644 --- a/lib/rules/prefer-wait-for.ts +++ b/lib/rules/prefer-wait-for.ts @@ -1,4 +1,5 @@ import { TSESTree, ASTUtils } from '@typescript-eslint/experimental-utils'; + import { createTestingLibraryRule } from '../create-testing-library-rule'; import { isImportSpecifier, @@ -12,8 +13,8 @@ import { export const RULE_NAME = 'prefer-wait-for'; export type MessageIds = - | 'preferWaitForMethod' | 'preferWaitForImport' + | 'preferWaitForMethod' | 'preferWaitForRequire'; type Options = []; @@ -51,7 +52,7 @@ export default createTestingLibraryRule({ const reportRequire = (node: TSESTree.ObjectPattern) => { context.report({ - node: node, + node, messageId: 'preferWaitForRequire', fix(fixer) { const excludedImports = [...DEPRECATED_METHODS, 'waitFor']; @@ -76,7 +77,7 @@ export default createTestingLibraryRule({ const reportImport = (node: TSESTree.ImportDeclaration) => { context.report({ - node: node, + node, messageId: 'preferWaitForImport', fix(fixer) { const excludedImports = [...DEPRECATED_METHODS, 'waitFor']; @@ -119,6 +120,7 @@ export default createTestingLibraryRule({ const [arg] = callExpressionNode.arguments; const fixers = []; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (arg) { // if method been fixed already had a callback // then we just replace the method name. @@ -189,7 +191,8 @@ export default createTestingLibraryRule({ helpers.getCustomModuleImportNode() ?? helpers.getTestingLibraryImportNode(); if (isCallExpression(testingLibraryNode)) { - const parent = testingLibraryNode.parent as TSESTree.VariableDeclarator; + const parent = + testingLibraryNode.parent as TSESTree.VariableDeclarator; if (!isObjectPattern(parent.id)) { // if there is no destructuring, there is nothing to replace return; diff --git a/lib/rules/render-result-naming-convention.ts b/lib/rules/render-result-naming-convention.ts index df636a9c..8e9d9e4f 100644 --- a/lib/rules/render-result-naming-convention.ts +++ b/lib/rules/render-result-naming-convention.ts @@ -1,3 +1,5 @@ +import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils'; + import { createTestingLibraryRule } from '../create-testing-library-rule'; import { getDeepestIdentifierNode, @@ -5,7 +7,6 @@ import { getInnermostReturningFunction, isObjectPattern, } from '../node-utils'; -import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils'; export const RULE_NAME = 'render-result-naming-convention'; export type MessageIds = 'renderResultNamingConvention'; @@ -89,9 +90,8 @@ export default createTestingLibraryRule({ return; } - const isAllowedRenderResultName = ALLOWED_VAR_NAMES.includes( - renderResultName - ); + const isAllowedRenderResultName = + ALLOWED_VAR_NAMES.includes(renderResultName); // check if return value var name is allowed if (isAllowedRenderResultName) { diff --git a/lib/utils/file-import.ts b/lib/utils/file-import.ts index 9dc9d1db..e332ae29 100644 --- a/lib/utils/file-import.ts +++ b/lib/utils/file-import.ts @@ -1,8 +1,9 @@ // Copied from https://github.com/babel/babel/blob/b35c78f08dd854b08575fc66ebca323fdbc59dab/packages/babel-helpers/src/helpers.js#L615-L619 // eslint-disable-next-line @typescript-eslint/no-explicit-any -const interopRequireDefault = (obj: any): { default: T } => +const interopRequireDefault = (obj: any): { default: T } => + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment obj?.__esModule ? obj : { default: obj }; -export const importDefault = (moduleName: string): T => +export const importDefault = (moduleName: string): T => // eslint-disable-next-line @typescript-eslint/no-var-requires interopRequireDefault(require(moduleName)).default; diff --git a/lib/utils/types.ts b/lib/utils/types.ts index eeb3b507..42aa4a0d 100644 --- a/lib/utils/types.ts +++ b/lib/utils/types.ts @@ -23,9 +23,9 @@ type TestingLibraryRuleMetaDocs = Omit< export type TestingLibraryRuleMeta< TMessageIds extends string, TOptions extends readonly unknown[] -> = { +> = Omit, 'docs'> & { docs: TestingLibraryRuleMetaDocs; -} & Omit, 'docs'>; +}; export const SUPPORTED_TESTING_FRAMEWORKS = [ 'dom', @@ -33,4 +33,5 @@ export const SUPPORTED_TESTING_FRAMEWORKS = [ 'react', 'vue', ] as const; -export type SupportedTestingFramework = typeof SUPPORTED_TESTING_FRAMEWORKS[number]; +export type SupportedTestingFramework = + typeof SUPPORTED_TESTING_FRAMEWORKS[number]; diff --git a/package.json b/package.json index 2de1d9a2..7fe39437 100644 --- a/package.json +++ b/package.json @@ -49,20 +49,20 @@ "@typescript-eslint/eslint-plugin": "^4.21.0", "@typescript-eslint/parser": "^4.21.0", "cpy-cli": "^3.1.1", - "eslint": "^7.24.0", - "eslint-config-prettier": "^8.1.0", - "eslint-config-standard": "^16.0.2", - "eslint-plugin-import": "^2.22.1", - "eslint-plugin-jest": "^24.3.4", + "eslint": "^7.26.0", + "eslint-config-kentcdodds": "^18.1.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-import": "^2.23.2", + "eslint-plugin-jest": "^24.3.6", "eslint-plugin-jest-formatting": "^2.0.1", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^3.3.1", + "eslint-plugin-prettier": "^3.4.0", "eslint-plugin-promise": "^5.1.0", "husky": "^4.3.8", "jest": "^26.6.3", "jest-environment-jsdom": "^25.5.0", "lint-staged": "^10.5.4", - "prettier": "2.2.1", + "prettier": "2.3.0", "semantic-release": "^17.4.2", "ts-jest": "^26.5.4", "typescript": "^4.2.4" diff --git a/tests/create-testing-library-rule.test.ts b/tests/create-testing-library-rule.test.ts index c3af7151..8861cafd 100644 --- a/tests/create-testing-library-rule.test.ts +++ b/tests/create-testing-library-rule.test.ts @@ -1,5 +1,5 @@ -import { createRuleTester } from './lib/test-utils'; import rule, { RULE_NAME } from './fake-rule'; +import { createRuleTester } from './lib/test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/fake-rule.ts b/tests/fake-rule.ts index 5dacdb9e..70a8d5da 100644 --- a/tests/fake-rule.ts +++ b/tests/fake-rule.ts @@ -3,21 +3,22 @@ * detectTestingLibraryUtils properly */ import { TSESTree } from '@typescript-eslint/experimental-utils'; + import { createTestingLibraryRule } from '../lib/create-testing-library-rule'; export const RULE_NAME = 'fake-rule'; type Options = []; type MessageIds = - | 'fakeError' - | 'renderError' + | 'absenceAssertError' | 'asyncUtilError' - | 'getByError' - | 'queryByError' - | 'findByError' | 'customQueryError' - | 'userEventError' + | 'fakeError' + | 'findByError' + | 'getByError' | 'presenceAssertError' - | 'absenceAssertError'; + | 'queryByError' + | 'renderError' + | 'userEventError'; export default createTestingLibraryRule({ name: RULE_NAME, @@ -85,6 +86,8 @@ export default createTestingLibraryRule({ if (helpers.isFindQueryVariant(node)) { return context.report({ node, messageId: 'findByError' }); } + + return undefined; }; const reportMemberExpression = (node: TSESTree.MemberExpression) => { @@ -95,6 +98,8 @@ export default createTestingLibraryRule({ if (helpers.isAbsenceAssert(node)) { return context.report({ node, messageId: 'absenceAssertError' }); } + + return undefined; }; const reportImportDeclaration = (node: TSESTree.ImportDeclaration) => { diff --git a/tests/index.test.ts b/tests/index.test.ts index 2ba1adc7..6b77bb0b 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -47,7 +47,7 @@ it('should have the correct amount of rules', () => { }); it("should have run 'generate:configs' script when changing config rules", async () => { - await generateConfigs(); + generateConfigs(); const allConfigs = plugin.configs; expect(allConfigs).toMatchSnapshot(); diff --git a/tests/lib/rules/await-async-query.test.ts b/tests/lib/rules/await-async-query.test.ts index 625eb951..648b0ce5 100644 --- a/tests/lib/rules/await-async-query.test.ts +++ b/tests/lib/rules/await-async-query.test.ts @@ -1,5 +1,5 @@ -import { TestCaseError } from '@typescript-eslint/experimental-utils/dist/ts-eslint'; -import { createRuleTester } from '../test-utils'; +import { TSESLint } from '@typescript-eslint/experimental-utils'; + import rule, { RULE_NAME } from '../../../lib/rules/await-async-query'; import { ASYNC_QUERIES_COMBINATIONS, @@ -7,6 +7,7 @@ import { combineQueries, SYNC_QUERIES_COMBINATIONS, } from '../../../lib/utils'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); @@ -27,13 +28,15 @@ function createTestCode({ code, isAsync = true }: TestCode) { interface TestCaseParams { isAsync?: boolean; combinations?: string[]; - errors?: TestCaseError<'awaitAsyncQuery' | 'asyncQueryWrapper'>[]; + errors?: TSESLint.TestCaseError<'asyncQueryWrapper' | 'awaitAsyncQuery'>[]; } function createTestCase( getTest: ( query: string - ) => string | { code: string; errors?: TestCaseError<'awaitAsyncQuery'>[] }, + ) => + | string + | { code: string; errors?: TSESLint.TestCaseError<'awaitAsyncQuery'>[] }, { combinations = ALL_ASYNC_COMBINATIONS_TO_TEST, isAsync, diff --git a/tests/lib/rules/await-async-utils.test.ts b/tests/lib/rules/await-async-utils.test.ts index 99f39ccb..9c595926 100644 --- a/tests/lib/rules/await-async-utils.test.ts +++ b/tests/lib/rules/await-async-utils.test.ts @@ -1,6 +1,6 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/await-async-utils'; import { ASYNC_UTILS } from '../../../lib/utils'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/await-fire-event.test.ts b/tests/lib/rules/await-fire-event.test.ts index 4918ebc0..2369539f 100644 --- a/tests/lib/rules/await-fire-event.test.ts +++ b/tests/lib/rules/await-fire-event.test.ts @@ -1,5 +1,5 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/await-fire-event'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/consistent-data-testid.test.ts b/tests/lib/rules/consistent-data-testid.test.ts index 4ea34f6c..8a6096ec 100644 --- a/tests/lib/rules/consistent-data-testid.test.ts +++ b/tests/lib/rules/consistent-data-testid.test.ts @@ -1,18 +1,17 @@ -import type { TSESLint } from '@typescript-eslint/experimental-utils'; - import rule, { MessageIds, Options, RULE_NAME, } from '../../../lib/rules/consistent-data-testid'; - import { createRuleTester } from '../test-utils'; +import type { TSESLint } from '@typescript-eslint/experimental-utils'; + const ruleTester = createRuleTester(); type ValidTestCase = TSESLint.ValidTestCase; type InvalidTestCase = TSESLint.InvalidTestCase; -type TestCase = ValidTestCase | InvalidTestCase; +type TestCase = InvalidTestCase | ValidTestCase; const disableAggressiveReporting = (array: T[]): T[] => array.map((testCase) => ({ ...testCase, diff --git a/tests/lib/rules/no-await-sync-events.test.ts b/tests/lib/rules/no-await-sync-events.test.ts index 63679459..e63c130b 100644 --- a/tests/lib/rules/no-await-sync-events.test.ts +++ b/tests/lib/rules/no-await-sync-events.test.ts @@ -1,5 +1,5 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/no-await-sync-events'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-await-sync-query.test.ts b/tests/lib/rules/no-await-sync-query.test.ts index a6655d03..fb01165d 100644 --- a/tests/lib/rules/no-await-sync-query.test.ts +++ b/tests/lib/rules/no-await-sync-query.test.ts @@ -1,9 +1,9 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/no-await-sync-query'; import { SYNC_QUERIES_COMBINATIONS, ASYNC_QUERIES_COMBINATIONS, } from '../../../lib/utils'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-container.test.ts b/tests/lib/rules/no-container.test.ts index 0c15d5f4..c28d3071 100644 --- a/tests/lib/rules/no-container.test.ts +++ b/tests/lib/rules/no-container.test.ts @@ -1,5 +1,5 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/no-container'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-debug.test.ts b/tests/lib/rules/no-debug.test.ts index 81507a38..aabbfb61 100644 --- a/tests/lib/rules/no-debug.test.ts +++ b/tests/lib/rules/no-debug.test.ts @@ -1,5 +1,5 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/no-debug'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-dom-import.test.ts b/tests/lib/rules/no-dom-import.test.ts index 2855cd74..4dfc0623 100644 --- a/tests/lib/rules/no-dom-import.test.ts +++ b/tests/lib/rules/no-dom-import.test.ts @@ -1,5 +1,5 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/no-dom-import'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-manual-cleanup.test.ts b/tests/lib/rules/no-manual-cleanup.test.ts index d89eb3b2..73732736 100644 --- a/tests/lib/rules/no-manual-cleanup.test.ts +++ b/tests/lib/rules/no-manual-cleanup.test.ts @@ -1,5 +1,5 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/no-manual-cleanup'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-node-access.test.ts b/tests/lib/rules/no-node-access.test.ts index 4e58bb7b..39d172a4 100644 --- a/tests/lib/rules/no-node-access.test.ts +++ b/tests/lib/rules/no-node-access.test.ts @@ -1,5 +1,5 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/no-node-access'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-promise-in-fire-event.test.ts b/tests/lib/rules/no-promise-in-fire-event.test.ts index 66023be2..05425dbf 100644 --- a/tests/lib/rules/no-promise-in-fire-event.test.ts +++ b/tests/lib/rules/no-promise-in-fire-event.test.ts @@ -1,5 +1,5 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/no-promise-in-fire-event'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-render-in-setup.test.ts b/tests/lib/rules/no-render-in-setup.test.ts index 8633e280..4db0796a 100644 --- a/tests/lib/rules/no-render-in-setup.test.ts +++ b/tests/lib/rules/no-render-in-setup.test.ts @@ -1,6 +1,6 @@ -import { createRuleTester } from '../test-utils'; -import { TESTING_FRAMEWORK_SETUP_HOOKS } from '../../../lib/utils'; import rule, { RULE_NAME } from '../../../lib/rules/no-render-in-setup'; +import { TESTING_FRAMEWORK_SETUP_HOOKS } from '../../../lib/utils'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-unnecessary-act.test.ts b/tests/lib/rules/no-unnecessary-act.test.ts index b5bb7992..63aebf17 100644 --- a/tests/lib/rules/no-unnecessary-act.test.ts +++ b/tests/lib/rules/no-unnecessary-act.test.ts @@ -1,5 +1,5 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/no-unnecessary-act'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-wait-for-empty-callback.test.ts b/tests/lib/rules/no-wait-for-empty-callback.test.ts index 87bbd3fc..d9dae719 100644 --- a/tests/lib/rules/no-wait-for-empty-callback.test.ts +++ b/tests/lib/rules/no-wait-for-empty-callback.test.ts @@ -1,5 +1,5 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/no-wait-for-empty-callback'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-wait-for-multiple-assertions.test.ts b/tests/lib/rules/no-wait-for-multiple-assertions.test.ts index c470c02c..84a3f4be 100644 --- a/tests/lib/rules/no-wait-for-multiple-assertions.test.ts +++ b/tests/lib/rules/no-wait-for-multiple-assertions.test.ts @@ -1,7 +1,7 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME, } from '../../../lib/rules/no-wait-for-multiple-assertions'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-wait-for-side-effects.test.ts b/tests/lib/rules/no-wait-for-side-effects.test.ts index f802ffe5..e5102126 100644 --- a/tests/lib/rules/no-wait-for-side-effects.test.ts +++ b/tests/lib/rules/no-wait-for-side-effects.test.ts @@ -1,5 +1,5 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/no-wait-for-side-effects'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-wait-for-snapshot.test.ts b/tests/lib/rules/no-wait-for-snapshot.test.ts index 6aae1adc..b6f3e474 100644 --- a/tests/lib/rules/no-wait-for-snapshot.test.ts +++ b/tests/lib/rules/no-wait-for-snapshot.test.ts @@ -1,6 +1,6 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/no-wait-for-snapshot'; import { ASYNC_UTILS } from '../../../lib/utils'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/prefer-explicit-assert.test.ts b/tests/lib/rules/prefer-explicit-assert.test.ts index 11cdf141..03c60349 100644 --- a/tests/lib/rules/prefer-explicit-assert.test.ts +++ b/tests/lib/rules/prefer-explicit-assert.test.ts @@ -1,6 +1,6 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/prefer-explicit-assert'; import { ALL_QUERIES_METHODS } from '../../../lib/utils'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/prefer-find-by.test.ts b/tests/lib/rules/prefer-find-by.test.ts index 96e892e7..e59c9b91 100644 --- a/tests/lib/rules/prefer-find-by.test.ts +++ b/tests/lib/rules/prefer-find-by.test.ts @@ -1,18 +1,16 @@ -import { - InvalidTestCase, - ValidTestCase, -} from '@typescript-eslint/experimental-utils/dist/ts-eslint'; -import { createRuleTester } from '../test-utils'; -import { - ASYNC_QUERIES_COMBINATIONS, - SYNC_QUERIES_COMBINATIONS, -} from '../../../lib/utils'; +import { TSESLint } from '@typescript-eslint/experimental-utils'; + import rule, { WAIT_METHODS, RULE_NAME, getFindByQueryVariant, MessageIds, } from '../../../lib/rules/prefer-find-by'; +import { + ASYNC_QUERIES_COMBINATIONS, + SYNC_QUERIES_COMBINATIONS, +} from '../../../lib/utils'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); @@ -21,7 +19,9 @@ function buildFindByMethod(queryMethod: string) { } function createScenario< - T extends ValidTestCase<[]> | InvalidTestCase + T extends + | TSESLint.InvalidTestCase + | TSESLint.ValidTestCase<[]> >(callback: (waitMethod: string, queryMethod: string) => T) { return WAIT_METHODS.reduce( (acc: T[], waitMethod) => diff --git a/tests/lib/rules/prefer-presence-queries.test.ts b/tests/lib/rules/prefer-presence-queries.test.ts index 296b6903..8ff037d4 100644 --- a/tests/lib/rules/prefer-presence-queries.test.ts +++ b/tests/lib/rules/prefer-presence-queries.test.ts @@ -1,10 +1,11 @@ -import { createRuleTester } from '../test-utils'; +import { TSESLint } from '@typescript-eslint/experimental-utils'; + import rule, { RULE_NAME, MessageIds, } from '../../../lib/rules/prefer-presence-queries'; import { ALL_QUERIES_METHODS } from '../../../lib/utils'; -import { TSESLint } from '@typescript-eslint/experimental-utils'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/prefer-screen-queries.test.ts b/tests/lib/rules/prefer-screen-queries.test.ts index b6eeff11..052433b9 100644 --- a/tests/lib/rules/prefer-screen-queries.test.ts +++ b/tests/lib/rules/prefer-screen-queries.test.ts @@ -1,10 +1,10 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME } from '../../../lib/rules/prefer-screen-queries'; import { ALL_QUERIES_COMBINATIONS, ALL_QUERIES_VARIANTS, combineQueries, } from '../../../lib/utils'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/prefer-user-event.test.ts b/tests/lib/rules/prefer-user-event.test.ts index f4b23cfa..4b195f70 100644 --- a/tests/lib/rules/prefer-user-event.test.ts +++ b/tests/lib/rules/prefer-user-event.test.ts @@ -1,9 +1,5 @@ -import { - InvalidTestCase, - ValidTestCase, -} from '@typescript-eslint/experimental-utils/dist/ts-eslint'; -import { createRuleTester } from '../test-utils'; -import { LIBRARY_MODULES } from '../../../lib/utils'; +import { TSESLint } from '@typescript-eslint/experimental-utils'; + import rule, { MAPPING_TO_USER_EVENT, MessageIds, @@ -11,9 +7,13 @@ import rule, { RULE_NAME, UserEventMethods, } from '../../../lib/rules/prefer-user-event'; +import { LIBRARY_MODULES } from '../../../lib/utils'; +import { createRuleTester } from '../test-utils'; function createScenarioWithImport< - T extends ValidTestCase | InvalidTestCase + T extends + | TSESLint.InvalidTestCase + | TSESLint.ValidTestCase >(callback: (libraryModule: string, fireEventMethod: string) => T) { return LIBRARY_MODULES.reduce( (acc: Array, libraryModule) => @@ -69,7 +69,7 @@ ruleTester.run(RULE_NAME, rule, { userEvent.${userEventMethod}(foo) `, })), - ...createScenarioWithImport>( + ...createScenarioWithImport>( (libraryModule: string, fireEventMethod: string) => ({ code: ` import { fireEvent } from '${libraryModule}' @@ -79,7 +79,7 @@ ruleTester.run(RULE_NAME, rule, { options: [{ allowedMethods: [fireEventMethod] }], }) ), - ...createScenarioWithImport>( + ...createScenarioWithImport>( (libraryModule: string, fireEventMethod: string) => ({ code: ` import { fireEvent as fireEventAliased } from '${libraryModule}' @@ -89,7 +89,7 @@ ruleTester.run(RULE_NAME, rule, { options: [{ allowedMethods: [fireEventMethod] }], }) ), - ...createScenarioWithImport>( + ...createScenarioWithImport>( (libraryModule: string, fireEventMethod: string) => ({ code: ` import * as dom from '${libraryModule}' @@ -206,7 +206,7 @@ ruleTester.run(RULE_NAME, rule, { `, ], invalid: [ - ...createScenarioWithImport>( + ...createScenarioWithImport>( (libraryModule: string, fireEventMethod: string) => ({ code: ` import { fireEvent } from '${libraryModule}' @@ -220,13 +220,13 @@ ruleTester.run(RULE_NAME, rule, { column: 9, data: { userEventMethods: formatUserEventMethodsMessage(fireEventMethod), - fireEventMethod: fireEventMethod, + fireEventMethod, }, }, ], }) ), - ...createScenarioWithImport>( + ...createScenarioWithImport>( (libraryModule: string, fireEventMethod: string) => ({ code: ` import * as dom from '${libraryModule}' @@ -239,13 +239,13 @@ ruleTester.run(RULE_NAME, rule, { column: 9, data: { userEventMethods: formatUserEventMethodsMessage(fireEventMethod), - fireEventMethod: fireEventMethod, + fireEventMethod, }, }, ], }) ), - ...createScenarioWithImport>( + ...createScenarioWithImport>( (libraryModule: string, fireEventMethod: string) => ({ code: ` const { fireEvent } = require('${libraryModule}') @@ -258,13 +258,13 @@ ruleTester.run(RULE_NAME, rule, { column: 9, data: { userEventMethods: formatUserEventMethodsMessage(fireEventMethod), - fireEventMethod: fireEventMethod, + fireEventMethod, }, }, ], }) ), - ...createScenarioWithImport>( + ...createScenarioWithImport>( (libraryModule: string, fireEventMethod: string) => ({ code: ` const rtl = require('${libraryModule}') @@ -277,7 +277,7 @@ ruleTester.run(RULE_NAME, rule, { column: 9, data: { userEventMethods: formatUserEventMethodsMessage(fireEventMethod), - fireEventMethod: fireEventMethod, + fireEventMethod, }, }, ], @@ -299,10 +299,9 @@ ruleTester.run(RULE_NAME, rule, { line: 3, column: 9, data: { - userEventMethods: formatUserEventMethodsMessage( - fireEventMethod - ), - fireEventMethod: fireEventMethod, + userEventMethods: + formatUserEventMethodsMessage(fireEventMethod), + fireEventMethod, }, }, ], @@ -324,10 +323,9 @@ ruleTester.run(RULE_NAME, rule, { line: 3, column: 9, data: { - userEventMethods: formatUserEventMethodsMessage( - fireEventMethod - ), - fireEventMethod: fireEventMethod, + userEventMethods: + formatUserEventMethodsMessage(fireEventMethod), + fireEventMethod, }, }, ], @@ -348,10 +346,9 @@ ruleTester.run(RULE_NAME, rule, { line: 5, column: 9, data: { - userEventMethods: formatUserEventMethodsMessage( - fireEventMethod - ), - fireEventMethod: fireEventMethod, + userEventMethods: + formatUserEventMethodsMessage(fireEventMethod), + fireEventMethod, }, }, ], @@ -373,10 +370,9 @@ ruleTester.run(RULE_NAME, rule, { line: 3, column: 9, data: { - userEventMethods: formatUserEventMethodsMessage( - fireEventMethod - ), - fireEventMethod: fireEventMethod, + userEventMethods: + formatUserEventMethodsMessage(fireEventMethod), + fireEventMethod, }, }, ], diff --git a/tests/lib/rules/prefer-wait-for.test.ts b/tests/lib/rules/prefer-wait-for.test.ts index 410934b1..ae6a85c4 100644 --- a/tests/lib/rules/prefer-wait-for.test.ts +++ b/tests/lib/rules/prefer-wait-for.test.ts @@ -1,6 +1,6 @@ -import { createRuleTester } from '../test-utils'; -import { LIBRARY_MODULES } from '../../../lib/utils'; import rule, { RULE_NAME } from '../../../lib/rules/prefer-wait-for'; +import { LIBRARY_MODULES } from '../../../lib/utils'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/render-result-naming-convention.test.ts b/tests/lib/rules/render-result-naming-convention.test.ts index 0bf82ed6..51b9e023 100644 --- a/tests/lib/rules/render-result-naming-convention.test.ts +++ b/tests/lib/rules/render-result-naming-convention.test.ts @@ -1,7 +1,7 @@ -import { createRuleTester } from '../test-utils'; import rule, { RULE_NAME, } from '../../../lib/rules/render-result-naming-convention'; +import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/test-utils.ts b/tests/lib/test-utils.ts index 88c1b778..4c7cbf46 100644 --- a/tests/lib/test-utils.ts +++ b/tests/lib/test-utils.ts @@ -1,4 +1,5 @@ import { resolve } from 'path'; + import { TSESLint } from '@typescript-eslint/experimental-utils'; const DEFAULT_TEST_CASE_CONFIG = { diff --git a/tools/generate-configs/index.ts b/tools/generate-configs/index.ts index f688d567..c0427a68 100644 --- a/tools/generate-configs/index.ts +++ b/tools/generate-configs/index.ts @@ -1,4 +1,3 @@ -import type { LinterConfigRules } from '../../lib/configs'; import rules from '../../lib/rules'; import { SUPPORTED_TESTING_FRAMEWORKS, @@ -7,14 +6,21 @@ import { import { LinterConfig, writeConfig } from './utils'; +import type { LinterConfigRules } from '../../lib/configs'; + const RULE_NAME_PREFIX = 'testing-library/'; const getRecommendedRulesForTestingFramework = ( framework: SupportedTestingFramework ): LinterConfigRules => Object.entries(rules) - .filter(([_, { meta: { docs } }]) => - Boolean(docs.recommendedConfig[framework]) + .filter( + ([ + _, + { + meta: { docs }, + }, + ]) => Boolean(docs.recommendedConfig[framework]) ) .reduce((allRules, [ruleName, { meta }]) => { const name = `${RULE_NAME_PREFIX}${ruleName}`; diff --git a/tools/generate-configs/utils.ts b/tools/generate-configs/utils.ts index 0394c044..e21723f8 100644 --- a/tools/generate-configs/utils.ts +++ b/tools/generate-configs/utils.ts @@ -1,9 +1,10 @@ import { writeFileSync } from 'fs'; import { resolve } from 'path'; -import type { TSESLint } from '@typescript-eslint/experimental-utils'; import { format, resolveConfig } from 'prettier'; +import type { TSESLint } from '@typescript-eslint/experimental-utils'; + const prettierConfig = resolveConfig.sync(__dirname); export type LinterConfig = TSESLint.Linter.Config;