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

structure-rules.mddocs/

Test Structure Rules

Rules that enforce proper test organization, structure, and prevent anti-patterns in Mocha test suites.

Capabilities

No Nested Tests Rule

Prevents nested test cases which can lead to confusing test hierarchies and execution order issues.

/**
 * Disallows nested test cases within other tests
 * Prevents confusing test structure and execution issues
 */
const noNestedTestsRule = {
  meta: {
    type: 'problem',
    docs: {
      description: 'Disallow nested tests',
      url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-nested-tests.md'
    },
    schema: []
  },
  create: (context) => ESLintVisitor
};

Usage:

{
  "rules": {
    "mocha/no-nested-tests": "error"
  }
}

Examples:

// ✓ Good - flat test structure
describe('Calculator', function() {
  it('should add numbers', function() {
    assert.equal(add(1, 2), 3);
  });
  
  it('should subtract numbers', function() {
    assert.equal(subtract(5, 2), 3);
  });
});

// ✗ Bad - nested test within test
describe('Calculator', function() {
  it('should perform operations', function() {
    assert.equal(add(1, 2), 3);
    
    // Nested test - not allowed
    it('should also subtract', function() {
      assert.equal(subtract(5, 2), 3);
    });
  });
});

No Setup In Describe Rule

Prevents setup code execution directly in describe blocks, ensuring proper test isolation.

/**
 * Disallows setup code in describe blocks
 * Ensures proper test isolation and prevents side effects
 */
const noSetupInDescribeRule = {
  meta: {
    type: 'problem',
    docs: {
      description: 'Disallow setup in describe blocks',
      url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-setup-in-describe.md'
    },
    schema: []
  },
  create: (context) => ESLintVisitor
};

Usage:

{
  "rules": {
    "mocha/no-setup-in-describe": "error"
  }
}

Examples:

// ✓ Good - setup in hooks
describe('UserService', function() {
  let userService;
  
  beforeEach(function() {
    userService = new UserService();
  });
  
  it('should create user', function() {
    const user = userService.create('John');
    assert.equal(user.name, 'John');
  });
});

// ✗ Bad - setup directly in describe
describe('UserService', function() {
  const userService = new UserService(); // Setup in describe
  userService.initialize(); // Side effect in describe
  
  it('should create user', function() {
    const user = userService.create('John');
    assert.equal(user.name, 'John');
  });
});

No Hooks For Single Case Rule

Disallows hooks (before, after, beforeEach, afterEach) when there's only one test case in a suite.

/**
 * Disallows hooks for single test case suites
 * Prevents unnecessary complexity for simple test suites
 */
const noHooksForSingleCaseRule = {
  meta: {
    type: 'suggestion',
    docs: {
      description: 'Disallow hooks for a single test case',
      url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-hooks-for-single-case.md'
    },
    schema: []
  },
  create: (context) => ESLintVisitor
};

Usage:

{
  "rules": {
    "mocha/no-hooks-for-single-case": "error"
  }
}

No Sibling Hooks Rule

Prevents multiple hooks of the same type (e.g., multiple beforeEach) in the same scope.

/**
 * Disallows sibling hooks of the same type
 * Prevents confusing hook execution order
 */
const noSiblingHooksRule = {
  meta: {
    type: 'problem',
    docs: {
      description: 'Disallow sibling hooks',
      url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-sibling-hooks.md'
    },
    schema: []
  },
  create: (context) => ESLintVisitor
};

Usage:

{
  "rules": {
    "mocha/no-sibling-hooks": "error"
  }
}

Examples:

// ✓ Good - single hook of each type
describe('Service', function() {
  beforeEach(function() {
    // Setup
  });
  
  afterEach(function() {
    // Cleanup
  });
  
  it('should work', function() {
    // Test
  });
});

// ✗ Bad - multiple hooks of same type
describe('Service', function() {
  beforeEach(function() {
    // First setup
  });
  
  beforeEach(function() {
    // Second setup - not allowed
  });
  
  it('should work', function() {
    // Test
  });
});

No Top Level Hooks Rule

Disallows hooks at the top level (outside of describe blocks).

/**
 * Disallows top-level hooks outside describe blocks
 * Ensures hooks are properly scoped to test suites
 */
const noTopLevelHooksRule = {
  meta: {
    type: 'problem',
    docs: {
      description: 'Disallow top-level hooks',
      url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-top-level-hooks.md'
    },
    schema: []
  },
  create: (context) => ESLintVisitor
};

Usage:

{
  "rules": {
    "mocha/no-top-level-hooks": "error"
  }
}

No Hooks Rule

Completely disallows all hooks (before, after, beforeEach, afterEach) in test files.

/**
 * Disallows all hooks in tests
 * Enforces direct setup/teardown in test functions
 */
const noHooksRule = {
  meta: {
    type: 'suggestion',
    docs: {
      description: 'Disallow hooks',
      url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/no-hooks.md'
    },
    schema: []
  },
  create: (context) => ESLintVisitor
};

Usage:

{
  "rules": {
    "mocha/no-hooks": "error"
  }
}

Usage Examples

Comprehensive Structure Setup

{
  "rules": {
    "mocha/no-nested-tests": "error",
    "mocha/no-setup-in-describe": "error",
    "mocha/no-hooks-for-single-case": "warn",
    "mocha/no-sibling-hooks": "error",
    "mocha/no-top-level-hooks": "error",
    "mocha/no-hooks": "off"
  }
}

Strict Structure Enforcement

{
  "rules": {
    "mocha/no-nested-tests": "error",
    "mocha/no-setup-in-describe": "error",
    "mocha/no-hooks-for-single-case": "error",
    "mocha/no-sibling-hooks": "error",
    "mocha/no-top-level-hooks": "error",
    "mocha/no-hooks": "error"
  }
}

Well-Structured Test Examples

// ✓ Good - proper test structure
describe('UserService', function() {
  let userService;
  let database;
  
  before(function() {
    database = new TestDatabase();
  });
  
  beforeEach(function() {
    userService = new UserService(database);
  });
  
  afterEach(function() {
    userService.cleanup();
  });
  
  after(function() {
    database.close();
  });
  
  describe('#create', function() {
    it('should create a new user', function() {
      const user = userService.create('John', 'john@example.com');
      assert.equal(user.name, 'John');
      assert.equal(user.email, 'john@example.com');
    });
    
    it('should validate email format', function() {
      assert.throws(() => {
        userService.create('John', 'invalid-email');
      }, /Invalid email format/);
    });
  });
  
  describe('#update', function() {
    beforeEach(function() {
      userService.create('John', 'john@example.com');
    });
    
    it('should update user details', function() {
      const updated = userService.update('John', { email: 'newemail@example.com' });
      assert.equal(updated.email, 'newemail@example.com');
    });
  });
});