Files
flipper/desktop/flipper-plugin/src/ui/__tests__/DataFormatter.node.tsx
Michel Weststrate 1060ea6e9e Fix message truncating failing in production builds
Summary: Message truncated worked in devs build, but failed in production build, as it JSON formatted React elements in prod build (incorreclty), while it didn't do so in Dev builds, as in dev that generates an exception (undesired) meaning the serialisation gets skipped (desired).

Reviewed By: passy, nikoant, priteshrnandgaonkar

Differential Revision: D27467280

fbshipit-source-id: 1f8e0ca4750464c778c33b69a8cf13d05f019143
2021-03-31 09:24:32 -07:00

339 lines
9.2 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {render, fireEvent} from '@testing-library/react';
import React from 'react';
import {act} from 'react-dom/test-utils';
import {DataFormatter, TruncateHelper} from '../DataFormatter';
test('default formatter', () => {
expect(DataFormatter.format(true)).toMatchInlineSnapshot(`"true"`);
expect(DataFormatter.format(false)).toMatchInlineSnapshot(`"false"`);
expect(DataFormatter.format(3)).toMatchInlineSnapshot(`"3"`);
expect(DataFormatter.format(null)).toMatchInlineSnapshot(`""`);
expect(DataFormatter.format(undefined)).toMatchInlineSnapshot(`""`);
expect(
DataFormatter.format(new Date(2020, 2, 3, 5, 8, 4, 244654)),
).toMatchInlineSnapshot(`"05:12:08.654"`);
expect(DataFormatter.format('test')).toMatchInlineSnapshot(`"test"`);
expect(DataFormatter.format({hello: 'world'})).toMatchInlineSnapshot(`
"{
\\"hello\\": \\"world\\"
}"
`);
expect(DataFormatter.format({hello: ['world']})).toMatchInlineSnapshot(`
"{
\\"hello\\": [
\\"world\\"
]
}"
`);
expect(DataFormatter.format(new Map([['hello', 'world']])))
.toMatchInlineSnapshot(`
"[
[
\\"hello\\",
\\"world\\"
]
]"
`);
expect(DataFormatter.format(new Set([['hello', 'world']])))
.toMatchInlineSnapshot(`
"[
[
\\"hello\\",
\\"world\\"
]
]"
`);
const unserializable: any = {};
unserializable.x = unserializable;
expect(DataFormatter.format(unserializable)).toMatchInlineSnapshot(`
"<Failed to serialize: TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
--- property 'x' closes the circle>"
`);
// make sure we preserve newlines
expect(DataFormatter.format('Test 123\n\t\t345\n\t\t67'))
.toMatchInlineSnapshot(`
"Test 123
345
67"
`);
});
test('linkify formatter', () => {
const linkify = (value: any) =>
DataFormatter.format(value, DataFormatter.linkify);
// verify fallback
expect(linkify({hello: 'world'})).toMatchInlineSnapshot(`
"{
\\"hello\\": \\"world\\"
}"
`);
expect(linkify('hi there!')).toMatchInlineSnapshot(`"hi there!"`);
expect(linkify('https://www.google.com')).toMatchInlineSnapshot(`
<React.Fragment>
<ForwardRef(Link)
href="https://www.google.com"
>
https://www.google.com
</ForwardRef(Link)>
</React.Fragment>
`);
expect(linkify('www.google.com')).toMatchInlineSnapshot(`"www.google.com"`);
expect(linkify('stuff.google.com')).toMatchInlineSnapshot(
`"stuff.google.com"`,
);
expect(linkify('test https://www.google.com test')).toMatchInlineSnapshot(`
<React.Fragment>
test
<ForwardRef(Link)
href="https://www.google.com"
>
https://www.google.com
</ForwardRef(Link)>
test
</React.Fragment>
`);
expect(linkify('https://www.google.com test http://fb.com'))
.toMatchInlineSnapshot(`
<React.Fragment>
<ForwardRef(Link)
href="https://www.google.com"
>
https://www.google.com
</ForwardRef(Link)>
test
<ForwardRef(Link)
href="http://fb.com"
>
http://fb.com
</ForwardRef(Link)>
</React.Fragment>
`);
expect(linkify('fb.com')).toMatchInlineSnapshot(`"fb.com"`);
});
test('jsonify formatter', () => {
const jsonify = (value: any) =>
DataFormatter.format(value, DataFormatter.prettyPrintJson);
expect(jsonify({hello: 'world'})).toMatchInlineSnapshot(`
"{
\\"hello\\": \\"world\\"
}"
`);
expect(jsonify([{hello: 'world'}])).toMatchInlineSnapshot(`
"[
{
\\"hello\\": \\"world\\"
}
]"
`);
// linkify json!
expect(
DataFormatter.format({hello: 'http://facebook.com'}, [
DataFormatter.prettyPrintJson,
DataFormatter.linkify,
]),
).toMatchInlineSnapshot(`
<React.Fragment>
{
"hello": "
<ForwardRef(Link)
href="http://facebook.com"
>
http://facebook.com
</ForwardRef(Link)>
"
}
</React.Fragment>
`);
});
test("jsonify doesn't process react elements", () => {
const jsonify = (value: any) =>
DataFormatter.format(value, DataFormatter.prettyPrintJson);
expect(jsonify('abcde')).toEqual('abcde');
expect(jsonify('{ a: 1 }')).toMatchInlineSnapshot(`"{ a: 1 }"`);
expect(jsonify({a: 1})).toMatchInlineSnapshot(`
"{
\\"a\\": 1
}"
`);
expect(jsonify(<span>hi</span>)).toMatchInlineSnapshot(`
<span>
hi
</span>
`);
});
test('truncate formatter', () => {
const truncate = (value: any) =>
DataFormatter.format(value, DataFormatter.truncate(5));
expect(truncate({test: true})).toMatchInlineSnapshot(`
"{
\\"test\\": true
}"
`);
expect(truncate('abcde')).toEqual('abcde');
expect(truncate('abcdefghi')).toMatchInlineSnapshot(`
<TruncateHelper
maxLength={5}
value="abcdefghi"
/>
`);
});
test('render truncate helper', () => {
const res = render(
<TruncateHelper value="!! COOL CONTENT !!" maxLength={4} />,
);
expect(res.baseElement).toMatchInlineSnapshot(`
<body>
<div>
!! C
<button
class="ant-btn ant-btn-text ant-btn-sm"
style="margin-left: 4px;"
type="button"
>
<span
aria-label="caret-right"
class="anticon anticon-caret-right"
role="img"
>
<svg
aria-hidden="true"
data-icon="caret-right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M715.8 493.5L335 165.1c-14.2-12.2-35-1.2-35 18.5v656.8c0 19.7 20.8 30.7 35 18.5l380.8-328.4c10.9-9.4 10.9-27.6 0-37z"
/>
</svg>
</span>
<span>
and 14 more
</span>
</button>
<button
class="ant-btn ant-btn-text ant-btn-sm"
style="margin-left: 4px;"
type="button"
>
<span
aria-label="copy"
class="anticon anticon-copy"
role="img"
>
<svg
aria-hidden="true"
data-icon="copy"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"
/>
</svg>
</span>
<span>
copy
</span>
</button>
</div>
</body>
`);
act(() => {
fireEvent.click(res.getAllByText(/and \d+ more/)[0]);
});
expect(res.baseElement).toMatchInlineSnapshot(`
<body>
<div>
!! COOL CONTENT !!
<button
class="ant-btn ant-btn-text ant-btn-sm"
style="margin-left: 4px;"
type="button"
>
<span
aria-label="caret-up"
class="anticon anticon-caret-up"
role="img"
>
<svg
aria-hidden="true"
data-icon="caret-up"
fill="currentColor"
focusable="false"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M858.9 689L530.5 308.2c-9.4-10.9-27.5-10.9-37 0L165.1 689c-12.2 14.2-1.2 35 18.5 35h656.8c19.7 0 30.7-20.8 18.5-35z"
/>
</svg>
</span>
<span>
collapse
</span>
</button>
<button
class="ant-btn ant-btn-text ant-btn-sm"
style="margin-left: 4px;"
type="button"
>
<span
aria-label="copy"
class="anticon anticon-copy"
role="img"
>
<svg
aria-hidden="true"
data-icon="copy"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"
/>
</svg>
</span>
<span>
copy
</span>
</button>
</div>
</body>
`);
});