From c8826a5cc72473f1e5b3ab2d1af50675c08316f4 Mon Sep 17 00:00:00 2001 From: Rahul Gurung Date: Fri, 3 May 2019 22:55:23 +0530 Subject: [PATCH 1/9] rule `prevent-errortype` --- docs/rules/prevent-errortype.md | 35 +++++++++++++++++++++++ index.js | 1 + rules/prevent-errortype.js | 50 +++++++++++++++++++++++++++++++++ test/prevent-errortype.js | 32 +++++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 docs/rules/prevent-errortype.md create mode 100644 rules/prevent-errortype.js create mode 100644 test/prevent-errortype.js diff --git a/docs/rules/prevent-errortype.md b/docs/rules/prevent-errortype.md new file mode 100644 index 00000000..885a5ceb --- /dev/null +++ b/docs/rules/prevent-errortype.md @@ -0,0 +1,35 @@ +# Prevent specifying error type in `t.notThrows()` + +AVA will fail if error type is specified with `t.notThrows()`. + + +## Fail + +```js +const test = require('ava'); + +test('some test', t => { + t.notThrows(() => { + t.pass(); + }, TypeError); +}); +``` + + +## Pass + +```js +const test = require('ava'); + +test('some test', t => { + t.notThrows(() => { + t.pass(); + }); +}); + +test('some test', t => { + t.throws(() => { + t.pass(); + }, TypeError); +}); +``` diff --git a/index.js b/index.js index 55595393..e5e09883 100644 --- a/index.js +++ b/index.js @@ -43,6 +43,7 @@ module.exports = { 'ava/prefer-async-await': 'error', 'ava/prefer-power-assert': 'off', 'ava/prefer-t-regex': 'error', + 'ava/prevent-errortype': 'error', 'ava/test-ended': 'error', 'ava/test-title': 'error', 'ava/test-title-format': 'off', diff --git a/rules/prevent-errortype.js b/rules/prevent-errortype.js new file mode 100644 index 00000000..ec19c352 --- /dev/null +++ b/rules/prevent-errortype.js @@ -0,0 +1,50 @@ +'use strict'; +const {visitIf} = require('enhance-visitors'); +const util = require('../util'); +const createAvaRule = require('../create-ava-rule'); + +const nameRegexp = /^(?:[A-Z][a-z0-9]*)*Error$/; + +const create = context => { + const ava = createAvaRule(); + + return ava.merge({ + CallExpression: visitIf([ + ava.isInTestFile, + ava.isInTestNode + ])(node => { + const functionArgIndex = node.arguments.length - 1; + let functionArgName; + + if (typeof node.callee.property === 'undefined') { + return; + } + + const calleeProperty = node.callee.property.name; + + if (functionArgIndex === 1) { + functionArgName = node.arguments[1].name; + } else { + return; + } + + if (calleeProperty === 'notThrows') { + if (nameRegexp.test(functionArgName)) { + context.report({ + node, + message: 'Do not specify Error in t.notThrows()' + }); + } + } + }) + }); +}; + +module.exports = { + create, + meta: { + docs: { + url: util.getDocsUrl(__filename) + } + } +}; diff --git a/test/prevent-errortype.js b/test/prevent-errortype.js new file mode 100644 index 00000000..71cd3c95 --- /dev/null +++ b/test/prevent-errortype.js @@ -0,0 +1,32 @@ +import test from 'ava'; +import avaRuleTester from 'eslint-ava-rule-tester'; +import rule from '../rules/prevent-errortype'; + +const ruleTester = avaRuleTester(test, { + env: { + es6: true + } +}); + +const errors = [{ruleId: 'prevent-errortype'}]; + +const header = 'const test = require(\'ava\');\n'; + +ruleTester.run('prevent-errortype', rule, { + valid: [ + header + 'test(\'some test\',t => {t.notThrows(() => {t.pass();});});', + header + 'test(t => {t.notThrows(() => {t.pass();});});', + header + 'test(t => {t.throws(() => {t.pass();}, TypeError);});', + header + 'test(t => {t.end(); });' + ], + invalid: [ + { + code: header + 'test(t => {t.notThrows(() => {t.pass();}, TypeError);});', + errors + }, + { + code: header + 'test(\'some test\',t => {t.notThrows(() => {t.pass();}, TypeError);});', + errors + } + ] +}); From 75f72a642ad400074905ec7d6adb56a7e67cf209 Mon Sep 17 00:00:00 2001 From: Rahul Gurung Date: Mon, 6 May 2019 00:10:41 +0530 Subject: [PATCH 2/9] feedback - I changed name of test and added more tests with other requested changes. --- ...type.md => no-typeerror-with-notthrows.md} | 0 index.js | 1 + readme.md | 2 ++ ...type.js => no-typeerror-with-notthrows.js} | 11 +++--- test/no-typeerror-with-notthrows.js | 35 +++++++++++++++++++ test/prevent-errortype.js | 32 ----------------- 6 files changed, 43 insertions(+), 38 deletions(-) rename docs/rules/{prevent-errortype.md => no-typeerror-with-notthrows.md} (100%) rename rules/{prevent-errortype.js => no-typeerror-with-notthrows.js} (78%) create mode 100644 test/no-typeerror-with-notthrows.js delete mode 100644 test/prevent-errortype.js diff --git a/docs/rules/prevent-errortype.md b/docs/rules/no-typeerror-with-notthrows.md similarity index 100% rename from docs/rules/prevent-errortype.md rename to docs/rules/no-typeerror-with-notthrows.md diff --git a/index.js b/index.js index e5e09883..57059516 100644 --- a/index.js +++ b/index.js @@ -39,6 +39,7 @@ module.exports = { 'ava/no-statement-after-end': 'error', 'ava/no-todo-implementation': 'error', 'ava/no-todo-test': 'warn', + 'ava/no-typeerror-with-notthrows': 'error', 'ava/no-unknown-modifiers': 'error', 'ava/prefer-async-await': 'error', 'ava/prefer-power-assert': 'off', diff --git a/readme.md b/readme.md index cc80a4eb..a1c64003 100644 --- a/readme.md +++ b/readme.md @@ -55,6 +55,7 @@ Configure it in `package.json`. "ava/no-statement-after-end": "error", "ava/no-todo-implementation": "error", "ava/no-todo-test": "warn", + "ava/no-typeerror-with-notthrows": "error", "ava/no-unknown-modifiers": "error", "ava/prefer-async-await": "error", "ava/prefer-power-assert": "off", @@ -95,6 +96,7 @@ The rules will only activate in test files. - [no-statement-after-end](docs/rules/no-statement-after-end.md) - Ensure `t.end()` is the last statement executed. - [no-todo-implementation](docs/rules/no-todo-implementation.md) - Ensure `test.todo()` is not given an implementation function. - [no-todo-test](docs/rules/no-todo-test.md) - Ensure no `test.todo()` is used. +- [no-typeerror-with-notthrows](docs/rules/no-typeerror-with-notthrows.md) - Prevent use of typerror with notthrows. - [no-unknown-modifiers](docs/rules/no-unknown-modifiers.md) - Prevent the use of unknown test modifiers. - [prefer-async-await](docs/rules/prefer-async-await.md) - Prefer using async/await instead of returning a Promise. - [prefer-power-assert](docs/rules/prefer-power-assert.md) - Allow only use of the asserts that have no [power-assert](https://github.com/power-assert-js/power-assert) alternative. diff --git a/rules/prevent-errortype.js b/rules/no-typeerror-with-notthrows.js similarity index 78% rename from rules/prevent-errortype.js rename to rules/no-typeerror-with-notthrows.js index ec19c352..7a1e031a 100644 --- a/rules/prevent-errortype.js +++ b/rules/no-typeerror-with-notthrows.js @@ -3,7 +3,7 @@ const {visitIf} = require('enhance-visitors'); const util = require('../util'); const createAvaRule = require('../create-ava-rule'); -const nameRegexp = /^(?:[A-Z][a-z0-9]*)*Error$/; +const errorNameRegex = /^(?:[A-Z][a-z\d]*)*Error$/; const create = context => { const ava = createAvaRule(); @@ -14,7 +14,6 @@ const create = context => { ava.isInTestNode ])(node => { const functionArgIndex = node.arguments.length - 1; - let functionArgName; if (typeof node.callee.property === 'undefined') { return; @@ -22,14 +21,14 @@ const create = context => { const calleeProperty = node.callee.property.name; - if (functionArgIndex === 1) { - functionArgName = node.arguments[1].name; - } else { + if (functionArgIndex !== 1) { return; } + const functionArgName = node.arguments[1].name; + if (calleeProperty === 'notThrows') { - if (nameRegexp.test(functionArgName)) { + if (errorNameRegex.test(functionArgName)) { context.report({ node, message: 'Do not specify Error in t.notThrows()' diff --git a/test/no-typeerror-with-notthrows.js b/test/no-typeerror-with-notthrows.js new file mode 100644 index 00000000..18879892 --- /dev/null +++ b/test/no-typeerror-with-notthrows.js @@ -0,0 +1,35 @@ +import test from 'ava'; +import avaRuleTester from 'eslint-ava-rule-tester'; +import rule from '../rules/no-typeerror-with-notthrows'; + +const ruleTester = avaRuleTester(test, { + env: { + es6: true + } +}); + +const errors = [{ruleId: 'no-typerror-with-notthrows'}]; + +const header = `const test = require('ava');\n`; // eslint-disable-line quotes + +ruleTester.run('no-typeerror-with-notthrows', rule, { + valid: [ + `${header} test('some test',t => {t.notThrows(() => {t.pass();});});`, + `${header} test(t => {t.notThrows(() => {t.pass();});});`, + `${header} test(t => {t.throws(() => {t.pass();}, TypeError);});`, + `${header} test(t => {t.end(); })`, + `${header} test('some test',t => {t.notThrows(() => {t.pass();}, true);});`, + `${header} test('some test',t => {t.notThrows(() => {t.pass();}, 'some string');});`, + `${header} test('some test',t => {t.notThrows(() => {t.pass();}, {firstName:'some', lastName: 'object'});});` + ], + invalid: [ + { + code: `${header} test(t => {t.notThrows(() => {t.pass();}, TypeError);});`, + errors + }, + { + code: `${header} test('some test',t => {t.notThrows(() => {t.pass();}, TypeError);});`, + errors + } + ] +}); diff --git a/test/prevent-errortype.js b/test/prevent-errortype.js deleted file mode 100644 index 71cd3c95..00000000 --- a/test/prevent-errortype.js +++ /dev/null @@ -1,32 +0,0 @@ -import test from 'ava'; -import avaRuleTester from 'eslint-ava-rule-tester'; -import rule from '../rules/prevent-errortype'; - -const ruleTester = avaRuleTester(test, { - env: { - es6: true - } -}); - -const errors = [{ruleId: 'prevent-errortype'}]; - -const header = 'const test = require(\'ava\');\n'; - -ruleTester.run('prevent-errortype', rule, { - valid: [ - header + 'test(\'some test\',t => {t.notThrows(() => {t.pass();});});', - header + 'test(t => {t.notThrows(() => {t.pass();});});', - header + 'test(t => {t.throws(() => {t.pass();}, TypeError);});', - header + 'test(t => {t.end(); });' - ], - invalid: [ - { - code: header + 'test(t => {t.notThrows(() => {t.pass();}, TypeError);});', - errors - }, - { - code: header + 'test(\'some test\',t => {t.notThrows(() => {t.pass();}, TypeError);});', - errors - } - ] -}); From 0d604412786977caa8903020c4d649af9d70aed6 Mon Sep 17 00:00:00 2001 From: Rahul Gurung Date: Wed, 15 May 2019 00:19:00 +0530 Subject: [PATCH 3/9] feedback --- docs/rules/no-typeerror-with-notthrows.md | 4 +- rules/no-typeerror-with-notthrows.js | 7 +- test/no-typeerror-with-notthrows.js | 107 ++++++++++++++++++++-- 3 files changed, 103 insertions(+), 15 deletions(-) diff --git a/docs/rules/no-typeerror-with-notthrows.md b/docs/rules/no-typeerror-with-notthrows.md index 885a5ceb..75202b0c 100644 --- a/docs/rules/no-typeerror-with-notthrows.md +++ b/docs/rules/no-typeerror-with-notthrows.md @@ -1,6 +1,6 @@ -# Prevent specifying error type in `t.notThrows()` +# No specifying error type in `t.notThrows()` -AVA will fail if error type is specified with `t.notThrows()`. +AVA will fail if error constructor is specified in the second argument of `t.notThrows()`. ## Fail diff --git a/rules/no-typeerror-with-notthrows.js b/rules/no-typeerror-with-notthrows.js index 7a1e031a..976d1660 100644 --- a/rules/no-typeerror-with-notthrows.js +++ b/rules/no-typeerror-with-notthrows.js @@ -27,11 +27,11 @@ const create = context => { const functionArgName = node.arguments[1].name; - if (calleeProperty === 'notThrows') { + if (calleeProperty === 'notThrows' || calleeProperty === 'notThrowsAsync') { if (errorNameRegex.test(functionArgName)) { context.report({ node, - message: 'Do not specify Error in t.notThrows()' + message: 'Do not specify an error constructor in the second argument of t.notThrows()' }); } } @@ -44,6 +44,7 @@ module.exports = { meta: { docs: { url: util.getDocsUrl(__filename) - } + }, + type: 'problem' } }; diff --git a/test/no-typeerror-with-notthrows.js b/test/no-typeerror-with-notthrows.js index 18879892..be0bab5a 100644 --- a/test/no-typeerror-with-notthrows.js +++ b/test/no-typeerror-with-notthrows.js @@ -8,27 +8,114 @@ const ruleTester = avaRuleTester(test, { } }); -const errors = [{ruleId: 'no-typerror-with-notthrows'}]; +const errors = [{ruleId: 'no-typeerror-with-notthrows'}]; const header = `const test = require('ava');\n`; // eslint-disable-line quotes ruleTester.run('no-typeerror-with-notthrows', rule, { valid: [ - `${header} test('some test',t => {t.notThrows(() => {t.pass();});});`, - `${header} test(t => {t.notThrows(() => {t.pass();});});`, - `${header} test(t => {t.throws(() => {t.pass();}, TypeError);});`, - `${header} test(t => {t.end(); })`, - `${header} test('some test',t => {t.notThrows(() => {t.pass();}, true);});`, - `${header} test('some test',t => {t.notThrows(() => {t.pass();}, 'some string');});`, - `${header} test('some test',t => {t.notThrows(() => {t.pass();}, {firstName:'some', lastName: 'object'});});` + `${header} + test('some test',t => { + t.notThrows(() => { + t.pass(); + }); + });`, + + `${header} + test(t => { + t.notThrows(() => { + t.pass(); + }); + });`, + + `${header} + test(t => { + t.throws(() => { + t.pass(); + }, TypeError); + });`, + + `${header} + test(t => { + t.end(); })`, + + `${header} + test('some test',t => { + t.notThrows(() => { + t.pass(); + }, true); + });`, + + `${header} + test('some test',t => { + t.notThrows(() => { + t.pass(); + }, 'some string'); + });`, + + `${header} + test('some test',t => { + t.notThrows(() => { + t.pass(); + }, {firstName:'some', lastName: 'object'}); + });`, + + `${header} + test('some test',t => { + t.notThrowsAsync(() => { + t.pass(); + }); + });`, + + `${header} + test(t => { + t.notThrowsAsync(() => { + t.pass(); + }); + });`, + + `${header} + test('some test',t => { + t.notThrowsAsync(() => { + t.pass(); + }, {firstName:'some', lastName: 'object'}); + });` ], invalid: [ { - code: `${header} test(t => {t.notThrows(() => {t.pass();}, TypeError);});`, + code: `${header} + test(t => { + t.notThrows(() => { + t.pass(); + }, TypeError); + });`, + errors + }, + { + code: `${header} + test('some test',t => { + t.notThrows(() => { + t.pass(); + }, TypeError); + });`, + errors + }, + { + code: `${header} + test(t => { + t.notThrowsAsync(() => { + t.pass(); + }, TypeError); + });`, errors }, { - code: `${header} test('some test',t => {t.notThrows(() => {t.pass();}, TypeError);});`, + code: `${header} + test('some test',t => { + t.notThrowsAsync(() => { + t.pass(); + }, TypeError); + });`, errors } ] From a6de63488ae84a8835a7930892024f6c9f1f588a Mon Sep 17 00:00:00 2001 From: Rahul Gurung Date: Wed, 15 May 2019 00:33:50 +0530 Subject: [PATCH 4/9] changed name to no-error-ctor-with-notthrows --- ...or-with-notthrows.md => no-error-ctor-with-notthrows.md} | 0 index.js | 2 +- readme.md | 4 ++-- ...or-with-notthrows.js => no-error-ctor-with-notthrows.js} | 0 ...or-with-notthrows.js => no-error-ctor-with-notthrows.js} | 6 +++--- 5 files changed, 6 insertions(+), 6 deletions(-) rename docs/rules/{no-typeerror-with-notthrows.md => no-error-ctor-with-notthrows.md} (100%) rename rules/{no-typeerror-with-notthrows.js => no-error-ctor-with-notthrows.js} (100%) rename test/{no-typeerror-with-notthrows.js => no-error-ctor-with-notthrows.js} (90%) diff --git a/docs/rules/no-typeerror-with-notthrows.md b/docs/rules/no-error-ctor-with-notthrows.md similarity index 100% rename from docs/rules/no-typeerror-with-notthrows.md rename to docs/rules/no-error-ctor-with-notthrows.md diff --git a/index.js b/index.js index 57059516..223604c9 100644 --- a/index.js +++ b/index.js @@ -26,6 +26,7 @@ module.exports = { 'ava/no-async-fn-without-await': 'error', 'ava/no-cb-test': 'off', 'ava/no-duplicate-modifiers': 'error', + 'ava/no-error-ctor-with-notthrows': 'error', 'ava/no-identical-title': 'error', 'ava/no-ignored-test-files': 'error', 'ava/no-import-test-files': 'error', @@ -39,7 +40,6 @@ module.exports = { 'ava/no-statement-after-end': 'error', 'ava/no-todo-implementation': 'error', 'ava/no-todo-test': 'warn', - 'ava/no-typeerror-with-notthrows': 'error', 'ava/no-unknown-modifiers': 'error', 'ava/prefer-async-await': 'error', 'ava/prefer-power-assert': 'off', diff --git a/readme.md b/readme.md index a1c64003..9f8c4bd0 100644 --- a/readme.md +++ b/readme.md @@ -42,6 +42,7 @@ Configure it in `package.json`. "ava/no-async-fn-without-await": "error", "ava/no-cb-test": "off", "ava/no-duplicate-modifiers": "error", + "ava/no-error-ctor-with-notthrows": "error", "ava/no-identical-title": "error", "ava/no-ignored-test-files": "error", "ava/no-import-test-files": "error", @@ -55,7 +56,6 @@ Configure it in `package.json`. "ava/no-statement-after-end": "error", "ava/no-todo-implementation": "error", "ava/no-todo-test": "warn", - "ava/no-typeerror-with-notthrows": "error", "ava/no-unknown-modifiers": "error", "ava/prefer-async-await": "error", "ava/prefer-power-assert": "off", @@ -83,6 +83,7 @@ The rules will only activate in test files. - [no-async-fn-without-await](docs/rules/no-async-fn-without-await.md) - Ensure that async tests use `await`. - [no-cb-test](docs/rules/no-cb-test.md) - Ensure no `test.cb()` is used. - [no-duplicate-modifiers](docs/rules/no-duplicate-modifiers.md) - Ensure tests do not have duplicate modifiers. +- [no-error-ctor-with-notthrows](docs/rules/no-error-ctor-with-notthrows.md) - Prevent use of typerror with notthrows. - [no-identical-title](docs/rules/no-identical-title.md) - Ensure no tests have the same title. - [no-ignored-test-files](docs/rules/no-ignored-test-files.md) - Ensure no tests are written in ignored files. - [no-import-test-files](docs/rules/no-import-test-files.md) - Ensure no test files are imported anywhere. @@ -96,7 +97,6 @@ The rules will only activate in test files. - [no-statement-after-end](docs/rules/no-statement-after-end.md) - Ensure `t.end()` is the last statement executed. - [no-todo-implementation](docs/rules/no-todo-implementation.md) - Ensure `test.todo()` is not given an implementation function. - [no-todo-test](docs/rules/no-todo-test.md) - Ensure no `test.todo()` is used. -- [no-typeerror-with-notthrows](docs/rules/no-typeerror-with-notthrows.md) - Prevent use of typerror with notthrows. - [no-unknown-modifiers](docs/rules/no-unknown-modifiers.md) - Prevent the use of unknown test modifiers. - [prefer-async-await](docs/rules/prefer-async-await.md) - Prefer using async/await instead of returning a Promise. - [prefer-power-assert](docs/rules/prefer-power-assert.md) - Allow only use of the asserts that have no [power-assert](https://github.com/power-assert-js/power-assert) alternative. diff --git a/rules/no-typeerror-with-notthrows.js b/rules/no-error-ctor-with-notthrows.js similarity index 100% rename from rules/no-typeerror-with-notthrows.js rename to rules/no-error-ctor-with-notthrows.js diff --git a/test/no-typeerror-with-notthrows.js b/test/no-error-ctor-with-notthrows.js similarity index 90% rename from test/no-typeerror-with-notthrows.js rename to test/no-error-ctor-with-notthrows.js index be0bab5a..3cb2421b 100644 --- a/test/no-typeerror-with-notthrows.js +++ b/test/no-error-ctor-with-notthrows.js @@ -1,6 +1,6 @@ import test from 'ava'; import avaRuleTester from 'eslint-ava-rule-tester'; -import rule from '../rules/no-typeerror-with-notthrows'; +import rule from '../rules/no-error-ctor-with-notthrows'; const ruleTester = avaRuleTester(test, { env: { @@ -8,11 +8,11 @@ const ruleTester = avaRuleTester(test, { } }); -const errors = [{ruleId: 'no-typeerror-with-notthrows'}]; +const errors = [{ruleId: 'no-error-ctor-with-notthrows'}]; const header = `const test = require('ava');\n`; // eslint-disable-line quotes -ruleTester.run('no-typeerror-with-notthrows', rule, { +ruleTester.run('no-error-ctor-with-notthrows', rule, { valid: [ `${header} test('some test',t => { From f45f2139146ef22759f64aebc9d87858ea7c7544 Mon Sep 17 00:00:00 2001 From: Rahul Gurung Date: Tue, 9 Jul 2019 18:24:40 +0530 Subject: [PATCH 5/9] feedback defined variables just before they are used and added more tests --- readme.md | 2 +- rules/no-error-ctor-with-notthrows.js | 8 ++-- test/no-error-ctor-with-notthrows.js | 61 +++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/readme.md b/readme.md index 9f8c4bd0..f4a0c1ad 100644 --- a/readme.md +++ b/readme.md @@ -83,7 +83,7 @@ The rules will only activate in test files. - [no-async-fn-without-await](docs/rules/no-async-fn-without-await.md) - Ensure that async tests use `await`. - [no-cb-test](docs/rules/no-cb-test.md) - Ensure no `test.cb()` is used. - [no-duplicate-modifiers](docs/rules/no-duplicate-modifiers.md) - Ensure tests do not have duplicate modifiers. -- [no-error-ctor-with-notthrows](docs/rules/no-error-ctor-with-notthrows.md) - Prevent use of typerror with notthrows. +- [no-error-ctor-with-notthrows](docs/rules/no-error-ctor-with-notthrows.md) - No specifying error type in `t.notThrows()`. - [no-identical-title](docs/rules/no-identical-title.md) - Ensure no tests have the same title. - [no-ignored-test-files](docs/rules/no-ignored-test-files.md) - Ensure no tests are written in ignored files. - [no-import-test-files](docs/rules/no-import-test-files.md) - Ensure no test files are imported anywhere. diff --git a/rules/no-error-ctor-with-notthrows.js b/rules/no-error-ctor-with-notthrows.js index 976d1660..2bbf7d85 100644 --- a/rules/no-error-ctor-with-notthrows.js +++ b/rules/no-error-ctor-with-notthrows.js @@ -3,7 +3,7 @@ const {visitIf} = require('enhance-visitors'); const util = require('../util'); const createAvaRule = require('../create-ava-rule'); -const errorNameRegex = /^(?:[A-Z][a-z\d]*)*Error$/; +const errorNameRegex = /^([A-Z][a-z\d]*)*Error$/; const create = context => { const ava = createAvaRule(); @@ -13,25 +13,25 @@ const create = context => { ava.isInTestFile, ava.isInTestNode ])(node => { - const functionArgIndex = node.arguments.length - 1; if (typeof node.callee.property === 'undefined') { return; } - const calleeProperty = node.callee.property.name; + const functionArgIndex = node.arguments.length - 1; if (functionArgIndex !== 1) { return; } + const calleeProperty = node.callee.property.name; const functionArgName = node.arguments[1].name; if (calleeProperty === 'notThrows' || calleeProperty === 'notThrowsAsync') { if (errorNameRegex.test(functionArgName)) { context.report({ node, - message: 'Do not specify an error constructor in the second argument of t.notThrows()' + message: `Do not specify an error constructor in the second argument of \`t.${calleeProperty}()\`` }); } } diff --git a/test/no-error-ctor-with-notthrows.js b/test/no-error-ctor-with-notthrows.js index 3cb2421b..4469458b 100644 --- a/test/no-error-ctor-with-notthrows.js +++ b/test/no-error-ctor-with-notthrows.js @@ -79,6 +79,13 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { t.notThrowsAsync(() => { t.pass(); }, {firstName:'some', lastName: 'object'}); + });`, + + // Shouldn't be triggered since it's not a test file + `test('some test',t => { + t.notThrowsAsync(() => { + t.pass(); + }, TypeError); });` ], invalid: [ @@ -117,6 +124,60 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { }, TypeError); });`, errors + }, + { + code: `${header} + test('some test',t => { + t.notThrowsAsync(() => { + t.pass(); + }, Error); + });`, + errors + }, + { + code: `${header} + test('some test',t => { + t.notThrowsAsync(() => { + t.pass(); + }, SyntaxError); + });`, + errors + }, + { + code: `${header} + test('some test',t => { + t.notThrowsAsync(() => { + t.pass(); + }, AssertionError); + });`, + errors + }, + { + code: `${header} + test('some test',t => { + t.notThrowsAsync(() => { + t.pass(); + }, ReferenceError); + });`, + errors + }, + { + code: `${header} + test('some test',t => { + t.notThrowsAsync(() => { + t.pass(); + }, RangeError); + });`, + errors + }, + { + code: `${header} + test('some test',t => { + t.notThrowsAsync(() => { + t.pass(); + }, SystemError); + });`, + errors } ] }); From fcdb7e1cbf20010242e0821ddae3075a4002d355 Mon Sep 17 00:00:00 2001 From: Rahul Gurung Date: Fri, 12 Jul 2019 16:02:36 +0530 Subject: [PATCH 6/9] wip --- rules/no-error-ctor-with-notthrows.js | 11 ++--------- test/no-error-ctor-with-notthrows.js | 9 ++++++++- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/rules/no-error-ctor-with-notthrows.js b/rules/no-error-ctor-with-notthrows.js index 2bbf7d85..b2e72d9d 100644 --- a/rules/no-error-ctor-with-notthrows.js +++ b/rules/no-error-ctor-with-notthrows.js @@ -3,8 +3,6 @@ const {visitIf} = require('enhance-visitors'); const util = require('../util'); const createAvaRule = require('../create-ava-rule'); -const errorNameRegex = /^([A-Z][a-z\d]*)*Error$/; - const create = context => { const ava = createAvaRule(); @@ -14,21 +12,16 @@ const create = context => { ava.isInTestNode ])(node => { - if (typeof node.callee.property === 'undefined') { - return; - } - const functionArgIndex = node.arguments.length - 1; - if (functionArgIndex !== 1) { + if (typeof node.callee.property === 'undefined' || functionArgIndex !== 1 || node.callee.type !== 'MemberExpression' || node.arguments[1].type !== 'Identifier') { return; } const calleeProperty = node.callee.property.name; const functionArgName = node.arguments[1].name; - if (calleeProperty === 'notThrows' || calleeProperty === 'notThrowsAsync') { - if (errorNameRegex.test(functionArgName)) { + if (functionArgName.endsWith("Error")) { context.report({ node, message: `Do not specify an error constructor in the second argument of \`t.${calleeProperty}()\`` diff --git a/test/no-error-ctor-with-notthrows.js b/test/no-error-ctor-with-notthrows.js index 4469458b..9b8fcb89 100644 --- a/test/no-error-ctor-with-notthrows.js +++ b/test/no-error-ctor-with-notthrows.js @@ -86,7 +86,14 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { t.notThrowsAsync(() => { t.pass(); }, TypeError); - });` + });`, + { + code: `const { notThrows } = require("./my-custom-not-throws") + ${header} + test('some test',t => { + notThrows(foo); + });` + }, ], invalid: [ { From 1ec54fe0c124aa5a7672986c919ded5195a92073 Mon Sep 17 00:00:00 2001 From: Rahul Gurung Date: Sat, 27 Jul 2019 13:01:35 +0530 Subject: [PATCH 7/9] Rebase --- index.js | 1 - rules/no-error-ctor-with-notthrows.js | 5 ++-- test/no-error-ctor-with-notthrows.js | 36 +++++++++++++++++++++------ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index 223604c9..95ebf33e 100644 --- a/index.js +++ b/index.js @@ -44,7 +44,6 @@ module.exports = { 'ava/prefer-async-await': 'error', 'ava/prefer-power-assert': 'off', 'ava/prefer-t-regex': 'error', - 'ava/prevent-errortype': 'error', 'ava/test-ended': 'error', 'ava/test-title': 'error', 'ava/test-title-format': 'off', diff --git a/rules/no-error-ctor-with-notthrows.js b/rules/no-error-ctor-with-notthrows.js index b2e72d9d..00b9d7d6 100644 --- a/rules/no-error-ctor-with-notthrows.js +++ b/rules/no-error-ctor-with-notthrows.js @@ -11,17 +11,16 @@ const create = context => { ava.isInTestFile, ava.isInTestNode ])(node => { - const functionArgIndex = node.arguments.length - 1; - if (typeof node.callee.property === 'undefined' || functionArgIndex !== 1 || node.callee.type !== 'MemberExpression' || node.arguments[1].type !== 'Identifier') { + if (typeof node.callee.property === 'undefined' || functionArgIndex !== 1 || node.callee.type !== 'MemberExpression' || node.arguments[1].type !== 'Identifier' || util.getNameOfRootNodeObject(node.callee) !== 't') { return; } const calleeProperty = node.callee.property.name; const functionArgName = node.arguments[1].name; if (calleeProperty === 'notThrows' || calleeProperty === 'notThrowsAsync') { - if (functionArgName.endsWith("Error")) { + if (functionArgName.endsWith('Error')) { context.report({ node, message: `Do not specify an error constructor in the second argument of \`t.${calleeProperty}()\`` diff --git a/test/no-error-ctor-with-notthrows.js b/test/no-error-ctor-with-notthrows.js index 9b8fcb89..17453140 100644 --- a/test/no-error-ctor-with-notthrows.js +++ b/test/no-error-ctor-with-notthrows.js @@ -5,6 +5,9 @@ import rule from '../rules/no-error-ctor-with-notthrows'; const ruleTester = avaRuleTester(test, { env: { es6: true + }, + parserOptions: { + ecmaVersion: 2019 } }); @@ -81,19 +84,27 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { }, {firstName:'some', lastName: 'object'}); });`, + `${header} + test('some test',t => { + notThrows(foo); + });`, + + `${header} + test('some test',t => { + myCustomNotThrows.notThrows(foo); + });`, + + `${header} + t.notThrows(() => { + t.pass(); + }, void 0);`, + // Shouldn't be triggered since it's not a test file `test('some test',t => { t.notThrowsAsync(() => { t.pass(); }, TypeError); - });`, - { - code: `const { notThrows } = require("./my-custom-not-throws") - ${header} - test('some test',t => { - notThrows(foo); - });` - }, + });` ], invalid: [ { @@ -185,6 +196,15 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { }, SystemError); });`, errors + }, + { + code: `${header} + test('some test',t => { + t.notThrowsAsync(() => { + t.pass(); + }, $DOMError); + });`, + errors } ] }); From 8e4133a910dda7798c6a226b5b3a6b348d226976 Mon Sep 17 00:00:00 2001 From: Guillaume Martigny Date: Wed, 24 Mar 2021 15:57:47 +0100 Subject: [PATCH 8/9] Review --- readme.md | 2 +- test/no-error-ctor-with-notthrows.js | 41 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/readme.md b/readme.md index f4a0c1ad..84a317da 100644 --- a/readme.md +++ b/readme.md @@ -83,7 +83,7 @@ The rules will only activate in test files. - [no-async-fn-without-await](docs/rules/no-async-fn-without-await.md) - Ensure that async tests use `await`. - [no-cb-test](docs/rules/no-cb-test.md) - Ensure no `test.cb()` is used. - [no-duplicate-modifiers](docs/rules/no-duplicate-modifiers.md) - Ensure tests do not have duplicate modifiers. -- [no-error-ctor-with-notthrows](docs/rules/no-error-ctor-with-notthrows.md) - No specifying error type in `t.notThrows()`. +- [no-error-ctor-with-notthrows](docs/rules/no-error-ctor-with-notthrows.md) - Ensure no error constructor is specified in `t.notThrows()`. - [no-identical-title](docs/rules/no-identical-title.md) - Ensure no tests have the same title. - [no-ignored-test-files](docs/rules/no-ignored-test-files.md) - Ensure no tests are written in ignored files. - [no-import-test-files](docs/rules/no-import-test-files.md) - Ensure no test files are imported anywhere. diff --git a/test/no-error-ctor-with-notthrows.js b/test/no-error-ctor-with-notthrows.js index 17453140..cbda38f3 100644 --- a/test/no-error-ctor-with-notthrows.js +++ b/test/no-error-ctor-with-notthrows.js @@ -13,12 +13,12 @@ const ruleTester = avaRuleTester(test, { const errors = [{ruleId: 'no-error-ctor-with-notthrows'}]; -const header = `const test = require('ava');\n`; // eslint-disable-line quotes +const header = 'const test = require(\'ava\');\n'; ruleTester.run('no-error-ctor-with-notthrows', rule, { valid: [ `${header} - test('some test',t => { + test('some test', t => { t.notThrows(() => { t.pass(); }); @@ -39,32 +39,31 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { });`, `${header} - test(t => { - t.end(); })`, + test(t => { t.end(); })`, `${header} - test('some test',t => { + test('some test', t => { t.notThrows(() => { t.pass(); }, true); });`, `${header} - test('some test',t => { + test('some test', t => { t.notThrows(() => { t.pass(); }, 'some string'); });`, `${header} - test('some test',t => { + test('some test', t => { t.notThrows(() => { t.pass(); }, {firstName:'some', lastName: 'object'}); });`, `${header} - test('some test',t => { + test('some test', t => { t.notThrowsAsync(() => { t.pass(); }); @@ -78,19 +77,19 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { });`, `${header} - test('some test',t => { + test('some test', t => { t.notThrowsAsync(() => { t.pass(); }, {firstName:'some', lastName: 'object'}); });`, `${header} - test('some test',t => { + test('some test', t => { notThrows(foo); });`, `${header} - test('some test',t => { + test('some test', t => { myCustomNotThrows.notThrows(foo); });`, @@ -100,7 +99,7 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { }, void 0);`, // Shouldn't be triggered since it's not a test file - `test('some test',t => { + `test('some test', t => { t.notThrowsAsync(() => { t.pass(); }, TypeError); @@ -118,7 +117,7 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { }, { code: `${header} - test('some test',t => { + test('some test', t => { t.notThrows(() => { t.pass(); }, TypeError); @@ -136,7 +135,7 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { }, { code: `${header} - test('some test',t => { + test('some test', t => { t.notThrowsAsync(() => { t.pass(); }, TypeError); @@ -145,7 +144,7 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { }, { code: `${header} - test('some test',t => { + test('some test', t => { t.notThrowsAsync(() => { t.pass(); }, Error); @@ -154,7 +153,7 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { }, { code: `${header} - test('some test',t => { + test('some test', t => { t.notThrowsAsync(() => { t.pass(); }, SyntaxError); @@ -163,7 +162,7 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { }, { code: `${header} - test('some test',t => { + test('some test', t => { t.notThrowsAsync(() => { t.pass(); }, AssertionError); @@ -172,7 +171,7 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { }, { code: `${header} - test('some test',t => { + test('some test', t => { t.notThrowsAsync(() => { t.pass(); }, ReferenceError); @@ -181,7 +180,7 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { }, { code: `${header} - test('some test',t => { + test('some test', t => { t.notThrowsAsync(() => { t.pass(); }, RangeError); @@ -190,7 +189,7 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { }, { code: `${header} - test('some test',t => { + test('some test', t => { t.notThrowsAsync(() => { t.pass(); }, SystemError); @@ -199,7 +198,7 @@ ruleTester.run('no-error-ctor-with-notthrows', rule, { }, { code: `${header} - test('some test',t => { + test('some test', t => { t.notThrowsAsync(() => { t.pass(); }, $DOMError); From 41925d87263df5e52cfed9e30aad89ed8b07cebe Mon Sep 17 00:00:00 2001 From: Guillaume Martigny Date: Wed, 24 Mar 2021 16:14:01 +0100 Subject: [PATCH 9/9] Fix linting error --- rules/no-error-ctor-with-notthrows.js | 12 +++++------- test/no-error-ctor-with-notthrows.js | 8 ++++---- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/rules/no-error-ctor-with-notthrows.js b/rules/no-error-ctor-with-notthrows.js index 00b9d7d6..e651726b 100644 --- a/rules/no-error-ctor-with-notthrows.js +++ b/rules/no-error-ctor-with-notthrows.js @@ -19,13 +19,11 @@ const create = context => { const calleeProperty = node.callee.property.name; const functionArgName = node.arguments[1].name; - if (calleeProperty === 'notThrows' || calleeProperty === 'notThrowsAsync') { - if (functionArgName.endsWith('Error')) { - context.report({ - node, - message: `Do not specify an error constructor in the second argument of \`t.${calleeProperty}()\`` - }); - } + if ((calleeProperty === 'notThrows' || calleeProperty === 'notThrowsAsync') && functionArgName.endsWith('Error')) { + context.report({ + node, + message: `Do not specify an error constructor in the second argument of \`t.${calleeProperty}()\`` + }); } }) }); diff --git a/test/no-error-ctor-with-notthrows.js b/test/no-error-ctor-with-notthrows.js index cbda38f3..d444cf79 100644 --- a/test/no-error-ctor-with-notthrows.js +++ b/test/no-error-ctor-with-notthrows.js @@ -1,6 +1,6 @@ -import test from 'ava'; -import avaRuleTester from 'eslint-ava-rule-tester'; -import rule from '../rules/no-error-ctor-with-notthrows'; +const test = require('ava'); +const avaRuleTester = require('eslint-ava-rule-tester'); +const rule = require('../rules/no-error-ctor-with-notthrows'); const ruleTester = avaRuleTester(test, { env: { @@ -11,7 +11,7 @@ const ruleTester = avaRuleTester(test, { } }); -const errors = [{ruleId: 'no-error-ctor-with-notthrows'}]; +const errors = [{}]; const header = 'const test = require(\'ava\');\n';