Rules for proper handling of asynchronous tests, callbacks, promises, and async/await patterns in Mocha test suites.
Enforces proper handling of done callbacks in asynchronous tests to prevent hanging tests.
/**
* Enforces handling of callbacks for async tests
* Prevents tests from hanging when done callback is not called
*/
const handleDoneCallbackRule = {
meta: {
type: 'problem',
docs: {
description: 'Enforces handling of callbacks for async tests',
url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/handle-done-callback.md'
},
schema: [{
type: 'object',
properties: {
ignoreSkipped: {
type: 'boolean',
default: false
}
},
additionalProperties: false
}]
},
create: (context) => ESLintVisitor
};Usage:
{
"rules": {
"mocha/handle-done-callback": ["error", { "ignoreSkipped": false }]
}
}Examples:
// ✓ Good - done callback is called
it('should handle async operation', function(done) {
setTimeout(() => {
assert.equal(1, 1);
done();
}, 100);
});
// ✗ Bad - done callback is never called
it('should handle async operation', function(done) {
setTimeout(() => {
assert.equal(1, 1);
// Missing done() call
}, 100);
});Prevents mixing return statements with done callbacks in the same test, which causes confusing behavior.
/**
* Disallows both return statement and callback usage in the same test
* Prevents confusing async test patterns
*/
const noReturnAndCallbackRule = {
meta: {
type: 'problem',
docs: {
description: 'Disallow return statements in tests with callbacks',
url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-return-and-callback.md'
},
schema: []
},
create: (context) => ESLintVisitor
};Usage:
{
"rules": {
"mocha/no-return-and-callback": "error"
}
}Examples:
// ✓ Good - using only done callback
it('should handle async operation', function(done) {
doAsync(() => {
assert.equal(1, 1);
done();
});
});
// ✓ Good - using only return statement with promise
it('should handle async operation', function() {
return doAsync().then(result => {
assert.equal(result, 1);
});
});
// ✗ Bad - mixing return and callback
it('should handle async operation', function(done) {
return doAsync(() => {
assert.equal(1, 1);
done();
});
});Disallows return statements in async tests when using done callbacks, which can cause unexpected behavior.
/**
* Disallows return statements in async tests with done callbacks
* Prevents confusing test execution patterns
*/
const noReturnFromAsyncRule = {
meta: {
type: 'problem',
docs: {
description: 'Disallow return statements in tests with done callback',
url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-return-from-async.md'
},
schema: []
},
create: (context) => ESLintVisitor
};Usage:
{
"rules": {
"mocha/no-return-from-async": "error"
}
}Disallows synchronous tests when async testing is expected, enforcing consistent async patterns.
/**
* Disallows synchronous tests
* Enforces consistent async test patterns
*/
const noSynchronousTestsRule = {
meta: {
type: 'suggestion',
docs: {
description: 'Disallow synchronous tests',
url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-synchronous-tests.md'
},
schema: []
},
create: (context) => ESLintVisitor
};Usage:
{
"rules": {
"mocha/no-synchronous-tests": "error"
}
}Examples:
// ✓ Good - async test with done callback
it('should handle operation', function(done) {
doSomething(done);
});
// ✓ Good - async test with promise return
it('should handle operation', function() {
return doSomethingAsync();
});
// ✓ Good - async test with async/await
it('should handle operation', async function() {
await doSomethingAsync();
});
// ✗ Bad - synchronous test
it('should handle operation', function() {
const result = doSomething();
assert.equal(result, 1);
});{
"rules": {
"mocha/handle-done-callback": "error",
"mocha/no-return-and-callback": "error",
"mocha/no-return-from-async": "error",
"mocha/no-synchronous-tests": "off"
}
}{
"rules": {
"mocha/handle-done-callback": ["error", { "ignoreSkipped": true }],
"mocha/no-return-and-callback": "error",
"mocha/no-return-from-async": "error",
"mocha/no-synchronous-tests": "error"
}
}// Promise-based async test
it('should resolve promise', function() {
return fetchData().then(data => {
expect(data).to.exist;
});
});
// Async/await pattern
it('should handle async operation', async function() {
const result = await processData();
expect(result).to.equal('processed');
});
// Callback-based async test
it('should handle callback', function(done) {
processWithCallback((err, result) => {
if (err) return done(err);
expect(result).to.be.ok;
done();
});
});
// Error handling with done callback
it('should handle errors', function(done) {
processWithCallback((err, result) => {
expect(err).to.be.null;
expect(result).to.exist;
done();
});
});