Skip to content

Commit

Permalink
Merge pull request #23 from codejedi365/fix-no-identical-titles
Browse files Browse the repository at this point in the history
fix: `no-identical-titles` edge cases
  • Loading branch information
codejedi365 committed Sep 29, 2021
2 parents 714f8b9 + e2cc9e2 commit 8c1a4bc
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 84 deletions.
80 changes: 61 additions & 19 deletions lib/rules/no-identical-title.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,51 @@
import { CallExpression } from "typescript";
import {
AST_NODE_TYPES,
CallExpression,
CallExpressionArgument,
Literal
} from "@typescript-eslint/types/dist/ast-spec";
import { createRule } from "../create-rule";

/**
* Typescript type validation/conversion method
* @param arg variable to type check
* @returns arg as type Literal
*/
function isLiteral(arg: CallExpressionArgument): arg is Literal {
// from ast-spec types Expression -> LiteralExpression -> Literal, all literals have attribute 'value'
return arg.type === AST_NODE_TYPES.Literal;
}

/**
* Type safe method to extract possible test name of type string
* Prevents user from providing invalid arg0 to `test()` which can cause eslint to crash
* @param node Eslint evaluated ASTTree Node based on CallExpression[callee.name=test]
* @returns string of possible test name
*/
function getValidTestName(node: CallExpression): string {
if (!isLiteral(node.arguments[0])) {
throw new Error("Not a Literal expression.");
}
const arg0value: Literal["value"] = node.arguments[0].value;
if (
arg0value === null ||
Object.getPrototypeOf(arg0value) === RegExp.prototype
) {
throw new Error(
"Unusable Literal value for test names (NullLiteral & RegExpLiteral)"
);
}
return arg0value.toString();
}

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

export default createRule({
name: __filename,
defaultOptions: [],
meta: {
type:"problem",
type: "problem",
messages: {
noIdenticalTitles: "Don't use identical titles for your tests"
},
Expand All @@ -20,31 +56,37 @@ export default createRule({
},
schema: []
},

create(context) {
const testTitles: {[key: string]:[any]} = {};
const testTitles: { [key: string]: [CallExpression] } = {};
return {
["CallExpression[callee.name=test]"](node:any) {
const testTitle = node.arguments[0].value as string;
if(testTitle in testTitles) {
testTitles[testTitle].push(node)
"CallExpression[callee.name=test]": (node: CallExpression) => {
let testTitle;
try {
testTitle = getValidTestName(node);
} catch (e) {
return;
}
if (testTitle in testTitles) {
testTitles[testTitle].push(node);
} else {
testTitles[testTitle] = [node];
}
// const title = testTitles[testTitle];
// testTitles[testTitle] = [title, node]

},
["Program:exit"]() {
Object.keys(testTitles).forEach(testTitle => {
if(testTitles[testTitle].length > 1) {
for(const testTitleNode of testTitles[testTitle]) {
context.report({node: testTitleNode, messageId: "noIdenticalTitles"})

}
"Program:exit": () => {
Object.values(testTitles).forEach((nodeList) => {
if (nodeList.length > 1) {
nodeList.forEach((testTitleNode) => {
context.report({
node: testTitleNode,
messageId: "noIdenticalTitles"
});
});
}
})
});
}
}
};
}
});
162 changes: 114 additions & 48 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@
},
"dependencies": {
"@types/eslint": "^7.2.2",
"@typescript-eslint/experimental-utils": "^4.0.1",
"@typescript-eslint/experimental-utils": "^4.32.0",
"@typescript-eslint/types": "^4.32.0",
"requireindex": "^1.2.0"
}
}

0 comments on commit 8c1a4bc

Please sign in to comment.