consistent-test-it.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _utils = require("@typescript-eslint/utils");
  7. var _utils2 = require("./utils");
  8. const buildFixer = (callee, nodeName, preferredTestKeyword) => fixer => [fixer.replaceText(callee.type === _utils.AST_NODE_TYPES.MemberExpression ? callee.object : callee, getPreferredNodeName(nodeName, preferredTestKeyword))];
  9. var _default = (0, _utils2.createRule)({
  10. name: __filename,
  11. meta: {
  12. docs: {
  13. category: 'Best Practices',
  14. description: 'Have control over `test` and `it` usages',
  15. recommended: false
  16. },
  17. fixable: 'code',
  18. messages: {
  19. consistentMethod: "Prefer using '{{ testKeyword }}' instead of '{{ oppositeTestKeyword }}'",
  20. consistentMethodWithinDescribe: "Prefer using '{{ testKeywordWithinDescribe }}' instead of '{{ oppositeTestKeyword }}' within describe"
  21. },
  22. schema: [{
  23. type: 'object',
  24. properties: {
  25. fn: {
  26. enum: [_utils2.TestCaseName.it, _utils2.TestCaseName.test]
  27. },
  28. withinDescribe: {
  29. enum: [_utils2.TestCaseName.it, _utils2.TestCaseName.test]
  30. }
  31. },
  32. additionalProperties: false
  33. }],
  34. type: 'suggestion'
  35. },
  36. defaultOptions: [{
  37. fn: _utils2.TestCaseName.test,
  38. withinDescribe: _utils2.TestCaseName.it
  39. }],
  40. create(context) {
  41. const configObj = context.options[0] || {};
  42. const testKeyword = configObj.fn || _utils2.TestCaseName.test;
  43. const testKeywordWithinDescribe = configObj.withinDescribe || configObj.fn || _utils2.TestCaseName.it;
  44. let describeNestingLevel = 0;
  45. return {
  46. CallExpression(node) {
  47. const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
  48. if (!jestFnCall) {
  49. return;
  50. }
  51. if (jestFnCall.type === 'describe') {
  52. describeNestingLevel++;
  53. return;
  54. }
  55. const funcNode = node.callee.type === _utils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _utils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
  56. if (jestFnCall.type === 'test' && describeNestingLevel === 0 && !jestFnCall.name.endsWith(testKeyword)) {
  57. const oppositeTestKeyword = getOppositeTestKeyword(testKeyword);
  58. context.report({
  59. messageId: 'consistentMethod',
  60. node: node.callee,
  61. data: {
  62. testKeyword,
  63. oppositeTestKeyword
  64. },
  65. fix: buildFixer(funcNode, jestFnCall.name, testKeyword)
  66. });
  67. }
  68. if (jestFnCall.type === 'test' && describeNestingLevel > 0 && !jestFnCall.name.endsWith(testKeywordWithinDescribe)) {
  69. const oppositeTestKeyword = getOppositeTestKeyword(testKeywordWithinDescribe);
  70. context.report({
  71. messageId: 'consistentMethodWithinDescribe',
  72. node: node.callee,
  73. data: {
  74. testKeywordWithinDescribe,
  75. oppositeTestKeyword
  76. },
  77. fix: buildFixer(funcNode, jestFnCall.name, testKeywordWithinDescribe)
  78. });
  79. }
  80. },
  81. 'CallExpression:exit'(node) {
  82. if ((0, _utils2.isTypeOfJestFnCall)(node, context, ['describe'])) {
  83. describeNestingLevel--;
  84. }
  85. }
  86. };
  87. }
  88. });
  89. exports.default = _default;
  90. function getPreferredNodeName(nodeName, preferredTestKeyword) {
  91. if (nodeName === _utils2.TestCaseName.fit) {
  92. return 'test.only';
  93. }
  94. return nodeName.startsWith('f') || nodeName.startsWith('x') ? nodeName.charAt(0) + preferredTestKeyword : preferredTestKeyword;
  95. }
  96. function getOppositeTestKeyword(test) {
  97. if (test === _utils2.TestCaseName.test) {
  98. return _utils2.TestCaseName.it;
  99. }
  100. return _utils2.TestCaseName.test;
  101. }