Fix #5250 Json data is not visible properly in entity details page -> sample data tab (#5284)

This commit is contained in:
Sachin Chaurasiya 2022-06-04 13:15:28 +05:30 committed by GitHub
parent 3f682b6685
commit a62e57c6dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 283 additions and 4 deletions

View File

@ -0,0 +1,92 @@
/*
* Copyright 2021 Collate
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { fireEvent, render } from '@testing-library/react';
import React from 'react';
import ReactDOM from 'react-dom';
import { MemoryRouter } from 'react-router-dom';
import SchemaModal from './SchemaModal';
const onClose = jest.fn();
const mockProp = {
onClose,
data: {},
};
jest.mock('../../schema-editor/SchemaEditor', () => {
return jest.fn().mockReturnValue(<div>SchemaEditor</div>);
});
describe('Test Schema modal component', () => {
beforeAll(() => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
ReactDOM.createPortal = jest.fn().mockImplementation((element, _node) => {
return element;
});
});
it('Should render schema modal component', async () => {
const { findByTestId } = render(<SchemaModal {...mockProp} />, {
wrapper: MemoryRouter,
});
const modalContainer = await findByTestId('schema-modal');
expect(modalContainer).toBeInTheDocument();
const modalBackdrop = await findByTestId('schema-modal-backdrop');
expect(modalBackdrop).toBeInTheDocument();
const header = await findByTestId('schema-modal-header');
expect(header).toBeInTheDocument();
const modalCloseButton = await findByTestId('schema-modal-close-button');
expect(modalCloseButton).toBeInTheDocument();
const modalBody = await findByTestId('schem-modal-body');
expect(modalBody).toBeInTheDocument();
});
it('Should call onClose method on click of backedrop', async () => {
const { findByTestId } = render(<SchemaModal {...mockProp} />, {
wrapper: MemoryRouter,
});
const modalBackdrop = await findByTestId('schema-modal-backdrop');
expect(modalBackdrop).toBeInTheDocument();
fireEvent.click(modalBackdrop);
expect(onClose).toBeCalled();
});
it('Should call onClose method on click of close button', async () => {
const { findByTestId } = render(<SchemaModal {...mockProp} />, {
wrapper: MemoryRouter,
});
const modalCloseButton = await findByTestId('schema-modal-close-button');
expect(modalCloseButton).toBeInTheDocument();
fireEvent.click(modalCloseButton);
expect(onClose).toBeCalled();
});
});

View File

@ -0,0 +1,74 @@
/*
* Copyright 2021 Collate
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import classNames from 'classnames';
import React, { FC, HTMLAttributes } from 'react';
import ReactDOM from 'react-dom';
import SchemaEditor from '../../schema-editor/SchemaEditor';
interface Prop extends HTMLAttributes<HTMLDivElement> {
onClose: () => void;
// eslint-disable-next-line
data: any;
}
const SchemaModal: FC<Prop> = ({ className, onClose, data }) => {
return ReactDOM.createPortal(
<dialog
className={classNames('tw-modal', className)}
data-testid="schema-modal">
<div
className="tw-modal-backdrop"
data-testid="schema-modal-backdrop"
onClick={onClose}
/>
<div className="tw-modal-container tw-w-8/12">
<div className={classNames('tw-modal-header')}>
<p className="tw-modal-title" data-testid="schema-modal-header">
JSON data
</p>
<div className="tw-flex">
<svg
className="tw-w-6 tw-h-6 tw-ml-1 tw-cursor-pointer"
data-testid="schema-modal-close-button"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
onClick={onClose}>
<path
d="M6 18L18 6M6 6l12 12"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
/>
</svg>
</div>
</div>
<div
className={classNames('tw-modal-body')}
data-testid="schem-modal-body">
<SchemaEditor
className="tw-border tw-border-main tw-rounded-md tw-py-4"
editorClass="custom-entity-schema"
value={data}
/>
</div>
</div>
</dialog>,
document.body
);
};
export default SchemaModal;

View File

@ -0,0 +1,63 @@
/*
* Copyright 2021 Collate
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { fireEvent, render } from '@testing-library/react';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import { RowData } from './RowData';
jest.mock('../Modals/SchemaModal/SchemaModal', () => {
return jest
.fn()
.mockReturnValue(<div data-testid="schema-modal">Schema Modal</div>);
});
const mockProp = {
data: {},
};
describe('Test RowData Component', () => {
it('Should render json data if data is typeof object', async () => {
const { findByTestId } = render(<RowData {...mockProp} />, {
wrapper: MemoryRouter,
});
const jsonData = await findByTestId('json-object');
expect(jsonData).toBeInTheDocument();
fireEvent.click(jsonData);
expect(await findByTestId('schema-modal')).toBeInTheDocument();
});
it('Should render string data if data is not a tyeopf object', async () => {
const { findByTestId } = render(<RowData data="data" />, {
wrapper: MemoryRouter,
});
const stringData = await findByTestId('string-data');
expect(stringData).toBeInTheDocument();
});
it('Should render fallback data if no data is there', async () => {
const { findByTestId } = render(<RowData data={undefined} />, {
wrapper: MemoryRouter,
});
const emptyData = await findByTestId('empty-data');
expect(emptyData).toBeInTheDocument();
});
});

View File

@ -0,0 +1,46 @@
/*
* Copyright 2021 Collate
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { Fragment, useState } from 'react';
import SchemaModal from '../Modals/SchemaModal/SchemaModal';
// eslint-disable-next-line
export const RowData = ({ data }: { data: any }) => {
const [isFullView, setIsFullView] = useState<boolean>(false);
const onClose = () => setIsFullView(false);
const onOpen = () => setIsFullView(true);
// eslint-disable-next-line
const getDataElement = (rowValue: any) => {
if (typeof rowValue === 'object') {
return (
<p
className="tw-w-52 tw-truncate tw-cursor-pointer"
data-testid="json-object"
onClick={onOpen}>
{JSON.stringify(rowValue)}
</p>
);
}
return <p data-testid="string-data">{rowValue.toString()}</p>;
};
return (
<Fragment>
{data ? getDataElement(data) : <p data-testid="empty-data">--</p>}
{isFullView && <SchemaModal data={data} onClose={onClose} />}
</Fragment>
);
};

View File

@ -28,15 +28,19 @@ import React, {
import { TableData } from '../../generated/entity/data/table'; import { TableData } from '../../generated/entity/data/table';
import { withLoader } from '../../hoc/withLoader'; import { withLoader } from '../../hoc/withLoader';
import { isEven } from '../../utils/CommonUtils'; import { isEven } from '../../utils/CommonUtils';
import { RowData } from './RowData';
export type SampleColumns = { name: string; dataType: string }; export interface SampleColumns {
name: string;
dataType: string;
}
type Props = { interface Props {
sampleData?: { sampleData?: {
columns?: Array<SampleColumns>; columns?: Array<SampleColumns>;
rows?: TableData['rows']; rows?: TableData['rows'];
}; };
}; }
const SampleDataTable: FunctionComponent<Props> = ({ sampleData }: Props) => { const SampleDataTable: FunctionComponent<Props> = ({ sampleData }: Props) => {
const tableRef = useRef<HTMLDivElement>(null); const tableRef = useRef<HTMLDivElement>(null);
@ -133,7 +137,7 @@ const SampleDataTable: FunctionComponent<Props> = ({ sampleData }: Props) => {
className="tableBody-cell" className="tableBody-cell"
data-testid="cell" data-testid="cell"
key={index}> key={index}>
{data ? data.toString() : '--'} <RowData data={data} />
</td> </td>
); );
})} })}