From c2c7281018250c62c9e77cfca3dc1f921ab01a5f Mon Sep 17 00:00:00 2001 From: Aniket Katkar Date: Wed, 14 Dec 2022 18:14:55 +0530 Subject: [PATCH] Fix(UI) #9277: Fixed issue with dropdown options not resetting for different drop-downs (#9279) * Fixed issue with dropdown options not resetting for different dropdowns * Added unit test for additional checks Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com> --- .../Explore/ExploreQuickFilters.test.tsx | 153 ++++++++++++++++-- .../Explore/ExploreQuickFilters.tsx | 1 + .../Explore/mocks/ExploreQuickFilters.mock.ts | 153 ++++++++++++++++++ 3 files changed, 295 insertions(+), 12 deletions(-) create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Explore/mocks/ExploreQuickFilters.mock.ts diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.test.tsx index 4cb2c9cd3e2..14421b3a0c7 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.test.tsx @@ -11,11 +11,20 @@ * limitations under the License. */ -import { fireEvent, render } from '@testing-library/react'; +import { act, fireEvent, render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import React from 'react'; +import { getAdvancedFieldDefaultOptions } from '../../axiosAPIs/miscAPI'; import { SearchIndex } from '../../enums/search.enum'; import { ExploreQuickFilterField } from '../Explore/explore.interface'; +import { SearchDropdownProps } from '../SearchDropdown/SearchDropdown.interface'; import ExploreQuickFilters from './ExploreQuickFilters'; +import { + mockAdvancedFieldDefaultOptions, + mockAdvancedFieldOptions, + mockTagSuggestions, + mockUserSuggestions, +} from './mocks/ExploreQuickFilters.mock'; const mockOnFieldRemove = jest.fn(); const mockOnAdvanceSearch = jest.fn(); @@ -28,18 +37,84 @@ const mockOnUpdateFilterValues = jest.fn(); jest.mock('../SearchDropdown/SearchDropdown', () => jest .fn() - .mockReturnValue(
SearchDropdown
) + .mockImplementation( + ({ options, searchKey, onChange, onSearch }: SearchDropdownProps) => ( +
+ {options.map((option) => ( +
+ {option} +
+ ))} +
onSearch('', searchKey)}> + onSearch +
+
onChange([''], searchKey)}> + onChange +
+
+ ) + ) ); jest.mock('./AdvanceSearchModal.component', () => ({ AdvanceSearchModal: jest.fn().mockReturnValue(

AdvanceSearchModal

), })); +jest.mock('../../axiosAPIs/miscAPI', () => ({ + getAdvancedFieldDefaultOptions: jest + .fn() + .mockImplementation(() => Promise.resolve(mockAdvancedFieldDefaultOptions)), + getAdvancedFieldOptions: jest + .fn() + .mockImplementation(() => Promise.resolve(mockAdvancedFieldOptions)), + getTagSuggestions: jest + .fn() + .mockImplementation(() => Promise.resolve(mockTagSuggestions)), + getUserSuggestions: jest + .fn() + .mockImplementation(() => Promise.resolve(mockUserSuggestions)), +})); + const index = SearchIndex.TABLE; -const fields = [ - { key: 'owner.name', value: undefined }, - { key: 'column_names', value: undefined }, -] as ExploreQuickFilterField[]; +const mockFields: ExploreQuickFilterField[] = [ + { + label: 'Column', + key: 'columns.name', + value: undefined, + }, + { + label: 'Schema', + key: 'databaseSchema.name', + value: undefined, + }, + { + label: 'Database', + key: 'database.name', + value: undefined, + }, + { + label: 'Owner', + key: 'owner.name', + value: undefined, + }, + { + label: 'Tag', + key: 'tags.tagFQN', + value: undefined, + }, + { + label: 'Service', + key: 'service.name', + value: undefined, + }, +]; const onFieldRemove = mockOnFieldRemove; const onAdvanceSearch = mockOnAdvanceSearch; @@ -51,7 +126,7 @@ const onUpdateFilterValues = mockOnUpdateFilterValues; const mockProps = { index, - fields, + fields: mockFields, onFieldRemove, onAdvanceSearch, onClear, @@ -63,22 +138,22 @@ const mockProps = { describe('Test ExploreQuickFilters component', () => { it('Should render ExploreQuickFilters component', async () => { - const { findAllByTestId } = render(); + const { findAllByTitle } = render(); - const fields = await findAllByTestId('search-dropdown'); + const fields = await findAllByTitle('search-dropdown'); expect(fields).toHaveLength(fields.length); }); it('Should call onAdvanceSearch method on click of Advance Search button', async () => { - const { findByTestId, findAllByTestId } = render( + const { findByTestId, findAllByTitle } = render( ); - const fields = await findAllByTestId('search-dropdown'); + const fields = await findAllByTitle('search-dropdown'); const advanceSearchButton = await findByTestId('advance-search-button'); - expect(fields).toHaveLength(fields.length); + expect(fields).toHaveLength(mockFields.length); expect(advanceSearchButton).toBeInTheDocument(); @@ -86,4 +161,58 @@ describe('Test ExploreQuickFilters component', () => { expect(onAdvanceSearch).toBeCalled(); }); + + it('All options should be passed to SearchDropdown component for proper API response', async () => { + const { findByTestId, findAllByTestId } = render( + + ); + + const databaseFieldOnSearch = await findByTestId('onSearch-database.name'); + + expect(databaseFieldOnSearch).toBeInTheDocument(); + + await act(async () => { + userEvent.click(databaseFieldOnSearch); + }); + + const options = await findAllByTestId('option-database.name'); + + expect(options).toHaveLength( + mockAdvancedFieldDefaultOptions.data.aggregations['sterms#database.name'] + .buckets.length + ); + }); + + it('No previous options should be present after getAdvancedFieldDefaultOptions API fails', async () => { + const { findByTestId, findAllByTestId, queryAllByTestId } = render( + + ); + + const databaseFieldOnSearch = await findByTestId('onSearch-database.name'); + + expect(databaseFieldOnSearch).toBeInTheDocument(); + + await act(async () => { + userEvent.click(databaseFieldOnSearch); + }); + + let options = await findAllByTestId('option-database.name'); + + expect(options).toHaveLength( + mockAdvancedFieldDefaultOptions.data.aggregations['sterms#database.name'] + .buckets.length + ); + + (getAdvancedFieldDefaultOptions as jest.Mock).mockImplementationOnce(() => + Promise.reject('not done') + ); + + await act(async () => { + userEvent.click(databaseFieldOnSearch); + }); + + options = queryAllByTestId('option-database.name'); + + expect(options).toHaveLength(0); + }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.tsx index fb2bdcd8dfb..e8f93af5ea7 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.tsx @@ -74,6 +74,7 @@ const ExploreQuickFilters: FC = ({ const getFilterOptions = async (value: string, key: string) => { setIsOptionsLoading(true); + setOptions([]); try { if (value) { await fetchOptions(value, key); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/mocks/ExploreQuickFilters.mock.ts b/openmetadata-ui/src/main/resources/ui/src/components/Explore/mocks/ExploreQuickFilters.mock.ts new file mode 100644 index 00000000000..77ef357e8a6 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/mocks/ExploreQuickFilters.mock.ts @@ -0,0 +1,153 @@ +/* + * Copyright 2022 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. + */ + +export const mockAdvancedFieldDefaultOptions = { + data: { + took: 3, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0, + }, + hits: { + total: { + value: 84, + relation: 'eq', + }, + hits: [], + }, + aggregations: { + 'sterms#database.name': { + buckets: [ + { + key: 'ecommerce_db', + }, + { + key: 'modified-leaf-330420', + }, + ], + }, + }, + }, +}; + +export const mockAdvancedFieldOptions = { + data: { + suggest: { + 'metadata-suggest': [ + { + text: 'e', + offset: 0, + length: 1, + options: [ + { + text: 'ecommerce_db', + _source: { + id: '0e8ec01e-a57f-4173-8d30-deda453174d0', + name: 'dim.api/client', + fullyQualifiedName: + 'sample_data.ecommerce_db.shopify."dim.api/client"', + version: 5.7, + updatedAt: 1670495113513, + updatedBy: 'admin', + href: 'http://localhost:8585/api/v1/tables/0e8ec01e-a57f-4173-8d30-deda453174d0', + tableType: 'Regular', + }, + }, + ], + }, + ], + }, + }, +}; + +export const mockTagSuggestions = { + data: { + suggest: { + 'metadata-suggest': [ + { + text: 'pi', + offset: 0, + length: 2, + options: [ + { + text: 'PII.NonSensitive', + _source: { + id: '5555ba21-644f-45f7-bb00-4257a120e94f', + name: 'NonSensitive', + fullyQualifiedName: 'PII.NonSensitive', + }, + }, + { + text: 'PII.None', + _source: { + id: 'c3abf789-518d-47f2-9c15-569c9bb1da90', + name: 'None', + fullyQualifiedName: 'PII.None', + }, + }, + { + text: 'PII.Sensitive', + _source: { + id: 'f011a65f-939a-4ee5-b849-7e1f3e22acad', + name: 'Sensitive', + fullyQualifiedName: 'PII.Sensitive', + }, + }, + ], + }, + ], + }, + }, +}; + +export const mockUserSuggestions = { + data: { + suggest: { + 'metadata-suggest': [ + { + text: 'aa', + offset: 0, + length: 2, + options: [ + { + text: 'Aaron Johnson', + _source: { + id: '0b4bfce9-0fcb-4578-b563-f566f8c45e10', + name: 'aaron_johnson0', + fullyQualifiedName: 'aaron_johnson0', + }, + }, + { + text: 'Aaron Singh', + _source: { + id: '4e7b5402-d88a-4eb3-a4a6-788e5dc6f59b', + name: 'aaron_singh2', + fullyQualifiedName: 'aaron_singh2', + }, + }, + { + text: 'Aaron Warren', + _source: { + id: 'a2802c79-9007-4e75-a04c-0978a406fcd7', + name: 'aaron_warren5', + fullyQualifiedName: 'aaron_warren5', + }, + }, + ], + }, + ], + }, + }, +};