UNPKG

1.84 kBJavaScriptView Raw
1'use strict';
2
3const {isDeepStrictEqual} = require('node:util');
4const espurify = require('espurify');
5const {visitIf} = require('enhance-visitors');
6const util = require('../util');
7const createAvaRule = require('../create-ava-rule');
8
9const purify = node => node && espurify(node);
10
11const isStaticTemplateLiteral = node => node.expressions.every(expression => isStatic(expression));
12
13const isStatic = node => node.type === 'Literal'
14 || (node.type === 'TemplateLiteral' && isStaticTemplateLiteral(node))
15 || (node.type === 'BinaryExpression' && isStatic(node.left) && isStatic(node.right));
16
17function isTitleUsed(usedTitleNodes, titleNode) {
18 const purifiedNode = purify(titleNode);
19 return usedTitleNodes.some(usedTitle => isDeepStrictEqual(purifiedNode, usedTitle));
20}
21
22const create = context => {
23 const ava = createAvaRule();
24 let usedTitleNodes = [];
25
26 return ava.merge({
27 CallExpression: visitIf([
28 ava.isInTestFile,
29 ava.isTestNode,
30 ava.hasNoUtilityModifier,
31 ])(node => {
32 const arguments_ = node.arguments;
33 const titleNode = arguments_.length > 1 || ava.hasTestModifier('todo') ? arguments_[0] : undefined;
34
35 // Don't flag computed titles
36 if (!titleNode || !isStatic(titleNode)) {
37 return;
38 }
39
40 // Don't flag what look to be macros
41 if (arguments_.length > 2 && !util.isFunctionExpression(arguments_[1])) {
42 return;
43 }
44
45 if (isTitleUsed(usedTitleNodes, titleNode)) {
46 context.report({
47 node: titleNode,
48 message: 'Test title is used multiple times in the same file.',
49 });
50 return;
51 }
52
53 usedTitleNodes.push(purify(titleNode));
54 }),
55 'Program:exit'() {
56 usedTitleNodes = [];
57 },
58 });
59};
60
61module.exports = {
62 create,
63 meta: {
64 type: 'problem',
65 docs: {
66 description: 'Ensure no tests have the same title.',
67 url: util.getDocsUrl(__filename),
68 },
69 schema: [],
70 },
71};