no-identical-title.js 1.86 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
'use strict';

const {
  getDocsUrl,
  isDescribe,
  isTestCase,
  isString,
  hasExpressions,
  getStringValue,
} = require('./util');

const newDescribeContext = () => ({
  describeTitles: [],
  testTitles: [],
});

const handleTestCaseTitles = (context, titles, node, title) => {
  if (isTestCase(node)) {
    if (titles.indexOf(title) !== -1) {
      context.report({
        message:
          'Test title is used multiple times in the same describe block.',
        node,
      });
    }
    titles.push(title);
  }
};

const handleDescribeBlockTitles = (context, titles, node, title) => {
  if (!isDescribe(node)) {
    return;
  }
  if (titles.indexOf(title) !== -1) {
    context.report({
      message:
        'Describe block title is used multiple times in the same describe block.',
      node,
    });
  }
  titles.push(title);
};

const isFirstArgValid = arg => {
  if (!arg || !isString(arg)) {
    return false;
  }
  if (arg.type === 'TemplateLiteral' && hasExpressions(arg)) {
    return false;
  }
  return true;
};

module.exports = {
  meta: {
    docs: {
      url: getDocsUrl(__filename),
    },
  },
  create(context) {
    const contexts = [newDescribeContext()];
    return {
      CallExpression(node) {
        const currentLayer = contexts[contexts.length - 1];
        if (isDescribe(node)) {
          contexts.push(newDescribeContext());
        }
        const [firstArgument] = node.arguments;
        if (!isFirstArgValid(firstArgument)) {
          return;
        }
        const title = getStringValue(firstArgument);
        handleTestCaseTitles(context, currentLayer.testTitles, node, title);
        handleDescribeBlockTitles(
          context,
          currentLayer.describeTitles,
          node,
          title
        );
      },
      'CallExpression:exit'(node) {
        if (isDescribe(node)) {
          contexts.pop();
        }
      },
    };
  },
};