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

fix(no-large-snapshots): support inline snapshots #186

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 4 additions & 3 deletions docs/rules/no-large-snapshots.md
Expand Up @@ -22,9 +22,10 @@ parserOptions: {

## Rule Details

This rule looks at all Jest snapshot files (files with `.snap` extension) and
validates that each stored snapshot within those files does not exceed 50 lines
(by default, this is configurable as explained in `Options` section below).
This rule looks at all Jest inline and external snapshots (files with `.snap`
extension) and validates that each stored snapshot within those files does not
exceed 50 lines (by default, this is configurable as explained in `Options`
section below).

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

Expand Down
53 changes: 52 additions & 1 deletion rules/__tests__/no-large-snapshots.test.js
@@ -1,6 +1,57 @@
'use strict';

const noLargeSnapshots = require('../no-large-snapshots').create;
const RuleTester = require('eslint').RuleTester;
const rule = require('../no-large-snapshots');
const noLargeSnapshots = rule.create;

const ruleTester = new RuleTester({
parserOptions: {
ecmaVersion: 2015,
},
});

ruleTester.run('no-large-snapshots', rule, {
valid: [
{
filename: 'mock.js',
code: `expect(something).toMatchInlineSnapshot(\`\n${'line\n'.repeat(
2
)}\`);`,
},
{
filename: 'mock.js',
code: `expect(something).toThrowErrorMatchingInlineSnapshot(\`\n${'line\n'.repeat(
2
)}\`);`,
},
],
invalid: [
{
filename: 'mock.js',
code: `expect(something).toMatchInlineSnapshot(\`\n${'line\n'.repeat(
50
)}\`);`,
errors: [
{
message:
'Expected Jest snapshot to be smaller than 50 lines but was 51 lines long',
},
],
},
{
filename: 'mock.js',
code: `expect(something).toThrowErrorMatchingInlineSnapshot(\`\n${'line\n'.repeat(
50
)}\`);`,
errors: [
{
message:
'Expected Jest snapshot to be smaller than 50 lines but was 51 lines long',
},
],
},
],
});

// was not able to use https://eslint.org/docs/developer-guide/nodejs-api#ruletester for these because there is no way to configure RuleTester to run non .js files
describe('no-large-snapshots', () => {
Expand Down
52 changes: 34 additions & 18 deletions rules/no-large-snapshots.js
Expand Up @@ -2,6 +2,27 @@

const getDocsUrl = require('./util').getDocsUrl;

const reportOnViolation = (context, node) => {
const lineLimit =
context.options[0] && Number.isFinite(context.options[0].maxSize)
? context.options[0].maxSize
: 50;
const startLine = node.loc.start.line;
const endLine = node.loc.end.line;
const lineCount = endLine - startLine;

if (lineCount > lineLimit) {
context.report({
message:
lineLimit === 0
? 'Expected to not encounter a Jest snapshot but was found with {{ lineCount }} lines long'
: 'Expected Jest snapshot to be smaller than {{ lineLimit }} lines but was {{ lineCount }} lines long',
data: { lineLimit, lineCount },
node,
});
}
};

module.exports = {
meta: {
docs: {
Expand All @@ -10,26 +31,21 @@ module.exports = {
},
create(context) {
if (context.getFilename().endsWith('.snap')) {
const lineLimit =
context.options[0] && Number.isFinite(context.options[0].maxSize)
? context.options[0].maxSize
: 50;

return {
ExpressionStatement(node) {
const startLine = node.loc.start.line;
const endLine = node.loc.end.line;
const lineCount = endLine - startLine;

if (lineCount > lineLimit) {
context.report({
message:
lineLimit === 0
? 'Expected to not encounter a Jest snapshot but was found with {{ lineCount }} lines long'
: 'Expected Jest snapshot to be smaller than {{ lineLimit }} lines but was {{ lineCount }} lines long',
data: { lineLimit, lineCount },
node,
});
reportOnViolation(context, node);
},
};
} else if (context.getFilename().endsWith('.js')) {
return {
CallExpression(node) {
const propertyName =
node.callee.property && node.callee.property.name;
if (
propertyName === 'toMatchInlineSnapshot' ||
propertyName === 'toThrowErrorMatchingInlineSnapshot'
) {
reportOnViolation(context, node);
}
},
};
Expand Down