-
Notifications
You must be signed in to change notification settings - Fork 237
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: create
prefer-snapshot-hint
rule (#1012)
* feat: create `prefer-snapshot-hint` rule * feat(prefer-snapshot-hint): check nested scope for multiple snapshot matchers * fix: update import * test: update number
- Loading branch information
Showing
6 changed files
with
1,020 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
# Prefer including a hint with external snapshots (`prefer-snapshot-hint`) | ||
|
||
When working with external snapshot matchers it's considered best practice to | ||
provide a hint (as the last argument to the matcher) describing the expected | ||
snapshot content that will be included in the snapshots name by Jest. | ||
|
||
This makes it easier for reviewers to verify the snapshots during review, and | ||
for anyone to know whether an outdated snapshot is the correct behavior before | ||
updating. | ||
|
||
## Rule details | ||
|
||
This rule looks for any use of an external snapshot matcher (e.g. | ||
`toMatchSnapshot` and `toThrowErrorMatchingSnapshot`) and checks if they include | ||
a snapshot hint. | ||
|
||
## Options | ||
|
||
### `'always'` | ||
|
||
Require a hint to _always_ be provided when using external snapshot matchers. | ||
|
||
Examples of **incorrect** code for the `'always'` option: | ||
|
||
```js | ||
const snapshotOutput = ({ stdout, stderr }) => { | ||
expect(stdout).toMatchSnapshot(); | ||
expect(stderr).toMatchSnapshot(); | ||
}; | ||
|
||
describe('cli', () => { | ||
describe('--version flag', () => { | ||
it('prints the version', async () => { | ||
snapshotOutput(await runCli(['--version'])); | ||
}); | ||
}); | ||
|
||
describe('--config flag', () => { | ||
it('reads the config', async () => { | ||
const { stdout, parsedConfig } = await runCli([ | ||
'--config', | ||
'jest.config.js', | ||
]); | ||
|
||
expect(stdout).toMatchSnapshot(); | ||
expect(parsedConfig).toMatchSnapshot(); | ||
}); | ||
|
||
it('prints nothing to stderr', async () => { | ||
const { stderr } = await runCli(['--config', 'jest.config.js']); | ||
|
||
expect(stderr).toMatchSnapshot(); | ||
}); | ||
|
||
describe('when the file does not exist', () => { | ||
it('throws an error', async () => { | ||
await expect( | ||
runCli(['--config', 'does-not-exist.js']), | ||
).rejects.toThrowErrorMatchingSnapshot(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
``` | ||
|
||
Examples of **correct** code for the `'always'` option: | ||
|
||
```js | ||
const snapshotOutput = ({ stdout, stderr }, hints) => { | ||
expect(stdout).toMatchSnapshot({}, `stdout: ${hints.stdout}`); | ||
expect(stderr).toMatchSnapshot({}, `stderr: ${hints.stderr}`); | ||
}; | ||
|
||
describe('cli', () => { | ||
describe('--version flag', () => { | ||
it('prints the version', async () => { | ||
snapshotOutput(await runCli(['--version']), { | ||
stdout: 'version string', | ||
stderr: 'empty', | ||
}); | ||
}); | ||
}); | ||
|
||
describe('--config flag', () => { | ||
it('reads the config', async () => { | ||
const { stdout } = await runCli(['--config', 'jest.config.js']); | ||
|
||
expect(stdout).toMatchSnapshot({}, 'stdout: config settings'); | ||
}); | ||
|
||
it('prints nothing to stderr', async () => { | ||
const { stderr } = await runCli(['--config', 'jest.config.js']); | ||
|
||
expect(stderr).toMatchInlineSnapshot(); | ||
}); | ||
|
||
describe('when the file does not exist', () => { | ||
it('throws an error', async () => { | ||
await expect( | ||
runCli(['--config', 'does-not-exist.js']), | ||
).rejects.toThrowErrorMatchingSnapshot('stderr: config error'); | ||
}); | ||
}); | ||
}); | ||
}); | ||
``` | ||
|
||
### `'multi'` (default) | ||
|
||
Require a hint to be provided when there are multiple external snapshot matchers | ||
within the scope (meaning it includes nested calls). | ||
|
||
Examples of **incorrect** code for the `'multi'` option: | ||
|
||
```js | ||
const snapshotOutput = ({ stdout, stderr }) => { | ||
expect(stdout).toMatchSnapshot(); | ||
expect(stderr).toMatchSnapshot(); | ||
}; | ||
|
||
describe('cli', () => { | ||
describe('--version flag', () => { | ||
it('prints the version', async () => { | ||
snapshotOutput(await runCli(['--version'])); | ||
}); | ||
}); | ||
|
||
describe('--config flag', () => { | ||
it('reads the config', async () => { | ||
const { stdout, parsedConfig } = await runCli([ | ||
'--config', | ||
'jest.config.js', | ||
]); | ||
|
||
expect(stdout).toMatchSnapshot(); | ||
expect(parsedConfig).toMatchSnapshot(); | ||
}); | ||
|
||
it('prints nothing to stderr', async () => { | ||
const { stderr } = await runCli(['--config', 'jest.config.js']); | ||
|
||
expect(stderr).toMatchSnapshot(); | ||
}); | ||
}); | ||
}); | ||
``` | ||
|
||
Examples of **correct** code for the `'multi'` option: | ||
|
||
```js | ||
const snapshotOutput = ({ stdout, stderr }, hints) => { | ||
expect(stdout).toMatchSnapshot({}, `stdout: ${hints.stdout}`); | ||
expect(stderr).toMatchSnapshot({}, `stderr: ${hints.stderr}`); | ||
}; | ||
|
||
describe('cli', () => { | ||
describe('--version flag', () => { | ||
it('prints the version', async () => { | ||
snapshotOutput(await runCli(['--version']), { | ||
stdout: 'version string', | ||
stderr: 'empty', | ||
}); | ||
}); | ||
}); | ||
|
||
describe('--config flag', () => { | ||
it('reads the config', async () => { | ||
const { stdout } = await runCli(['--config', 'jest.config.js']); | ||
|
||
expect(stdout).toMatchSnapshot(); | ||
}); | ||
|
||
it('prints nothing to stderr', async () => { | ||
const { stderr } = await runCli(['--config', 'jest.config.js']); | ||
|
||
expect(stderr).toMatchInlineSnapshot(); | ||
}); | ||
|
||
describe('when the file does not exist', () => { | ||
it('throws an error', async () => { | ||
await expect( | ||
runCli(['--config', 'does-not-exist.js']), | ||
).rejects.toThrowErrorMatchingSnapshot(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.