From 97b1f9d8063811d8ebb7ad41b92a5286c56aa2c4 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Sun, 20 Mar 2022 12:54:07 +1300 Subject: [PATCH] fix(prefer-snapshot-hint): support passing hint to `toMatchSnapshot` as first argument (#1070) --- .../__tests__/prefer-snapshot-hint.test.ts | 36 +++++++++++++++++++ src/rules/prefer-snapshot-hint.ts | 26 +++++++++++--- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/rules/__tests__/prefer-snapshot-hint.test.ts b/src/rules/__tests__/prefer-snapshot-hint.test.ts index cd11661e5..25fc0e052 100644 --- a/src/rules/__tests__/prefer-snapshot-hint.test.ts +++ b/src/rules/__tests__/prefer-snapshot-hint.test.ts @@ -28,6 +28,28 @@ ruleTester.run('prefer-snapshot-hint (always)', rule, { code: 'expect(1).toMatchSnapshot({}, "my snapshot");', options: ['always'], }, + { + code: 'expect(1).toMatchSnapshot("my snapshot");', + options: ['always'], + }, + { + code: 'expect(1).toMatchSnapshot(`my snapshot`);', + options: ['always'], + }, + { + code: dedent` + const x = {}; + expect(1).toMatchSnapshot(x, "my snapshot"); + `, + options: ['always'], + }, + { + code: dedent` + const x = "snapshot"; + expect(1).toMatchSnapshot(\`my $\{x}\`); + `, + options: ['always'], + }, { code: 'expect(1).toThrowErrorMatchingSnapshot("my snapshot");', options: ['always'], @@ -64,6 +86,20 @@ ruleTester.run('prefer-snapshot-hint (always)', rule, { }, ], }, + { + code: dedent` + const x = "we can't know if this is a string or not"; + expect(1).toMatchSnapshot(x); + `, + options: ['always'], + errors: [ + { + messageId: 'missingHint', + column: 11, + line: 2, + }, + ], + }, { code: 'expect(1).toThrowErrorMatchingSnapshot();', options: ['always'], diff --git a/src/rules/prefer-snapshot-hint.ts b/src/rules/prefer-snapshot-hint.ts index 98f82d3a2..4a118b5f7 100644 --- a/src/rules/prefer-snapshot-hint.ts +++ b/src/rules/prefer-snapshot-hint.ts @@ -2,6 +2,7 @@ import { ParsedExpectMatcher, createRule, isExpectCall, + isStringNode, parseExpectCall, } from './utils'; @@ -12,10 +13,27 @@ const isSnapshotMatcher = (matcher: ParsedExpectMatcher) => { }; const isSnapshotMatcherWithoutHint = (matcher: ParsedExpectMatcher) => { - const expectedNumberOfArgumentsWithHint = - 1 + Number(matcher.name === 'toMatchSnapshot'); - - return matcher.arguments?.length !== expectedNumberOfArgumentsWithHint; + if (!matcher.arguments || matcher.arguments.length === 0) { + return true; + } + + // this matcher only supports one argument which is the hint + if (matcher.name !== 'toMatchSnapshot') { + return matcher.arguments.length !== 1; + } + + // if we're being passed two arguments, + // the second one should be the hint + if (matcher.arguments.length === 2) { + return false; + } + + const [arg] = matcher.arguments; + + // the first argument to `toMatchSnapshot` can be _either_ a snapshot hint or + // an object with asymmetric matchers, so we can't just assume that the first + // argument is a hint when it's by itself. + return !isStringNode(arg); }; const messages = {