no-container.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.RULE_NAME = void 0;
  4. const utils_1 = require("@typescript-eslint/utils");
  5. const create_testing_library_rule_1 = require("../create-testing-library-rule");
  6. const node_utils_1 = require("../node-utils");
  7. exports.RULE_NAME = 'no-container';
  8. exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
  9. name: exports.RULE_NAME,
  10. meta: {
  11. type: 'problem',
  12. docs: {
  13. description: 'Disallow the use of `container` methods',
  14. recommendedConfig: {
  15. dom: false,
  16. angular: 'error',
  17. react: 'error',
  18. vue: 'error',
  19. marko: 'error',
  20. },
  21. },
  22. messages: {
  23. noContainer: 'Avoid using container methods. Prefer using the methods from Testing Library, such as "getByRole()"',
  24. },
  25. schema: [],
  26. },
  27. defaultOptions: [],
  28. create(context, _, helpers) {
  29. const destructuredContainerPropNames = [];
  30. const renderWrapperNames = [];
  31. let renderResultVarName = null;
  32. let containerName = null;
  33. let containerCallsMethod = false;
  34. function detectRenderWrapper(node) {
  35. const innerFunction = (0, node_utils_1.getInnermostReturningFunction)(context, node);
  36. if (innerFunction) {
  37. renderWrapperNames.push((0, node_utils_1.getFunctionName)(innerFunction));
  38. }
  39. }
  40. function showErrorIfChainedContainerMethod(innerNode) {
  41. if ((0, node_utils_1.isMemberExpression)(innerNode)) {
  42. if (utils_1.ASTUtils.isIdentifier(innerNode.object)) {
  43. const isContainerName = innerNode.object.name === containerName;
  44. if (isContainerName) {
  45. context.report({
  46. node: innerNode,
  47. messageId: 'noContainer',
  48. });
  49. return;
  50. }
  51. const isRenderWrapper = innerNode.object.name === renderResultVarName;
  52. containerCallsMethod =
  53. utils_1.ASTUtils.isIdentifier(innerNode.property) &&
  54. innerNode.property.name === 'container' &&
  55. isRenderWrapper;
  56. if (containerCallsMethod) {
  57. context.report({
  58. node: innerNode.property,
  59. messageId: 'noContainer',
  60. });
  61. return;
  62. }
  63. }
  64. showErrorIfChainedContainerMethod(innerNode.object);
  65. }
  66. }
  67. return {
  68. CallExpression(node) {
  69. const callExpressionIdentifier = (0, node_utils_1.getDeepestIdentifierNode)(node);
  70. if (!callExpressionIdentifier) {
  71. return;
  72. }
  73. if (helpers.isRenderUtil(callExpressionIdentifier)) {
  74. detectRenderWrapper(callExpressionIdentifier);
  75. }
  76. if ((0, node_utils_1.isMemberExpression)(node.callee)) {
  77. showErrorIfChainedContainerMethod(node.callee);
  78. }
  79. else if (utils_1.ASTUtils.isIdentifier(node.callee) &&
  80. destructuredContainerPropNames.includes(node.callee.name)) {
  81. context.report({
  82. node,
  83. messageId: 'noContainer',
  84. });
  85. }
  86. },
  87. VariableDeclarator(node) {
  88. if (!node.init) {
  89. return;
  90. }
  91. const initIdentifierNode = (0, node_utils_1.getDeepestIdentifierNode)(node.init);
  92. if (!initIdentifierNode) {
  93. return;
  94. }
  95. const isRenderWrapperVariableDeclarator = renderWrapperNames.includes(initIdentifierNode.name);
  96. if (!helpers.isRenderVariableDeclarator(node) &&
  97. !isRenderWrapperVariableDeclarator) {
  98. return;
  99. }
  100. if ((0, node_utils_1.isObjectPattern)(node.id)) {
  101. const containerIndex = node.id.properties.findIndex((property) => (0, node_utils_1.isProperty)(property) &&
  102. utils_1.ASTUtils.isIdentifier(property.key) &&
  103. property.key.name === 'container');
  104. const nodeValue = containerIndex !== -1 && node.id.properties[containerIndex].value;
  105. if (!nodeValue) {
  106. return;
  107. }
  108. if (utils_1.ASTUtils.isIdentifier(nodeValue)) {
  109. containerName = nodeValue.name;
  110. }
  111. else if ((0, node_utils_1.isObjectPattern)(nodeValue)) {
  112. nodeValue.properties.forEach((property) => (0, node_utils_1.isProperty)(property) &&
  113. utils_1.ASTUtils.isIdentifier(property.key) &&
  114. destructuredContainerPropNames.push(property.key.name));
  115. }
  116. }
  117. else if (utils_1.ASTUtils.isIdentifier(node.id)) {
  118. renderResultVarName = node.id.name;
  119. }
  120. },
  121. };
  122. },
  123. });