diff --git a/benchmarks/measure.js b/benchmarks/measure.js index 58b8129..b8dbe88 100644 --- a/benchmarks/measure.js +++ b/benchmarks/measure.js @@ -1,24 +1,29 @@ -const os = require('node:os'); -const { performance: performanceHooks } = require('node:perf_hooks'); -const { times, median, map, prop } = require('rambda'); +import os from 'node:os'; +import { performance as performanceHooks } from 'node:perf_hooks'; +import { filter, lt as isLowerThan, map, median, prop, times } from 'rambda'; const [{ speed: cpuSpeed }] = os.cpus(); -function clearRequireCache() { - Object.keys(require.cache).forEach((key) => { - delete require.cache[key]; - }); +export { cpuSpeed }; + +export async function importFresh(modulePath) { + const cacheBuster = `${performanceHooks.now()}_${Math.random()}`; + const cacheBustingModulePath = `${modulePath}?buster=${cacheBuster}`; + + await import(cacheBustingModulePath); } -function runBenchmark(fn, count) { +const isNegative = isLowerThan(0); + +export function runSyncBenchmark(fn, count) { const results = []; times(() => { const startTime = performanceHooks.now(); - const startMemory = process.memoryUsage().rss; + const startMemory = process.memoryUsage.rss(); fn(); const endTime = performanceHooks.now(); - const endMemory = process.memoryUsage().rss; + const endMemory = process.memoryUsage.rss(); const duration = endTime - startTime; const memory = endMemory - startMemory; @@ -26,13 +31,33 @@ function runBenchmark(fn, count) { }, count); const medianDuration = median(map(prop('duration'), results)); - const medianMemory = median(map(prop('memory'), results)); + const medianMemory = median(filter(isNegative, map(prop('memory'), results))); return { medianDuration, medianMemory }; } -module.exports = { - runBenchmark, - clearRequireCache, - cpuSpeed -}; +async function measureSingleAsyncTask(fn) { + const startTime = performanceHooks.now(); + const startMemory = process.memoryUsage().rss; + await fn(); + const endTime = performanceHooks.now(); + const endMemory = process.memoryUsage().rss; + const duration = endTime - startTime; + const memory = endMemory - startMemory; + + return { duration, memory }; +} + +export async function runAsyncBenchmark(fn, count) { + const results = []; + + for (let iteration = 0; iteration < count; iteration += 1) { + const result = await measureSingleAsyncTask(fn); + results.push(result); + } + + const medianDuration = median(map(prop('duration'), results)); + const medianMemory = median(filter(isNegative, map(prop('memory'), results))); + + return { medianDuration, medianMemory }; +} diff --git a/benchmarks/runtime.bench.js b/benchmarks/runtime.bench.js index 3c899ff..17846c7 100644 --- a/benchmarks/runtime.bench.js +++ b/benchmarks/runtime.bench.js @@ -1,11 +1,8 @@ -const assert = require('node:assert'); -const { Linter } = require('eslint'); -const { times } = require('rambda'); -const { - runBenchmark, - cpuSpeed -} = require('./measure'); -const mochaPlugin = require('../'); +import { Linter } from 'eslint'; +import assert from 'node:assert'; +import { times } from 'rambda'; +import mochaPlugin from '../index.js'; +import { cpuSpeed, runSyncBenchmark } from './measure.js'; const allRules = mochaPlugin.configs.all.rules; @@ -17,6 +14,7 @@ function lintManyFilesWithAllRecommendedRules(options) { plugins: { mocha: mochaPlugin }, rules: allRules, languageOptions: { + sourceType: 'script', ecmaVersion: 2018 } }; @@ -82,10 +80,10 @@ const iterations = 50; describe('runtime', function () { it('should not take longer as the defined budget to lint many files with the recommended config', function () { - const cpuAgnosticBudget = 3_750_000; + const cpuAgnosticBudget = 3_250_000; const budget = cpuAgnosticBudget / cpuSpeed; - const { medianDuration } = runBenchmark(() => { + const { medianDuration } = runSyncBenchmark(() => { lintManyFilesWithAllRecommendedRules({ numberOfFiles: 350 }); }, iterations); @@ -93,9 +91,9 @@ describe('runtime', function () { }); it('should not consume more memory as the defined budget to lint many files with the recommended config', function () { - const budget = 2_750_000; + const budget = 1_250_000; - const { medianMemory } = runBenchmark(() => { + const { medianMemory } = runSyncBenchmark(() => { lintManyFilesWithAllRecommendedRules({ numberOfFiles: 350 }); }, iterations); diff --git a/benchmarks/startup.bench.js b/benchmarks/startup.bench.js index 2e4c982..822c2ae 100644 --- a/benchmarks/startup.bench.js +++ b/benchmarks/startup.bench.js @@ -1,27 +1,25 @@ -const assert = require('node:assert'); -const { runBenchmark, cpuSpeed, clearRequireCache } = require('./measure'); +import assert from 'node:assert'; +import { cpuSpeed, importFresh, runAsyncBenchmark } from './measure.js'; const iterations = 50; describe('startup / require time', function () { - it('should not take longer as the defined budget to require the plugin', function () { - const cpuAgnosticBudget = 85_000; + it('should not take longer as the defined budget to require the plugin', async function () { + const cpuAgnosticBudget = 20_000; const budget = cpuAgnosticBudget / cpuSpeed; - const { medianDuration } = runBenchmark(() => { - clearRequireCache(); - require('../index'); + const { medianDuration } = await runAsyncBenchmark(async () => { + await importFresh('../index.js'); }, iterations); assert.strictEqual(medianDuration < budget, true); }); - it('should not consume more memory as the defined budget', function () { - const budget = 600_000; + it('should not consume more memory as the defined budget', async function () { + const budget = 50_000; - const { medianMemory } = runBenchmark(() => { - clearRequireCache(); - require('../index'); + const { medianMemory } = await runAsyncBenchmark(async () => { + await importFresh('../index.js'); }, iterations); assert.strictEqual(medianMemory < budget, true); diff --git a/eslint.config.mjs b/eslint.config.js similarity index 94% rename from eslint.config.mjs rename to eslint.config.js index c0bad18..8b3d721 100644 --- a/eslint.config.mjs +++ b/eslint.config.js @@ -3,18 +3,11 @@ import { baseConfig } from '@enormora/eslint-config-base'; import { mochaConfig } from '@enormora/eslint-config-mocha'; import { nodeConfig, nodeConfigFileConfig, nodeEntryPointFileConfig } from '@enormora/eslint-config-node'; import eslintPluginEslintPlugin from 'eslint-plugin-eslint-plugin'; -import globals from 'globals'; export default [ { ignores: ['target/**/*'] }, - { - files: ['**/*.js', '**/*.mjs'], - languageOptions: { - globals: globals.node - } - }, baseConfig, nodeConfig, { @@ -33,6 +26,8 @@ export default [ 'import/newline-after-import': 'off', 'import/no-amd': 'off', 'import/no-commonjs': 'off', + 'import/no-useless-path-segments': 'off', + 'import/first': 'off', // incompatible with dprint '@stylistic/indent-binary-ops': 'off' @@ -40,7 +35,7 @@ export default [ }, { ...nodeConfigFileConfig, - files: ['eslint.config.mjs'] + files: ['eslint.config.js'] }, { ...mochaConfig, @@ -75,6 +70,12 @@ export default [ ...nodeEntryPointFileConfig, files: ['index.js'] }, + { + files: ['index.js'], + rules: { + 'import/no-default-export': 'off' + } + }, { files: ['lib/rules/**/*.js', 'test/rules/**/*.js'], plugins: { 'eslint-plugin': eslintPluginEslintPlugin }, diff --git a/index.js b/index.js index ae9cb4d..8538cc0 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,28 @@ -const globals = require('globals'); +import globals from 'globals'; +import { consistentSpacingBetweenBlocksRule } from './lib/rules/consistent-spacing-between-blocks.js'; +import { handleDoneCallbackRule } from './lib/rules/handle-done-callback.js'; +import { maxTopLevelSuitesRule } from './lib/rules/max-top-level-suites.js'; +import { noAsyncDescribeRule } from './lib/rules/no-async-describe.js'; +import { noEmptyDescriptionRule } from './lib/rules/no-empty-description.js'; +import { noExclusiveTestsRule } from './lib/rules/no-exclusive-tests.js'; +import { noExportsRule } from './lib/rules/no-exports.js'; +import { noGlobalTestsRule } from './lib/rules/no-global-tests.js'; +import { noHooksForSingleCaseRule } from './lib/rules/no-hooks-for-single-case.js'; +import { noHooksRule } from './lib/rules/no-hooks.js'; +import { noIdenticalTitleRule } from './lib/rules/no-identical-title.js'; +import { noMochaArrowsRule } from './lib/rules/no-mocha-arrows.js'; +import { noNestedTestsRule } from './lib/rules/no-nested-tests.js'; +import { noPendingTestsRule } from './lib/rules/no-pending-tests.js'; +import { noReturnAndCallbackRule } from './lib/rules/no-return-and-callback.js'; +import { noReturnFromAsyncRule } from './lib/rules/no-return-from-async.js'; +import { noSetupInDescribeRule } from './lib/rules/no-setup-in-describe.js'; +import { noSiblingHooksRule } from './lib/rules/no-sibling-hooks.js'; +import { noSkippedTestsRule } from './lib/rules/no-skipped-tests.js'; +import { noSynchronousTestsRule } from './lib/rules/no-synchronous-tests.js'; +import { noTopLevelHooksRule } from './lib/rules/no-top-level-hooks.js'; +import { preferArrowCallbackRule } from './lib/rules/prefer-arrow-callback.js'; +import { validSuiteDescriptionRule } from './lib/rules/valid-suite-description.js'; +import { validTestDescriptionRule } from './lib/rules/valid-test-description.js'; const allRules = { 'mocha/handle-done-callback': 'error', @@ -54,32 +78,32 @@ const recommendedRules = { 'mocha/consistent-spacing-between-blocks': 'error' }; -const mod = { +const mochaPlugin = { rules: { - 'handle-done-callback': require('./lib/rules/handle-done-callback'), - 'max-top-level-suites': require('./lib/rules/max-top-level-suites'), - 'no-async-describe': require('./lib/rules/no-async-describe'), - 'no-exclusive-tests': require('./lib/rules/no-exclusive-tests'), - 'no-exports': require('./lib/rules/no-exports'), - 'no-global-tests': require('./lib/rules/no-global-tests'), - 'no-hooks': require('./lib/rules/no-hooks'), - 'no-hooks-for-single-case': require('./lib/rules/no-hooks-for-single-case'), - 'no-identical-title': require('./lib/rules/no-identical-title'), - 'no-mocha-arrows': require('./lib/rules/no-mocha-arrows'), - 'no-nested-tests': require('./lib/rules/no-nested-tests'), - 'no-pending-tests': require('./lib/rules/no-pending-tests'), - 'no-return-and-callback': require('./lib/rules/no-return-and-callback'), - 'no-return-from-async': require('./lib/rules/no-return-from-async'), - 'no-setup-in-describe': require('./lib/rules/no-setup-in-describe'), - 'no-sibling-hooks': require('./lib/rules/no-sibling-hooks'), - 'no-skipped-tests': require('./lib/rules/no-skipped-tests'), - 'no-synchronous-tests': require('./lib/rules/no-synchronous-tests'), - 'no-top-level-hooks': require('./lib/rules/no-top-level-hooks'), - 'prefer-arrow-callback': require('./lib/rules/prefer-arrow-callback'), - 'valid-suite-description': require('./lib/rules/valid-suite-description'), - 'valid-test-description': require('./lib/rules/valid-test-description'), - 'no-empty-description': require('./lib/rules/no-empty-description.js'), - 'consistent-spacing-between-blocks': require('./lib/rules/consistent-spacing-between-blocks.js') + 'handle-done-callback': handleDoneCallbackRule, + 'max-top-level-suites': maxTopLevelSuitesRule, + 'no-async-describe': noAsyncDescribeRule, + 'no-exclusive-tests': noExclusiveTestsRule, + 'no-exports': noExportsRule, + 'no-global-tests': noGlobalTestsRule, + 'no-hooks': noHooksRule, + 'no-hooks-for-single-case': noHooksForSingleCaseRule, + 'no-identical-title': noIdenticalTitleRule, + 'no-mocha-arrows': noMochaArrowsRule, + 'no-nested-tests': noNestedTestsRule, + 'no-pending-tests': noPendingTestsRule, + 'no-return-and-callback': noReturnAndCallbackRule, + 'no-return-from-async': noReturnFromAsyncRule, + 'no-setup-in-describe': noSetupInDescribeRule, + 'no-sibling-hooks': noSiblingHooksRule, + 'no-skipped-tests': noSkippedTestsRule, + 'no-synchronous-tests': noSynchronousTestsRule, + 'no-top-level-hooks': noTopLevelHooksRule, + 'prefer-arrow-callback': preferArrowCallbackRule, + 'valid-suite-description': validSuiteDescriptionRule, + 'valid-test-description': validTestDescriptionRule, + 'no-empty-description': noEmptyDescriptionRule, + 'consistent-spacing-between-blocks': consistentSpacingBetweenBlocksRule }, configs: { all: { @@ -95,19 +119,19 @@ const mod = { } }; -mod.configs.flat = { +mochaPlugin.configs.flat = { all: { name: 'mocha/all', - plugins: { mocha: mod }, + plugins: { mocha: mochaPlugin }, languageOptions: { globals: globals.mocha }, rules: allRules }, recommended: { name: 'mocha/recommended', - plugins: { mocha: mod }, + plugins: { mocha: mochaPlugin }, languageOptions: { globals: globals.mocha }, rules: recommendedRules } }; -module.exports = mod; +export default mochaPlugin; diff --git a/lib/rules/consistent-spacing-between-blocks.js b/lib/rules/consistent-spacing-between-blocks.js index ad00dd5..21aa116 100644 --- a/lib/rules/consistent-spacing-between-blocks.js +++ b/lib/rules/consistent-spacing-between-blocks.js @@ -1,16 +1,5 @@ /* eslint "complexity": [ "error", 6 ] -- we need to refactor this file to reduce complexity */ -exports.meta = { - type: 'suggestion', - fixable: 'whitespace', - schema: [], - docs: { - description: 'Require consistent spacing between blocks', - url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/' + - 'consistent-spacing-between-blocks.md' - } -}; - // List of Mocha functions that should have a line break before them. const MOCHA_FUNCTIONS = new Set([ 'before', @@ -38,35 +27,48 @@ function isInsideDescribeBlock(node) { ); } -exports.create = function (context) { - return { - CallExpression(node) { - if ( - !MOCHA_FUNCTIONS.has(node.callee.name) || - !isInsideDescribeBlock(node) || - isFirstStatementInScope(node) - ) { - return; - } +export const consistentSpacingBetweenBlocksRule = { + meta: { + type: 'suggestion', + fixable: 'whitespace', + schema: [], + docs: { + description: 'Require consistent spacing between blocks', + url: 'https://github.com/lo1tuma/eslint-plugin-mocha/blob/main/docs/rules/' + + 'consistent-spacing-between-blocks.md' + } + }, + + create(context) { + return { + CallExpression(node) { + if ( + !MOCHA_FUNCTIONS.has(node.callee.name) || + !isInsideDescribeBlock(node) || + isFirstStatementInScope(node) + ) { + return; + } - // Retrieves the token before the current node, skipping comments. - const beforeToken = context.getSourceCode().getTokenBefore(node); + // Retrieves the token before the current node, skipping comments. + const beforeToken = context.getSourceCode().getTokenBefore(node); - // And then count the number of lines between the two. - const linesBetween = node.loc.start.line - beforeToken.loc.end.line; - const minimumAmountOfLinesBetweenNeeded = 2; - if (linesBetween < minimumAmountOfLinesBetweenNeeded) { - context.report({ - node, - message: 'Expected line break before this statement.', - fix(fixer) { - return fixer.insertTextAfter( - beforeToken, - linesBetween === 0 ? '\n\n' : '\n' - ); - } - }); + // And then count the number of lines between the two. + const linesBetween = node.loc.start.line - beforeToken.loc.end.line; + const minimumAmountOfLinesBetweenNeeded = 2; + if (linesBetween < minimumAmountOfLinesBetweenNeeded) { + context.report({ + node, + message: 'Expected line break before this statement.', + fix(fixer) { + return fixer.insertTextAfter( + beforeToken, + linesBetween === 0 ? '\n\n' : '\n' + ); + } + }); + } } - } - }; + }; + } }; diff --git a/lib/rules/handle-done-callback.js b/lib/rules/handle-done-callback.js index 70f3720..ed1c440 100644 --- a/lib/rules/handle-done-callback.js +++ b/lib/rules/handle-done-callback.js @@ -1,7 +1,7 @@ -const { find } = require('rambda'); -const createAstUtils = require('../util/ast'); +import { find } from 'rambda'; +import { createAstUtils } from '../util/ast.js'; -module.exports = { +export const handleDoneCallbackRule = { meta: { type: 'problem', docs: { diff --git a/lib/rules/max-top-level-suites.js b/lib/rules/max-top-level-suites.js index a4163dc..115cd66 100644 --- a/lib/rules/max-top-level-suites.js +++ b/lib/rules/max-top-level-suites.js @@ -3,8 +3,8 @@ * @author Alexander Afanasyev */ -const { isNil } = require('rambda'); -const createAstUtils = require('../util/ast'); +import { isNil } from 'rambda'; +import { createAstUtils } from '../util/ast.js'; const defaultSuiteLimit = 1; @@ -12,7 +12,7 @@ function isTopLevelScope(scope) { return scope.type === 'module' || scope.upper === null; } -module.exports = { +export const maxTopLevelSuitesRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/rules/no-async-describe.js b/lib/rules/no-async-describe.js index f879646..62605ff 100644 --- a/lib/rules/no-async-describe.js +++ b/lib/rules/no-async-describe.js @@ -4,9 +4,9 @@ * @fileoverview Disallow async functions as arguments to describe */ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; -module.exports = { +export const noAsyncDescribeRule = { meta: { type: 'problem', docs: { diff --git a/lib/rules/no-empty-description.js b/lib/rules/no-empty-description.js index 3667a7b..bebcff7 100644 --- a/lib/rules/no-empty-description.js +++ b/lib/rules/no-empty-description.js @@ -1,4 +1,4 @@ -const { getStringIfConstant } = require('@eslint-community/eslint-utils'); +import { getStringIfConstant } from '@eslint-community/eslint-utils'; const DEFAULT_TEST_NAMES = ['describe', 'context', 'suite', 'it', 'test', 'specify']; const ERROR_MESSAGE = 'Unexpected empty test description.'; @@ -48,7 +48,7 @@ function isValidDescriptionArgumentNode(node) { .includes(node.type); } -module.exports = { +export const noEmptyDescriptionRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/rules/no-exclusive-tests.js b/lib/rules/no-exclusive-tests.js index 8110515..6733649 100644 --- a/lib/rules/no-exclusive-tests.js +++ b/lib/rules/no-exclusive-tests.js @@ -1,6 +1,6 @@ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; -module.exports = { +export const noExclusiveTestsRule = { meta: { type: 'problem', docs: { diff --git a/lib/rules/no-exports.js b/lib/rules/no-exports.js index f01bdcf..a1dab30 100644 --- a/lib/rules/no-exports.js +++ b/lib/rules/no-exports.js @@ -1,6 +1,6 @@ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; -module.exports = { +export const noExportsRule = { meta: { docs: { description: 'Disallow exports from test files', diff --git a/lib/rules/no-global-tests.js b/lib/rules/no-global-tests.js index 27dfb8c..7639eb0 100644 --- a/lib/rules/no-global-tests.js +++ b/lib/rules/no-global-tests.js @@ -1,6 +1,6 @@ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; -module.exports = { +export const noGlobalTestsRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/rules/no-hooks-for-single-case.js b/lib/rules/no-hooks-for-single-case.js index 72c3e87..a2da77f 100644 --- a/lib/rules/no-hooks-for-single-case.js +++ b/lib/rules/no-hooks-for-single-case.js @@ -1,4 +1,4 @@ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; function newDescribeLayer(describeNode) { return { @@ -8,7 +8,7 @@ function newDescribeLayer(describeNode) { }; } -module.exports = { +export const noHooksForSingleCaseRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/rules/no-hooks.js b/lib/rules/no-hooks.js index a29e4ab..0c4fd4a 100644 --- a/lib/rules/no-hooks.js +++ b/lib/rules/no-hooks.js @@ -1,6 +1,6 @@ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; -module.exports = { +export const noHooksRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/rules/no-identical-title.js b/lib/rules/no-identical-title.js index 994024c..01c3cbb 100644 --- a/lib/rules/no-identical-title.js +++ b/lib/rules/no-identical-title.js @@ -1,4 +1,4 @@ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; function newLayer() { return { @@ -15,7 +15,7 @@ function isFirstArgLiteral(node) { ); } -module.exports = { +export const noIdenticalTitleRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/rules/no-mocha-arrows.js b/lib/rules/no-mocha-arrows.js index 71e950d..dc1dc4e 100644 --- a/lib/rules/no-mocha-arrows.js +++ b/lib/rules/no-mocha-arrows.js @@ -3,7 +3,7 @@ * @author Paul Melnikow */ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; function extractSourceTextByRange(sourceCode, start, end) { return sourceCode.text.slice(start, end).trim(); @@ -65,7 +65,7 @@ function fixArrowFunction(fixer, sourceCode, fn) { ); } -module.exports = { +export const noMochaArrowsRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/rules/no-nested-tests.js b/lib/rules/no-nested-tests.js index 9e65d19..7c94634 100644 --- a/lib/rules/no-nested-tests.js +++ b/lib/rules/no-nested-tests.js @@ -1,8 +1,8 @@ /* eslint "complexity": [ "error", 5 ] -- we need to refactor this rule to reduce the complexity */ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; -module.exports = { +export const noNestedTestsRule = { meta: { type: 'problem', docs: { diff --git a/lib/rules/no-pending-tests.js b/lib/rules/no-pending-tests.js index d76951b..bb13f52 100644 --- a/lib/rules/no-pending-tests.js +++ b/lib/rules/no-pending-tests.js @@ -1,6 +1,6 @@ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; -module.exports = { +export const noPendingTestsRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/rules/no-return-and-callback.js b/lib/rules/no-return-and-callback.js index 21b16c0..dda653b 100644 --- a/lib/rules/no-return-and-callback.js +++ b/lib/rules/no-return-and-callback.js @@ -1,4 +1,4 @@ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; function reportIfShortArrowFunction(context, node) { if (node.body.type !== 'BlockStatement') { @@ -17,7 +17,7 @@ function isFunctionCallWithName(node, name) { node.callee.name === name; } -module.exports = { +export const noReturnAndCallbackRule = { meta: { type: 'problem', docs: { diff --git a/lib/rules/no-return-from-async.js b/lib/rules/no-return-from-async.js index 1aec14d..877e719 100644 --- a/lib/rules/no-return-from-async.js +++ b/lib/rules/no-return-from-async.js @@ -1,4 +1,4 @@ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; function reportIfShortArrowFunction(context, node) { if (node.body.type !== 'BlockStatement') { @@ -11,7 +11,7 @@ function reportIfShortArrowFunction(context, node) { return false; } -module.exports = { +export const noReturnFromAsyncRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/rules/no-setup-in-describe.js b/lib/rules/no-setup-in-describe.js index 257bb4f..fdaa0cc 100644 --- a/lib/rules/no-setup-in-describe.js +++ b/lib/rules/no-setup-in-describe.js @@ -1,4 +1,4 @@ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; const FUNCTION = 1; const DESCRIBE = 2; @@ -32,7 +32,7 @@ function reportMemberExpression(context, memberExpression) { }); } -module.exports = { +export const noSetupInDescribeRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/rules/no-sibling-hooks.js b/lib/rules/no-sibling-hooks.js index 7eba21e..4439cfc 100644 --- a/lib/rules/no-sibling-hooks.js +++ b/lib/rules/no-sibling-hooks.js @@ -1,4 +1,4 @@ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; function newDescribeLayer(describeNode) { return { @@ -10,7 +10,7 @@ function newDescribeLayer(describeNode) { }; } -module.exports = { +export const noSiblingHooksRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/rules/no-skipped-tests.js b/lib/rules/no-skipped-tests.js index afe5973..0b44e6d 100644 --- a/lib/rules/no-skipped-tests.js +++ b/lib/rules/no-skipped-tests.js @@ -1,6 +1,6 @@ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; -module.exports = { +export const noSkippedTestsRule = { meta: { docs: { description: 'Disallow skipped tests', diff --git a/lib/rules/no-synchronous-tests.js b/lib/rules/no-synchronous-tests.js index d9c2ebc..2ff5797 100644 --- a/lib/rules/no-synchronous-tests.js +++ b/lib/rules/no-synchronous-tests.js @@ -1,5 +1,5 @@ -const { isNil, find } = require('rambda'); -const createAstUtils = require('../util/ast'); +import { find, isNil } from 'rambda'; +import { createAstUtils } from '../util/ast.js'; const asyncMethods = ['async', 'callback', 'promise']; @@ -37,7 +37,7 @@ function doesReturnPromise(functionExpression) { return returnStatement !== null && returnStatement !== undefined; } -module.exports = { +export const noSynchronousTestsRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/rules/no-top-level-hooks.js b/lib/rules/no-top-level-hooks.js index 0e4cbbc..c85ee90 100644 --- a/lib/rules/no-top-level-hooks.js +++ b/lib/rules/no-top-level-hooks.js @@ -1,6 +1,6 @@ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; -module.exports = { +export const noTopLevelHooksRule = { meta: { type: 'problem', docs: { diff --git a/lib/rules/prefer-arrow-callback.js b/lib/rules/prefer-arrow-callback.js index 6aad7b5..765b1fe 100644 --- a/lib/rules/prefer-arrow-callback.js +++ b/lib/rules/prefer-arrow-callback.js @@ -10,7 +10,7 @@ * @author Toru Nagashima (core eslint rule) * @author Michael Fields (mocha-aware rule modifications) */ -const createAstUtils = require('../util/ast'); +import { createAstUtils } from '../util/ast.js'; // ------------------------------------------------------------------------------ // Helpers @@ -113,7 +113,7 @@ function hasDuplicateParams(paramsList) { // Rule Definition // ------------------------------------------------------------------------------ -module.exports = { +export const preferArrowCallbackRule = { meta: { type: 'suggestion', diff --git a/lib/rules/valid-suite-description.js b/lib/rules/valid-suite-description.js index 7d0d20f..42c8f52 100644 --- a/lib/rules/valid-suite-description.js +++ b/lib/rules/valid-suite-description.js @@ -1,4 +1,4 @@ -const { getStringIfConstant } = require('@eslint-community/eslint-utils'); +import { getStringIfConstant } from '@eslint-community/eslint-utils'; /** * @fileoverview Match suite descriptions to match a pre-configured regular expression @@ -44,7 +44,7 @@ const messageSchema = { type: 'string' }; -module.exports = { +export const validSuiteDescriptionRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/rules/valid-test-description.js b/lib/rules/valid-test-description.js index 9233b5e..cf78c16 100644 --- a/lib/rules/valid-test-description.js +++ b/lib/rules/valid-test-description.js @@ -1,4 +1,4 @@ -const { getStringIfConstant } = require('@eslint-community/eslint-utils'); +import { getStringIfConstant } from '@eslint-community/eslint-utils'; /** * @fileoverview Match test descriptions to match a pre-configured regular expression @@ -43,7 +43,7 @@ const messageSchema = { type: 'string' }; -module.exports = { +export const validTestDescriptionRule = { meta: { type: 'suggestion', docs: { diff --git a/lib/util/ast.js b/lib/util/ast.js index 8d710a5..64a7622 100644 --- a/lib/util/ast.js +++ b/lib/util/ast.js @@ -1,6 +1,6 @@ -const { complement, both, isNil, propEq, pathEq, find } = require('rambda'); -const { getTestCaseNames, getSuiteNames } = require('./names'); -const { getAdditionalNames } = require('./settings'); +import { both, complement, find, isNil, pathEq, propEq } from 'rambda'; +import { getSuiteNames, getTestCaseNames } from './names.js'; +import { getAdditionalNames } from './settings.js'; const isDefined = complement(isNil); const isCallExpression = both(isDefined, propEq('CallExpression', 'type')); @@ -73,7 +73,7 @@ function isFunctionCallWithName(node, names) { } // eslint-disable-next-line max-statements -- this needs to be refactored to reduce complexity -function createAstUtils(settings) { +export function createAstUtils(settings) { const additionalCustomNames = getAdditionalNames(settings); function buildIsDescribeAnswerer(options = {}) { @@ -180,5 +180,3 @@ function createAstUtils(settings) { buildIsMochaFunctionCallAnswerer }; } - -module.exports = createAstUtils; diff --git a/lib/util/memoizeWith.js b/lib/util/memoizeWith.js index 4bb8aea..9c4e3b0 100644 --- a/lib/util/memoizeWith.js +++ b/lib/util/memoizeWith.js @@ -6,7 +6,7 @@ * @param {Function} fn The function to memoize. * @return {Function} Memoized version of `fn`. */ -const memoizeWith = (keyGen, fn) => { +export const memoizeWith = (keyGen, fn) => { const cache = new Map(); return function (...args) { @@ -19,7 +19,3 @@ const memoizeWith = (keyGen, fn) => { return cache.get(key); }; }; - -module.exports = { - memoizeWith -}; diff --git a/lib/util/names.js b/lib/util/names.js index d804bd9..080e4e2 100644 --- a/lib/util/names.js +++ b/lib/util/names.js @@ -1,20 +1,20 @@ -const { - where, +import { + allPass, + assoc, + complement, + filter, + flip, includes, intersection, - pipe, isEmpty, - complement, - flip, - filter, - over, lensProp, map, + over, + pipe, view, - assoc, - allPass -} = require('rambda'); -const { memoizeWith } = require('./memoizeWith'); + where +} from 'rambda'; +import { memoizeWith } from './memoizeWith.js'; const INTERFACES = { BDD: 'BDD', @@ -132,15 +132,10 @@ const getNamesByTypeMemoized = memoizeWith((type, options) => { return JSON.stringify({ type, options }); }, getNamesByType); -function getTestCaseNames(options) { +export function getTestCaseNames(options) { return getNamesByTypeMemoized(TYPES.testCase, options); } -function getSuiteNames(options) { +export function getSuiteNames(options) { return getNamesByTypeMemoized(TYPES.suite, options); } - -module.exports = { - getTestCaseNames, - getSuiteNames -}; diff --git a/lib/util/settings.js b/lib/util/settings.js index 46c55d5..07c6065 100644 --- a/lib/util/settings.js +++ b/lib/util/settings.js @@ -5,9 +5,7 @@ function settingFor(settings, propertyName, fallback) { return value || mochaSettings[propertyName] || fallback; } -module.exports = { - getAdditionalNames(settings) { - const additionalCustomNames = settingFor(settings, 'additionalCustomNames', []); - return additionalCustomNames; - } -}; +export function getAdditionalNames(settings) { + const additionalCustomNames = settingFor(settings, 'additionalCustomNames', []); + return additionalCustomNames; +} diff --git a/package-lock.json b/package-lock.json index e871e91..9eb1fbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "@enormora/eslint-config-mocha": "0.0.6", "@enormora/eslint-config-node": "0.0.12", "c8": "^10.1.2", + "change-case": "^5.4.4", "coveralls": "3.1.1", "dprint": "0.47.2", "eslint": "9.9.0", @@ -2886,6 +2887,12 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "dev": true + }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", diff --git a/package.json b/package.json index aa92409..c6ea17c 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "eslint-plugin-mocha", "version": "10.4.0", "description": "Eslint rules for mocha.", + "type": "module", "engines": { "node": ">=20.0.0" }, @@ -44,6 +45,7 @@ "@enormora/eslint-config-mocha": "0.0.6", "@enormora/eslint-config-node": "0.0.12", "c8": "^10.1.2", + "change-case": "^5.4.4", "coveralls": "3.1.1", "dprint": "0.47.2", "eslint": "9.9.0", diff --git a/test/index.js b/test/index.js index 180471f..f279338 100644 --- a/test/index.js +++ b/test/index.js @@ -1,9 +1,13 @@ -const assert = require('node:assert'); -const fs = require('node:fs'); -const path = require('node:path'); -const rulesDir = path.join(__dirname, '../lib/rules/'); -const documentationDir = path.join(__dirname, '../docs/rules/'); -const plugin = require('..'); +import { camelCase } from 'change-case'; +import assert from 'node:assert'; +import fs from 'node:fs'; +import path from 'node:path'; +import plugin from '../index.js'; + +const { pathname: currentFolderName } = new URL('.', import.meta.url); + +const rulesDir = path.join(currentFolderName, '../lib/rules/'); +const documentationDir = path.join(currentFolderName, '../docs/rules/'); async function determineAllRuleFiles() { const ruleFiles = await fs.promises.readdir(rulesDir); @@ -30,11 +34,14 @@ describe('eslint-plugin-mocha', function () { it('should expose all rules', async function () { const ruleFiles = await determineAllRuleFiles(); - ruleFiles.forEach(function (file) { + for (const file of ruleFiles) { const ruleName = path.basename(file, '.js'); + const importedRuleModule = await import(path.join(rulesDir, file)); + const importedRule = importedRuleModule[`${camelCase(ruleName)}Rule`]; - assert.strictEqual(plugin.rules[ruleName], require(rulesDir + ruleName)); - }); + assert.notStrictEqual(importedRule, undefined); + assert.strictEqual(plugin.rules[ruleName], importedRule); + } }); describe('documentation', function () { diff --git a/test/rules/consistent-spacing-between-blocks.js b/test/rules/consistent-spacing-between-blocks.js index b8e5680..9d806fb 100644 --- a/test/rules/consistent-spacing-between-blocks.js +++ b/test/rules/consistent-spacing-between-blocks.js @@ -1,10 +1,9 @@ -const { RuleTester } = require('eslint'); - -const rule = require('../../lib/rules/consistent-spacing-between-blocks.js'); +import { RuleTester } from 'eslint'; +import { consistentSpacingBetweenBlocksRule } from '../../lib/rules/consistent-spacing-between-blocks.js'; const ruleTester = new RuleTester({ languageOptions: { ecmaVersion: 2020, sourceType: 'script' } }); -ruleTester.run('require-spacing-between-mocha-calls', rule, { +ruleTester.run('require-spacing-between-mocha-calls', consistentSpacingBetweenBlocksRule, { valid: [ // Basic describe block `describe('My Test', () => { diff --git a/test/rules/handle-done-callback.js b/test/rules/handle-done-callback.js index 9cdc878..0983d45 100644 --- a/test/rules/handle-done-callback.js +++ b/test/rules/handle-done-callback.js @@ -1,8 +1,8 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); -ruleTester.run('handle-done-callback', rules['handle-done-callback'], { +ruleTester.run('handle-done-callback', plugin.rules['handle-done-callback'], { valid: [ 'foo(function (done) { });', 'var foo = function (done) { };', diff --git a/test/rules/max-top-level-suites.js b/test/rules/max-top-level-suites.js index b812f4e..1664b7a 100644 --- a/test/rules/max-top-level-suites.js +++ b/test/rules/max-top-level-suites.js @@ -1,8 +1,8 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); -ruleTester.run('max-top-level-suites', rules['max-top-level-suites'], { +ruleTester.run('max-top-level-suites', plugin.rules['max-top-level-suites'], { valid: [ { code: 'describe("This is a test", function () { });' diff --git a/test/rules/no-async-describe.js b/test/rules/no-async-describe.js index ec7f24b..c3b8e34 100644 --- a/test/rules/no-async-describe.js +++ b/test/rules/no-async-describe.js @@ -1,8 +1,8 @@ -const { RuleTester } = require('eslint'); -const rule = require('../../lib/rules/no-async-describe'); +import { RuleTester } from 'eslint'; +import { noAsyncDescribeRule } from '../../lib/rules/no-async-describe.js'; const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); -ruleTester.run('no-async-describe', rule, { +ruleTester.run('no-async-describe', noAsyncDescribeRule, { valid: [ 'describe()', 'describe("hello")', diff --git a/test/rules/no-empty-description.js b/test/rules/no-empty-description.js index 6e2adf9..f59dd7e 100644 --- a/test/rules/no-empty-description.js +++ b/test/rules/no-empty-description.js @@ -1,11 +1,12 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../..'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); const defaultErrorMessage = 'Unexpected empty test description.'; const firstLine = { column: 1, line: 1 }; -ruleTester.run('no-empty-description', rules['no-empty-description'], { +ruleTester.run('no-empty-description', plugin.rules['no-empty-description'], { valid: [ 'describe("some text")', 'describe.only("some text")', diff --git a/test/rules/no-exclusive-tests.js b/test/rules/no-exclusive-tests.js index e973253..3b78487 100644 --- a/test/rules/no-exclusive-tests.js +++ b/test/rules/no-exclusive-tests.js @@ -1,9 +1,10 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); const expectedErrorMessage = 'Unexpected exclusive mocha test.'; -ruleTester.run('no-exclusive-tests', rules['no-exclusive-tests'], { +ruleTester.run('no-exclusive-tests', plugin.rules['no-exclusive-tests'], { valid: [ 'describe()', 'it()', diff --git a/test/rules/no-exports.js b/test/rules/no-exports.js index 430bab1..dc542b6 100644 --- a/test/rules/no-exports.js +++ b/test/rules/no-exports.js @@ -1,8 +1,8 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); -ruleTester.run('no-exports', rules['no-exports'], { +ruleTester.run('no-exports', plugin.rules['no-exports'], { valid: [ 'describe(function() {});', 'context(function() {});', diff --git a/test/rules/no-global-tests.js b/test/rules/no-global-tests.js index e514707..216dca8 100644 --- a/test/rules/no-global-tests.js +++ b/test/rules/no-global-tests.js @@ -1,9 +1,10 @@ -const { RuleTester } = require('eslint'); -const rule = require('../../lib/rules/no-global-tests'); +import { RuleTester } from 'eslint'; +import { noGlobalTestsRule } from '../../lib/rules/no-global-tests.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); const expectedErrorMessage = 'Unexpected global mocha test.'; -ruleTester.run('no-global-tests', rule, { +ruleTester.run('no-global-tests', noGlobalTestsRule, { valid: [ 'describe();', 'suite();', diff --git a/test/rules/no-hooks-for-single-case.js b/test/rules/no-hooks-for-single-case.js index 941d186..381701c 100644 --- a/test/rules/no-hooks-for-single-case.js +++ b/test/rules/no-hooks-for-single-case.js @@ -1,8 +1,8 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); -ruleTester.run('no-hooks-for-single-case', rules['no-hooks-for-single-case'], { +ruleTester.run('no-hooks-for-single-case', plugin.rules['no-hooks-for-single-case'], { valid: [ [ 'describe(function() {', diff --git a/test/rules/no-hooks.js b/test/rules/no-hooks.js index e9cdbff..cf3fbd4 100644 --- a/test/rules/no-hooks.js +++ b/test/rules/no-hooks.js @@ -1,8 +1,8 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); -ruleTester.run('no-hooks', rules['no-hooks'], { +ruleTester.run('no-hooks', plugin.rules['no-hooks'], { valid: [ 'describe(function() { it(function() {}); });', 'describe(function() { it(function() {}); it(function() {}); });', diff --git a/test/rules/no-identical-title.js b/test/rules/no-identical-title.js index f708e5c..21c1e36 100644 --- a/test/rules/no-identical-title.js +++ b/test/rules/no-identical-title.js @@ -1,8 +1,8 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); -ruleTester.run('no-identical-title', rules['no-identical-title'], { +ruleTester.run('no-identical-title', plugin.rules['no-identical-title'], { valid: [ [ 'describe("describe", function() {', diff --git a/test/rules/no-mocha-arrows.js b/test/rules/no-mocha-arrows.js index a9f7781..c0b19bd 100644 --- a/test/rules/no-mocha-arrows.js +++ b/test/rules/no-mocha-arrows.js @@ -1,12 +1,12 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; const ruleTester = new RuleTester({ languageOptions: { ecmaVersion: 2017, sourceType: 'script' } }); const expectedErrorMessage = 'Do not pass arrow functions to it()'; const errors = [{ message: expectedErrorMessage, column: 1, line: 1 }]; -ruleTester.run('no-mocha-arrows', rules['no-mocha-arrows'], { +ruleTester.run('no-mocha-arrows', plugin.rules['no-mocha-arrows'], { valid: [ 'it()', 'it(function() { assert(something, false); })', diff --git a/test/rules/no-nested-tests.js b/test/rules/no-nested-tests.js index 9f922b2..d9f3d1c 100644 --- a/test/rules/no-nested-tests.js +++ b/test/rules/no-nested-tests.js @@ -1,8 +1,9 @@ -const { RuleTester } = require('eslint'); -const rule = require('../../lib/rules/no-nested-tests'); +import { RuleTester } from 'eslint'; +import { noNestedTestsRule } from '../../lib/rules/no-nested-tests.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); -ruleTester.run('no-nested-tests', rule, { +ruleTester.run('no-nested-tests', noNestedTestsRule, { valid: [ 'it()', 'it(); it(); it()', diff --git a/test/rules/no-pending-tests.js b/test/rules/no-pending-tests.js index 470080b..cb1cb15 100644 --- a/test/rules/no-pending-tests.js +++ b/test/rules/no-pending-tests.js @@ -1,9 +1,10 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); const expectedErrorMessage = 'Unexpected pending mocha test.'; -ruleTester.run('no-pending-tests', rules['no-pending-tests'], { +ruleTester.run('no-pending-tests', plugin.rules['no-pending-tests'], { valid: [ 'it()', 'it("should be false", function() { assert(something, false); })', diff --git a/test/rules/no-return-and-callback.js b/test/rules/no-return-and-callback.js index 7a8c789..347ab63 100644 --- a/test/rules/no-return-and-callback.js +++ b/test/rules/no-return-and-callback.js @@ -1,5 +1,6 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); const message = 'Unexpected use of `return` in a test with callback'; const es6LanguageOptions = { @@ -7,7 +8,7 @@ const es6LanguageOptions = { ecmaVersion: 6 }; -ruleTester.run('no-return-and-callback', rules['no-return-and-callback'], { +ruleTester.run('no-return-and-callback', plugin.rules['no-return-and-callback'], { valid: [ 'it("title", function(done) { done(); });', 'it("title", function(done) { foo.then(function() { return done(); }); });', diff --git a/test/rules/no-return-from-async.js b/test/rules/no-return-from-async.js index 77997d9..e5d0677 100644 --- a/test/rules/no-return-from-async.js +++ b/test/rules/no-return-from-async.js @@ -1,5 +1,6 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); const message = 'Unexpected use of `return` in a test with an async function'; const es6LanguageOptions = { @@ -7,7 +8,7 @@ const es6LanguageOptions = { ecmaVersion: 8 }; -ruleTester.run('no-return-from-async', rules['no-return-from-async'], { +ruleTester.run('no-return-from-async', plugin.rules['no-return-from-async'], { valid: [ { code: 'it("title", async function() {});', diff --git a/test/rules/no-setup-in-describe.js b/test/rules/no-setup-in-describe.js index 132de02..f967405 100644 --- a/test/rules/no-setup-in-describe.js +++ b/test/rules/no-setup-in-describe.js @@ -1,10 +1,11 @@ -const { RuleTester } = require('eslint'); -const rule = require('../../lib/rules/no-setup-in-describe'); +import { RuleTester } from 'eslint'; +import { noSetupInDescribeRule } from '../../lib/rules/no-setup-in-describe.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); const memberExpressionError = 'Unexpected member expression in describe block. ' + 'Member expressions may call functions via getters.'; -ruleTester.run('no-setup-in-describe', rule, { +ruleTester.run('no-setup-in-describe', noSetupInDescribeRule, { valid: [ 'it()', 'it(); it(); it()', diff --git a/test/rules/no-sibling-hooks.js b/test/rules/no-sibling-hooks.js index fd08ae7..cb18b00 100644 --- a/test/rules/no-sibling-hooks.js +++ b/test/rules/no-sibling-hooks.js @@ -1,8 +1,9 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); -ruleTester.run('no-sibling-hooks', rules['no-sibling-hooks'], { +ruleTester.run('no-sibling-hooks', plugin.rules['no-sibling-hooks'], { valid: [ 'describe(function() { before(function() {}); it(function() {}); });', 'describe(function() { after(function() {}); it(function() {}); });', diff --git a/test/rules/no-skipped-tests.js b/test/rules/no-skipped-tests.js index 0ff7d04..de6603b 100644 --- a/test/rules/no-skipped-tests.js +++ b/test/rules/no-skipped-tests.js @@ -1,9 +1,10 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); const expectedErrorMessage = 'Unexpected skipped mocha test.'; -ruleTester.run('no-skipped-tests', rules['no-skipped-tests'], { +ruleTester.run('no-skipped-tests', plugin.rules['no-skipped-tests'], { valid: [ 'describe()', 'it()', diff --git a/test/rules/no-synchronous-tests.js b/test/rules/no-synchronous-tests.js index de3b71f..f5c8b8b 100644 --- a/test/rules/no-synchronous-tests.js +++ b/test/rules/no-synchronous-tests.js @@ -1,8 +1,9 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); -ruleTester.run('no-synchronous-tests', rules['no-synchronous-tests'], { +ruleTester.run('no-synchronous-tests', plugin.rules['no-synchronous-tests'], { valid: [ 'it();', 'it("");', diff --git a/test/rules/no-top-level-hooks.js b/test/rules/no-top-level-hooks.js index 503cf48..594b80f 100644 --- a/test/rules/no-top-level-hooks.js +++ b/test/rules/no-top-level-hooks.js @@ -1,8 +1,9 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugins from '../../index.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); -ruleTester.run('no-top-level-hooks', rules['no-top-level-hooks'], { +ruleTester.run('no-top-level-hooks', plugins.rules['no-top-level-hooks'], { valid: [ 'describe(function() { before(function() {}); });', 'describe(function() { after(function() {}); });', diff --git a/test/rules/prefer-arrow-callback.js b/test/rules/prefer-arrow-callback.js index fe54658..c724354 100644 --- a/test/rules/prefer-arrow-callback.js +++ b/test/rules/prefer-arrow-callback.js @@ -8,8 +8,9 @@ // Requirements // ------------------------------------------------------------------------------ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; + const ruleTester = new RuleTester({ languageOptions: { ecmaVersion: 2017, sourceType: 'script' } }); @@ -23,7 +24,7 @@ const errors = [{ type: 'FunctionExpression' }]; -ruleTester.run('prefer-arrow-callback', rules['prefer-arrow-callback'], { +ruleTester.run('prefer-arrow-callback', plugin.rules['prefer-arrow-callback'], { valid: [ 'foo(a => a);', 'foo(function*() {});', diff --git a/test/rules/valid-suite-description.js b/test/rules/valid-suite-description.js index 78de46a..765c44b 100644 --- a/test/rules/valid-suite-description.js +++ b/test/rules/valid-suite-description.js @@ -1,8 +1,9 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); -ruleTester.run('valid-suite-description', rules['valid-suite-description'], { +ruleTester.run('valid-suite-description', plugin.rules['valid-suite-description'], { valid: [ { options: ['^[A-Z]'], diff --git a/test/rules/valid-test-description.js b/test/rules/valid-test-description.js index 2086992..bc8c749 100644 --- a/test/rules/valid-test-description.js +++ b/test/rules/valid-test-description.js @@ -1,8 +1,9 @@ -const { RuleTester } = require('eslint'); -const { rules } = require('../../'); +import { RuleTester } from 'eslint'; +import plugin from '../../index.js'; + const ruleTester = new RuleTester({ languageOptions: { sourceType: 'script' } }); -ruleTester.run('valid-test-description', rules['valid-test-description'], { +ruleTester.run('valid-test-description', plugin.rules['valid-test-description'], { valid: [ 'it("should respond to GET", function() { });', 'it("should do something");', diff --git a/test/util/namesSpec.js b/test/util/namesSpec.js index 4de5228..678a3dc 100644 --- a/test/util/namesSpec.js +++ b/test/util/namesSpec.js @@ -1,5 +1,5 @@ -const assert = require('node:assert'); -const { getTestCaseNames, getSuiteNames } = require('../../lib/util/names'); +import assert from 'node:assert'; +import { getSuiteNames, getTestCaseNames } from '../../lib/util/names.js'; describe('mocha names', function () { describe('test case names', function () {