or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

async-rules.mdconfigurations.mdexecution-rules.mdindex.mdquality-rules.mdsettings.mdstructure-rules.mdstyle-rules.md
tile.json

style-rules.mddocs/

Function Style Rules

Rules for consistent function style and arrow function usage in Mocha test suites.

Capabilities

No Mocha Arrows Rule

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
  });
});

Prefer Arrow Callback Rule

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');
  });
});

No Async Describe Rule

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
});

Usage Examples

Comprehensive Style Setup

{
  "rules": {
    "mocha/no-mocha-arrows": "error",
    "mocha/prefer-arrow-callback": ["warn", {
      "allowNamedFunctions": false,
      "allowUnboundThis": true
    }],
    "mocha/no-async-describe": "error"
  }
}

Strict Arrow Function Policy

{
  "rules": {
    "mocha/no-mocha-arrows": "error",
    "mocha/prefer-arrow-callback": "off",
    "mocha/no-async-describe": "error"
  }
}

Modern JavaScript Style

{
  "rules": {
    "mocha/no-mocha-arrows": "warn",
    "mocha/prefer-arrow-callback": ["error", {
      "allowNamedFunctions": true,
      "allowUnboundThis": false
    }],
    "mocha/no-async-describe": "error"
  }
}

Function Style Examples

// ✓ 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');
    });
  });
});