From 31b11323896e9046d79e66dc3921dbccd79dfcff Mon Sep 17 00:00:00 2001 From: Pranita Fulsundar Date: Wed, 18 Dec 2024 14:40:10 +0530 Subject: [PATCH] feat(ui): highlight search term for schema table in table details page (#19110) * feat: highlight search term * refactor: use stringToHTML instead of parse * test: highlightSearchText method * fix: test for schema table * fix: mock implemetation of stringToHTML * test: highlightSearchText function with null or falsy parameters --- .../SchemaTable/SchemaTable.component.tsx | 12 ++-- .../Database/SchemaTable/SchemaTable.test.tsx | 10 ++++ .../ui/src/utils/EntityUtils.test.tsx | 56 +++++++++++++++++++ .../resources/ui/src/utils/EntityUtils.tsx | 13 +++++ .../ui/src/utils/mocks/EntityUtils.mock.ts | 8 +++ 5 files changed, 95 insertions(+), 4 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/SchemaTable/SchemaTable.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Database/SchemaTable/SchemaTable.component.tsx index dc4b6c9128f..1736e47f18d 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/SchemaTable/SchemaTable.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/SchemaTable/SchemaTable.component.tsx @@ -55,9 +55,11 @@ import { getColumnSorter, getEntityName, getFrequentlyJoinedColumns, + highlightSearchText, searchInColumns, } from '../../../utils/EntityUtils'; import { getEntityColumnFQN } from '../../../utils/FeedUtils'; +import { stringToHTML } from '../../../utils/StringsUtils'; import { getAllTags, searchTagInData, @@ -249,7 +251,7 @@ const SchemaTable = ({ - {displayValue} + {stringToHTML(highlightSearchText(displayValue, searchText))} ); }; @@ -264,7 +266,7 @@ const SchemaTable = ({ - {name} + {stringToHTML(highlightSearchText(name, searchText))} {!isEmpty(displayName) ? ( @@ -382,7 +384,9 @@ const SchemaTable = ({ - {getEntityName(record)} + {stringToHTML( + highlightSearchText(getEntityName(record), searchText) + )} ) : null} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/SchemaTable/SchemaTable.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Database/SchemaTable/SchemaTable.test.tsx index 1e49687b4a5..401a7328534 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/SchemaTable/SchemaTable.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/SchemaTable/SchemaTable.test.tsx @@ -167,6 +167,16 @@ jest.mock('../../../constants/Table.constants', () => ({ }, })); +jest.mock('../../../utils/StringsUtils', () => ({ + ...jest.requireActual('../../../utils/StringsUtils'), + stringToHTML: jest.fn((text) => text), +})); + +jest.mock('../../../utils/EntityUtils', () => ({ + ...jest.requireActual('../../../utils/EntityUtils'), + highlightSearchText: jest.fn((text) => text), +})); + describe('Test EntityTable Component', () => { it('Initially, Table should load', async () => { render(, { diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.test.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.test.tsx index 264482fe8fc..757e69de9f7 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.test.tsx @@ -23,12 +23,16 @@ import { getEntityLinkFromType, getEntityOverview, highlightEntityNameAndDescription, + highlightSearchText, } from './EntityUtils'; import { entityWithoutNameAndDescHighlight, highlightedEntityDescription, highlightedEntityDisplayName, + mockHighlightedResult, mockHighlights, + mockSearchText, + mockText, } from './mocks/EntityUtils.mock'; jest.mock('../constants/constants', () => ({ @@ -199,4 +203,56 @@ describe('EntityUtils unit tests', () => { expect(sorter(item2, item1)).toBe(1); }); }); + + describe('highlightSearchText method', () => { + it('should return the text with highlighted search text', () => { + const result = highlightSearchText(mockText, mockSearchText); + + expect(result).toBe(mockHighlightedResult); + }); + + it('should return the original text if searchText is not found', () => { + const result = highlightSearchText(mockText, 'nonexistent'); + + expect(result).toBe(mockText); + }); + + it('should return an empty string if no text is provided', () => { + const result = highlightSearchText('', 'test'); + + expect(result).toBe(''); + }); + + it('should return an empty string if no searchText is provided', () => { + const result = highlightSearchText(mockText, ''); + + expect(result).toBe(mockText); + }); + + it('should return empty string if both text and searchText are missing', () => { + const result = highlightSearchText('', ''); + + expect(result).toBe(''); + }); + + const falsyTestCases = [ + { text: null, searchText: 'test', expected: '' }, + { text: 'mockText', searchText: null, expected: 'mockText' }, + { text: null, searchText: null, expected: '' }, + { text: 0 as any, searchText: '', expected: 0 }, + { text: false as any, searchText: '', expected: false }, + ]; + + it.each(falsyTestCases)( + 'should return expected when text or searchText is null or falsy', + ({ text, searchText, expected }) => { + const result = highlightSearchText( + text ?? undefined, + searchText ?? undefined + ); + + expect(result).toBe(expected); + } + ); + }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx index b3b4b6fed8b..1802654d2e4 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx @@ -2393,3 +2393,16 @@ export const getColumnSorter = (field: K) => { return 0; }; }; + +export const highlightSearchText = ( + text?: string, + searchText?: string +): string => { + if (!searchText || !text) { + return text ?? ''; + } + + const regex = new RegExp(`(${searchText})`, 'gi'); + + return text.replace(regex, `$1`); +}; diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/mocks/EntityUtils.mock.ts b/openmetadata-ui/src/main/resources/ui/src/utils/mocks/EntityUtils.mock.ts index aaea1f5e86a..295ef7a9168 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/mocks/EntityUtils.mock.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/mocks/EntityUtils.mock.ts @@ -136,3 +136,11 @@ export const mockHighlights = { export const highlightedEntityDescription = `This dimension table contains the billing and shipping addresses of customers.`; export const highlightedEntityDisplayName = `dim_address`; + +export const mockText = + 'This is a test description to verify highlightText method.'; + +export const mockSearchText = 'test'; + +export const mockHighlightedResult = + 'This is a test description to verify highlightText method.';