ESLint plugin providing 24 rules for Mocha testing framework best practices and error detection.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Rules for consistent function style and arrow function usage in Mocha test suites.
Prevents arrow functions in Mocha tests where this context is needed for timeouts and other Mocha features.
/**
* Disallows arrow functions in Mocha tests
* Prevents issues with 'this' context binding in Mocha
*/
const noMochaArrowsRule = {
meta: {
type: 'problem',
docs: {
description: 'Disallow arrow functions as arguments to Mocha functions',
url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-mocha-arrows.md'
},
schema: []
},
create: (context) => ESLintVisitor
};Usage:
{
"rules": {
"mocha/no-mocha-arrows": "error"
}
}Examples:
// ✓ Good - regular functions that preserve 'this' context
describe('Calculator', function() {
it('should handle timeout', function() {
this.timeout(5000); // 'this' context available
// Test implementation
});
beforeEach(function() {
this.calculator = new Calculator();
});
});
// ✗ Bad - arrow functions lose 'this' context
describe('Calculator', () => { // Not allowed
it('should handle timeout', () => { // Not allowed
this.timeout(5000); // 'this' is undefined
// Test implementation
});
beforeEach(() => { // Not allowed
this.calculator = new Calculator(); // 'this' is undefined
});
});Enforces arrow functions for test callbacks when this context is not needed, promoting consistent style.
/**
* Prefers arrow functions for test callbacks
* Promotes consistent modern JavaScript style when 'this' is not needed
*/
const preferArrowCallbackRule = {
meta: {
type: 'suggestion',
docs: {
description: 'Prefer arrow function callbacks',
url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/prefer-arrow-callback.md'
},
fixable: 'code',
schema: [{
type: 'object',
properties: {
allowNamedFunctions: {
type: 'boolean',
default: false
},
allowUnboundThis: {
type: 'boolean',
default: true
}
},
additionalProperties: false
}]
},
create: (context) => ESLintVisitor
};Usage:
{
"rules": {
"mocha/prefer-arrow-callback": ["error", {
"allowNamedFunctions": false,
"allowUnboundThis": true
}]
}
}Examples:
// ✓ Good - arrow functions when 'this' not needed
describe('Calculator', function() {
it('should add numbers', () => {
const result = add(1, 2);
assert.equal(result, 3);
});
it('should subtract numbers', () => {
const result = subtract(5, 2);
assert.equal(result, 3);
});
});
// ✗ Bad - regular functions when arrow would suffice
describe('Calculator', function() {
it('should add numbers', function() { // Could be arrow function
const result = add(1, 2);
assert.equal(result, 3);
});
});
// ✓ Good - regular function when using 'this'
describe('Calculator', function() {
it('should handle timeout', function() {
this.timeout(5000); // Needs 'this' context
const result = slowOperation();
assert.equal(result, 'done');
});
});Prevents async functions in describe blocks, which can cause unexpected behavior in test execution.
/**
* Disallows async functions in describe blocks
* Prevents unexpected behavior in test suite execution
*/
const noAsyncDescribeRule = {
meta: {
type: 'problem',
docs: {
description: 'Disallow async functions passed to describe',
url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-async-describe.md'
},
schema: []
},
create: (context) => ESLintVisitor
};Usage:
{
"rules": {
"mocha/no-async-describe": "error"
}
}Examples:
// ✓ Good - regular function in describe
describe('UserService', function() {
let userService;
beforeEach(function() {
userService = new UserService();
});
it('should create user', async function() {
const user = await userService.create('John');
assert.equal(user.name, 'John');
});
});
// ✗ Bad - async function in describe
describe('UserService', async function() { // Not allowed
let userService;
beforeEach(function() {
userService = new UserService();
});
it('should create user', async function() {
const user = await userService.create('John');
assert.equal(user.name, 'John');
});
});
// ✗ Bad - async arrow in describe
describe('UserService', async () => { // Not allowed
// Tests
});{
"rules": {
"mocha/no-mocha-arrows": "error",
"mocha/prefer-arrow-callback": ["warn", {
"allowNamedFunctions": false,
"allowUnboundThis": true
}],
"mocha/no-async-describe": "error"
}
}{
"rules": {
"mocha/no-mocha-arrows": "error",
"mocha/prefer-arrow-callback": "off",
"mocha/no-async-describe": "error"
}
}{
"rules": {
"mocha/no-mocha-arrows": "warn",
"mocha/prefer-arrow-callback": ["error", {
"allowNamedFunctions": true,
"allowUnboundThis": false
}],
"mocha/no-async-describe": "error"
}
}// ✓ Best practices - mixed approach based on context
// Use regular functions for describe blocks
describe('UserService', function() {
let userService;
// Use regular functions when you need 'this' context
beforeEach(function() {
this.timeout(10000);
userService = new UserService();
});
// Use arrow functions for simple tests without 'this'
it('should create user with valid data', () => {
const user = userService.create('John', 'john@example.com');
assert.equal(user.name, 'John');
assert.equal(user.email, 'john@example.com');
});
// Use regular functions for async tests with 'this'
it('should handle slow operations', function() {
this.timeout(30000);
return userService.slowOperation().then(result => {
assert.equal(result.status, 'completed');
});
});
// Use async functions for async/await patterns
it('should handle async operations', async () => {
const result = await userService.asyncOperation();
assert.equal(result.success, true);
});
// Use regular functions with done callback
it('should handle callback-based async', function(done) {
userService.callbackOperation((err, result) => {
if (err) return done(err);
assert.equal(result.status, 'ok');
done();
});
});
});
// Nested describe blocks - regular functions
describe('UserService', function() {
describe('#create', function() {
it('should validate input', () => {
assert.throws(() => userService.create(''), /Name required/);
});
});
describe('#update', function() {
beforeEach(function() {
this.existingUser = userService.create('John', 'john@example.com');
});
it('should update user properties', () => {
const updated = userService.update(this.existingUser.id, {
email: 'newemail@example.com'
});
assert.equal(updated.email, 'newemail@example.com');
});
});
});