From 60dee1fce5c5f4bbf40d30e690b5bc09e5c3af9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Mon, 17 Jul 2017 01:30:12 +0800 Subject: [PATCH 1/6] New: rule prefer-output-null --- lib/rules/prefer-output-null.js | 46 ++++++++++++++++++++++ tests/lib/rules/prefer-output-null.js | 56 +++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 lib/rules/prefer-output-null.js create mode 100644 tests/lib/rules/prefer-output-null.js diff --git a/lib/rules/prefer-output-null.js b/lib/rules/prefer-output-null.js new file mode 100644 index 00000000..34e86420 --- /dev/null +++ b/lib/rules/prefer-output-null.js @@ -0,0 +1,46 @@ +/** + * @fileoverview disallows invalid RuleTester test cases with the output the same as the code. + * @author 薛定谔的猫 + */ + +'use strict'; + +const utils = require('../utils'); + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: 'disallows invalid RuleTester test cases with the output the same as the code.', + category: 'Tests', + recommended: false, + }, + fixable: null, + schema: [], + }, + + create (context) { + // ---------------------------------------------------------------------- + // Public + // ---------------------------------------------------------------------- + const message = 'Prefer `output: null` to assert that a test case is not autofixed.'; + + return { + Program (ast) { + utils.getTestInfo(context, ast).forEach(testRun => { + (testRun.invalid || []).forEach(test => { + if (!test.properties.some(item => item.key.name === 'output')) { + context.report({ + node: test, + message, + }); + } + }); + }); + }, + }; + }, +}; diff --git a/tests/lib/rules/prefer-output-null.js b/tests/lib/rules/prefer-output-null.js new file mode 100644 index 00000000..7a4b2324 --- /dev/null +++ b/tests/lib/rules/prefer-output-null.js @@ -0,0 +1,56 @@ +/** + * @fileoverview disallows invalid RuleTester test cases with the output the same as the code. + * @author 薛定谔的猫 + */ + +'use strict'; + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const rule = require('../../../lib/rules/prefer-output-null'); +const RuleTester = require('eslint').RuleTester; + +const ERROR = { message: 'Prefer `output: null` to assert that a test case is not autofixed.' }; + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); +ruleTester.run('prefer-output-null', rule, { + valid: [ + ` + new RuleTester().run('foo', bar, { + valid: [], + invalid: [ + {code: 'foo', output: 'bar', errors: ['bar']}, + ] + }); + `, + ` + new RuleTester().run('foo', bar, { + valid: [], + invalid: [ + {code: 'foo', output: null, errors: ['bar']}, + ] + }); + `, + ], + + invalid: [ + { + code: ` + new RuleTester().run('foo', bar, { + valid: [], + invalid: [ + {code: 'foo', errors: ['bar']}, + ] + }); + `, + errors: [ERROR], + output: null, + }, + ], +}); From 295250625a6b1e7c94300fe39e1d3c4511544e35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Mon, 17 Jul 2017 01:38:17 +0800 Subject: [PATCH 2/6] Docs: prefer-output-null --- README.md | 1 + docs/rules/prefer-output-null.md | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 docs/rules/prefer-output-null.md diff --git a/README.md b/README.md index 424d4869..80da4977 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ Name | ✔️ | 🛠 | Description [no-identical-tests](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/no-identical-tests.md) | | 🛠 | Disallows identical tests [no-missing-placeholders](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/no-missing-placeholders.md) | ✔️ | | Disallows missing placeholders in rule report messages [no-useless-token-range](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/no-useless-token-range.md) | ✔️ | 🛠 | Disallows unnecessary calls to sourceCode.getFirstToken and sourceCode.getLastToken +[prefer-output-null](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/prefer-output-null.md) | | | Disallows invalid RuleTester test cases with the output the same as the code. [prefer-placeholders](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/prefer-placeholders.md) | | | Disallows template literals as report messages [report-message-format](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/report-message-format.md) | | | Enforces a consistent format for report messages [require-meta-fixable](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/require-meta-fixable.md) | ✔️ | | Requires a `meta.fixable` property for fixable rules diff --git a/docs/rules/prefer-output-null.md b/docs/rules/prefer-output-null.md new file mode 100644 index 00000000..11693673 --- /dev/null +++ b/docs/rules/prefer-output-null.md @@ -0,0 +1,31 @@ +# Disallows invalid RuleTester test cases with the output the same as the code. (prefer-output-null) + +## Rule Details + +This rule aims to enforce `output: null` for invalid test cases to indicate that no output is produced. + +Examples of **incorrect** code for this rule: + +```js +/* eslint eslint-plugin/prefer-output-null: error */ + +new RuleTester().run('foo', bar, { + valid: [], + invalid: [ + { code: 'foo', errors: [{ message: 'bar' }] }, + ] +}); +``` + +Examples of **correct** code for this rule: + +```js +/* eslint eslint-plugin/prefer-output-null: error */ + +new RuleTester().run('foo', bar, { + valid: [], + invalid: [ + { code: 'foo', output: null, errors: [{ message: 'bar' }] }, + ] +}); +``` From 62bfc46d215a1a2686e49d072d7ea3a26ac3f458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Sun, 16 Jul 2017 23:23:21 +0100 Subject: [PATCH 3/6] update: check output property is the same as the code property. --- lib/rules/prefer-output-null.js | 19 ++++++++++--------- tests/lib/rules/prefer-output-null.js | 3 +-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/rules/prefer-output-null.js b/lib/rules/prefer-output-null.js index 34e86420..822136af 100644 --- a/lib/rules/prefer-output-null.js +++ b/lib/rules/prefer-output-null.js @@ -27,18 +27,19 @@ module.exports = { // Public // ---------------------------------------------------------------------- const message = 'Prefer `output: null` to assert that a test case is not autofixed.'; - + const sourceCode = context.getSourceCode(); return { Program (ast) { utils.getTestInfo(context, ast).forEach(testRun => { - (testRun.invalid || []).forEach(test => { - if (!test.properties.some(item => item.key.name === 'output')) { - context.report({ - node: test, - message, - }); - } - }); + const reportInfo = utils.getReportInfo(testRun.invalid); + const code = sourceCode.getText(reportInfo.code); + const output = sourceCode.getText(reportInfo.output); + if (output && output === code) { + context.report({ + node: reportInfo.output, + message, + }); + } }); }, }; diff --git a/tests/lib/rules/prefer-output-null.js b/tests/lib/rules/prefer-output-null.js index 7a4b2324..7bd2bbed 100644 --- a/tests/lib/rules/prefer-output-null.js +++ b/tests/lib/rules/prefer-output-null.js @@ -45,12 +45,11 @@ ruleTester.run('prefer-output-null', rule, { new RuleTester().run('foo', bar, { valid: [], invalid: [ - {code: 'foo', errors: ['bar']}, + {code: 'foo', output: 'foo', errors: ['bar']}, ] }); `, errors: [ERROR], - output: null, }, ], }); From 1f87ebfb376d8e6cbbc600d2736791d968287e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Mon, 17 Jul 2017 07:57:23 +0800 Subject: [PATCH 4/6] update: check output property is the same as the code property. --- lib/rules/prefer-output-null.js | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/lib/rules/prefer-output-null.js b/lib/rules/prefer-output-null.js index 822136af..a4ddc764 100644 --- a/lib/rules/prefer-output-null.js +++ b/lib/rules/prefer-output-null.js @@ -26,20 +26,34 @@ module.exports = { // ---------------------------------------------------------------------- // Public // ---------------------------------------------------------------------- + const message = 'Prefer `output: null` to assert that a test case is not autofixed.'; const sourceCode = context.getSourceCode(); + return { Program (ast) { utils.getTestInfo(context, ast).forEach(testRun => { - const reportInfo = utils.getReportInfo(testRun.invalid); - const code = sourceCode.getText(reportInfo.code); - const output = sourceCode.getText(reportInfo.output); - if (output && output === code) { - context.report({ - node: reportInfo.output, - message, - }); - } + (testRun.invalid || []).forEach(test => { + /** + * Get a test case's giving keyname node. + * @param {string} the keyname to find. + * @returns {Node} found node; if not found, return null; + */ + function getTestInfo (key) { + const res = test.properties.filter(item => item.key.name === key); + return res.length ? res[res.length - 1] : null; + } + + const code = getTestInfo('code'); + const output = getTestInfo('output'); + + if (output && sourceCode.getText(output.value) === sourceCode.getText(code.value)) { + context.report({ + node: test, + message, + }); + } + }); }); }, }; From 9989a283295a72f97d306f9cffd2d5025dffd336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Mon, 17 Jul 2017 07:57:39 +0800 Subject: [PATCH 5/6] Fix: linting errors. --- tests/lib/rules/no-deprecated-report-api.js | 24 +++------------------ 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/tests/lib/rules/no-deprecated-report-api.js b/tests/lib/rules/no-deprecated-report-api.js index f0eeafe0..e5e3559b 100644 --- a/tests/lib/rules/no-deprecated-report-api.js +++ b/tests/lib/rules/no-deprecated-report-api.js @@ -124,13 +124,7 @@ ruleTester.run('no-deprecated-report-api', rule, { } }; `, - output: ` - module.exports = { - create(context) { - context.report(theNode, theMessage, theData, theFix); - } - }; - `, + output: null, errors: [ERROR], }, { @@ -175,13 +169,7 @@ ruleTester.run('no-deprecated-report-api', rule, { } }; `, - output: ` - module.exports = { - create(notContext) { - notContext.report(theNode, theMessage, theData, theFix); - } - }; - `, + output: null, errors: [ERROR], }, { @@ -218,13 +206,7 @@ ruleTester.run('no-deprecated-report-api', rule, { } }; `, - output: ` - module.exports = { - create(context) { - context.report(theNode, theLocation, theMessage, theData, theFix, somethingElse, somethingElse, somethingElse); - } - }; - `, + output: null, errors: [ERROR], }, ], From fd7e63e2ec239a2640ec3a6c89ac25bdcf8d2bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Tue, 18 Jul 2017 09:23:42 +0800 Subject: [PATCH 6/6] Fix: some small suggestions. --- docs/rules/prefer-output-null.md | 4 ++-- lib/rules/prefer-output-null.js | 2 +- tests/lib/rules/prefer-output-null.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/rules/prefer-output-null.md b/docs/rules/prefer-output-null.md index 11693673..3a95b525 100644 --- a/docs/rules/prefer-output-null.md +++ b/docs/rules/prefer-output-null.md @@ -2,7 +2,7 @@ ## Rule Details -This rule aims to enforce `output: null` for invalid test cases to indicate that no output is produced. +The rule reports an error if it encounters a test case where the output is the same as the code. Examples of **incorrect** code for this rule: @@ -12,7 +12,7 @@ Examples of **incorrect** code for this rule: new RuleTester().run('foo', bar, { valid: [], invalid: [ - { code: 'foo', errors: [{ message: 'bar' }] }, + { code: 'foo', output: 'foo', errors: [{ message: 'bar' }] }, ] }); ``` diff --git a/lib/rules/prefer-output-null.js b/lib/rules/prefer-output-null.js index a4ddc764..9f31645a 100644 --- a/lib/rules/prefer-output-null.js +++ b/lib/rules/prefer-output-null.js @@ -27,7 +27,7 @@ module.exports = { // Public // ---------------------------------------------------------------------- - const message = 'Prefer `output: null` to assert that a test case is not autofixed.'; + const message = 'Use `output: null` to assert that a test case is not autofixed.'; const sourceCode = context.getSourceCode(); return { diff --git a/tests/lib/rules/prefer-output-null.js b/tests/lib/rules/prefer-output-null.js index 7bd2bbed..24ee3eae 100644 --- a/tests/lib/rules/prefer-output-null.js +++ b/tests/lib/rules/prefer-output-null.js @@ -12,7 +12,7 @@ const rule = require('../../../lib/rules/prefer-output-null'); const RuleTester = require('eslint').RuleTester; -const ERROR = { message: 'Prefer `output: null` to assert that a test case is not autofixed.' }; +const ERROR = { message: 'Use `output: null` to assert that a test case is not autofixed.' }; // ------------------------------------------------------------------------------ // Tests