@snutsjs/core
v1.2.3
Published
AST-based test smell detection core for JavaScript and TypeScript projects.
Readme
@snutsjs/core
🎯 Goal
@snutsjs/core aims to be a robust and extensible static analysis tool designed to identify and report common "smells" or anti-patterns in JavaScript and TypeScript test files. By integrating with your development workflow, it helps maintain high-quality, readable, and effective test suites.
📦 Installation
npm install @snutsjs/core🚀 Library Usage (Extension-Friendly)
import { DetectorRunner, detectors } from "@snutsjs/core";
const detectorInstances = Object.values(detectors).map((DetectorClass) => new DetectorClass());
const runner = new DetectorRunner(detectorInstances);
const smells = await runner.run("/absolute/path/to/example.test.ts");
console.log(smells);👀 Runtime Watcher Entry
Use the runtime subpath when you want the side-effectful watcher behavior:
import "@snutsjs/core/runtime/watch";The root package import is side-effect free and safe for VS Code extension integration.
CLI Usage
npx @snutsjs/core watch .You can also point to a specific directory:
npx @snutsjs/core watch src📁 Project Structure
├── lib/
│ ├── ast/ # AST (Abstract Syntax Tree) related services for parsing and querying
│ │ ├── ast.service.test.ts
│ │ └── ast.service.ts
│ ├── core/ # Core logic for detector runner and file watching
│ │ ├── detector.interface.ts
│ │ ├── detector-runner.test.ts
│ │ ├── detector-runner.ts
│ │ ├── watcher.test.ts
│ │ └── watcher.ts
│ ├── detectors/ # Collection of predefined test smell detectors
│ │ ├── anonymousTestLogic.ts
│ │ ├── anonymousTestLogic.test.ts
│ │ ├── commentsOnlyTestLogic.test.ts
│ │ ├── commentsOnlyTestLogic.ts
│ │ ├── conditionalTestLogic.test.ts
│ │ ├── conditionalTestLogic.ts
│ │ ├── identicalDescriptionTestLogic.test.ts
│ │ ├── identicalDescriptionTestLogic.ts
│ │ ├── index.ts
│ │ ├── overcommentedTestLogic.test.ts
│ │ └── overcommentedTestLogic.ts
│ ├── runtime/
│ │ └── watch.ts
│ ├── shared/ # Shared utilities, constants, and plugins
│ │ ├── aliases/ # Module aliases configuration
│ │ │ └── index.ts
│ │ ├── constants.ts
│ │ ├── logger/ # Logging utility
│ │ │ └── index.ts
│ │ └── plugins/ # Plugin system for extensibility
│ │ └── index.ts
│ ├── test/ # Internal testing utilities and builders
│ │ └── builders/
│ │ └── astNodeBuilder.ts
│ └── index.ts # Main entry point for the library
├── .gitignore
├── .prettierignore
├── .prettierrc.json
├── eslint.config.js
├── jest.config.js
├── LICENSE
├── package.json
├── README.md
├── tsconfig.json
├── tsconfig.test.json
└── yarn.lockLicense
This project is licensed under the GPL-3.0 License. See the LICENSE file for details.
✨ Features
- 🔧 Static Analysis: Identifies anti-patterns in test files using AST parsing.
- 💬 Extensible Detectors: Easily add new test smell detection logic.
- 🛠️ Real-time File Watching: Monitors your codebase for changes and re-runs detectors automatically.
- 🧪 Jest Testing: Integrated testing setup for robust development.
- 💡 TypeScript Support: Built with TypeScript for type safety and improved developer experience.
- 🚀 CLI Tool: Command-line interface for easy interaction.
🔌 Core Libraries
⚛️ Core
- TypeScript: Primary language for the project.
- @babel/parser: Used for parsing JavaScript/TypeScript code into an AST.
- @babel/types: Utilities for working with Babel AST nodes.
- esquery: Powerful tool for querying ASTs with CSS-like selectors.
- chokidar: File system watcher for real-time monitoring of file changes.
- commander: Node.js command-line interfaces made easy.
🧪 Testing
- Jest: JavaScript testing framework.
- ts-jest: TypeScript preprocessor for Jest.
🚀 Getting Started
🔧 Prerequisites
To run this project, you will need:
- Node.js (recommended v18+)
- Yarn or npm as package manager
- A code editor (recommendation: Visual Studio Code)
▶️ Run Project
Clone this repository to your local machine.
Install the project dependencies:
yarn installTo start watching your files for smelly tests, run:
yarn start@snutsjs/corewill automatically watch all files in the selected directory and its subdirectories and report findings.
📚 Build and Validate
yarn lint
yarn test
yarn typecheck
yarn build
npm pack --dry-run🧾 Release Automation (Changesets)
Create a changeset:
yarn changesetVersion packages and changelog:
yarn version-packagesPublish to npm:
yarn releaseGitHub Actions workflows are configured to run CI on pull requests and publish through Changesets on merges to main.
🧑💻 Contributing
Want to contribute? Here's how you can help:
- Create a new branch for your changes:
git checkout -b feature/your-feature-name - Implement your changes and commit them with a meaningful message (e.g.,
:sparkles: feat: Your message here):git commit -m "feat: Add new detector for unused imports" - Push your branch to the remote repository:
git push origin feature/your-feature-name - Open a pull request and request a code review.
🔁 Git Workflow
Common Commands:
- Create a new branch:
git checkout -b your-branch-name - Switch to a branch:
git checkout branch-name - Commit your changes:
git commit -m "Your commit message" - Push changes to remote:
git push - Pull updates from remote:
git pull
📚 Development Setup
🧭 Path Aliases
This project uses path aliases for cleaner imports. Instead of relative paths like ../../../shared/constants, you can use:
// Before
import { MY_CONSTANT } from "../../../shared/constants";
// After
import { MY_CONSTANT } from "@/shared/constants";Path aliases are configured in:
tsconfig.json- For TypeScript resolutionbabel.config.js- For Babel transpilation (if applicable)jest.config.js- For testing with Jest
🧪 Troubleshooting
TypeScript and Aliases Issues
If VS Code or Jest doesn't recognize path aliases:
- Restart TypeScript server:
Ctrl+Shift+P→ "TypeScript: Restart TS Server" - Ensure
tsconfig.jsonhas correctbaseUrlandpathsconfigurations. - Run
yarn tsc --noEmitto verify TypeScript configuration.
File Watcher Issues
If the file watcher (chokidar) doesn't seem to be picking up changes:
- Ensure you are running
yarn startfrom the project's root directory. - Check for any system-level file watch limits (e.g.,
fs.inotify.max_user_watcheson Linux) that might be preventingchokidarfrom functioning correctly in large projects.
