prefer-wait-for.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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 = 'prefer-wait-for';
  8. const DEPRECATED_METHODS = ['wait', 'waitForElement', 'waitForDomChange'];
  9. exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
  10. name: exports.RULE_NAME,
  11. meta: {
  12. type: 'suggestion',
  13. docs: {
  14. description: 'Use `waitFor` instead of deprecated wait methods',
  15. recommendedConfig: {
  16. dom: false,
  17. angular: false,
  18. react: false,
  19. vue: false,
  20. marko: false,
  21. },
  22. },
  23. messages: {
  24. preferWaitForMethod: '`{{ methodName }}` is deprecated in favour of `waitFor`',
  25. preferWaitForImport: 'import `waitFor` instead of deprecated async utils',
  26. preferWaitForRequire: 'require `waitFor` instead of deprecated async utils',
  27. },
  28. fixable: 'code',
  29. schema: [],
  30. },
  31. defaultOptions: [],
  32. create(context, _, helpers) {
  33. let addWaitFor = false;
  34. const reportRequire = (node) => {
  35. context.report({
  36. node,
  37. messageId: 'preferWaitForRequire',
  38. fix(fixer) {
  39. const excludedImports = [...DEPRECATED_METHODS, 'waitFor'];
  40. const newAllRequired = node.properties
  41. .filter((s) => (0, node_utils_1.isProperty)(s) &&
  42. utils_1.ASTUtils.isIdentifier(s.key) &&
  43. !excludedImports.includes(s.key.name))
  44. .map((s) => s.key.name);
  45. newAllRequired.push('waitFor');
  46. return fixer.replaceText(node, `{ ${newAllRequired.join(',')} }`);
  47. },
  48. });
  49. };
  50. const reportImport = (node) => {
  51. context.report({
  52. node,
  53. messageId: 'preferWaitForImport',
  54. fix(fixer) {
  55. const excludedImports = [...DEPRECATED_METHODS, 'waitFor'];
  56. const newImports = node.specifiers
  57. .map((specifier) => (0, node_utils_1.isImportSpecifier)(specifier) &&
  58. !excludedImports.includes(specifier.imported.name) &&
  59. specifier.imported.name)
  60. .filter(Boolean);
  61. newImports.push('waitFor');
  62. const newNode = `import { ${newImports.join(',')} } from '${node.source.value}';`;
  63. return fixer.replaceText(node, newNode);
  64. },
  65. });
  66. };
  67. const reportWait = (node) => {
  68. context.report({
  69. node,
  70. messageId: 'preferWaitForMethod',
  71. data: {
  72. methodName: node.name,
  73. },
  74. fix(fixer) {
  75. const callExpressionNode = (0, node_utils_1.findClosestCallExpressionNode)(node);
  76. if (!callExpressionNode) {
  77. return null;
  78. }
  79. const [arg] = callExpressionNode.arguments;
  80. const fixers = [];
  81. if (arg) {
  82. fixers.push(fixer.replaceText(node, 'waitFor'));
  83. if (node.name === 'waitForDomChange') {
  84. fixers.push(fixer.insertTextBefore(arg, '() => {}, '));
  85. }
  86. }
  87. else {
  88. let methodReplacement = 'waitFor(() => {})';
  89. if ((0, node_utils_1.isMemberExpression)(node.parent) &&
  90. utils_1.ASTUtils.isIdentifier(node.parent.object)) {
  91. methodReplacement = `${node.parent.object.name}.${methodReplacement}`;
  92. }
  93. const newText = methodReplacement;
  94. fixers.push(fixer.replaceText(callExpressionNode, newText));
  95. }
  96. return fixers;
  97. },
  98. });
  99. };
  100. return {
  101. 'CallExpression > MemberExpression'(node) {
  102. const isDeprecatedMethod = utils_1.ASTUtils.isIdentifier(node.property) &&
  103. DEPRECATED_METHODS.includes(node.property.name);
  104. if (!isDeprecatedMethod) {
  105. return;
  106. }
  107. if (!helpers.isNodeComingFromTestingLibrary(node)) {
  108. return;
  109. }
  110. addWaitFor = true;
  111. reportWait(node.property);
  112. },
  113. 'CallExpression > Identifier'(node) {
  114. if (!DEPRECATED_METHODS.includes(node.name)) {
  115. return;
  116. }
  117. if (!helpers.isNodeComingFromTestingLibrary(node)) {
  118. return;
  119. }
  120. addWaitFor = true;
  121. reportWait(node);
  122. },
  123. 'Program:exit'() {
  124. var _a;
  125. if (!addWaitFor) {
  126. return;
  127. }
  128. const testingLibraryNode = (_a = helpers.getCustomModuleImportNode()) !== null && _a !== void 0 ? _a : helpers.getTestingLibraryImportNode();
  129. if ((0, node_utils_1.isCallExpression)(testingLibraryNode)) {
  130. const parent = testingLibraryNode.parent;
  131. if (!(0, node_utils_1.isObjectPattern)(parent.id)) {
  132. return;
  133. }
  134. reportRequire(parent.id);
  135. }
  136. else if (testingLibraryNode) {
  137. if (testingLibraryNode.specifiers.length === 1 &&
  138. (0, node_utils_1.isImportNamespaceSpecifier)(testingLibraryNode.specifiers[0])) {
  139. return;
  140. }
  141. reportImport(testingLibraryNode);
  142. }
  143. },
  144. };
  145. },
  146. });