text: "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  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-screen-queries';
  const ALLOWED_RENDER_PROPERTIES_FOR_DESTRUCTURING = [
      'container',
      'baseElement',
  ];
  function usesContainerOrBaseElement(node) {
      const secondArgument = node.arguments[1];
      return ((0, node_utils_1.isObjectExpression)(secondArgument) &&
          secondArgument.properties.some((property) => (0, node_utils_1.isProperty)(property) &&
              utils_1.ASTUtils.isIdentifier(property.key) &&
              ALLOWED_RENDER_PROPERTIES_FOR_DESTRUCTURING.includes(property.key.name)));
  }
  exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
      name: exports.RULE_NAME,
      meta: {
          type: 'suggestion',
          docs: {
              description: 'Suggest using `screen` while querying',
              recommendedConfig: {
                  dom: 'error',
                  angular: 'error',
                  react: 'error',
                  vue: 'error',
                  marko: 'error',
              },
          },
          messages: {
              preferScreenQueries: 'Avoid destructuring queries from `render` result, use `screen.{{ name }}` instead',
          },
          schema: [],
      },
      defaultOptions: [],
      create(context, _, helpers) {
          const renderWrapperNames = [];
          function detectRenderWrapper(node) {
              const innerFunction = (0, node_utils_1.getInnermostReturningFunction)(context, node);
              if (innerFunction) {
                  renderWrapperNames.push((0, node_utils_1.getFunctionName)(innerFunction));
              }
          }
          function isReportableRender(node) {
              return (helpers.isRenderUtil(node) || renderWrapperNames.includes(node.name));
          }
          function reportInvalidUsage(node) {
              context.report({
                  node,
                  messageId: 'preferScreenQueries',
                  data: {
                      name: node.name,
                  },
              });
          }
          function saveSafeDestructuredQueries(node) {
              if ((0, node_utils_1.isObjectPattern)(node.id)) {
                  for (const property of node.id.properties) {
                      if ((0, node_utils_1.isProperty)(property) &&
                          utils_1.ASTUtils.isIdentifier(property.key) &&
                          helpers.isBuiltInQuery(property.key)) {
                          safeDestructuredQueries.push(property.key.name);
                      }
                  }
              }
          }
          function isIdentifierAllowed(name) {
              return ['screen', ...withinDeclaredVariables].includes(name);
          }
          const safeDestructuredQueries = [];
          const withinDeclaredVariables = [];
          return {
              VariableDeclarator(node) {
                  if (!(0, node_utils_1.isCallExpression)(node.init) ||
                      !utils_1.ASTUtils.isIdentifier(node.init.callee)) {
                      return;
                  }
                  const isComingFromValidRender = isReportableRender(node.init.callee);
                  if (!isComingFromValidRender) {
                      saveSafeDestructuredQueries(node);
                  }
                  const isWithinFunction = node.init.callee.name === 'within';
                  const usesRenderOptions = isComingFromValidRender && usesContainerOrBaseElement(node.init);
                  if (!isWithinFunction && !usesRenderOptions) {
                      return;
                  }
                  if ((0, node_utils_1.isObjectPattern)(node.id)) {
                      saveSafeDestructuredQueries(node);
                  }
                  else if (utils_1.ASTUtils.isIdentifier(node.id)) {
                      withinDeclaredVariables.push(node.id.name);
                  }
              },
              CallExpression(node) {
                  const identifierNode = (0, node_utils_1.getDeepestIdentifierNode)(node);
                  if (!identifierNode) {
                      return;
                  }
                  if (helpers.isRenderUtil(identifierNode)) {
                      detectRenderWrapper(identifierNode);
                  }
                  if (!helpers.isBuiltInQuery(identifierNode)) {
                      return;
                  }
                  if (!(0, node_utils_1.isMemberExpression)(identifierNode.parent)) {
                      const isSafeDestructuredQuery = safeDestructuredQueries.some((queryName) => queryName === identifierNode.name);
                      if (isSafeDestructuredQuery) {
                          return;
                      }
                      reportInvalidUsage(identifierNode);
                      return;
                  }
                  const memberExpressionNode = identifierNode.parent;
                  if ((0, node_utils_1.isCallExpression)(memberExpressionNode.object) &&
                      utils_1.ASTUtils.isIdentifier(memberExpressionNode.object.callee) &&
                      memberExpressionNode.object.callee.name !== 'within' &&
                      isReportableRender(memberExpressionNode.object.callee) &&
                      !usesContainerOrBaseElement(memberExpressionNode.object)) {
                      reportInvalidUsage(identifierNode);
                      return;
                  }
                  if (utils_1.ASTUtils.isIdentifier(memberExpressionNode.object) &&
                      !isIdentifierAllowed(memberExpressionNode.object.name)) {
                      reportInvalidUsage(identifierNode);
                  }
              },
          };
      },
  });
  