Skip to content

Commit bf6ff5f

Browse files
committed
feat: add description and explanation to each smell
1 parent eb9f436 commit bf6ff5f

12 files changed

+86
-0
lines changed

lib/core/detector-runner.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,17 @@ describe("DetectorRunner", () => {
5151
end: { line: 1, column: 5 },
5252
message: "Smell 1",
5353
codeBlock: "const",
54+
description: "Mock Smell 1",
55+
explanation: "Explanation for mock smell 1.",
5456
};
5557
const mockSmell2: Smell = {
5658
file: mockFilePath,
5759
start: { line: 2, column: 0 },
5860
end: { line: 2, column: 5 },
5961
message: "Smell 2",
6062
codeBlock: "a = 1",
63+
description: "Mock Smell 2",
64+
explanation: "Explanation for mock smell 2.",
6165
};
6266

6367
const mockDetector1: Detector = {

lib/core/detector.interface.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ export interface Smell {
1212
};
1313
message: string;
1414
codeBlock: string;
15+
description: string;
16+
explanation: string;
1517
}
1618

1719
export interface Detector {

lib/core/watcher.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ describe("Watcher", () => {
168168
end: { line: 1, column: 10 },
169169
message: "Smell detected",
170170
codeBlock: "if (true) {}",
171+
description: "Mock Smell",
172+
explanation: "Explanation for mock smell.",
171173
};
172174
const mockRun = jest.fn<() => Promise<Smell[]>>().mockResolvedValue([mockSmell]);
173175
(DetectorRunner as jest.Mock).mockImplementation(() => ({

lib/detectors/anonymousTestLogic.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Detector, Smell } from "@/core/detector.interface";
44
import astService from "@/ast/ast.service";
55
import { logger } from "@/shared/logger";
66
import { jestTestAliases } from "@/shared/aliases";
7+
import { SMELL_DESCRIPTIONS } from "@/shared/smell-descriptions";
78

89
const MINIMUM_WORDS_THRESHOLD = 2;
910

@@ -40,6 +41,8 @@ export class AnonymousTestLogicDetector implements Detector {
4041
end: { line: endLine, column: loc?.end.column ?? 0 },
4142
message: `Anonymous test case detected.`,
4243
codeBlock,
44+
description: SMELL_DESCRIPTIONS.AnonymousTest.description,
45+
explanation: SMELL_DESCRIPTIONS.AnonymousTest.explanation,
4346
});
4447
}
4548
}

lib/detectors/commentsOnlyTestLogic.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Detector, Smell } from "@/core/detector.interface";
44
import astService from "@/ast/ast.service";
55
import { logger } from "@/shared/logger";
66
import { jestTestAliases } from "@/shared/aliases";
7+
import { SMELL_DESCRIPTIONS } from "@/shared/smell-descriptions";
78

89
export class CommentsOnlyLogicTestDetector implements Detector {
910
/**
@@ -36,6 +37,8 @@ export class CommentsOnlyLogicTestDetector implements Detector {
3637
end: { line: endLine, column: loc?.end.column ?? 0 },
3738
message: `Test case with only comments or empty body detected.`,
3839
codeBlock,
40+
description: SMELL_DESCRIPTIONS.CommentsOnlyTest.description,
41+
explanation: SMELL_DESCRIPTIONS.CommentsOnlyTest.explanation,
3942
});
4043
}
4144
}

lib/detectors/complexSnapshotTestLogic.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as t from "@babel/types";
33
import { Detector, Smell } from "@/core/detector.interface";
44
import astService from "@/ast/ast.service";
55
import { logger } from "@/shared/logger";
6+
import { SMELL_DESCRIPTIONS } from "@/shared/smell-descriptions";
67

78
const MAX_LINES_IN_SNAPSHOT = 50;
89

@@ -31,6 +32,8 @@ function buildSmell(
3132
message: `Complex ${kind} snapshot detected: snapshot exceeds ${MAX_LINES_IN_SNAPSHOT} lines. Consider simplifying the tested output or breaking it into smaller assertions.`,
3233
codeBlock:
3334
sourceCode.slice(node.start ?? 0, node.end ?? 0) || "// Unable to extract code snippet",
35+
description: SMELL_DESCRIPTIONS.ComplexSnapshotTest.description,
36+
explanation: SMELL_DESCRIPTIONS.ComplexSnapshotTest.explanation,
3437
};
3538
}
3639

lib/detectors/conditionalTestLogic.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Detector, Smell } from "@/core/detector.interface";
44
import astService from "@/ast/ast.service";
55
import { logger } from "@/shared/logger";
66
import { jestTestAliases } from "@/shared/aliases";
7+
import { SMELL_DESCRIPTIONS } from "@/shared/smell-descriptions";
78

89
export class ConditionalTestLogicDetector implements Detector {
910
/**
@@ -36,6 +37,8 @@ export class ConditionalTestLogicDetector implements Detector {
3637
end: { line: endLine, column: loc?.end.column ?? 0 },
3738
message: `Conditional logic inside test case detected: ${node.type}`,
3839
codeBlock,
40+
description: SMELL_DESCRIPTIONS.ConditionalTestLogic.description,
41+
explanation: SMELL_DESCRIPTIONS.ConditionalTestLogic.explanation,
3942
});
4043
}
4144
} catch (err) {

lib/detectors/generalFixtureTestLogic.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as t from "@babel/types";
33
import astService from "@/ast/ast.service";
44
import { Detector, Smell } from "@/core/detector.interface";
55
import { logger } from "@/shared/logger";
6+
import { SMELL_DESCRIPTIONS } from "@/shared/smell-descriptions";
67

78
interface SetupVariableOccurrence {
89
startLine: number;
@@ -64,6 +65,8 @@ export class GeneralFixtureTestLogicDetector implements Detector {
6465
end: { line: occurrence.endLine, column: occurrence.endColumn },
6566
message: `General fixture detected: setup variable "${variableName}" is never used in test cases.`,
6667
codeBlock,
68+
description: SMELL_DESCRIPTIONS.GeneralFixture.description,
69+
explanation: SMELL_DESCRIPTIONS.GeneralFixture.explanation,
6770
});
6871
}
6972
}

lib/detectors/identicalDescriptionTestLogic.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Detector, Smell } from "@/core/detector.interface";
44
import { logger } from "@/shared/logger";
55
import { jestTestAliases } from "@/shared/aliases";
66
import astService from "@/ast/ast.service";
7+
import { SMELL_DESCRIPTIONS } from "@/shared/smell-descriptions";
78

89
export class IdenticalDescriptionTestLogicDetector implements Detector {
910
async detect(ast: t.File, sourceCode: string, file: string): Promise<Smell[]> {
@@ -34,6 +35,8 @@ export class IdenticalDescriptionTestLogicDetector implements Detector {
3435
end: { line: endLine, column: loc?.end.column ?? 0 },
3536
message: `Identical Description test case detected.`,
3637
codeBlock,
38+
description: SMELL_DESCRIPTIONS.IdenticalDescription.description,
39+
explanation: SMELL_DESCRIPTIONS.IdenticalDescription.explanation,
3740
});
3841
}
3942
testDescriptionSet.add(testDescription);

lib/detectors/overcommentedTestLogic.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as t from "@babel/types";
33
import { Detector, Smell } from "@/core/detector.interface";
44
import astService from "@/ast/ast.service";
55
import { MAX_COMMENTS_PER_TEST } from "@/shared/constants";
6+
import { SMELL_DESCRIPTIONS } from "@/shared/smell-descriptions";
67
import { jestTestAliases } from "@/shared/aliases";
78

89
export class OvercommentedTestLogicDetector implements Detector {
@@ -31,6 +32,8 @@ export class OvercommentedTestLogicDetector implements Detector {
3132
codeBlock:
3233
sourceCode.substring(testStatement.start!, testStatement.end!) ||
3334
"// Unable to extract code snippet",
35+
description: SMELL_DESCRIPTIONS.OvercommentedTest.description,
36+
explanation: SMELL_DESCRIPTIONS.OvercommentedTest.explanation,
3437
});
3538
}
3639
}

0 commit comments

Comments
 (0)