From e30eafa67b0ac156c42ebc7ce3119afcace08c34 Mon Sep 17 00:00:00 2001 From: Alex Zherdev Date: Mon, 16 Sep 2019 06:54:43 -0700 Subject: [PATCH] Support named imports and destructured requires (#232) Co-authored-by: Sindre Sorhus --- create-ava-rule.js | 135 ++++++++++++++++++++++++++++++++++++++-- test/create-ava-rule.js | 71 +++++++++++++++++++++ 2 files changed, 200 insertions(+), 6 deletions(-) create mode 100644 test/create-ava-rule.js diff --git a/create-ava-rule.js b/create-ava-rule.js index 3806cf02..0c648943 100644 --- a/create-ava-rule.js +++ b/create-ava-rule.js @@ -4,7 +4,7 @@ const enhance = require('enhance-visitors'); const deepStrictEqual = require('deep-strict-equal'); const util = require('./util'); -const avaImportDeclarationAst = { +const avaImportDeclarationAsts = [{ type: 'ImportDeclaration', specifiers: [ { @@ -19,9 +19,66 @@ const avaImportDeclarationAst = { type: 'Literal', value: 'ava' } -}; +}, { + type: 'ImportDeclaration', + specifiers: [ + { + type: 'ImportSpecifier', + imported: { + type: 'Identifier', + name: 'serial' + }, + local: { + type: 'Identifier', + name: 'test' + } + } + ], + source: { + type: 'Literal', + value: 'ava' + } +}, { + type: 'ImportDeclaration', + specifiers: [ + { + type: 'ImportSpecifier', + imported: { + type: 'Identifier', + name: 'serial' + }, + local: { + type: 'Identifier', + name: 'test' + } + } + ], + source: { + type: 'Literal', + value: 'ava' + } +}, { + type: 'ImportDeclaration', + specifiers: [ + { + type: 'ImportSpecifier', + imported: { + type: 'Identifier', + name: 'serial' + }, + local: { + type: 'Identifier', + name: 'serial' + } + } + ], + source: { + type: 'Literal', + value: 'ava' + } +}]; -const avaVariableDeclaratorAst = { +const avaVariableDeclaratorAsts = [{ type: 'VariableDeclarator', id: { type: 'Identifier', @@ -40,7 +97,73 @@ const avaVariableDeclaratorAst = { } ] } -}; +}, { + type: 'VariableDeclarator', + id: { + type: 'ObjectPattern', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'serial' + }, + value: { + type: 'Identifier', + name: 'serial' + }, + kind: 'init', + method: false, + shorthand: true, + computed: false + }] + }, + init: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'require' + }, + arguments: [ + { + type: 'Literal', + value: 'ava' + } + ] + } +}, { + type: 'VariableDeclarator', + id: { + type: 'ObjectPattern', + properties: [{ + type: 'Property', + key: { + type: 'Identifier', + name: 'serial' + }, + value: { + type: 'Identifier', + name: 'test' + }, + kind: 'init', + method: false, + shorthand: false, + computed: false + }] + }, + init: { + type: 'CallExpression', + callee: { + type: 'Identifier', + name: 'require' + }, + arguments: [ + { + type: 'Literal', + value: 'ava' + } + ] + } +}]; function isTestFunctionCall(node) { if (node.type === 'Identifier') { @@ -65,12 +188,12 @@ module.exports = () => { /* eslint quote-props: [2, "as-needed"] */ const predefinedRules = { ImportDeclaration: node => { - if (!isTestFile && deepStrictEqual(espurify(node), avaImportDeclarationAst)) { + if (!isTestFile && avaImportDeclarationAsts.some(ast => deepStrictEqual(espurify(node), ast))) { isTestFile = true; } }, VariableDeclarator: node => { - if (!isTestFile && deepStrictEqual(espurify(node), avaVariableDeclaratorAst)) { + if (!isTestFile && avaVariableDeclaratorAsts.some(ast => deepStrictEqual(espurify(node), ast))) { isTestFile = true; } }, diff --git a/test/create-ava-rule.js b/test/create-ava-rule.js new file mode 100644 index 00000000..b9a6b298 --- /dev/null +++ b/test/create-ava-rule.js @@ -0,0 +1,71 @@ +import test from 'ava'; +import avaRuleTester from 'eslint-ava-rule-tester'; +import {visitIf} from 'enhance-visitors'; +import createAvaRule from '../create-ava-rule'; + +const rule = { + create: context => { + const ava = createAvaRule(); + + return ava.merge({ + 'Program:exit': node => { + if (!ava.isInTestFile()) { + context.report({node, message: 'not a test file'}); + } + } + }); + } +}; + +const ruleTester = avaRuleTester(test, { + env: { + es6: true, + }, + parserOptions: { + sourceType: 'module' + } +}); + +const errors = [ + { + message: 'not a test file' + } +]; + +ruleTester.run('rule-fixture', rule, { + valid: [ + 'const test = require(\'ava\');', + 'const {serial} = require(\'ava\');', + 'const {serial: test} = require(\'ava\');', + 'import test from \'ava\';', + 'import {serial} from \'ava\';', + 'import {serial as test} from \'ava\';' + ], + + invalid: [ + { + code: 'const test2 = require(\'ava\');', + errors + }, + { + code: 'const {serial2} = require(\'ava\');', + errors + }, + { + code: 'const {serial2: test} = require(\'ava\');', + errors + }, + { + code: 'import test2 from \'ava\';', + errors + }, + { + code: 'import {serial2} from \'ava\';', + errors + }, + { + code: 'import {serial2 as test} from \'ava\';', + errors + } + ] +});