From 9895ab62e36de0fd2219089ed9b07618e61b02b0 Mon Sep 17 00:00:00 2001 From: Macklin Underdown Date: Sat, 3 Feb 2018 13:35:54 -0500 Subject: [PATCH] feat(wip): add no-async-describe rule --- README.md | 1 + docs/rules/no-async-describe.md | 3 ++ index.js | 4 +-- rules/__tests__/no_async_describe.test.js | 43 +++++++++++++++++++++++ rules/no_async_describe.js | 34 ++++++++++++++++++ 5 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 docs/rules/no-async-describe.md create mode 100644 rules/__tests__/no_async_describe.test.js create mode 100644 rules/no_async_describe.js diff --git a/README.md b/README.md index cbbd8e232..d9a8685cc 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ for more information about extending configuration files. | Rule | Description | Recommended | Fixable | | ------------------------------------------------------------------ | --------------------------------------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------- | +| [no-async-describe](docs/rules/no-async-describe.md) | Prevent async describe callback | | | | [no-disabled-tests](docs/rules/no-disabled-tests.md) | Disallow disabled tests | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | | | [no-focused-tests](docs/rules/no-focused-tests.md) | Disallow focused tests | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | | | [no-identical-title](docs/rules/no-identical-title.md) | Disallow identical titles | ![recommended](https://img.shields.io/badge/-recommended-lightgrey.svg) | | diff --git a/docs/rules/no-async-describe.md b/docs/rules/no-async-describe.md new file mode 100644 index 000000000..9f16adf28 --- /dev/null +++ b/docs/rules/no-async-describe.md @@ -0,0 +1,3 @@ +# Prevent async describe callback (no-async-describe) + +TODO diff --git a/index.js b/index.js index d3eac65e4..42ce4508c 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,4 @@ -'use strict'; - +const noAsyncDescribe = require('./rules/no_async_describe'); const noDisabledTests = require('./rules/no_disabled_tests'); const noFocusedTests = require('./rules/no_focused_tests'); const noIdenticalTitle = require('./rules/no_identical_title'); @@ -56,6 +55,7 @@ module.exports = { '.snap': snapshotProcessor, }, rules: { + 'no-async-describe': noAsyncDescribe, 'no-disabled-tests': noDisabledTests, 'no-focused-tests': noFocusedTests, 'no-identical-title': noIdenticalTitle, diff --git a/rules/__tests__/no_async_describe.test.js b/rules/__tests__/no_async_describe.test.js new file mode 100644 index 000000000..c3c0777fd --- /dev/null +++ b/rules/__tests__/no_async_describe.test.js @@ -0,0 +1,43 @@ +const RuleTester = require('eslint').RuleTester; +const rules = require('../..').rules; + +const ruleTester = new RuleTester({ + parserOptions: { + ecmaVersion: 8, + }, +}); + +const expectedErrorMessage = 'No async describe'; + +ruleTester.run('no-async-describe', rules['no-async-describe'], { + valid: [ + 'describe("foo")', + 'describe("foo", function() {})', + 'describe("foo", () => {})', + ], + invalid: [ + { + code: 'describe("foo", async () => {})', + errors: [{ message: expectedErrorMessage, line: 1, column: 17 }], + }, + { + code: 'describe("foo", async function () {})', + errors: [{ message: expectedErrorMessage, line: 1, column: 17 }], + }, + { + code: ` + describe('sample case', () => { + it('works', () => { + expect(true).toEqual(true); + }); + describe('async', async () => { + await new Promise(setImmediate); + it('breaks', () => { + throw new Error('Fail'); + }); + }); + });`, + errors: [{ message: expectedErrorMessage, line: 6, column: 27 }], + }, + ], +}); diff --git a/rules/no_async_describe.js b/rules/no_async_describe.js new file mode 100644 index 000000000..c44a00f94 --- /dev/null +++ b/rules/no_async_describe.js @@ -0,0 +1,34 @@ +function isDescribe(node) { + return node.type === 'CallExpression' && node.callee.name === 'describe'; +} + +function isFunction(node) { + return ( + node.type === 'FunctionExpression' || + node.type === 'ArrowFunctionExpression' + ); +} + +function isAsync(node) { + return node.async; +} + +module.exports = context => { + return { + CallExpression(node) { + if (node && isDescribe(node)) { + const callbackFunction = node.arguments[1]; + if ( + callbackFunction && + isFunction(callbackFunction) && + isAsync(callbackFunction) + ) { + context.report({ + message: 'No async describe', + node: callbackFunction, + }); + } + } + }, + }; +};