Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create no-interpolation-in-snapshots rule #553

Merged
merged 21 commits into from Jul 27, 2020
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
118351c
feat(rules): add no-interpolation-inline-snapshot rule
viestat Apr 2, 2020
d96ae67
docs: fix fromat in rule documentation
viestat Apr 2, 2020
b6c50ec
fix: add chamges requested in review
viestat May 4, 2020
ba43b09
Merge branch 'master' of github.com:jest-community/eslint-plugin-jest…
viestat May 4, 2020
d8872c2
test: update number of rules
viestat May 4, 2020
ea5644e
docs: update docs/rules/no-interpolation-inline-snapshot.md
viestat Jun 29, 2020
7dc3bd7
feat: add toThrowErrorMatchingInlineSnapshot
viestat Jun 29, 2020
3579ef1
Merge branch 'master' of github.com:jest-community/eslint-plugin-jest…
viestat Jun 29, 2020
d83c060
docs: update rules table in README
viestat Jun 29, 2020
8c448e9
docs: apply suggestions from code review
viestat Jul 1, 2020
825687e
docs: fix format in README
viestat Jul 1, 2020
96eaf9b
fix: add review suggestions
viestat Jul 1, 2020
a405636
docs: add examples to README
viestat Jul 1, 2020
3dfd3a6
chore: rename rule to no-interpolation-in-snapshots
viestat Jul 1, 2020
ab2c365
chore: remove changes from CHANGELOG.md
viestat Jul 1, 2020
3fcf261
docs: update rule table with new name
viestat Jul 1, 2020
3738c2d
fix: apply suggestions from code review
viestat Jul 6, 2020
f98accf
test: add test to cover missing branch
viestat Jul 6, 2020
e9e2eed
Merge branch 'master' of github.com:jest-community/eslint-plugin-jest…
viestat Jul 27, 2020
032c8bc
docs: regenerate table with the new script
viestat Jul 27, 2020
6029742
fix: edit rule description
viestat Jul 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
83 changes: 42 additions & 41 deletions README.md
Expand Up @@ -127,47 +127,48 @@ installations requiring long-term consistency.

<!-- begin rules list -->

| Rule | Description | Configurations | Fixable |
| ---------------------------------------------------------------------- | --------------------------------------------------------------- | ---------------- | ------------ |
| [consistent-test-it](docs/rules/consistent-test-it.md) | Have control over `test` and `it` usages | | ![fixable][] |
| [expect-expect](docs/rules/expect-expect.md) | Enforce assertion to be made in a test body | ![recommended][] | |
| [lowercase-name](docs/rules/lowercase-name.md) | Enforce lowercase test names | | ![fixable][] |
| [no-alias-methods](docs/rules/no-alias-methods.md) | Disallow alias methods | ![style][] | ![fixable][] |
| [no-commented-out-tests](docs/rules/no-commented-out-tests.md) | Disallow commented out tests | ![recommended][] | |
| [no-conditional-expect](docs/rules/no-conditional-expect.md) | Prevent calling `expect` conditionally | | |
| [no-deprecated-functions](docs/rules/no-deprecated-functions.md) | Disallow use of deprecated functions | | ![fixable][] |
| [no-disabled-tests](docs/rules/no-disabled-tests.md) | Disallow disabled tests | ![recommended][] | |
| [no-duplicate-hooks](docs/rules/no-duplicate-hooks.md) | Disallow duplicate setup and teardown hooks | | |
| [no-export](docs/rules/no-export.md) | Prevent exporting from test files | ![recommended][] | |
| [no-focused-tests](docs/rules/no-focused-tests.md) | Disallow focused tests | ![recommended][] | ![fixable][] |
| [no-hooks](docs/rules/no-hooks.md) | Disallow setup and teardown hooks | | |
| [no-identical-title](docs/rules/no-identical-title.md) | Disallow identical titles | ![recommended][] | |
| [no-if](docs/rules/no-if.md) | Disallow conditional logic | | |
| [no-jasmine-globals](docs/rules/no-jasmine-globals.md) | Disallow Jasmine globals | ![recommended][] | ![fixable][] |
| [no-jest-import](docs/rules/no-jest-import.md) | Disallow importing Jest | ![recommended][] | |
| [no-large-snapshots](docs/rules/no-large-snapshots.md) | disallow large snapshots | | |
| [no-mocks-import](docs/rules/no-mocks-import.md) | Disallow manually importing from **mocks** | ![recommended][] | |
| [no-restricted-matchers](docs/rules/no-restricted-matchers.md) | Disallow specific matchers & modifiers | | |
| [no-standalone-expect](docs/rules/no-standalone-expect.md) | Prevents expects that are outside of an it or test block. | ![recommended][] | |
| [no-test-callback](docs/rules/no-test-callback.md) | Avoid using a callback in asynchronous tests | ![recommended][] | ![suggest][] |
| [no-test-prefixes](docs/rules/no-test-prefixes.md) | Use `.only` and `.skip` over `f` and `x` | ![recommended][] | ![fixable][] |
| [no-test-return-statement](docs/rules/no-test-return-statement.md) | Disallow explicitly returning from tests | | |
| [prefer-called-with](docs/rules/prefer-called-with.md) | Suggest using `toBeCalledWith()` OR `toHaveBeenCalledWith()` | | |
| [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using `expect.assertions()` OR `expect.hasAssertions()` | | ![suggest][] |
| [prefer-hooks-on-top](docs/rules/prefer-hooks-on-top.md) | Suggest to have all hooks at top level | | |
| [prefer-spy-on](docs/rules/prefer-spy-on.md) | Suggest using `jest.spyOn()` | | ![fixable][] |
| [prefer-strict-equal](docs/rules/prefer-strict-equal.md) | Suggest using toStrictEqual() | | ![suggest][] |
| [prefer-to-be-null](docs/rules/prefer-to-be-null.md) | Suggest using `toBeNull()` | ![style][] | ![fixable][] |
| [prefer-to-be-undefined](docs/rules/prefer-to-be-undefined.md) | Suggest using `toBeUndefined()` | ![style][] | ![fixable][] |
| [prefer-to-contain](docs/rules/prefer-to-contain.md) | Suggest using `toContain()` | ![style][] | ![fixable][] |
| [prefer-to-have-length](docs/rules/prefer-to-have-length.md) | Suggest using `toHaveLength()` | ![style][] | ![fixable][] |
| [prefer-todo](docs/rules/prefer-todo.md) | Suggest using `test.todo` | | ![fixable][] |
| [require-to-throw-message](docs/rules/require-to-throw-message.md) | Require a message for `toThrow()` | | |
| [require-top-level-describe](docs/rules/require-top-level-describe.md) | Prevents test cases and hooks to be outside of a describe block | | |
| [valid-describe](docs/rules/valid-describe.md) | Enforce valid `describe()` callback | ![recommended][] | |
| [valid-expect](docs/rules/valid-expect.md) | Enforce valid `expect()` usage | ![recommended][] | |
| [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | Enforce having return statement when testing with promises | ![recommended][] | |
| [valid-title](docs/rules/valid-title.md) | Enforce valid titles | | ![fixable][] |
| Rule | Description | Configurations | Fixable |
| ---------------------------------------------------------------------------- | --------------------------------------------------------------- | ---------------- | ------------ |
| [consistent-test-it](docs/rules/consistent-test-it.md) | Have control over `test` and `it` usages | | ![fixable][] |
| [expect-expect](docs/rules/expect-expect.md) | Enforce assertion to be made in a test body | ![recommended][] | |
| [lowercase-name](docs/rules/lowercase-name.md) | Enforce lowercase test names | | ![fixable][] |
| [no-alias-methods](docs/rules/no-alias-methods.md) | Disallow alias methods | ![style][] | ![fixable][] |
| [no-commented-out-tests](docs/rules/no-commented-out-tests.md) | Disallow commented out tests | ![recommended][] | |
| [no-conditional-expect](docs/rules/no-conditional-expect.md) | Prevent calling `expect` conditionally | | |
| [no-deprecated-functions](docs/rules/no-deprecated-functions.md) | Disallow use of deprecated functions | | ![fixable][] |
| [no-disabled-tests](docs/rules/no-disabled-tests.md) | Disallow disabled tests | ![recommended][] | |
| [no-duplicate-hooks](docs/rules/no-duplicate-hooks.md) | Disallow duplicate setup and teardown hooks | | |
| [no-export](docs/rules/no-export.md) | Prevent exporting from test files | ![recommended][] | |
| [no-focused-tests](docs/rules/no-focused-tests.md) | Disallow focused tests | ![recommended][] | ![fixable][] |
| [no-hooks](docs/rules/no-hooks.md) | Disallow setup and teardown hooks | | |
| [no-identical-title](docs/rules/no-identical-title.md) | Disallow identical titles | ![recommended][] | |
| [no-if](docs/rules/no-if.md) | Disallow conditional logic | | |
| [no-interpolation-in-snapshots](docs/rules/no-interpolation-in-snapshots.md) | Disallow string interpolation inside inline snapshots. | | |
| [no-jasmine-globals](docs/rules/no-jasmine-globals.md) | Disallow Jasmine globals | ![recommended][] | ![fixable][] |
| [no-jest-import](docs/rules/no-jest-import.md) | Disallow importing Jest | ![recommended][] | |
| [no-large-snapshots](docs/rules/no-large-snapshots.md) | disallow large snapshots | | |
| [no-mocks-import](docs/rules/no-mocks-import.md) | Disallow manually importing from **mocks** | ![recommended][] | |
| [no-restricted-matchers](docs/rules/no-restricted-matchers.md) | Disallow specific matchers & modifiers | | |
| [no-standalone-expect](docs/rules/no-standalone-expect.md) | Prevents expects that are outside of an it or test block. | ![recommended][] | |
| [no-test-callback](docs/rules/no-test-callback.md) | Avoid using a callback in asynchronous tests | ![recommended][] | ![suggest][] |
| [no-test-prefixes](docs/rules/no-test-prefixes.md) | Use `.only` and `.skip` over `f` and `x` | ![recommended][] | ![fixable][] |
| [no-test-return-statement](docs/rules/no-test-return-statement.md) | Disallow explicitly returning from tests | | |
| [prefer-called-with](docs/rules/prefer-called-with.md) | Suggest using `toBeCalledWith()` OR `toHaveBeenCalledWith()` | | |
| [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using `expect.assertions()` OR `expect.hasAssertions()` | | ![suggest][] |
| [prefer-hooks-on-top](docs/rules/prefer-hooks-on-top.md) | Suggest to have all hooks at top level | | |
| [prefer-spy-on](docs/rules/prefer-spy-on.md) | Suggest using `jest.spyOn()` | | ![fixable][] |
| [prefer-strict-equal](docs/rules/prefer-strict-equal.md) | Suggest using toStrictEqual() | | ![suggest][] |
| [prefer-to-be-null](docs/rules/prefer-to-be-null.md) | Suggest using `toBeNull()` | ![style][] | ![fixable][] |
| [prefer-to-be-undefined](docs/rules/prefer-to-be-undefined.md) | Suggest using `toBeUndefined()` | ![style][] | ![fixable][] |
| [prefer-to-contain](docs/rules/prefer-to-contain.md) | Suggest using `toContain()` | ![style][] | ![fixable][] |
| [prefer-to-have-length](docs/rules/prefer-to-have-length.md) | Suggest using `toHaveLength()` | ![style][] | ![fixable][] |
| [prefer-todo](docs/rules/prefer-todo.md) | Suggest using `test.todo` | | ![fixable][] |
| [require-to-throw-message](docs/rules/require-to-throw-message.md) | Require a message for `toThrow()` | | |
| [require-top-level-describe](docs/rules/require-top-level-describe.md) | Prevents test cases and hooks to be outside of a describe block | | |
| [valid-describe](docs/rules/valid-describe.md) | Enforce valid `describe()` callback | ![recommended][] | |
| [valid-expect](docs/rules/valid-expect.md) | Enforce valid `expect()` usage | ![recommended][] | |
| [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | Enforce having return statement when testing with promises | ![recommended][] | |
| [valid-title](docs/rules/valid-title.md) | Enforce valid titles | | ![fixable][] |

<!-- end rules list -->

Expand Down
60 changes: 60 additions & 0 deletions docs/rules/no-interpolation-in-snapshots.md
@@ -0,0 +1,60 @@
# Disallow string interpolation inside inline snapshots (`no-interpolation-in-snapshots`)
viestat marked this conversation as resolved.
Show resolved Hide resolved

Prevents the use of string interpolations in snapshots.

## Rule Details

Interpolation prevents snapshots from being updated. Instead, properties should
be overloaded with a matcher by using
[property matchers](https://jestjs.io/docs/en/snapshot-testing#property-matchers).

Examples of **incorrect** code for this rule:

```js
expect(something).toMatchInlineSnapshot(
`Object {
property: ${interpolated}
}`,
);

expect(something).toMatchInlineSnapshot(
{ other: expect.any(Number) },
`Object {
other: Any<Number>,
property: ${interpolated}
}`,
);

expect(errorThrowingFunction).toThrowErrorMatchingInlineSnapshot(
`${interpolated}`,
);
```

Examples of **correct** code for this rule:

```js
expect(something).toMatchInlineSnapshot();

expect(something).toMatchInlineSnapshot(
`Object {
property: 1
}`,
);

expect(something).toMatchInlineSnapshot(
{ property: expect.any(Date) },
`Object {
property: Any<Date>
}`,
);

expect(errorThrowingFunction).toThrowErrorMatchingInlineSnapshot();

expect(errorThrowingFunction).toThrowErrorMatchingInlineSnapshot(
`Error Message`,
);
```

## When Not To Use It

Don't use this rule on non-jest test files.
1 change: 1 addition & 0 deletions src/__tests__/__snapshots__/rules.test.ts.snap
Expand Up @@ -25,6 +25,7 @@ Object {
"jest/no-hooks": "error",
"jest/no-identical-title": "error",
"jest/no-if": "error",
"jest/no-interpolation-in-snapshots": "error",
"jest/no-jasmine-globals": "error",
"jest/no-jest-import": "error",
"jest/no-large-snapshots": "error",
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/rules.test.ts
Expand Up @@ -3,7 +3,7 @@ import { resolve } from 'path';
import plugin from '../';

const ruleNames = Object.keys(plugin.rules);
const numberOfRules = 43;
const numberOfRules = 44;

describe('rules', () => {
it('should have a corresponding doc for each rule', () => {
Expand Down
92 changes: 92 additions & 0 deletions src/rules/__tests__/no-interpolation-in-snapshots.test.ts
@@ -0,0 +1,92 @@
import { TSESLint } from '@typescript-eslint/experimental-utils';
import resolveFrom from 'resolve-from';
import rule from '../no-interpolation-in-snapshots';

const ruleTester = new TSESLint.RuleTester({
parser: resolveFrom(require.resolve('eslint'), 'espree'),
parserOptions: {
ecmaVersion: 2017,
},
});

ruleTester.run('no-interpolation-in-snapshots', rule, {
valid: [
'expect(something).toMatchInlineSnapshot();',
'expect(something).toMatchInlineSnapshot(`No interpolation`);',
'expect(something).toMatchInlineSnapshot({}, `No interpolation`);',
'expect(something);',
'expect(something).not;',
'expect.toHaveAssertions();',
'myObjectWants.toMatchInlineSnapshot({}, `${interpolated}`);',
'myObjectWants.toMatchInlineSnapshot({}, `${interpolated1} ${interpolated2}`);',
'toMatchInlineSnapshot({}, `${interpolated}`);',
'toMatchInlineSnapshot({}, `${interpolated1} ${interpolated2}`);',
'expect(something).toThrowErrorMatchingInlineSnapshot();',
'expect(something).toThrowErrorMatchingInlineSnapshot(`No interpolation`);',
],
invalid: [
{
code: 'expect(something).toMatchInlineSnapshot(`${interpolated}`);',
errors: [
{
endColumn: 58,
column: 41,
messageId: 'noInterpolation',
},
],
},
{
code: 'expect(something).not.toMatchInlineSnapshot(`${interpolated}`);',
errors: [
{
endColumn: 62,
column: 45,
messageId: 'noInterpolation',
},
],
},
{
code: 'expect(something).toMatchInlineSnapshot({}, `${interpolated}`);',
errors: [
{
endColumn: 62,
column: 45,
messageId: 'noInterpolation',
},
],
},
{
code:
'expect(something).not.toMatchInlineSnapshot({}, `${interpolated}`);',
errors: [
{
endColumn: 66,
column: 49,
messageId: 'noInterpolation',
},
],
},
{
code:
'expect(something).toThrowErrorMatchingInlineSnapshot(`${interpolated}`);',
errors: [
{
endColumn: 71,
column: 54,
messageId: 'noInterpolation',
},
],
},
{
code:
'expect(something).not.toThrowErrorMatchingInlineSnapshot(`${interpolated}`);',
errors: [
{
endColumn: 75,
column: 58,
messageId: 'noInterpolation',
},
],
},
],
});