smelly-detector
Advanced tools
Comparing version 0.0.11 to 0.0.12
@@ -78,2 +78,3 @@ "use strict"; | ||
} | ||
const emptyDescribe = this.findEmptyDescribes(ast); | ||
const result = ifs.concat(forOfs) | ||
@@ -84,3 +85,4 @@ .concat(forIns) | ||
.concat(consoles) | ||
.concat(jestMockSmells); | ||
.concat(jestMockSmells) | ||
.concat(emptyDescribe); | ||
return result; | ||
@@ -162,4 +164,27 @@ } | ||
} | ||
findEmptyDescribes(sourceFile) { | ||
const emptyDescribes = []; | ||
function traverse(node) { | ||
if (ts.isCallExpression(node)) { | ||
const expression = node.expression; | ||
const isDescribeCall = ts.isIdentifier(expression) && expression.text === 'describe'; | ||
if (isDescribeCall && node.arguments.length === 2) { | ||
const secondArg = node.arguments[1]; | ||
if (ts.isArrowFunction(secondArg) || ts.isFunctionExpression(secondArg)) { | ||
const body = secondArg.body; | ||
if (ts.isBlock(body) && body.statements.length === 0) { | ||
const { line, character: startAt } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); | ||
const { line: lineEnd, character: endsAt } = sourceFile.getLineAndCharacterOfPosition(node.getEnd()); | ||
emptyDescribes.push(smells_builder_1.SmellsBuilder.emptyDescribe(line + 1, lineEnd + 1, startAt, endsAt)); | ||
} | ||
} | ||
} | ||
} | ||
ts.forEachChild(node, traverse); | ||
} | ||
traverse(sourceFile); | ||
return emptyDescribes; | ||
} | ||
} | ||
exports.TypescriptSmells = TypescriptSmells; | ||
//# sourceMappingURL=TypescriptSmells.js.map |
@@ -83,4 +83,15 @@ "use strict"; | ||
} | ||
static emptyDescribe(lineStart, lineEnd, startAt, endsAt) { | ||
return { | ||
type: types_1.SmellType.emptyDescribe, | ||
lineStart, | ||
lineEnd, | ||
startAt, | ||
endsAt, | ||
description: 'Smelly: avoid empty test cases.', | ||
diagnostic: 'Smelly: avoid empty test cases.', | ||
}; | ||
} | ||
} | ||
exports.SmellsBuilder = SmellsBuilder; | ||
//# sourceMappingURL=smells-builder.js.map |
@@ -50,6 +50,8 @@ "use strict"; | ||
testCases.push(...this.findItSkipCalls(ast)); | ||
const smells = new TypescriptSmells_1.TypescriptSmells(ast).searchSmells(); | ||
const smellsList = { | ||
fileName: this.fileName, | ||
fileContent: this.code, | ||
smells: new TypescriptSmells_1.TypescriptSmells(ast).searchSmells(), language | ||
smells, | ||
language | ||
}; | ||
@@ -56,0 +58,0 @@ return { smellsList, testCases }; |
@@ -18,3 +18,4 @@ "use strict"; | ||
SmellType["jestMock"] = "excessive-jest-mock"; | ||
SmellType["emptyDescribe"] = "empty-describe"; | ||
})(SmellType || (exports.SmellType = SmellType = {})); | ||
//# sourceMappingURL=types.js.map |
{ | ||
"name": "smelly-detector", | ||
"private": false, | ||
"version": "0.0.11", | ||
"version": "0.0.12", | ||
"main": "build/src/index.js", | ||
@@ -6,0 +6,0 @@ "description": "Find out the smells in your tests, suggestions for correction and the theory behind them", |
@@ -6,2 +6,3 @@ import * as ts from 'typescript'; | ||
export class TypescriptSmells implements SmellsFinder { | ||
@@ -114,2 +115,4 @@ | ||
const emptyDescribe = this.findEmptyDescribes(ast); | ||
const result = ifs.concat(forOfs) | ||
@@ -120,3 +123,4 @@ .concat(forIns) | ||
.concat(consoles) | ||
.concat(jestMockSmells); | ||
.concat(jestMockSmells) | ||
.concat(emptyDescribe); | ||
return result; | ||
@@ -221,2 +225,34 @@ } | ||
} | ||
private findEmptyDescribes(sourceFile: ts.SourceFile): Smell[] { | ||
const emptyDescribes: Smell[] = []; | ||
function traverse(node: ts.Node) { | ||
if (ts.isCallExpression(node)) { | ||
const expression = node.expression; | ||
const isDescribeCall = ts.isIdentifier(expression) && expression.text === 'describe'; | ||
if (isDescribeCall && node.arguments.length === 2) { | ||
const secondArg = node.arguments[1]; | ||
if (ts.isArrowFunction(secondArg) || ts.isFunctionExpression(secondArg)) { | ||
const body = secondArg.body; | ||
if (ts.isBlock(body) && body.statements.length === 0) { | ||
const { line, character: startAt } = sourceFile.getLineAndCharacterOfPosition(node.getStart()); | ||
const { line: lineEnd, character: endsAt } = sourceFile.getLineAndCharacterOfPosition(node.getEnd()); | ||
emptyDescribes.push(SmellsBuilder.emptyDescribe( | ||
line + 1, | ||
lineEnd + 1, | ||
startAt, | ||
endsAt, | ||
)); | ||
} | ||
} | ||
} | ||
} | ||
ts.forEachChild(node, traverse); | ||
} | ||
traverse(sourceFile); | ||
return emptyDescribes; | ||
} | ||
} |
@@ -121,4 +121,21 @@ import { Smell, SmellType } from "./types"; | ||
}; | ||
} | ||
public static emptyDescribe( | ||
lineStart: number, | ||
lineEnd: number, | ||
startAt: number, | ||
endsAt: number | ||
): Smell { | ||
return { | ||
type: SmellType.emptyDescribe, | ||
lineStart, | ||
lineEnd, | ||
startAt, | ||
endsAt, | ||
description: 'Smelly: avoid empty test cases.', | ||
diagnostic: 'Smelly: avoid empty test cases.', | ||
}; | ||
} | ||
} |
@@ -29,7 +29,11 @@ import * as ts from 'typescript'; | ||
const smells = new TypescriptSmells(ast).searchSmells(); | ||
const smellsList = { | ||
fileName: this.fileName, | ||
fileContent: this.code, | ||
smells: new TypescriptSmells(ast).searchSmells(), language | ||
smells, | ||
language | ||
}; | ||
return { smellsList, testCases }; | ||
@@ -36,0 +40,0 @@ } |
@@ -51,2 +51,3 @@ export type TestCase = { | ||
jestMock = "excessive-jest-mock", | ||
emptyDescribe = "empty-describe", | ||
} |
@@ -11,2 +11,3 @@ import { SmellDetector } from "../src"; | ||
export const MOCKERY = 'excessive-jest-mock'; | ||
export const EMPTY_DESCRIBE = 'empty-describe'; | ||
@@ -13,0 +14,0 @@ export const JAVASCRIPT_FILE = 'javascript.js'; |
import { describe, expect, test } from 'vitest'; | ||
import { CONSOLE, FOR, FOR_IN, FOR_OF, IF_STATEMENT, MOCKERY, smellDetectorInstance, TIMEOUT, totalTestCaseDetectorInstance, JAVASCRIPT_FILE, TYPESCRIPT_FILE } from './smells-detector-builder'; | ||
import { CONSOLE, FOR, FOR_IN, FOR_OF, IF_STATEMENT, MOCKERY, smellDetectorInstance, TIMEOUT, totalTestCaseDetectorInstance, JAVASCRIPT_FILE, TYPESCRIPT_FILE, EMPTY_DESCRIBE } from './smells-detector-builder'; | ||
@@ -361,5 +361,17 @@ describe('Smelly Test Smell Detection Suite', () => { | ||
diagnostic: `Smelly: Avoid mocking too many dependencies in the test file. Split the test cases to distribute the mocking load.`, | ||
}], | ||
[{ | ||
code: `describe('test', () => {})`, | ||
fileName: JAVASCRIPT_FILE, | ||
index: 0, | ||
type: EMPTY_DESCRIBE, | ||
lineStart: 1, | ||
lineEnd: 1, | ||
startAt: 0, | ||
endsAt: 26, | ||
total: 1, | ||
description: `Smelly: avoid empty test cases.`, | ||
diagnostic: `Smelly: avoid empty test cases.`, | ||
}] | ||
])(`detect test smell for %s %s: type %s %s at index %s`, ({ code, fileName, index, type, lineStart, lineEnd, startAt, endsAt, total, description, diagnostic }) => { | ||
test(`should find ${total} test smells`, () => { | ||
@@ -366,0 +378,0 @@ const result = smellDetectorInstance(code, fileName); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
176314
63
3310