diff --git a/desktop/flipper-plugin/src/ui/DataFormatter.tsx b/desktop/flipper-plugin/src/ui/DataFormatter.tsx index cdddbfa6d..b0f7a7afe 100644 --- a/desktop/flipper-plugin/src/ui/DataFormatter.tsx +++ b/desktop/flipper-plugin/src/ui/DataFormatter.tsx @@ -13,7 +13,7 @@ import { CopyOutlined, } from '@ant-design/icons'; import {Button, Typography} from 'antd'; -import {pad} from 'lodash'; +import {isPlainObject, pad} from 'lodash'; import React, {createElement, Fragment, isValidElement, useState} from 'react'; import {tryGetFlipperLibImplementation} from '../plugin/FlipperLib'; import {safeStringify} from '../utils/safeStringify'; @@ -97,6 +97,9 @@ export const DataFormatter = { }, prettyPrintJson(value: any) { + if (isValidElement(value)) { + return value; + } if (typeof value === 'string' && value.length >= 2) { const last = value.length - 1; // kinda looks like json @@ -112,7 +115,11 @@ export const DataFormatter = { } } } - if (typeof value === 'object' && value !== null) { + if ( + typeof value === 'object' && + value !== null && + (Array.isArray(value) || isPlainObject(value)) + ) { try { // Note: we don't need to be inserted
's in the output, but assume the text container uses // white-space: pre-wrap (or pre) @@ -137,7 +144,8 @@ export const DataFormatter = { }, }; -function TruncateHelper({ +// exported for testing +export function TruncateHelper({ value, maxLength, }: { diff --git a/desktop/flipper-plugin/src/ui/__tests__/DataFormatter.node.tsx b/desktop/flipper-plugin/src/ui/__tests__/DataFormatter.node.tsx index 5f465bd06..b41d7a802 100644 --- a/desktop/flipper-plugin/src/ui/__tests__/DataFormatter.node.tsx +++ b/desktop/flipper-plugin/src/ui/__tests__/DataFormatter.node.tsx @@ -7,7 +7,10 @@ * @format */ -import {DataFormatter} from '../DataFormatter'; +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"`); @@ -126,7 +129,7 @@ test('linkify formatter', () => { expect(linkify('fb.com')).toMatchInlineSnapshot(`"fb.com"`); }); -test('linkify formatter', () => { +test('jsonify formatter', () => { const jsonify = (value: any) => DataFormatter.format(value, DataFormatter.prettyPrintJson); @@ -162,3 +165,174 @@ test('linkify formatter', () => { `); }); + +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(hi)).toMatchInlineSnapshot(` + + hi + + `); +}); + +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(` + + `); +}); + +test('render truncate helper', () => { + const res = render( + , + ); + expect(res.baseElement).toMatchInlineSnapshot(` + +
+ !! C + + +
+ + `); + act(() => { + fireEvent.click(res.getAllByText(/and \d+ more/)[0]); + }); + expect(res.baseElement).toMatchInlineSnapshot(` + +
+ !! COOL CONTENT !! + + +
+ + `); +});