render-result-naming-convention.js 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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 = 'render-result-naming-convention';
  8. const ALLOWED_VAR_NAMES = ['view', 'utils'];
  9. const ALLOWED_VAR_NAMES_TEXT = ALLOWED_VAR_NAMES.map((name) => `\`${name}\``)
  10. .join(', ')
  11. .replace(/, ([^,]*)$/, ', or $1');
  12. exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
  13. name: exports.RULE_NAME,
  14. meta: {
  15. type: 'suggestion',
  16. docs: {
  17. description: 'Enforce a valid naming for return value from `render`',
  18. recommendedConfig: {
  19. dom: false,
  20. angular: 'error',
  21. react: 'error',
  22. vue: 'error',
  23. marko: 'error',
  24. },
  25. },
  26. messages: {
  27. renderResultNamingConvention: `\`{{ renderResultName }}\` is not a recommended name for \`render\` returned value. Instead, you should destructure it, or name it using one of: ${ALLOWED_VAR_NAMES_TEXT}`,
  28. },
  29. schema: [],
  30. },
  31. defaultOptions: [],
  32. create(context, _, helpers) {
  33. const renderWrapperNames = [];
  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. return {
  41. CallExpression(node) {
  42. const callExpressionIdentifier = (0, node_utils_1.getDeepestIdentifierNode)(node);
  43. if (!callExpressionIdentifier) {
  44. return;
  45. }
  46. if (helpers.isRenderUtil(callExpressionIdentifier)) {
  47. detectRenderWrapper(callExpressionIdentifier);
  48. }
  49. },
  50. VariableDeclarator(node) {
  51. if (!node.init) {
  52. return;
  53. }
  54. const initIdentifierNode = (0, node_utils_1.getDeepestIdentifierNode)(node.init);
  55. if (!initIdentifierNode) {
  56. return;
  57. }
  58. if (!helpers.isRenderVariableDeclarator(node) &&
  59. !renderWrapperNames.includes(initIdentifierNode.name)) {
  60. return;
  61. }
  62. if ((0, node_utils_1.isObjectPattern)(node.id)) {
  63. return;
  64. }
  65. const renderResultName = utils_1.ASTUtils.isIdentifier(node.id) && node.id.name;
  66. if (!renderResultName) {
  67. return;
  68. }
  69. const isAllowedRenderResultName = ALLOWED_VAR_NAMES.includes(renderResultName);
  70. if (isAllowedRenderResultName) {
  71. return;
  72. }
  73. context.report({
  74. node,
  75. messageId: 'renderResultNamingConvention',
  76. data: {
  77. renderResultName,
  78. },
  79. });
  80. },
  81. };
  82. },
  83. });