From 97a5fce6434f2e672783b37f05949f29d550a532 Mon Sep 17 00:00:00 2001 From: Steven Hargrove Date: Fri, 24 Aug 2018 12:16:58 -0400 Subject: [PATCH] feat(rule): add allow option to expect-expect rule (#139) --- docs/rules/expect-expect.md | 55 +++++++++++++++++++++++++-- rules/__tests__/expect-expect.test.js | 29 ++++++++++++++ rules/expect-expect.js | 20 +++++++++- 3 files changed, 98 insertions(+), 6 deletions(-) diff --git a/docs/rules/expect-expect.md b/docs/rules/expect-expect.md index e6c919148..8224f3e07 100644 --- a/docs/rules/expect-expect.md +++ b/docs/rules/expect-expect.md @@ -7,9 +7,7 @@ Ensure that there is at least one `expect` call made in a test. This rule triggers when there is no call made to `expect` in a test, to prevent users from forgetting to add assertions. -### Default configuration - -The following patterns are considered warnings: +Examples of **incorrect** code for this rule: ```js it('should be a test', () => { @@ -18,7 +16,7 @@ it('should be a test', () => { test('should assert something', () => {}); ``` -The following patterns are not warnings: +Examples of **correct** code for this rule: ```js it('should be a test', () => { @@ -28,3 +26,52 @@ it('should work with callbacks/async', () => { somePromise().then(res => expect(res).toBe('passed')); }); ``` + +## Options + +```json +{ + "jest/expect-expect": [ + "error", + { + "assertFunctionNames": ["expect"] + } + ] +} +``` + +### `assertFunctionNames` + +This array option whitelists the assertion function names to look for. + +Examples of **incorrect** code for the `{ "assertFunctionNames": ["expect"] }` +option: + +```js +/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect"] }] */ + +import { expectSaga } from 'redux-saga-test-plan'; +import { addSaga } from '../src/sagas'; + +test('returns sum', () => { + expectSaga(addSaga, 1, 1) + .returns(2) + .run(); +}); +``` + +Examples of **correct** code for the +`{ "assertFunctionNames": ["expect", "expectSaga"] }` option: + +```js +/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "expectSaga"] }] */ + +import { expectSaga } from 'redux-saga-test-plan'; +import { addSaga } from '../src/sagas'; + +test('returns sum', () => { + expectSaga(addSaga, 1, 1) + .returns(2) + .run(); +}); +``` diff --git a/rules/__tests__/expect-expect.test.js b/rules/__tests__/expect-expect.test.js index fc0b3aaed..cd1c78836 100644 --- a/rules/__tests__/expect-expect.test.js +++ b/rules/__tests__/expect-expect.test.js @@ -14,6 +14,15 @@ ruleTester.run('expect-expect', rule, { 'it("should pass", () => expect(true).toBeDefined())', 'test("should pass", () => expect(true).toBeDefined())', 'it("should pass", () => somePromise().then(() => expect(true).toBeDefined()))', + { + code: + 'test("should pass", () => { expect(true).toBeDefined(); foo(true).toBe(true); })', + options: [{ assertFunctionNames: ['expect', 'foo'] }], + }, + { + code: 'it("should return undefined",() => expectSaga(mySaga).returns());', + options: [{ assertFunctionNames: ['expectSaga'] }], + }, ], invalid: [ @@ -44,5 +53,25 @@ ruleTester.run('expect-expect', rule, { }, ], }, + { + code: 'test("should fail", () => { foo(true).toBe(true); })', + options: [{ assertFunctionNames: ['expect'] }], + errors: [ + { + message: 'Test has no assertions', + type: 'CallExpression', + }, + ], + }, + { + code: 'it("should also fail",() => expectSaga(mySaga).returns());', + options: [{ assertFunctionNames: ['expect'] }], + errors: [ + { + message: 'Test has no assertions', + type: 'CallExpression', + }, + ], + }, ], }); diff --git a/rules/expect-expect.js b/rules/expect-expect.js index 67ed27b37..d4b203a36 100644 --- a/rules/expect-expect.js +++ b/rules/expect-expect.js @@ -12,10 +12,26 @@ module.exports = { docs: { url: getDocsUrl(__filename), }, + schema: [ + { + type: 'object', + properties: { + assertFunctionNames: { + type: 'array', + items: [{ type: 'string' }], + }, + }, + additionalProperties: false, + }, + ], }, create(context) { // variables should be defined here const unchecked = []; + const assertFunctionNames = + context.options[0] && context.options[0].assertFunctionNames + ? context.options[0].assertFunctionNames + : ['expect']; //---------------------------------------------------------------------- // Helpers @@ -23,8 +39,8 @@ module.exports = { const isExpectCall = node => // if we're not calling a function, ignore node.type === 'CallExpression' && - // if we're not calling expect, ignore - node.callee.name === 'expect'; + // if we're not calling allowed assertion + assertFunctionNames.some(name => name === node.callee.name); //---------------------------------------------------------------------- // Public //----------------------------------------------------------------------