diff --git a/src/rules/__tests__/prefer-snapshot-hint.test.ts b/src/rules/__tests__/prefer-snapshot-hint.test.ts index 25fc0e052..99dbf887d 100644 --- a/src/rules/__tests__/prefer-snapshot-hint.test.ts +++ b/src/rules/__tests__/prefer-snapshot-hint.test.ts @@ -257,6 +257,21 @@ ruleTester.run('prefer-snapshot-hint (multi)', rule, { `, options: ['multi'], }, + { + code: dedent` + describe('my tests', () => { + it('is true', () => { + expect(1).toMatchSnapshot('this is a hint, all by itself'); + }); + + it('is false', () => { + expect(2).toMatchSnapshot('this is a hint'); + expect(2).toMatchSnapshot('and so is this'); + }); + }); + `, + options: ['multi'], + }, { code: dedent` it('is true', () => { @@ -264,7 +279,8 @@ ruleTester.run('prefer-snapshot-hint (multi)', rule, { }); it('is false', () => { - expect(2).toMatchSnapshot(); + expect(2).toMatchSnapshot('this is a hint'); + expect(2).toMatchSnapshot('and so is this'); }); `, options: ['multi'], @@ -311,6 +327,18 @@ ruleTester.run('prefer-snapshot-hint (multi)', rule, { `, options: ['multi'], }, + { + code: dedent` + it('is true', () => { + expect(1).toMatchSnapshot(); + }); + + it('is false', () => { + expect(1).toMatchSnapshot(); + }); + `, + options: ['multi'], + }, { code: dedent` const myReusableTestBody = (value, snapshotHint) => { @@ -606,6 +634,103 @@ ruleTester.run('prefer-snapshot-hint (multi)', rule, { }, ], }, + { + code: dedent` + describe('my tests', () => { + it('is true', () => { + expect(1).toMatchSnapshot(); + }); + + it('is false', () => { + expect(2).toMatchSnapshot(); + expect(2).toMatchSnapshot(); + }); + }); + `, + options: ['multi'], + errors: [ + { + messageId: 'missingHint', + column: 15, + line: 7, + }, + { + messageId: 'missingHint', + column: 15, + line: 8, + }, + ], + }, + { + code: dedent` + describe('my tests', () => { + it('is true', () => { + expect(1).toMatchSnapshot(); + }); + + it('is false', () => { + expect(2).toMatchSnapshot(); + expect(2).toMatchSnapshot('hello world'); + }); + }); + `, + options: ['multi'], + errors: [ + { + messageId: 'missingHint', + column: 15, + line: 7, + }, + ], + }, + { + code: dedent` + describe('my tests', () => { + describe('more tests', () => { + it('is true', () => { + expect(1).toMatchSnapshot(); + }); + }); + + it('is false', () => { + expect(2).toMatchSnapshot(); + expect(2).toMatchSnapshot('hello world'); + }); + }); + `, + options: ['multi'], + errors: [ + { + messageId: 'missingHint', + column: 15, + line: 9, + }, + ], + }, + { + code: dedent` + describe('my tests', () => { + it('is true', () => { + expect(1).toMatchSnapshot(); + }); + + describe('more tests', () => { + it('is false', () => { + expect(2).toMatchSnapshot(); + expect(2).toMatchSnapshot('hello world'); + }); + }); + }); + `, + options: ['multi'], + errors: [ + { + messageId: 'missingHint', + column: 17, + line: 8, + }, + ], + }, { code: dedent` const myReusableTestBody = (value, snapshotHint) => { diff --git a/src/rules/prefer-snapshot-hint.ts b/src/rules/prefer-snapshot-hint.ts index 4a118b5f7..31ddb8316 100644 --- a/src/rules/prefer-snapshot-hint.ts +++ b/src/rules/prefer-snapshot-hint.ts @@ -1,8 +1,10 @@ import { ParsedExpectMatcher, createRule, + isDescribeCall, isExpectCall, isStringNode, + isTestCaseCall, parseExpectCall, } from './utils'; @@ -60,6 +62,7 @@ export default createRule<[('always' | 'multi')?], keyof typeof messages>({ defaultOptions: ['multi'], create(context, [mode]) { const snapshotMatchers: ParsedExpectMatcher[] = []; + const depths: number[] = []; let expressionDepth = 0; const reportSnapshotMatchersWithoutHints = () => { @@ -103,7 +106,18 @@ export default createRule<[('always' | 'multi')?], keyof typeof messages>({ 'FunctionExpression:exit': exitExpression, ArrowFunctionExpression: enterExpression, 'ArrowFunctionExpression:exit': exitExpression, + 'CallExpression:exit'(node) { + if (isDescribeCall(node) || isTestCaseCall(node)) { + /* istanbul ignore next */ + expressionDepth = depths.pop() ?? 0; + } + }, CallExpression(node) { + if (isDescribeCall(node) || isTestCaseCall(node)) { + depths.push(expressionDepth); + expressionDepth = 0; + } + if (!isExpectCall(node)) { return; }