Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

eslint-plugin-testing-library

Package Overview
Dependencies
Maintainers
3
Versions
164
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-testing-library - npm Package Compare versions

Comparing version 4.0.0-alpha.0 to 4.0.0-alpha.1

109

detect-testing-library-utils.js

@@ -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 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc