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

jest-snapshot: Ignore indentation for most serialized objects #9203

Merged
merged 4 commits into from Nov 19, 2019
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -28,6 +28,7 @@
- `[jest-snapshot]` Display change counts in annotation lines ([#8982](https://github.com/facebook/jest/pull/8982))
- `[jest-snapshot]` [**BREAKING**] Improve report when the matcher has properties ([#9104](https://github.com/facebook/jest/pull/9104))
- `[jest-snapshot]` Improve colors when snapshots are updatable ([#9132](https://github.com/facebook/jest/pull/9132))
- `[jest-snapshot]` Ignore indentation for most serialized objects ([#9203](https://github.com/facebook/jest/pull/9203))
- `[@jest/test-result]` Create method to create empty `TestResult` ([#8867](https://github.com/facebook/jest/pull/8867))
- `[jest-worker]` [**BREAKING**] Return a promise from `end()`, resolving with the information whether workers exited gracefully ([#8206](https://github.com/facebook/jest/pull/8206))
- `[jest-reporters]` Transform file paths into hyperlinks ([#8980](https://github.com/facebook/jest/pull/8980))
Expand Down
Expand Up @@ -375,6 +375,90 @@ Snapshot: <m>"delete"</>
Received: <t>"insert"</>
`;

exports[`printSnapshotAndReceived ignore indentation markup delete 1`] = `
<m>- Snapshot - 2</>
<t>+ Received + 0</>

<d> <div></>
<m>- <div></>
<d> <h3></>
<d> Ignore indentation for most serialized objects</>
<d> </h3></>
<d> <p></>
<d> Call<Y> </Y></>
<d> <code></>
<d> diffLinesUnified2</>
<d> </code></>
<d> to compare without indentation</>
<d> </p></>
<m>- </div></>
<d> </div></>
`;

exports[`printSnapshotAndReceived ignore indentation markup fall back 1`] = `
<m>- Snapshot - 5</>
<t>+ Received + 7</>

<m>- <pre</>
<m>- className="language-js"</>
<m>- ></>
<m>- for (key in foo) {</>
<t>+ <div></>
<t>+ <pre</>
<t>+ className="language-js"</>
<t>+ ></>
<t>+ for (key in foo) {</>
<d> if (Object.prototype.hasOwnProperty.call(foo, key)) {</>
<d> doSomething(key);</>
<d> }</>
<d> }</>
<m>- </pre></>
<t>+ </pre></>
<t>+ </div></>
`;

exports[`printSnapshotAndReceived ignore indentation markup insert 1`] = `
<m>- Snapshot - 0</>
<t>+ Received + 7</>

<d> <th></>
<t>+ <span></>
<d> when</>
<t>+ </span></>
<t>+ <abbr</>
<t>+ title="ascending from older to newer"</>
<t>+ ></>
<t>+ ↓</>
<t>+ </abbr></>
<d> </th></>
`;

exports[`printSnapshotAndReceived ignore indentation object delete 1`] = `
<m>- Snapshot - 2</>
<t>+ Received + 0</>

<d> Object {</>
<m>- "payload": Object {</>
<d> "text": "Ignore indentation in snapshot",</>
<d> "time": "2019-11-11",</>
<m>- },</>
<d> "type": "CREATE_ITEM",</>
<d> }</>
`;

exports[`printSnapshotAndReceived ignore indentation object insert 1`] = `
<m>- Snapshot - 0</>
<t>+ Received + 2</>

<d> Object {</>
<t>+ "payload": Object {</>
<d> "text": "Ignore indentation in snapshot",</>
<d> "time": "2019-11-11",</>
<t>+ },</>
<d> "type": "CREATE_ITEM",</>
<d> }</>
`;

exports[`printSnapshotAndReceived isLineDiffable false asymmetric matcher 1`] = `
Snapshot: <m>null</>
Received: <t>Object {</>
Expand Down
268 changes: 268 additions & 0 deletions packages/jest-snapshot/src/__tests__/dedentLines.test.ts
@@ -0,0 +1,268 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import format = require('pretty-format');
import {dedentLines} from '../dedentLines';

const $$typeof = Symbol.for('react.test.json');
const plugins = [format.plugins.ReactTestComponent];

const formatLines2 = val => format(val, {indent: 2, plugins}).split('\n');
const formatLines0 = val => format(val, {indent: 0, plugins}).split('\n');

describe('dedentLines non-null', () => {
test('no lines', () => {
const indented = [];
const dedented = indented;

expect(dedentLines(indented)).toEqual(dedented);
});

test('one line empty string', () => {
const indented = [''];
const dedented = indented;

expect(dedentLines(indented)).toEqual(dedented);
});

test('one line empty object', () => {
const val = {};
const indented = formatLines2(val);
const dedented = formatLines0(val);

expect(dedentLines(indented)).toEqual(dedented);
});

test('one line self-closing element', () => {
const val = {
$$typeof,
children: null,
type: 'br',
};
const indented = formatLines2(val);
const dedented = formatLines0(val);

expect(dedentLines(indented)).toEqual(dedented);
});

test('object value empty string', () => {
const val = {
key: '',
};
const indented = formatLines2(val);
const dedented = formatLines0(val);

expect(dedentLines(indented)).toEqual(dedented);
});

test('object value string includes double-quote marks', () => {
const val = {
key: '"Always bet on JavaScript",',
};
const indented = formatLines2(val);
const dedented = formatLines0(val);

expect(dedentLines(indented)).toEqual(dedented);
});

test('markup with props and text', () => {
const val = {
$$typeof,
children: [
{
$$typeof,
props: {
alt: 'Jest logo',
src: 'jest.svg',
},
type: 'img',
},
{
$$typeof,
children: ['Delightful JavaScript testing'],
type: 'h2',
},
],
type: 'header',
};
const indented = formatLines2(val);
const dedented = formatLines0(val);

expect(dedentLines(indented)).toEqual(dedented);
});

test('markup with components as props', () => {
// https://daveceddia.com/pluggable-slots-in-react-components/
const val = {
$$typeof,
children: null,
props: {
content: {
$$typeof,
children: ['main content here'],
type: 'Content',
},
sidebar: {
$$typeof,
children: null,
props: {
user: '0123456789abcdef',
},
type: 'UserStats',
},
},
type: 'Body',
};
const indented = formatLines2(val);
const dedented = formatLines0(val);

expect(dedentLines(indented)).toEqual(dedented);
});
});

describe('dedentLines null', () => {
test('object key multi-line', () => {
const val = {
'multi\nline\nstring': false,
};
const indented = formatLines2(val);

expect(dedentLines(indented)).toEqual(null);
});

test('object value multi-line', () => {
const val = {
key: 'multi\nline\nstring',
};
const indented = formatLines2(val);

expect(dedentLines(indented)).toEqual(null);
});

test('object key and value multi-line', () => {
const val = {
'multi\nline\nstring': '\nleading newline',
};
const indented = formatLines2(val);

expect(dedentLines(indented)).toEqual(null);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's quite a bunch of repetition in these tests. It's quite readable and I don't say it's bad. However, have you considered using test.each where it makes sense (e.g. for smaller inputs)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, super suggestion!

});

test('markup prop multi-line', () => {
const val = {
$$typeof,
children: null,
props: {
alt: 'trailing newline\n',
src: 'jest.svg',
},
type: 'img',
};
const indented = formatLines2(val);

expect(dedentLines(indented)).toEqual(null);
});

test('markup prop component with multi-line text', () => {
// https://daveceddia.com/pluggable-slots-in-react-components/
const val = {
$$typeof,
children: [
{
$$typeof,
children: null,
props: {
content: {
$$typeof,
children: ['\n'],
type: 'Content',
},
sidebar: {
$$typeof,
children: null,
props: {
user: '0123456789abcdef',
},
type: 'UserStats',
},
},
type: 'Body',
},
],
type: 'main',
};
const indented = formatLines2(val);

expect(dedentLines(indented)).toEqual(null);
});

test('markup text multi-line', () => {
const text = [
'for (key in foo) {',
' if (Object.prototype.hasOwnProperty.call(foo, key)) {',
' doSomething(key);',
' }',
'}',
].join('\n');
const val = {
$$typeof,
children: [
{
$$typeof,
children: [text],
props: {
className: 'language-js',
},
type: 'pre',
},
],
type: 'div',
};
const indented = formatLines2(val);

expect(dedentLines(indented)).toEqual(null);
});

test('markup text multiple lines', () => {
const lines = [
'for (key in foo) {',
' if (Object.prototype.hasOwnProperty.call(foo, key)) {',
' doSomething(key);',
' }',
'}',
];
const val = {
$$typeof,
children: [
{
$$typeof,
children: lines,
props: {
className: 'language-js',
},
type: 'pre',
},
],
type: 'div',
};
const indented = formatLines2(val);

expect(dedentLines(indented)).toEqual(null);
});

test('markup unclosed self-closing start tag', () => {
const indented = ['<img', ' alt="Jest logo"', ' src="jest.svg"'];

expect(dedentLines(indented)).toEqual(null);
});

test('markup unclosed because no end tag', () => {
const indented = ['<p>', ' Delightful JavaScript testing'];

expect(dedentLines(indented)).toEqual(null);
});
});