diff --git a/.eslintrc.js b/.eslintrc.js index eb2992755..1a71970aa 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,6 +14,7 @@ module.exports = { }, env: { node: true, + es6: true, }, rules: { eqeqeq: ['error', 'smart'], diff --git a/rules/__tests__/no-disabled-tests.test.js b/rules/__tests__/no-disabled-tests.test.js index 0720d3403..0ba7aa4df 100644 --- a/rules/__tests__/no-disabled-tests.test.js +++ b/rules/__tests__/no-disabled-tests.test.js @@ -3,7 +3,11 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../no-disabled-tests'); -const ruleTester = new RuleTester(); +const ruleTester = new RuleTester({ + parserOptions: { + sourceType: 'module', + }, +}); ruleTester.run('no-disabled-tests', rule, { valid: [ @@ -17,6 +21,35 @@ ruleTester.run('no-disabled-tests', rule, { 'var calledSkip = it.skip; calledSkip.call(it)', '({ f: function () {} }).f()', '(a || b).f()', + [ + 'import { pending } from "actions"', + '', + 'test("foo", () => {', + ' expect(pending()).toEqual({})', + '})', + ].join('\n'), + [ + 'const { pending } = require("actions")', + '', + 'test("foo", () => {', + ' expect(pending()).toEqual({})', + '})', + ].join('\n'), + [ + 'test("foo", () => {', + ' const pending = getPending()', + ' expect(pending()).toEqual({})', + '})', + ].join('\n'), + [ + 'test("foo", () => {', + ' expect(pending()).toEqual({})', + '})', + '', + 'function pending() {', + ' return {}', + '}', + ].join('\n'), ], invalid: [ diff --git a/rules/no-disabled-tests.js b/rules/no-disabled-tests.js index ca796f985..24a9173ef 100644 --- a/rules/no-disabled-tests.js +++ b/rules/no-disabled-tests.js @@ -19,6 +19,33 @@ function getName(node) { return null; } +function collectReferences(scope) { + const locals = new Set(); + const unresolved = new Set(); + + let currentScope = scope; + + while (currentScope !== null) { + for (const ref of currentScope.variables) { + const isReferenceDefined = ref.defs.some(def => { + return def.type !== 'ImplicitGlobalVariable'; + }); + + if (isReferenceDefined) { + locals.add(ref.name); + } + } + + for (const ref of currentScope.through) { + unresolved.add(ref.identifier.name); + } + + currentScope = currentScope.upper; + } + + return { locals, unresolved }; +} + module.exports = { meta: { docs: { @@ -58,7 +85,19 @@ module.exports = { context.report({ message: 'Skipped test', node }); break; - case 'pending': + case 'pending': { + const references = collectReferences(context.getScope()); + + if ( + // `pending` was found as a local variable or function declaration. + references.locals.has('pending') || + // `pending` was not found as an unresolved reference, + // meaning it is likely not an implicit global reference. + !references.unresolved.has('pending') + ) { + break; + } + if (testDepth > 0) { context.report({ message: 'Call to pending() within test', @@ -76,6 +115,7 @@ module.exports = { }); } break; + } case 'xdescribe': context.report({ message: 'Disabled test suite', node });