Skip to content

Commit 8c1a4bc

Browse files
authored
Merge pull request #23 from codejedi365/fix-no-identical-titles
fix: `no-identical-titles` edge cases
2 parents 714f8b9 + e2cc9e2 commit 8c1a4bc

File tree

4 files changed

+198
-84
lines changed

4 files changed

+198
-84
lines changed

lib/rules/no-identical-title.ts

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,51 @@
1-
import { CallExpression } from "typescript";
1+
import {
2+
AST_NODE_TYPES,
3+
CallExpression,
4+
CallExpressionArgument,
5+
Literal
6+
} from "@typescript-eslint/types/dist/ast-spec";
27
import { createRule } from "../create-rule";
38

9+
/**
10+
* Typescript type validation/conversion method
11+
* @param arg variable to type check
12+
* @returns arg as type Literal
13+
*/
14+
function isLiteral(arg: CallExpressionArgument): arg is Literal {
15+
// from ast-spec types Expression -> LiteralExpression -> Literal, all literals have attribute 'value'
16+
return arg.type === AST_NODE_TYPES.Literal;
17+
}
18+
19+
/**
20+
* Type safe method to extract possible test name of type string
21+
* Prevents user from providing invalid arg0 to `test()` which can cause eslint to crash
22+
* @param node Eslint evaluated ASTTree Node based on CallExpression[callee.name=test]
23+
* @returns string of possible test name
24+
*/
25+
function getValidTestName(node: CallExpression): string {
26+
if (!isLiteral(node.arguments[0])) {
27+
throw new Error("Not a Literal expression.");
28+
}
29+
const arg0value: Literal["value"] = node.arguments[0].value;
30+
if (
31+
arg0value === null ||
32+
Object.getPrototypeOf(arg0value) === RegExp.prototype
33+
) {
34+
throw new Error(
35+
"Unusable Literal value for test names (NullLiteral & RegExpLiteral)"
36+
);
37+
}
38+
return arg0value.toString();
39+
}
40+
441
//------------------------------------------------------------------------------
542
// Rule Definition
643
//------------------------------------------------------------------------------
7-
844
export default createRule({
945
name: __filename,
1046
defaultOptions: [],
1147
meta: {
12-
type:"problem",
48+
type: "problem",
1349
messages: {
1450
noIdenticalTitles: "Don't use identical titles for your tests"
1551
},
@@ -20,31 +56,37 @@ export default createRule({
2056
},
2157
schema: []
2258
},
23-
59+
2460
create(context) {
25-
const testTitles: {[key: string]:[any]} = {};
61+
const testTitles: { [key: string]: [CallExpression] } = {};
2662
return {
27-
["CallExpression[callee.name=test]"](node:any) {
28-
const testTitle = node.arguments[0].value as string;
29-
if(testTitle in testTitles) {
30-
testTitles[testTitle].push(node)
63+
"CallExpression[callee.name=test]": (node: CallExpression) => {
64+
let testTitle;
65+
try {
66+
testTitle = getValidTestName(node);
67+
} catch (e) {
68+
return;
69+
}
70+
if (testTitle in testTitles) {
71+
testTitles[testTitle].push(node);
3172
} else {
3273
testTitles[testTitle] = [node];
3374
}
3475
// const title = testTitles[testTitle];
3576
// testTitles[testTitle] = [title, node]
36-
3777
},
38-
["Program:exit"]() {
39-
Object.keys(testTitles).forEach(testTitle => {
40-
if(testTitles[testTitle].length > 1) {
41-
for(const testTitleNode of testTitles[testTitle]) {
42-
context.report({node: testTitleNode, messageId: "noIdenticalTitles"})
43-
44-
}
78+
"Program:exit": () => {
79+
Object.values(testTitles).forEach((nodeList) => {
80+
if (nodeList.length > 1) {
81+
nodeList.forEach((testTitleNode) => {
82+
context.report({
83+
node: testTitleNode,
84+
messageId: "noIdenticalTitles"
85+
});
86+
});
4587
}
46-
})
88+
});
4789
}
48-
}
90+
};
4991
}
5092
});

package-lock.json

Lines changed: 114 additions & 48 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@
5353
},
5454
"dependencies": {
5555
"@types/eslint": "^7.2.2",
56-
"@typescript-eslint/experimental-utils": "^4.0.1",
56+
"@typescript-eslint/experimental-utils": "^4.32.0",
57+
"@typescript-eslint/types": "^4.32.0",
5758
"requireindex": "^1.2.0"
5859
}
5960
}

0 commit comments

Comments
 (0)