diff --git a/lib/static/components/details.jsx b/lib/static/components/details.jsx index 86e3a121b..c055e9775 100644 --- a/lib/static/components/details.jsx +++ b/lib/static/components/details.jsx @@ -3,7 +3,8 @@ import React, {useContext, useLayoutEffect, useState} from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import {isEmpty, isFunction} from 'lodash'; +import stringify from 'json-stringify-safe'; +import {isEmpty, isFunction, isPlainObject} from 'lodash'; import {Disclosure} from '@gravity-ui/uikit'; import {MeasurementContext} from './measurement-context'; @@ -28,8 +29,10 @@ export default function Details(props) { return null; } - const children = props.asHtml ? null : getContent(); - const extraProps = props.asHtml ? {dangerouslySetInnerHTML: {__html: getContent()}} : {}; + const content = getContent(); + const isObjectContent = isPlainObject(content) && !React.isValidElement(content); + const children = props.asHtml ? null : isObjectContent ? stringify(content) : content; + const extraProps = props.asHtml ? {dangerouslySetInnerHTML: {__html: content}} : {}; return
{children} diff --git a/lib/static/new-ui/components/ErrorInfo/index.tsx b/lib/static/new-ui/components/ErrorInfo/index.tsx index 8e8cc972a..589ba991b 100644 --- a/lib/static/new-ui/components/ErrorInfo/index.tsx +++ b/lib/static/new-ui/components/ErrorInfo/index.tsx @@ -4,9 +4,10 @@ import escapeHtml from 'escape-html'; import React, {ReactNode} from 'react'; import styles from './index.module.css'; +import stringify from 'json-stringify-safe'; interface ErrorInfoProps { - name: string; + name: unknown; stack?: string; className?: string; style?: React.CSSProperties; @@ -17,5 +18,15 @@ export function ErrorInfo(props: ErrorInfoProps): ReactNode { reset: ['eee', '00000000'] }); - return
; + let errorName = props.name; + + if (typeof errorName !== 'string') { + try { + errorName = stringify(errorName); + } catch { + errorName = String(errorName); + } + } + + return
; } diff --git a/test/unit/lib/static/components/details.jsx b/test/unit/lib/static/components/details.jsx index eae489a2a..4efdc18e1 100644 --- a/test/unit/lib/static/components/details.jsx +++ b/test/unit/lib/static/components/details.jsx @@ -78,4 +78,32 @@ describe('
', () => { const expectedHtml = '
' + props.content + '
'; assert.equal(component.container.querySelector('.details__content').parentNode.innerHTML, expectedHtml); }); + + it('should stringify plain object content', async () => { + const user = userEvent.setup(); + const content = {foo: 'bar'}; + content.self = content; + const props = { + title: 'some-title', + content: () => content + }; + + const component = render(
); + await user.click(component.container.querySelector('.details__summary')); + + assert.equal(component.container.querySelector('.details__content').textContent, '{"foo":"bar","self":"[Circular ~]"}'); + }); + + it('should render react node content as is', async () => { + const user = userEvent.setup(); + const props = { + title: 'some-title', + content: () => some content + }; + + const component = render(
); + await user.click(component.container.querySelector('.details__summary')); + + assert.equal(component.container.querySelector('.some-content').textContent, 'some content'); + }); });