123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.default = void 0;
- var _experimentalUtils = require("@typescript-eslint/experimental-utils");
- var _utils = require("./utils");
- const trimFXprefix = word => ['f', 'x'].includes(word.charAt(0)) ? word.substr(1) : word;
- const doesBinaryExpressionContainStringNode = binaryExp => {
- if ((0, _utils.isStringNode)(binaryExp.right)) {
- return true;
- }
- if (binaryExp.left.type === _experimentalUtils.AST_NODE_TYPES.BinaryExpression) {
- return doesBinaryExpressionContainStringNode(binaryExp.left);
- }
- return (0, _utils.isStringNode)(binaryExp.left);
- };
- const quoteStringValue = node => node.type === _experimentalUtils.AST_NODE_TYPES.TemplateLiteral ? `\`${node.quasis[0].value.raw}\`` : node.raw;
- const compileMatcherPattern = matcherMaybeWithMessage => {
- const [matcher, message] = Array.isArray(matcherMaybeWithMessage) ? matcherMaybeWithMessage : [matcherMaybeWithMessage];
- return [new RegExp(matcher, 'u'), message];
- };
- const compileMatcherPatterns = matchers => {
- if (typeof matchers === 'string' || Array.isArray(matchers)) {
- const compiledMatcher = compileMatcherPattern(matchers);
- return {
- describe: compiledMatcher,
- test: compiledMatcher,
- it: compiledMatcher
- };
- }
- return {
- describe: matchers.describe ? compileMatcherPattern(matchers.describe) : null,
- test: matchers.test ? compileMatcherPattern(matchers.test) : null,
- it: matchers.it ? compileMatcherPattern(matchers.it) : null
- };
- };
- const MatcherAndMessageSchema = {
- type: 'array',
- items: {
- type: 'string'
- },
- minItems: 1,
- maxItems: 2,
- additionalItems: false
- };
- var _default = (0, _utils.createRule)({
- name: __filename,
- meta: {
- docs: {
- category: 'Best Practices',
- description: 'Enforce valid titles',
- recommended: 'error'
- },
- messages: {
- titleMustBeString: 'Title must be a string',
- emptyTitle: '{{ jestFunctionName }} should not have an empty title',
- duplicatePrefix: 'should not have duplicate prefix',
- accidentalSpace: 'should not have leading or trailing spaces',
- disallowedWord: '"{{ word }}" is not allowed in test titles.',
- mustNotMatch: '{{ jestFunctionName }} should not match {{ pattern }}',
- mustMatch: '{{ jestFunctionName }} should match {{ pattern }}',
- mustNotMatchCustom: '{{ message }}',
- mustMatchCustom: '{{ message }}'
- },
- type: 'suggestion',
- schema: [{
- type: 'object',
- properties: {
- ignoreTypeOfDescribeName: {
- type: 'boolean',
- default: false
- },
- disallowedWords: {
- type: 'array',
- items: {
- type: 'string'
- }
- }
- },
- patternProperties: {
- [/^must(?:Not)?Match$/u.source]: {
- oneOf: [{
- type: 'string'
- }, MatcherAndMessageSchema, {
- type: 'object',
- propertyNames: {
- enum: ['describe', 'test', 'it']
- },
- additionalProperties: {
- oneOf: [{
- type: 'string'
- }, MatcherAndMessageSchema]
- }
- }]
- }
- },
- additionalProperties: false
- }],
- fixable: 'code'
- },
- defaultOptions: [{
- ignoreTypeOfDescribeName: false,
- disallowedWords: []
- }],
- create(context, [{
- ignoreTypeOfDescribeName,
- disallowedWords = [],
- mustNotMatch,
- mustMatch
- }]) {
- const disallowedWordsRegexp = new RegExp(`\\b(${disallowedWords.join('|')})\\b`, 'iu');
- const mustNotMatchPatterns = compileMatcherPatterns(mustNotMatch !== null && mustNotMatch !== void 0 ? mustNotMatch : {});
- const mustMatchPatterns = compileMatcherPatterns(mustMatch !== null && mustMatch !== void 0 ? mustMatch : {});
- return {
- CallExpression(node) {
- var _mustNotMatchPatterns, _mustMatchPatterns$je;
- if (!(0, _utils.isDescribeCall)(node) && !(0, _utils.isTestCaseCall)(node)) {
- return;
- }
- const [argument] = node.arguments;
- if (!argument) {
- return;
- }
- if (!(0, _utils.isStringNode)(argument)) {
- if (argument.type === _experimentalUtils.AST_NODE_TYPES.BinaryExpression && doesBinaryExpressionContainStringNode(argument)) {
- return;
- }
- if (argument.type !== _experimentalUtils.AST_NODE_TYPES.TemplateLiteral && !(ignoreTypeOfDescribeName && (0, _utils.isDescribeCall)(node))) {
- context.report({
- messageId: 'titleMustBeString',
- loc: argument.loc
- });
- }
- return;
- }
- const title = (0, _utils.getStringValue)(argument);
- if (!title) {
- context.report({
- messageId: 'emptyTitle',
- data: {
- jestFunctionName: (0, _utils.isDescribeCall)(node) ? _utils.DescribeAlias.describe : _utils.TestCaseName.test
- },
- node
- });
- return;
- }
- if (disallowedWords.length > 0) {
- const disallowedMatch = disallowedWordsRegexp.exec(title);
- if (disallowedMatch) {
- context.report({
- data: {
- word: disallowedMatch[1]
- },
- messageId: 'disallowedWord',
- node: argument
- });
- return;
- }
- }
- if (title.trim().length !== title.length) {
- context.report({
- messageId: 'accidentalSpace',
- node: argument,
- fix: fixer => [fixer.replaceTextRange(argument.range, quoteStringValue(argument).replace(/^([`'"]) +?/u, '$1').replace(/ +?([`'"])$/u, '$1'))]
- });
- }
- const nodeName = trimFXprefix((0, _utils.getNodeName)(node));
- const [firstWord] = title.split(' ');
- if (firstWord.toLowerCase() === nodeName) {
- context.report({
- messageId: 'duplicatePrefix',
- node: argument,
- fix: fixer => [fixer.replaceTextRange(argument.range, quoteStringValue(argument).replace(/^([`'"]).+? /u, '$1'))]
- });
- }
- const [jestFunctionName] = nodeName.split('.');
- const [mustNotMatchPattern, mustNotMatchMessage] = (_mustNotMatchPatterns = mustNotMatchPatterns[jestFunctionName]) !== null && _mustNotMatchPatterns !== void 0 ? _mustNotMatchPatterns : [];
- if (mustNotMatchPattern) {
- if (mustNotMatchPattern.test(title)) {
- context.report({
- messageId: mustNotMatchMessage ? 'mustNotMatchCustom' : 'mustNotMatch',
- node: argument,
- data: {
- jestFunctionName,
- pattern: mustNotMatchPattern,
- message: mustNotMatchMessage
- }
- });
- return;
- }
- }
- const [mustMatchPattern, mustMatchMessage] = (_mustMatchPatterns$je = mustMatchPatterns[jestFunctionName]) !== null && _mustMatchPatterns$je !== void 0 ? _mustMatchPatterns$je : [];
- if (mustMatchPattern) {
- if (!mustMatchPattern.test(title)) {
- context.report({
- messageId: mustMatchMessage ? 'mustMatchCustom' : 'mustMatch',
- node: argument,
- data: {
- jestFunctionName,
- pattern: mustMatchPattern,
- message: mustMatchMessage
- }
- });
- return;
- }
- }
- }
- };
- }
- });
- exports.default = _default;
|