Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@
}));

jest.mock('../../../utils/DataProductUtils', () => ({
getDataProductIconByUrl: jest.fn().mockReturnValue(<span>dp-icon</span>),

Check warning on line 56 in openmetadata-ui/src/main/resources/ui/src/components/DataMarketplace/MarketplaceSearchBar/MarketplaceSearchBar.test.tsx

View workflow job for this annotation

GitHub Actions / checkstyle

disallow literal string: <span>dp-icon</span>
}));

jest.mock('../../../utils/DomainUtils', () => ({
getDomainIcon: jest.fn().mockReturnValue(<span>domain-icon</span>),

Check warning on line 60 in openmetadata-ui/src/main/resources/ui/src/components/DataMarketplace/MarketplaceSearchBar/MarketplaceSearchBar.test.tsx

View workflow job for this annotation

GitHub Actions / checkstyle

disallow literal string: <span>domain-icon</span>
}));

jest.mock('../../../utils/RouterUtils', () => ({
Expand Down Expand Up @@ -113,7 +113,7 @@
});

jest.mock('@untitledui/icons', () => ({
SearchLg: () => <span data-testid="search-icon">search</span>,

Check warning on line 116 in openmetadata-ui/src/main/resources/ui/src/components/DataMarketplace/MarketplaceSearchBar/MarketplaceSearchBar.test.tsx

View workflow job for this annotation

GitHub Actions / checkstyle

disallow literal string: <span data-testid="search-icon">search</span>
}));

const mockDataProducts = [
Expand Down Expand Up @@ -156,13 +156,13 @@
renderComponent();

expect(screen.getByTestId('marketplace-search-bar')).toBeInTheDocument();
expect(screen.getByTestId('marketplace-search-input')).toBeInTheDocument();

Check warning on line 159 in openmetadata-ui/src/main/resources/ui/src/components/DataMarketplace/MarketplaceSearchBar/MarketplaceSearchBar.test.tsx

View workflow job for this annotation

GitHub Actions / checkstyle

Define a constant instead of duplicating this literal 13 times
});

it('shows NLQ toggle button when NLP is enabled', () => {
renderComponent();

const toggleBtn = screen.getByTestId('marketplace-nlq-toggle');

Check warning on line 165 in openmetadata-ui/src/main/resources/ui/src/components/DataMarketplace/MarketplaceSearchBar/MarketplaceSearchBar.test.tsx

View workflow job for this annotation

GitHub Actions / checkstyle

Define a constant instead of duplicating this literal 4 times

expect(toggleBtn).toBeInTheDocument();
expect(toggleBtn).not.toHaveClass('active');
Expand All @@ -179,20 +179,26 @@
).not.toBeInTheDocument();
});

it('bootstraps isNLPEnabled from API when store is cold (direct marketplace navigation)', async () => {
it('keeps NLQ disabled in OSS when store is cold', async () => {
useSearchStore.setState({
isNLPEnabled: false,
isNLPActive: false,
isNLPInitialized: false,
});
(getNLPEnabledStatus as jest.Mock).mockResolvedValue(true);

renderComponent();

await waitFor(() => {
expect(getNLPEnabledStatus).toHaveBeenCalledTimes(1);
expect(screen.getByTestId('marketplace-nlq-toggle')).toBeInTheDocument();
expect(useSearchStore.getState()).toMatchObject({
isNLPEnabled: false,
isNLPActive: false,
isNLPInitialized: true,
});
});

expect(getNLPEnabledStatus).not.toHaveBeenCalled();
expect(
screen.queryByTestId('marketplace-nlq-toggle')
).not.toBeInTheDocument();
});

it('skips the API call when store is already initialized', () => {
Expand Down Expand Up @@ -283,7 +289,7 @@
fireEvent.change(input, { target: { value: '' } });
});

expect(screen.queryByTestId('search-popover')).not.toBeInTheDocument();

Check warning on line 292 in openmetadata-ui/src/main/resources/ui/src/components/DataMarketplace/MarketplaceSearchBar/MarketplaceSearchBar.test.tsx

View workflow job for this annotation

GitHub Actions / checkstyle

Define a constant instead of duplicating this literal 5 times
});

it('shows data product results in the popover', async () => {
Expand All @@ -302,7 +308,7 @@
});

await waitFor(() => {
expect(screen.getByTestId('search-result-dp-dp-1')).toBeInTheDocument();

Check warning on line 311 in openmetadata-ui/src/main/resources/ui/src/components/DataMarketplace/MarketplaceSearchBar/MarketplaceSearchBar.test.tsx

View workflow job for this annotation

GitHub Actions / checkstyle

Define a constant instead of duplicating this literal 3 times
expect(screen.getByText('Product One')).toBeInTheDocument();
});
});
Expand All @@ -324,7 +330,7 @@

await waitFor(() => {
expect(
screen.getByTestId('search-result-domain-domain-1')

Check warning on line 333 in openmetadata-ui/src/main/resources/ui/src/components/DataMarketplace/MarketplaceSearchBar/MarketplaceSearchBar.test.tsx

View workflow job for this annotation

GitHub Actions / checkstyle

Define a constant instead of duplicating this literal 3 times
).toBeInTheDocument();
expect(screen.getByText('Marketing')).toBeInTheDocument();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright 2026 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 { act } from '@testing-library/react';
import { getNLPEnabledStatus } from '../rest/searchAPI';
import searchSettingsClassBase from '../utils/SearchSettingsClassBase';
import { useSearchStore } from './useSearchStore';

jest.mock('../rest/searchAPI', () => ({
getNLPEnabledStatus: jest.fn(),
}));

const mockGetNLPEnabledStatus = getNLPEnabledStatus as jest.MockedFunction<
typeof getNLPEnabledStatus
>;
const mockIsNLQSupported = jest.spyOn(
searchSettingsClassBase,
'isNLQSupported'
);

describe('useSearchStore', () => {
beforeEach(() => {
jest.clearAllMocks();
mockIsNLQSupported.mockReturnValue(false);
useSearchStore.setState({
isNLPActive: false,
isNLPEnabled: false,
isNLPInitialized: false,
});
});

it('keeps NLQ disabled in OSS without requesting the server setting', async () => {
mockGetNLPEnabledStatus.mockResolvedValue(true);
useSearchStore.getState().setNLPActive(true);

await act(async () => {
await useSearchStore.getState().initNLP();
});

expect(mockGetNLPEnabledStatus).not.toHaveBeenCalled();
expect(useSearchStore.getState()).toMatchObject({
isNLPActive: false,
isNLPEnabled: false,
isNLPInitialized: true,
});
});

it('uses the server setting when the Collate override supports NLQ', async () => {
mockIsNLQSupported.mockReturnValue(true);
mockGetNLPEnabledStatus.mockResolvedValue(true);

await act(async () => {
await useSearchStore.getState().initNLP();
});

expect(mockGetNLPEnabledStatus).toHaveBeenCalledTimes(1);
expect(useSearchStore.getState()).toMatchObject({
isNLPEnabled: true,
isNLPInitialized: true,
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
import { create } from 'zustand';
import { getNLPEnabledStatus } from '../rest/searchAPI';
import searchSettingsClassBase from '../utils/SearchSettingsClassBase';

interface SearchState {
// NLP flags
Expand All @@ -38,6 +39,17 @@ export const useSearchStore = create<SearchState>((set, get) => ({
if (get().isNLPInitialized) {
return;
}

if (!searchSettingsClassBase.isNLQSupported()) {
set({
isNLPActive: false,
isNLPEnabled: false,
isNLPInitialized: true,
});

return;
}

const enabled = await getNLPEnabledStatus().catch(() => false);
set({ isNLPEnabled: enabled, isNLPInitialized: true });
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2026 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 { SearchSettingsClassBase } from './SearchSettingsClassBase';

class HybridSearchSettingsClass extends SearchSettingsClassBase {
public showHybridSearchWeights(): boolean {
return true;
}
}

class CollateSearchSettingsClass extends SearchSettingsClassBase {
public isNLQSupported(): boolean {
return true;
}
}

describe('SearchSettingsClassBase', () => {
it('does not support NLQ in OSS', () => {
const searchSettings = new SearchSettingsClassBase();

expect(searchSettings.isNLQSupported()).toBe(false);
});

it('does not infer NLQ support from hybrid-search weights', () => {
const searchSettings = new HybridSearchSettingsClass();

expect(searchSettings.isNLQSupported()).toBe(false);
});

it('supports NLQ through the dedicated Collate override', () => {
const searchSettings = new CollateSearchSettingsClass();

expect(searchSettings.isNLQSupported()).toBe(true);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
*/

class SearchSettingsClassBase {
public isNLQSupported(): boolean {
return false;
}

public showHybridSearchWeights(): boolean {
return false;
}
Comment thread
shah-harshit marked this conversation as resolved.
Expand Down
Loading