Socket
Socket
Sign inDemoInstall

eslint-plugin-jest-dom

Package Overview
Dependencies
167
Maintainers
1
Versions
60
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 5.0.1 to 5.0.2

95

dist/rules/prefer-in-document.js

@@ -26,4 +26,7 @@ "use strict";

messages: {
"use-document": `Prefer .toBeInTheDocument() for asserting DOM node existence`
}
"use-document": `Prefer .toBeInTheDocument() for asserting DOM node existence`,
"invalid-combination-length-1": `Invalid combination of {{ query }} and .toHaveLength(1). Did you mean to use {{ allQuery }}?`,
"replace-query-with-all": `Replace {{ query }} with {{ allQuery }}`
},
hasSuggestions: true
};

@@ -42,2 +45,18 @@ exports.meta = meta;

}
/**
* Extract the DTL query identifier from a call expression
*
* <query>() -> <query>
* screen.<query>() -> <query>
*/
function getDTLQueryIdentifierNode(callExpressionNode) {
if (!callExpressionNode || callExpressionNode.type !== "CallExpression") {
return null;
}
if (callExpressionNode.callee.type === "Identifier") {
return callExpressionNode.callee;
}
return callExpressionNode.callee.property;
}
const create = context => {

@@ -72,11 +91,49 @@ const alternativeMatchers = /^(toHaveLength|toBeDefined|toBeNull|toBe|toEqual|toBeTruthy|toBeFalsy)$/;

// toHaveLength() is only invalid with 0 or 1
if (matcherNode.name === "toHaveLength" && matcherArguments.length) {
// *By* query with .toHaveLength(0/1) matcher are considered violations
//
// | Selector type | .toHaveLength(1) | .toHaveLength(0) |
// | ============= | =========================== | ===================================== |
// | *By* query | Did you mean to use *AllBy* | Replace with .not.toBeInTheDocument() |
// | *AllBy* query | Correct | Correct
//
// @see https://github.com/testing-library/eslint-plugin-jest-dom/issues/171
//
if (matcherNode.name === "toHaveLength" && matcherArguments.length === 1) {
const lengthValue = getLengthValue(matcherArguments);
// isNotToHaveLengthZero represents .not.toHaveLength(0) which is a valid use of toHaveLength
const isNotToHaveLengthZero = usesToHaveLengthZero(matcherNode, matcherArguments) && negatedMatcher;
const isValidUseOfToHaveLength = isNotToHaveLengthZero || !["Literal", "Identifier"].includes(matcherArguments[0].type) || lengthValue === undefined || lengthValue > 1;
if (isValidUseOfToHaveLength) {
const queryName = queryNode.name || queryNode.property.name;
const isSingleQuery = _queries.queries.includes(queryName) && !/AllBy/.test(queryName);
const hasViolation = isSingleQuery && [1, 0].includes(lengthValue);
if (!hasViolation) {
return;
}
// If length === 1, report violation with suggestions
// Otherwise fallback to default report
if (lengthValue === 1) {
const allQuery = queryName.replace("By", "AllBy");
return context.report({
node: matcherNode,
messageId: "invalid-combination-length-1",
data: {
query: queryName,
allQuery
},
loc: matcherNode.loc,
suggest: [{
messageId: "replace-query-with-all",
data: {
query: queryName,
allQuery
},
fix(fixer) {
return fixer.replaceText(queryNode.property || queryNode, allQuery);
}
}, {
desc: "Replace .toHaveLength(1) with .toBeInTheDocument()",
fix(fixer) {
// Remove any arguments in the matcher
return [...Array.from(matcherArguments).map(argument => fixer.remove(argument)), fixer.replaceText(matcherNode, "toBeInTheDocument")];
}
}]
});
}
}

@@ -151,2 +208,7 @@

const queryNode = (0, _assignmentAst.getAssignmentForIdentifier)(context, node.object.object.arguments[0].name);
// Not an RTL query
if (!queryNode || queryNode.type !== "CallExpression") {
return;
}
const matcherNode = node.property;

@@ -157,3 +219,3 @@ const matcherArguments = node.parent.arguments;

negatedMatcher: true,
queryNode: queryNode && queryNode.callee || queryNode,
queryNode: queryNode.callee,
matcherNode,

@@ -166,3 +228,10 @@ matcherArguments,

[`MemberExpression[object.callee.name=expect][property.name=${alternativeMatchers}][object.arguments.0.type=Identifier]`](node) {
const queryNode = (0, _assignmentAst.getAssignmentForIdentifier)(context, node.object.arguments[0].name);
// Value expression being assigned to the left-hand value
const rightValueNode = (0, _assignmentAst.getAssignmentForIdentifier)(context, node.object.arguments[0].name);
// Not a DTL query
if (!rightValueNode || rightValueNode.type !== "CallExpression") {
return;
}
const queryIdentifierNode = getDTLQueryIdentifierNode(rightValueNode);
const matcherNode = node.property;

@@ -172,3 +241,3 @@ const matcherArguments = node.parent.arguments;

negatedMatcher: false,
queryNode: queryNode && queryNode.callee || queryNode,
queryNode: queryIdentifierNode,
matcherNode,

@@ -185,3 +254,3 @@ matcherArguments

}
const queryNode = arg.type === "AwaitExpression" ? arg.argument.callee : arg.callee;
const queryIdentifierNode = arg.type === "AwaitExpression" ? getDTLQueryIdentifierNode(arg.argument) : getDTLQueryIdentifierNode(arg);
const matcherNode = node.callee.property;

@@ -191,3 +260,3 @@ const matcherArguments = node.arguments;

negatedMatcher: false,
queryNode,
queryNode: queryIdentifierNode,
matcherNode,

@@ -194,0 +263,0 @@ matcherArguments

8

package.json
{
"name": "eslint-plugin-jest-dom",
"version": "5.0.1",
"version": "5.0.2",
"description": "ESLint plugin to follow best practices and anticipate common mistakes when writing tests with jest-dom",

@@ -55,7 +55,7 @@ "main": "dist/index.js",

"kcd-scripts": "^12.0.0",
"typescript": "^4.5.3"
"typescript": "^5.1.3"
},
"peerDependencies": {
"eslint": "^6.8.0 || ^7.0.0 || ^8.0.0",
"@testing-library/dom": "^8.0.0 || ^9.0.0"
"@testing-library/dom": "^8.0.0 || ^9.0.0",
"eslint": "^6.8.0 || ^7.0.0 || ^8.0.0"
},

@@ -62,0 +62,0 @@ "eslintConfig": {

@@ -99,17 +99,18 @@ <div align="center">

✅ Set in the `recommended` configuration.\
🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).
🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\
💡 Manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).
| Name                        | Description | 💼 | 🔧 |
| :----------------------------------------------------------------------- | :-------------------------------------------------------------------- | :- | :- |
| [prefer-checked](docs/rules/prefer-checked.md) | prefer toBeChecked over checking attributes | ✅ | 🔧 |
| [prefer-empty](docs/rules/prefer-empty.md) | Prefer toBeEmpty over checking innerHTML | ✅ | 🔧 |
| [prefer-enabled-disabled](docs/rules/prefer-enabled-disabled.md) | prefer toBeDisabled or toBeEnabled over checking attributes | ✅ | 🔧 |
| [prefer-focus](docs/rules/prefer-focus.md) | prefer toHaveFocus over checking document.activeElement | ✅ | 🔧 |
| [prefer-in-document](docs/rules/prefer-in-document.md) | Prefer .toBeInTheDocument() for asserting the existence of a DOM node | ✅ | 🔧 |
| [prefer-required](docs/rules/prefer-required.md) | prefer toBeRequired over checking properties | ✅ | 🔧 |
| [prefer-to-have-attribute](docs/rules/prefer-to-have-attribute.md) | prefer toHaveAttribute over checking getAttribute/hasAttribute | ✅ | 🔧 |
| [prefer-to-have-class](docs/rules/prefer-to-have-class.md) | prefer toHaveClass over checking element className | ✅ | 🔧 |
| [prefer-to-have-style](docs/rules/prefer-to-have-style.md) | prefer toHaveStyle over checking element style | ✅ | 🔧 |
| [prefer-to-have-text-content](docs/rules/prefer-to-have-text-content.md) | Prefer toHaveTextContent over checking element.textContent | ✅ | 🔧 |
| [prefer-to-have-value](docs/rules/prefer-to-have-value.md) | prefer toHaveValue over checking element.value | ✅ | 🔧 |
| Name                        | Description | 💼 | 🔧 | 💡 |
| :----------------------------------------------------------------------- | :-------------------------------------------------------------------- | :- | :- | :- |
| [prefer-checked](docs/rules/prefer-checked.md) | prefer toBeChecked over checking attributes | ✅ | 🔧 | |
| [prefer-empty](docs/rules/prefer-empty.md) | Prefer toBeEmpty over checking innerHTML | ✅ | 🔧 | |
| [prefer-enabled-disabled](docs/rules/prefer-enabled-disabled.md) | prefer toBeDisabled or toBeEnabled over checking attributes | ✅ | 🔧 | |
| [prefer-focus](docs/rules/prefer-focus.md) | prefer toHaveFocus over checking document.activeElement | ✅ | 🔧 | |
| [prefer-in-document](docs/rules/prefer-in-document.md) | Prefer .toBeInTheDocument() for asserting the existence of a DOM node | ✅ | 🔧 | 💡 |
| [prefer-required](docs/rules/prefer-required.md) | prefer toBeRequired over checking properties | ✅ | 🔧 | |
| [prefer-to-have-attribute](docs/rules/prefer-to-have-attribute.md) | prefer toHaveAttribute over checking getAttribute/hasAttribute | ✅ | 🔧 | |
| [prefer-to-have-class](docs/rules/prefer-to-have-class.md) | prefer toHaveClass over checking element className | ✅ | 🔧 | |
| [prefer-to-have-style](docs/rules/prefer-to-have-style.md) | prefer toHaveStyle over checking element style | ✅ | 🔧 | |
| [prefer-to-have-text-content](docs/rules/prefer-to-have-text-content.md) | Prefer toHaveTextContent over checking element.textContent | ✅ | 🔧 | |
| [prefer-to-have-value](docs/rules/prefer-to-have-value.md) | prefer toHaveValue over checking element.value | ✅ | 🔧 | |

@@ -116,0 +117,0 @@ <!-- end auto-generated rules list -->

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc