123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.getFindByQueryVariant = exports.WAIT_METHODS = exports.RULE_NAME = void 0;
- const utils_1 = require("@typescript-eslint/utils");
- const create_testing_library_rule_1 = require("../create-testing-library-rule");
- const node_utils_1 = require("../node-utils");
- exports.RULE_NAME = 'prefer-find-by';
- exports.WAIT_METHODS = ['waitFor', 'waitForElement', 'wait'];
- function getFindByQueryVariant(queryMethod) {
- return queryMethod.includes('All') ? 'findAllBy' : 'findBy';
- }
- exports.getFindByQueryVariant = getFindByQueryVariant;
- function findRenderDefinitionDeclaration(scope, query) {
- var _a;
- if (!scope) {
- return null;
- }
- const variable = scope.variables.find((v) => v.name === query);
- if (variable) {
- return ((_a = variable.defs
- .map(({ name }) => name)
- .filter(utils_1.ASTUtils.isIdentifier)
- .find(({ name }) => name === query)) !== null && _a !== void 0 ? _a : null);
- }
- return findRenderDefinitionDeclaration(scope.upper, query);
- }
- exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
- name: exports.RULE_NAME,
- meta: {
- type: 'suggestion',
- docs: {
- description: 'Suggest using `find(All)By*` query instead of `waitFor` + `get(All)By*` to wait for elements',
- recommendedConfig: {
- dom: 'error',
- angular: 'error',
- react: 'error',
- vue: 'error',
- marko: 'error',
- },
- },
- messages: {
- preferFindBy: 'Prefer `{{queryVariant}}{{queryMethod}}` query over using `{{waitForMethodName}}` + `{{prevQuery}}`',
- },
- fixable: 'code',
- schema: [],
- },
- defaultOptions: [],
- create(context, _, helpers) {
- const sourceCode = context.getSourceCode();
- function reportInvalidUsage(node, replacementParams) {
- const { queryMethod, queryVariant, prevQuery, waitForMethodName, fix } = replacementParams;
- context.report({
- node,
- messageId: 'preferFindBy',
- data: {
- queryVariant,
- queryMethod,
- prevQuery,
- waitForMethodName,
- },
- fix,
- });
- }
- function getWrongQueryNameInAssertion(node) {
- if (!(0, node_utils_1.isCallExpression)(node.body) ||
- !(0, node_utils_1.isMemberExpression)(node.body.callee)) {
- return null;
- }
- if ((0, node_utils_1.isCallExpression)(node.body.callee.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.arguments[0]) &&
- utils_1.ASTUtils.isIdentifier(node.body.callee.object.arguments[0].callee)) {
- return node.body.callee.object.arguments[0].callee.name;
- }
- if (!utils_1.ASTUtils.isIdentifier(node.body.callee.property)) {
- return null;
- }
- if ((0, node_utils_1.isCallExpression)(node.body.callee.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.arguments[0]) &&
- (0, node_utils_1.isMemberExpression)(node.body.callee.object.arguments[0].callee) &&
- utils_1.ASTUtils.isIdentifier(node.body.callee.object.arguments[0].callee.property)) {
- return node.body.callee.object.arguments[0].callee.property.name;
- }
- if ((0, node_utils_1.isMemberExpression)(node.body.callee.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.object.arguments[0]) &&
- (0, node_utils_1.isMemberExpression)(node.body.callee.object.object.arguments[0].callee) &&
- utils_1.ASTUtils.isIdentifier(node.body.callee.object.object.arguments[0].callee.property)) {
- return node.body.callee.object.object.arguments[0].callee.property.name;
- }
- if ((0, node_utils_1.isMemberExpression)(node.body.callee.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.object.arguments[0]) &&
- utils_1.ASTUtils.isIdentifier(node.body.callee.object.object.arguments[0].callee)) {
- return node.body.callee.object.object.arguments[0].callee.name;
- }
- return node.body.callee.property.name;
- }
- function getWrongQueryName(node) {
- if (!(0, node_utils_1.isCallExpression)(node.body)) {
- return null;
- }
- if (utils_1.ASTUtils.isIdentifier(node.body.callee) &&
- helpers.isSyncQuery(node.body.callee)) {
- return node.body.callee.name;
- }
- return getWrongQueryNameInAssertion(node);
- }
- function getCaller(node) {
- if (!(0, node_utils_1.isCallExpression)(node.body) ||
- !(0, node_utils_1.isMemberExpression)(node.body.callee)) {
- return null;
- }
- if (utils_1.ASTUtils.isIdentifier(node.body.callee.object)) {
- return node.body.callee.object.name;
- }
- if ((0, node_utils_1.isCallExpression)(node.body.callee.object) &&
- utils_1.ASTUtils.isIdentifier(node.body.callee.object.callee) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.arguments[0]) &&
- (0, node_utils_1.isMemberExpression)(node.body.callee.object.arguments[0].callee) &&
- utils_1.ASTUtils.isIdentifier(node.body.callee.object.arguments[0].callee.object)) {
- return node.body.callee.object.arguments[0].callee.object.name;
- }
- if ((0, node_utils_1.isMemberExpression)(node.body.callee.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.object.arguments[0]) &&
- (0, node_utils_1.isMemberExpression)(node.body.callee.object.object.arguments[0].callee) &&
- utils_1.ASTUtils.isIdentifier(node.body.callee.object.object.arguments[0].callee.object)) {
- return node.body.callee.object.object.arguments[0].callee.object.name;
- }
- return null;
- }
- function isSyncQuery(node) {
- if (!(0, node_utils_1.isCallExpression)(node.body)) {
- return false;
- }
- const isQuery = utils_1.ASTUtils.isIdentifier(node.body.callee) &&
- helpers.isSyncQuery(node.body.callee);
- const isWrappedInPresenceAssert = (0, node_utils_1.isMemberExpression)(node.body.callee) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.arguments[0]) &&
- utils_1.ASTUtils.isIdentifier(node.body.callee.object.arguments[0].callee) &&
- helpers.isSyncQuery(node.body.callee.object.arguments[0].callee) &&
- helpers.isPresenceAssert(node.body.callee);
- const isWrappedInNegatedPresenceAssert = (0, node_utils_1.isMemberExpression)(node.body.callee) &&
- (0, node_utils_1.isMemberExpression)(node.body.callee.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.object.arguments[0]) &&
- utils_1.ASTUtils.isIdentifier(node.body.callee.object.object.arguments[0].callee) &&
- helpers.isSyncQuery(node.body.callee.object.object.arguments[0].callee) &&
- helpers.isPresenceAssert(node.body.callee.object);
- return (isQuery || isWrappedInPresenceAssert || isWrappedInNegatedPresenceAssert);
- }
- function isScreenSyncQuery(node) {
- if (!(0, node_utils_1.isArrowFunctionExpression)(node) || !(0, node_utils_1.isCallExpression)(node.body)) {
- return false;
- }
- if (!(0, node_utils_1.isMemberExpression)(node.body.callee) ||
- !utils_1.ASTUtils.isIdentifier(node.body.callee.property)) {
- return false;
- }
- if (!utils_1.ASTUtils.isIdentifier(node.body.callee.object) &&
- !(0, node_utils_1.isCallExpression)(node.body.callee.object) &&
- !(0, node_utils_1.isMemberExpression)(node.body.callee.object)) {
- return false;
- }
- const isWrappedInPresenceAssert = helpers.isPresenceAssert(node.body.callee) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.arguments[0]) &&
- (0, node_utils_1.isMemberExpression)(node.body.callee.object.arguments[0].callee) &&
- utils_1.ASTUtils.isIdentifier(node.body.callee.object.arguments[0].callee.object);
- const isWrappedInNegatedPresenceAssert = (0, node_utils_1.isMemberExpression)(node.body.callee.object) &&
- helpers.isPresenceAssert(node.body.callee.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.object) &&
- (0, node_utils_1.isCallExpression)(node.body.callee.object.object.arguments[0]) &&
- (0, node_utils_1.isMemberExpression)(node.body.callee.object.object.arguments[0].callee);
- return (helpers.isSyncQuery(node.body.callee.property) ||
- isWrappedInPresenceAssert ||
- isWrappedInNegatedPresenceAssert);
- }
- function getQueryArguments(node) {
- if ((0, node_utils_1.isMemberExpression)(node.callee) &&
- (0, node_utils_1.isCallExpression)(node.callee.object) &&
- (0, node_utils_1.isCallExpression)(node.callee.object.arguments[0])) {
- return node.callee.object.arguments[0].arguments;
- }
- if ((0, node_utils_1.isMemberExpression)(node.callee) &&
- (0, node_utils_1.isMemberExpression)(node.callee.object) &&
- (0, node_utils_1.isCallExpression)(node.callee.object.object) &&
- (0, node_utils_1.isCallExpression)(node.callee.object.object.arguments[0])) {
- return node.callee.object.object.arguments[0].arguments;
- }
- return node.arguments;
- }
- return {
- 'AwaitExpression > CallExpression'(node) {
- if (!utils_1.ASTUtils.isIdentifier(node.callee) ||
- !helpers.isAsyncUtil(node.callee, exports.WAIT_METHODS)) {
- return;
- }
- const argument = node.arguments[0];
- if (!(0, node_utils_1.isArrowFunctionExpression)(argument) ||
- !(0, node_utils_1.isCallExpression)(argument.body)) {
- return;
- }
- const waitForMethodName = node.callee.name;
- if (isScreenSyncQuery(argument)) {
- const caller = getCaller(argument);
- if (!caller) {
- return;
- }
- const fullQueryMethod = getWrongQueryName(argument);
- if (!fullQueryMethod) {
- return;
- }
- const waitOptions = node.arguments[1];
- let waitOptionsSourceCode = '';
- if ((0, node_utils_1.isObjectExpression)(waitOptions)) {
- waitOptionsSourceCode = `, ${sourceCode.getText(waitOptions)}`;
- }
- const queryVariant = getFindByQueryVariant(fullQueryMethod);
- const callArguments = getQueryArguments(argument.body);
- const queryMethod = fullQueryMethod.split('By')[1];
- if (!queryMethod) {
- return;
- }
- reportInvalidUsage(node, {
- queryMethod,
- queryVariant,
- prevQuery: fullQueryMethod,
- waitForMethodName,
- fix(fixer) {
- const property = argument.body
- .callee.property;
- if (helpers.isCustomQuery(property)) {
- return null;
- }
- const newCode = `${caller}.${queryVariant}${queryMethod}(${callArguments
- .map((callArgNode) => sourceCode.getText(callArgNode))
- .join(', ')}${waitOptionsSourceCode})`;
- return fixer.replaceText(node, newCode);
- },
- });
- return;
- }
- if (!isSyncQuery(argument)) {
- return;
- }
- const fullQueryMethod = getWrongQueryName(argument);
- if (!fullQueryMethod) {
- return;
- }
- const queryMethod = fullQueryMethod.split('By')[1];
- const queryVariant = getFindByQueryVariant(fullQueryMethod);
- const callArguments = getQueryArguments(argument.body);
- reportInvalidUsage(node, {
- queryMethod,
- queryVariant,
- prevQuery: fullQueryMethod,
- waitForMethodName,
- fix(fixer) {
- if (helpers.isCustomQuery(argument.body
- .callee)) {
- return null;
- }
- const findByMethod = `${queryVariant}${queryMethod}`;
- const allFixes = [];
- const newCode = `${findByMethod}(${callArguments
- .map((callArgNode) => sourceCode.getText(callArgNode))
- .join(', ')})`;
- allFixes.push(fixer.replaceText(node, newCode));
- const definition = findRenderDefinitionDeclaration(context.getScope(), fullQueryMethod);
- if (!definition) {
- return allFixes;
- }
- if (definition.parent &&
- (0, node_utils_1.isObjectPattern)(definition.parent.parent)) {
- const allVariableDeclarations = definition.parent.parent;
- if (allVariableDeclarations.properties.some((p) => (0, node_utils_1.isProperty)(p) &&
- utils_1.ASTUtils.isIdentifier(p.key) &&
- p.key.name === findByMethod)) {
- return allFixes;
- }
- const textDestructuring = sourceCode.getText(allVariableDeclarations);
- const text = textDestructuring.replace(/(\s*})$/, `, ${findByMethod}$1`);
- allFixes.push(fixer.replaceText(allVariableDeclarations, text));
- }
- return allFixes;
- },
- });
- },
- };
- },
- });
|