eslint-plugin-testing-library
Advanced tools
Comparing version 4.0.0-alpha.0 to 4.0.0-alpha.1
@@ -9,2 +9,3 @@ "use strict"; | ||
const FIRE_EVENT_NAME = 'fireEvent'; | ||
const RENDER_NAME = 'render'; | ||
function detectTestingLibraryUtils(ruleCreate) { | ||
@@ -15,5 +16,23 @@ return (context, optionsWithDefault) => { | ||
let importedCustomModuleNode = null; | ||
const customModule = context.settings['testing-library/module']; | ||
const customModule = context.settings['testing-library/utils-module']; | ||
const filenamePattern = (_a = context.settings['testing-library/filename-pattern']) !== null && _a !== void 0 ? _a : DEFAULT_FILENAME_PATTERN; | ||
const isAggressiveReportingEnabled = () => !customModule; | ||
const customRenders = context.settings['testing-library/custom-renders']; | ||
function isTestingLibraryUtil(node, isUtilCallback) { | ||
const referenceNode = node_utils_1.getReferenceNode(node); | ||
const referenceNodeIdentifier = node_utils_1.getPropertyIdentifierNode(referenceNode); | ||
const importedUtilSpecifier = getImportedUtilSpecifier(referenceNodeIdentifier); | ||
const originalNodeName = node_utils_1.isImportSpecifier(importedUtilSpecifier) && | ||
importedUtilSpecifier.local.name !== importedUtilSpecifier.imported.name | ||
? importedUtilSpecifier.imported.name | ||
: undefined; | ||
if (!isUtilCallback(node.name, originalNodeName)) { | ||
return false; | ||
} | ||
if (isAggressiveModuleReportingEnabled()) { | ||
return true; | ||
} | ||
return isNodeComingFromTestingLibrary(referenceNodeIdentifier); | ||
} | ||
const isAggressiveModuleReportingEnabled = () => !customModule; | ||
const isAggressiveRenderReportingEnabled = () => !Array.isArray(customRenders) || customRenders.length === 0; | ||
const getTestingLibraryImportNode = () => { | ||
@@ -32,6 +51,5 @@ return importedTestingLibraryNode; | ||
const isTestingLibraryImported = () => { | ||
if (isAggressiveReportingEnabled()) { | ||
return true; | ||
} | ||
return !!importedTestingLibraryNode || !!importedCustomModuleNode; | ||
return (isAggressiveModuleReportingEnabled() || | ||
!!importedTestingLibraryNode || | ||
!!importedCustomModuleNode); | ||
}; | ||
@@ -42,23 +60,28 @@ const isValidFilename = () => { | ||
}; | ||
const isGetByQuery = (node) => { | ||
const isGetQueryVariant = (node) => { | ||
return /^get(All)?By.+$/.test(node.name); | ||
}; | ||
const isQueryByQuery = (node) => { | ||
const isQueryQueryVariant = (node) => { | ||
return /^query(All)?By.+$/.test(node.name); | ||
}; | ||
const isFindByQuery = (node) => { | ||
const isFindQueryVariant = (node) => { | ||
return /^find(All)?By.+$/.test(node.name); | ||
}; | ||
const isSyncQuery = (node) => { | ||
return isGetByQuery(node) || isQueryByQuery(node); | ||
return isGetQueryVariant(node) || isQueryQueryVariant(node); | ||
}; | ||
const isAsyncQuery = (node) => { | ||
return isFindByQuery(node); | ||
return isFindQueryVariant(node); | ||
}; | ||
const isQuery = (node) => { | ||
return isSyncQuery(node) || isAsyncQuery(node); | ||
}; | ||
const isCustomQuery = (node) => { | ||
return ((isSyncQuery(node) || isAsyncQuery(node)) && | ||
!utils_1.ALL_QUERIES_COMBINATIONS.includes(node.name)); | ||
return isQuery(node) && !utils_1.ALL_QUERIES_COMBINATIONS.includes(node.name); | ||
}; | ||
const isAsyncUtil = (node) => { | ||
return utils_1.ASYNC_UTILS.includes(node.name); | ||
const isAsyncUtil = (node, validNames = utils_1.ASYNC_UTILS) => { | ||
return isTestingLibraryUtil(node, (identifierNodeName, originalNodeName) => { | ||
return (validNames.includes(identifierNodeName) || | ||
validNames.includes(originalNodeName)); | ||
}); | ||
}; | ||
@@ -73,3 +96,3 @@ const isFireEventMethod = (node) => { | ||
} | ||
else if (isAggressiveReportingEnabled()) { | ||
else if (isAggressiveModuleReportingEnabled()) { | ||
fireEventUtilName = FIRE_EVENT_NAME; | ||
@@ -98,2 +121,19 @@ } | ||
}; | ||
const isRenderUtil = (node) => { | ||
return isTestingLibraryUtil(node, (identifierNodeName, originalNodeName) => { | ||
if (isAggressiveRenderReportingEnabled()) { | ||
return identifierNodeName.toLowerCase().includes(RENDER_NAME); | ||
} | ||
return [RENDER_NAME, ...customRenders].some((validRenderName) => { | ||
let isMatch = false; | ||
if (validRenderName === identifierNodeName) { | ||
isMatch = true; | ||
} | ||
if (!!originalNodeName && validRenderName === originalNodeName) { | ||
isMatch = true; | ||
} | ||
return isMatch; | ||
}); | ||
}); | ||
}; | ||
const isPresenceAssert = (node) => { | ||
@@ -124,3 +164,6 @@ const { matcher, isNegated } = node_utils_1.getAssertNodeInfo(node); | ||
if (node_utils_1.isImportDeclaration(node)) { | ||
const namedExport = node.specifiers.find((n) => node_utils_1.isImportSpecifier(n) && n.imported.name === specifierName); | ||
const namedExport = node.specifiers.find((n) => { | ||
return (node_utils_1.isImportSpecifier(n) && | ||
[n.imported.name, n.local.name].includes(specifierName)); | ||
}); | ||
if (namedExport) { | ||
@@ -140,5 +183,13 @@ return namedExport; | ||
n.key.name === specifierName); | ||
if (!property) { | ||
return undefined; | ||
} | ||
return property.key; | ||
} | ||
}; | ||
const getImportedUtilSpecifier = (node) => { | ||
const identifierName = node_utils_1.getPropertyIdentifierNode(node) | ||
.name; | ||
return findImportedUtilSpecifier(identifierName); | ||
}; | ||
const canReportErrors = () => { | ||
@@ -148,13 +199,9 @@ return isTestingLibraryImported() && isValidFilename(); | ||
const isNodeComingFromTestingLibrary = (node) => { | ||
let identifierName; | ||
if (experimental_utils_1.ASTUtils.isIdentifier(node)) { | ||
identifierName = node.name; | ||
const importNode = getImportedUtilSpecifier(node); | ||
if (!importNode) { | ||
return false; | ||
} | ||
else if (experimental_utils_1.ASTUtils.isIdentifier(node.object)) { | ||
identifierName = node.object.name; | ||
} | ||
if (!identifierName) { | ||
return; | ||
} | ||
return !!findImportedUtilSpecifier(identifierName); | ||
const identifierName = node_utils_1.getPropertyIdentifierNode(node) | ||
.name; | ||
return node_utils_1.hasImportMatch(importNode, identifierName); | ||
}; | ||
@@ -168,10 +215,12 @@ const helpers = { | ||
isValidFilename, | ||
isGetByQuery, | ||
isQueryByQuery, | ||
isFindByQuery, | ||
isGetQueryVariant, | ||
isQueryQueryVariant, | ||
isFindQueryVariant, | ||
isSyncQuery, | ||
isAsyncQuery, | ||
isQuery, | ||
isCustomQuery, | ||
isAsyncUtil, | ||
isFireEventMethod, | ||
isRenderUtil, | ||
isPresenceAssert, | ||
@@ -178,0 +227,0 @@ isAbsenceAssert, |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getInnermostReturningFunction = exports.hasClosestExpectResolvesRejects = exports.getAssertNodeInfo = exports.getImportModuleName = exports.isRenderVariableDeclarator = exports.isRenderFunction = exports.getFunctionName = exports.getIdentifierNode = exports.getFunctionReturnStatementNode = exports.getInnermostFunctionScope = exports.getVariableReferences = exports.isPromiseHandled = exports.isPromisesArrayResolved = exports.isPromiseAllSettled = exports.isPromiseAll = exports.isPromiseIdentifier = exports.hasChainedThen = exports.isImportDeclaration = exports.isArrayExpression = exports.isReturnStatement = exports.isArrowFunctionExpression = exports.hasThenProperty = exports.isObjectExpression = exports.findClosestCallNode = exports.findClosestCallExpressionNode = exports.isJSXAttribute = exports.isProperty = exports.isObjectPattern = exports.isBlockStatement = exports.isImportDefaultSpecifier = exports.isImportNamespaceSpecifier = exports.isImportSpecifier = exports.isLiteral = exports.isMemberExpression = exports.isNewExpression = exports.isCallExpression = void 0; | ||
exports.hasImportMatch = exports.getInnermostReturningFunction = exports.hasClosestExpectResolvesRejects = exports.getAssertNodeInfo = exports.getImportModuleName = exports.isRenderVariableDeclarator = exports.isRenderFunction = exports.getFunctionName = exports.getReferenceNode = exports.getDeepestIdentifierNode = exports.getPropertyIdentifierNode = exports.getFunctionReturnStatementNode = exports.getInnermostFunctionScope = exports.getVariableReferences = exports.isPromiseHandled = exports.isPromisesArrayResolved = exports.isPromiseAllSettled = exports.isPromiseAll = exports.isPromiseIdentifier = exports.hasChainedThen = exports.isImportDeclaration = exports.isArrayExpression = exports.isReturnStatement = exports.isArrowFunctionExpression = exports.hasThenProperty = exports.isObjectExpression = exports.isCallExpressionCallee = exports.findClosestCallNode = exports.findClosestCallExpressionNode = exports.isJSXAttribute = exports.isProperty = exports.isObjectPattern = exports.isBlockStatement = exports.isImportDefaultSpecifier = exports.isImportNamespaceSpecifier = exports.isImportSpecifier = exports.isLiteral = exports.isMemberExpression = exports.isNewExpression = exports.isCallExpression = void 0; | ||
const experimental_utils_1 = require("@typescript-eslint/experimental-utils"); | ||
@@ -104,2 +104,10 @@ const ValidLeftHandSideExpressions = [ | ||
exports.findClosestCallNode = findClosestCallNode; | ||
function isCallExpressionCallee(node, identifier) { | ||
const nodeInnerIdentifier = getDeepestIdentifierNode(node); | ||
if (nodeInnerIdentifier) { | ||
return nodeInnerIdentifier.name === identifier.name; | ||
} | ||
return false; | ||
} | ||
exports.isCallExpressionCallee = isCallExpressionCallee; | ||
function isObjectExpression(node) { | ||
@@ -194,3 +202,4 @@ return (node === null || node === void 0 ? void 0 : node.type) === experimental_utils_1.AST_NODE_TYPES.ObjectExpression; | ||
var _a, _b; | ||
return ((experimental_utils_1.ASTUtils.isVariableDeclarator(node) && ((_b = (_a = context.getDeclaredVariables(node)[0]) === null || _a === void 0 ? void 0 : _a.references) === null || _b === void 0 ? void 0 : _b.slice(1))) || | ||
return ((experimental_utils_1.ASTUtils.isVariableDeclarator(node) && | ||
((_b = (_a = context.getDeclaredVariables(node)[0]) === null || _a === void 0 ? void 0 : _a.references) === null || _b === void 0 ? void 0 : _b.slice(1))) || | ||
[]); | ||
@@ -222,6 +231,19 @@ } | ||
exports.getFunctionReturnStatementNode = getFunctionReturnStatementNode; | ||
function getIdentifierNode(node) { | ||
function getPropertyIdentifierNode(node) { | ||
if (experimental_utils_1.ASTUtils.isIdentifier(node)) { | ||
return node; | ||
} | ||
if (isMemberExpression(node)) { | ||
return getPropertyIdentifierNode(node.object); | ||
} | ||
if (isCallExpression(node)) { | ||
return getPropertyIdentifierNode(node.callee); | ||
} | ||
return null; | ||
} | ||
exports.getPropertyIdentifierNode = getPropertyIdentifierNode; | ||
function getDeepestIdentifierNode(node) { | ||
if (experimental_utils_1.ASTUtils.isIdentifier(node)) { | ||
return node; | ||
} | ||
if (isMemberExpression(node) && experimental_utils_1.ASTUtils.isIdentifier(node.property)) { | ||
@@ -231,7 +253,14 @@ return node.property; | ||
if (isCallExpression(node)) { | ||
return getIdentifierNode(node.callee); | ||
return getDeepestIdentifierNode(node.callee); | ||
} | ||
return null; | ||
} | ||
exports.getIdentifierNode = getIdentifierNode; | ||
exports.getDeepestIdentifierNode = getDeepestIdentifierNode; | ||
function getReferenceNode(node) { | ||
if (isMemberExpression(node.parent) || isCallExpression(node.parent)) { | ||
return getReferenceNode(node.parent); | ||
} | ||
return node; | ||
} | ||
exports.getReferenceNode = getReferenceNode; | ||
function getFunctionName(node) { | ||
@@ -324,3 +353,3 @@ var _a, _b; | ||
} | ||
const returnStatementIdentifier = getIdentifierNode(returnStatementNode); | ||
const returnStatementIdentifier = getDeepestIdentifierNode(returnStatementNode); | ||
if ((returnStatementIdentifier === null || returnStatementIdentifier === void 0 ? void 0 : returnStatementIdentifier.name) !== node.name) { | ||
@@ -332,1 +361,8 @@ return; | ||
exports.getInnermostReturningFunction = getInnermostReturningFunction; | ||
function hasImportMatch(importNode, identifierName) { | ||
if (experimental_utils_1.ASTUtils.isIdentifier(importNode)) { | ||
return importNode.name === identifierName; | ||
} | ||
return importNode.local.name === identifierName; | ||
} | ||
exports.hasImportMatch = hasImportMatch; |
{ | ||
"name": "eslint-plugin-testing-library", | ||
"version": "4.0.0-alpha.0", | ||
"version": "4.0.0-alpha.1", | ||
"description": "ESLint rules for Testing Library", | ||
@@ -48,7 +48,6 @@ "keywords": [ | ||
"format:check": "prettier --check README.md \"{lib,docs,tests}/**/*.{js,json,yml,ts,md}\"", | ||
"test:local": "jest", | ||
"test:ci": "jest --coverage", | ||
"test:update": "npm run test:local -- --u", | ||
"test:watch": "npm run test:local -- --watch", | ||
"test": "is-ci test:ci test:local", | ||
"test": "jest", | ||
"test:ci": "jest --ci --coverage", | ||
"test:update": "npm run test -- --u", | ||
"test:watch": "npm run test -- --watch", | ||
"type-check": "tsc --noEmit", | ||
@@ -58,29 +57,28 @@ "semantic-release": "semantic-release" | ||
"dependencies": { | ||
"@typescript-eslint/experimental-utils": "^4.1.1" | ||
"@typescript-eslint/experimental-utils": "^4.18.0" | ||
}, | ||
"devDependencies": { | ||
"@commitlint/cli": "^11.0.0", | ||
"@commitlint/config-conventional": "^11.0.0", | ||
"@types/jest": "^26.0.14", | ||
"@typescript-eslint/eslint-plugin": "^4.1.1", | ||
"@typescript-eslint/parser": "^4.1.1", | ||
"@commitlint/cli": "^12.0.1", | ||
"@commitlint/config-conventional": "^12.0.1", | ||
"@types/jest": "^26.0.20", | ||
"@typescript-eslint/eslint-plugin": "^4.18.0", | ||
"@typescript-eslint/parser": "^4.18.0", | ||
"cpy-cli": "^3.1.1", | ||
"eslint": "^7.9.0", | ||
"eslint-config-prettier": "^6.11.0", | ||
"eslint-config-standard": "^14.1.1", | ||
"eslint-plugin-import": "^2.22.0", | ||
"eslint-plugin-jest": "^24.0.2", | ||
"eslint-plugin-jest-formatting": "^2.0.0", | ||
"eslint": "^7.22.0", | ||
"eslint-config-prettier": "^8.1.0", | ||
"eslint-config-standard": "^16.0.2", | ||
"eslint-plugin-import": "^2.22.1", | ||
"eslint-plugin-jest": "^24.3.1", | ||
"eslint-plugin-jest-formatting": "^2.0.1", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-prettier": "^3.1.4", | ||
"eslint-plugin-promise": "^4.2.1", | ||
"eslint-plugin-standard": "^4.0.1", | ||
"husky": "^4.3.0", | ||
"is-ci-cli": "^2.1.2", | ||
"jest": "^26.4.2", | ||
"lint-staged": "^10.4.0", | ||
"prettier": "2.1.2", | ||
"semantic-release": "^17.1.2", | ||
"ts-jest": "^26.4.0", | ||
"typescript": "^4.0.3" | ||
"eslint-plugin-prettier": "^3.3.1", | ||
"eslint-plugin-promise": "^4.3.1", | ||
"husky": "^4.3.8", | ||
"jest": "^26.6.3", | ||
"jest-environment-jsdom": "^25.5.0", | ||
"lint-staged": "^10.5.4", | ||
"prettier": "2.2.1", | ||
"semantic-release": "^17.4.2", | ||
"ts-jest": "^26.5.3", | ||
"typescript": "^4.2.3" | ||
}, | ||
@@ -87,0 +85,0 @@ "peerDependencies": { |
@@ -156,4 +156,4 @@ <div align="center"> | ||
[build-badge]: https://img.shields.io/travis/testing-library/eslint-plugin-testing-library?style=flat-square | ||
[build-url]: https://travis-ci.org/testing-library/eslint-plugin-testing-library | ||
[build-badge]: https://github.com/testing-library/eslint-plugin-testing-library/actions/workflows/pipeline.yml/badge.svg | ||
[build-url]: https://github.com/testing-library/eslint-plugin-testing-library/actions/workflows/pipeline.yml | ||
[version-badge]: https://img.shields.io/npm/v/eslint-plugin-testing-library?style=flat-square | ||
@@ -160,0 +160,0 @@ [version-url]: https://www.npmjs.com/package/eslint-plugin-testing-library |
@@ -35,7 +35,2 @@ "use strict"; | ||
if (helpers.isAsyncUtil(node)) { | ||
if (!helpers.isNodeComingFromTestingLibrary(node) && | ||
!(node_utils_1.isMemberExpression(node.parent) && | ||
helpers.isNodeComingFromTestingLibrary(node.parent))) { | ||
return; | ||
} | ||
detectAsyncUtilWrapper(node); | ||
@@ -42,0 +37,0 @@ const closestCallExpression = node_utils_1.findClosestCallExpressionNode(node, true); |
@@ -5,2 +5,3 @@ "use strict"; | ||
const create_testing_library_rule_1 = require("../create-testing-library-rule"); | ||
const node_utils_1 = require("../node-utils"); | ||
exports.RULE_NAME = 'no-await-sync-query'; | ||
@@ -26,2 +27,9 @@ exports.default = create_testing_library_rule_1.createTestingLibraryRule({ | ||
'AwaitExpression > CallExpression Identifier'(node) { | ||
const closestCallExpression = node_utils_1.findClosestCallExpressionNode(node, true); | ||
if (!closestCallExpression) { | ||
return; | ||
} | ||
if (!node_utils_1.isCallExpressionCallee(closestCallExpression, node)) { | ||
return; | ||
} | ||
if (helpers.isSyncQuery(node)) { | ||
@@ -28,0 +36,0 @@ context.report({ |
@@ -38,3 +38,3 @@ "use strict"; | ||
if (node_utils_1.isCallExpression(node)) { | ||
const domElementIdentifier = node_utils_1.getIdentifierNode(node); | ||
const domElementIdentifier = node_utils_1.getDeepestIdentifierNode(node); | ||
if (helpers.isAsyncQuery(domElementIdentifier) || | ||
@@ -41,0 +41,0 @@ node_utils_1.isPromiseIdentifier(domElementIdentifier)) { |
@@ -5,7 +5,6 @@ "use strict"; | ||
const experimental_utils_1 = require("@typescript-eslint/experimental-utils"); | ||
const utils_1 = require("../utils"); | ||
const node_utils_1 = require("../node-utils"); | ||
const create_testing_library_rule_1 = require("../create-testing-library-rule"); | ||
exports.RULE_NAME = 'no-wait-for-empty-callback'; | ||
const WAIT_EXPRESSION_QUERY = 'CallExpression[callee.name=/^(waitFor|waitForElementToBeRemoved)$/]'; | ||
exports.default = experimental_utils_1.ESLintUtils.RuleCreator(utils_1.getDocsUrl)({ | ||
exports.default = create_testing_library_rule_1.createTestingLibraryRule({ | ||
name: exports.RULE_NAME, | ||
@@ -26,4 +25,15 @@ meta: { | ||
defaultOptions: [], | ||
create: function (context) { | ||
create(context, _, helpers) { | ||
function isValidWaitFor(node) { | ||
const parentCallExpression = node.parent; | ||
const parentIdentifier = node_utils_1.getPropertyIdentifierNode(parentCallExpression); | ||
return helpers.isAsyncUtil(parentIdentifier, [ | ||
'waitFor', | ||
'waitForElementToBeRemoved', | ||
]); | ||
} | ||
function reportIfEmpty(node) { | ||
if (!isValidWaitFor(node)) { | ||
return; | ||
} | ||
if (node_utils_1.isBlockStatement(node.body) && | ||
@@ -44,2 +54,5 @@ node.body.body.length === 0 && | ||
function reportNoop(node) { | ||
if (!isValidWaitFor(node)) { | ||
return; | ||
} | ||
context.report({ | ||
@@ -49,10 +62,15 @@ node, | ||
messageId: 'noWaitForEmptyCallback', | ||
data: { | ||
methodName: node_utils_1.isCallExpression(node.parent) && | ||
experimental_utils_1.ASTUtils.isIdentifier(node.parent.callee) && | ||
node.parent.callee.name, | ||
}, | ||
}); | ||
} | ||
return { | ||
[`${WAIT_EXPRESSION_QUERY} > ArrowFunctionExpression`]: reportIfEmpty, | ||
[`${WAIT_EXPRESSION_QUERY} > FunctionExpression`]: reportIfEmpty, | ||
[`${WAIT_EXPRESSION_QUERY} > Identifier[name="noop"]`]: reportNoop, | ||
'CallExpression > ArrowFunctionExpression': reportIfEmpty, | ||
'CallExpression > FunctionExpression': reportIfEmpty, | ||
'CallExpression > Identifier[name="noop"]': reportNoop, | ||
}; | ||
}, | ||
}); |
@@ -31,3 +31,2 @@ "use strict"; | ||
if (experimental_utils_1.ASTUtils.isIdentifier(callExpression.callee) && | ||
helpers.isNodeComingFromTestingLibrary(callExpression.callee) && | ||
helpers.isAsyncUtil(callExpression.callee)) { | ||
@@ -38,3 +37,3 @@ return callExpression.callee; | ||
experimental_utils_1.ASTUtils.isIdentifier(callExpression.callee.property) && | ||
helpers.isNodeComingFromTestingLibrary(callExpression.callee)) { | ||
helpers.isAsyncUtil(callExpression.callee.property)) { | ||
return callExpression.callee.property; | ||
@@ -41,0 +40,0 @@ } |
@@ -43,3 +43,3 @@ "use strict"; | ||
'CallExpression Identifier'(node) { | ||
if (helpers.isGetByQuery(node)) { | ||
if (helpers.isGetQueryVariant(node)) { | ||
getQueryCalls.push(node); | ||
@@ -46,0 +46,0 @@ } |
@@ -34,3 +34,3 @@ "use strict"; | ||
} | ||
const isPresenceQuery = helpers.isGetByQuery(node); | ||
const isPresenceQuery = helpers.isGetQueryVariant(node); | ||
const expectStatement = expectCallNode.parent; | ||
@@ -37,0 +37,0 @@ const isPresenceAssert = helpers.isPresenceAssert(expectStatement); |
@@ -5,4 +5,4 @@ "use strict"; | ||
const experimental_utils_1 = require("@typescript-eslint/experimental-utils"); | ||
const utils_1 = require("../utils"); | ||
const node_utils_1 = require("../node-utils"); | ||
const create_testing_library_rule_1 = require("../create-testing-library-rule"); | ||
exports.RULE_NAME = 'prefer-screen-queries'; | ||
@@ -13,3 +13,2 @@ const ALLOWED_RENDER_PROPERTIES_FOR_DESTRUCTURING = [ | ||
]; | ||
const ALL_QUERIES_COMBINATIONS_REGEXP = utils_1.ALL_QUERIES_COMBINATIONS.join('|'); | ||
function usesContainerOrBaseElement(node) { | ||
@@ -22,3 +21,3 @@ const secondArgument = node.arguments[1]; | ||
} | ||
exports.default = experimental_utils_1.ESLintUtils.RuleCreator(utils_1.getDocsUrl)({ | ||
exports.default = create_testing_library_rule_1.createTestingLibraryRule({ | ||
name: exports.RULE_NAME, | ||
@@ -39,3 +38,3 @@ meta: { | ||
defaultOptions: [], | ||
create(context) { | ||
create(context, _, helpers) { | ||
function reportInvalidUsage(node) { | ||
@@ -50,4 +49,13 @@ context.report({ | ||
} | ||
const queriesRegex = new RegExp(ALL_QUERIES_COMBINATIONS_REGEXP); | ||
const queriesDestructuredInWithinDeclaration = []; | ||
function saveSafeDestructuredQueries(node) { | ||
if (node_utils_1.isObjectPattern(node.id)) { | ||
const identifiers = node.id.properties | ||
.filter((property) => node_utils_1.isProperty(property) && | ||
experimental_utils_1.ASTUtils.isIdentifier(property.key) && | ||
helpers.isQuery(property.key)) | ||
.map((property) => property.key.name); | ||
safeDestructuredQueries.push(...identifiers); | ||
} | ||
} | ||
const safeDestructuredQueries = []; | ||
const withinDeclaredVariables = []; | ||
@@ -60,5 +68,8 @@ return { | ||
} | ||
const isComingFromValidRender = helpers.isRenderUtil(node.init.callee); | ||
if (!isComingFromValidRender) { | ||
saveSafeDestructuredQueries(node); | ||
} | ||
const isWithinFunction = node.init.callee.name === 'within'; | ||
const usesRenderOptions = node.init.callee.name === 'render' && | ||
usesContainerOrBaseElement(node.init); | ||
const usesRenderOptions = isComingFromValidRender && usesContainerOrBaseElement(node.init); | ||
if (!isWithinFunction && !usesRenderOptions) { | ||
@@ -68,8 +79,3 @@ return; | ||
if (node_utils_1.isObjectPattern(node.id)) { | ||
const identifiers = node.id.properties | ||
.filter((property) => node_utils_1.isProperty(property) && | ||
experimental_utils_1.ASTUtils.isIdentifier(property.key) && | ||
queriesRegex.test(property.key.name)) | ||
.map((property) => property.key.name); | ||
queriesDestructuredInWithinDeclaration.push(...identifiers); | ||
saveSafeDestructuredQueries(node); | ||
return; | ||
@@ -81,11 +87,17 @@ } | ||
}, | ||
[`CallExpression > Identifier[name=/^${ALL_QUERIES_COMBINATIONS_REGEXP}$/]`](node) { | ||
if (!queriesDestructuredInWithinDeclaration.some((queryName) => queryName === node.name)) { | ||
'CallExpression > Identifier'(node) { | ||
if (!helpers.isQuery(node)) { | ||
return; | ||
} | ||
if (!safeDestructuredQueries.some((queryName) => queryName === node.name)) { | ||
reportInvalidUsage(node); | ||
} | ||
}, | ||
[`MemberExpression > Identifier[name=/^${ALL_QUERIES_COMBINATIONS_REGEXP}$/]`](node) { | ||
'MemberExpression > Identifier'(node) { | ||
function isIdentifierAllowed(name) { | ||
return ['screen', ...withinDeclaredVariables].includes(name); | ||
} | ||
if (!helpers.isQuery(node)) { | ||
return; | ||
} | ||
if (experimental_utils_1.ASTUtils.isIdentifier(node) && | ||
@@ -96,3 +108,3 @@ node_utils_1.isMemberExpression(node.parent) && | ||
node.parent.object.callee.name !== 'within' && | ||
node.parent.object.callee.name === 'render' && | ||
helpers.isRenderUtil(node.parent.object.callee) && | ||
!usesContainerOrBaseElement(node.parent.object)) { | ||
@@ -99,0 +111,0 @@ reportInvalidUsage(node); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.RULE_NAME = void 0; | ||
const create_testing_library_rule_1 = require("../create-testing-library-rule"); | ||
const node_utils_1 = require("../node-utils"); | ||
const experimental_utils_1 = require("@typescript-eslint/experimental-utils"); | ||
const utils_1 = require("../utils"); | ||
const node_utils_1 = require("../node-utils"); | ||
exports.RULE_NAME = 'render-result-naming-convention'; | ||
const ALLOWED_VAR_NAMES = ['view', 'utils']; | ||
const ALLOWED_VAR_NAMES_TEXT = ALLOWED_VAR_NAMES.map((name) => `\`${name}\``).join(', '); | ||
exports.default = experimental_utils_1.ESLintUtils.RuleCreator(utils_1.getDocsUrl)({ | ||
exports.default = create_testing_library_rule_1.createTestingLibraryRule({ | ||
name: exports.RULE_NAME, | ||
@@ -20,68 +20,32 @@ meta: { | ||
messages: { | ||
renderResultNamingConvention: `\`{{ varName }}\` is not a recommended name for \`render\` returned value. Instead, you should destructure it, or call it using one of the valid choices: ${ALLOWED_VAR_NAMES_TEXT}`, | ||
renderResultNamingConvention: `\`{{ renderResultName }}\` is not a recommended name for \`render\` returned value. Instead, you should destructure it, or name it using one of: ${ALLOWED_VAR_NAMES_TEXT}`, | ||
}, | ||
fixable: null, | ||
schema: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
renderFunctions: { | ||
type: 'array', | ||
}, | ||
}, | ||
}, | ||
], | ||
schema: [], | ||
}, | ||
defaultOptions: [ | ||
{ | ||
renderFunctions: [], | ||
}, | ||
], | ||
create(context, [options]) { | ||
const { renderFunctions } = options; | ||
let renderAlias; | ||
let wildcardImportName; | ||
defaultOptions: [], | ||
create(context, _, helpers) { | ||
const renderWrapperNames = []; | ||
function detectRenderWrapper(node) { | ||
const innerFunction = node_utils_1.getInnermostReturningFunction(context, node); | ||
if (innerFunction) { | ||
renderWrapperNames.push(node_utils_1.getFunctionName(innerFunction)); | ||
} | ||
} | ||
return { | ||
ImportDeclaration(node) { | ||
if (!utils_1.hasTestingLibraryImportModule(node)) { | ||
return; | ||
'CallExpression Identifier'(node) { | ||
if (helpers.isRenderUtil(node)) { | ||
detectRenderWrapper(node); | ||
} | ||
const renderImport = node.specifiers.find((node) => node_utils_1.isImportSpecifier(node) && node.imported.name === 'render'); | ||
if (!renderImport) { | ||
return; | ||
} | ||
renderAlias = renderImport.local.name; | ||
}, | ||
'ImportDeclaration ImportNamespaceSpecifier'(node) { | ||
if (!utils_1.hasTestingLibraryImportModule(node.parent)) { | ||
return; | ||
} | ||
wildcardImportName = node.local.name; | ||
}, | ||
VariableDeclarator(node) { | ||
if (node_utils_1.isObjectPattern(node.id)) { | ||
const initIdentifierNode = node_utils_1.getDeepestIdentifierNode(node.init); | ||
if (!initIdentifierNode) { | ||
return; | ||
} | ||
const isValidRenderDeclarator = node_utils_1.isRenderVariableDeclarator(node, [ | ||
...renderFunctions, | ||
renderAlias, | ||
]); | ||
const isValidWildcardImport = !!wildcardImportName; | ||
if (!isValidRenderDeclarator && !isValidWildcardImport) { | ||
if (!helpers.isRenderUtil(initIdentifierNode) && | ||
!renderWrapperNames.includes(initIdentifierNode.name)) { | ||
return; | ||
} | ||
const renderFunctionName = node_utils_1.isCallExpression(node.init) && | ||
experimental_utils_1.ASTUtils.isIdentifier(node.init.callee) && | ||
node.init.callee.name; | ||
const renderFunctionObjectName = node_utils_1.isCallExpression(node.init) && | ||
node_utils_1.isMemberExpression(node.init.callee) && | ||
experimental_utils_1.ASTUtils.isIdentifier(node.init.callee.property) && | ||
experimental_utils_1.ASTUtils.isIdentifier(node.init.callee.object) && | ||
node.init.callee.property.name === 'render' && | ||
node.init.callee.object.name; | ||
const isRenderAlias = !!renderAlias; | ||
const isCustomRender = renderFunctions.includes(renderFunctionName); | ||
const isWildCardRender = renderFunctionObjectName && | ||
renderFunctionObjectName === wildcardImportName; | ||
if (!isRenderAlias && !isCustomRender && !isWildCardRender) { | ||
if (node_utils_1.isObjectPattern(node.id)) { | ||
return; | ||
@@ -98,3 +62,3 @@ } | ||
data: { | ||
varName: renderResultName, | ||
renderResultName, | ||
}, | ||
@@ -101,0 +65,0 @@ }); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
157545
23
2827
0