diff --git a/src/rules/__tests__/no-duplicate-hooks.test.ts b/src/rules/__tests__/no-duplicate-hooks.test.ts index f3ee07bd1..8a14c00a3 100644 --- a/src/rules/__tests__/no-duplicate-hooks.test.ts +++ b/src/rules/__tests__/no-duplicate-hooks.test.ts @@ -288,3 +288,170 @@ ruleTester.run('nested describe blocks', rule, { }, ], }); + +ruleTester.run('describe.each blocks', rule, { + valid: [ + dedent` + describe.each(['hello'])('%s', () => { + beforeEach(() => {}); + + it('is fine', () => {}); + }); + `, + dedent` + describe('something', () => { + describe.each(['hello'])('%s', () => { + beforeEach(() => {}); + + it('is fine', () => {}); + }); + + describe.each(['world'])('%s', () => { + beforeEach(() => {}); + + it('is fine', () => {}); + }); + }); + `, + dedent` + describe.each\`\`('%s', () => { + beforeEach(() => {}); + + it('is fine', () => {}); + }); + `, + dedent` + describe('something', () => { + describe.each\`\`('%s', () => { + beforeEach(() => {}); + + it('is fine', () => {}); + }); + + describe.each\`\`('%s', () => { + beforeEach(() => {}); + + it('is fine', () => {}); + }); + }); + `, + ], + invalid: [ + { + code: dedent` + describe.each(['hello'])('%s', () => { + beforeEach(() => {}); + beforeEach(() => {}); + + it('is not fine', () => {}); + }); + `, + errors: [ + { + messageId: 'noDuplicateHook', + data: { hook: 'beforeEach' }, + column: 3, + line: 3, + }, + ], + }, + { + code: dedent` + describe('something', () => { + describe.each(['hello'])('%s', () => { + beforeEach(() => {}); + + it('is fine', () => {}); + }); + + describe.each(['world'])('%s', () => { + beforeEach(() => {}); + beforeEach(() => {}); + + it('is not fine', () => {}); + }); + }); + `, + errors: [ + { + messageId: 'noDuplicateHook', + data: { hook: 'beforeEach' }, + column: 5, + line: 10, + }, + ], + }, + { + code: dedent` + describe('something', () => { + describe.each(['hello'])('%s', () => { + beforeEach(() => {}); + + it('is fine', () => {}); + }); + + describe.each(['world'])('%s', () => { + describe('some more', () => { + beforeEach(() => {}); + beforeEach(() => {}); + + it('is not fine', () => {}); + }); + }); + }); + `, + errors: [ + { + messageId: 'noDuplicateHook', + data: { hook: 'beforeEach' }, + column: 7, + line: 11, + }, + ], + }, + { + code: dedent` + describe.each\`\`('%s', () => { + beforeEach(() => {}); + beforeEach(() => {}); + + it('is fine', () => {}); + }); + `, + errors: [ + { + messageId: 'noDuplicateHook', + data: { hook: 'beforeEach' }, + column: 3, + line: 3, + }, + ], + }, + { + code: dedent` + describe('something', () => { + describe.each\`\`('%s', () => { + beforeEach(() => {}); + + it('is fine', () => {}); + }); + + describe.each\`\`('%s', () => { + beforeEach(() => {}); + beforeEach(() => {}); + + it('is not fine', () => {}); + }); + }); + `, + errors: [ + { + messageId: 'noDuplicateHook', + data: { hook: 'beforeEach' }, + column: 5, + line: 10, + }, + ], + }, + ], +}); diff --git a/src/rules/no-duplicate-hooks.ts b/src/rules/no-duplicate-hooks.ts index d06da84b6..3a699d010 100644 --- a/src/rules/no-duplicate-hooks.ts +++ b/src/rules/no-duplicate-hooks.ts @@ -1,4 +1,4 @@ -import { createRule, isDescribe, isHook } from './utils'; +import { createRule, isDescribe, isEachCall, isHook } from './utils'; const newHookContext = () => ({ beforeAll: 0, @@ -45,7 +45,7 @@ export default createRule({ } }, 'CallExpression:exit'(node) { - if (isDescribe(node)) { + if (isDescribe(node) && !isEachCall(node)) { hookContexts.pop(); } },