Skip to content

Commit 562df3c

Browse files
LDrago27Maosaic
andauthored
[Fix] filter out Opensearch Data sources in Associate Direct Query Sources Modal (#9723)
* Fix Opensearch Connections not being filtered in DQS Assoication Modal Signed-off-by: Suchit Sahoo <[email protected]> * Update src/plugins/workspace/public/components/data_source_association/association_data_source_modal.tsx Co-authored-by: Joey Liu <[email protected]> Signed-off-by: Suchit Sahoo <[email protected]> --------- Signed-off-by: Suchit Sahoo <[email protected]> Signed-off-by: Suchit Sahoo <[email protected]> Co-authored-by: Joey Liu <[email protected]>
1 parent b1798c2 commit 562df3c

File tree

2 files changed

+144
-61
lines changed

2 files changed

+144
-61
lines changed

src/plugins/workspace/public/components/data_source_association/association_data_source_modal.test.tsx

Lines changed: 112 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Copyright OpenSearch Contributors
33
* SPDX-License-Identifier: Apache-2.0
44
*/
5-
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
5+
import { fireEvent, render, screen, waitFor, act } from '@testing-library/react';
66
import React from 'react';
77
import { IntlProvider } from 'react-intl';
88

@@ -15,7 +15,6 @@ import {
1515
AssociationDataSourceModalProps,
1616
} from './association_data_source_modal';
1717
import { AssociationDataSourceModalMode } from 'src/plugins/workspace/common/constants';
18-
import { DataSourceEngineType } from 'src/plugins/data_source/common/data_sources';
1918

2019
const setupAssociationDataSourceModal = ({
2120
mode,
@@ -38,13 +37,6 @@ const setupAssociationDataSourceModal = ({
3837
connectionType: DataSourceConnectionType.DirectQueryConnection,
3938
type: 'Amazon S3',
4039
},
41-
{
42-
id: 'ds1-cross-cluster-connection',
43-
name: 'cross-cluster-connection',
44-
parentId: 'ds1',
45-
connectionType: DataSourceConnectionType.OpenSearchConnection,
46-
type: DataSourceEngineType.OpenSearchCrossCluster,
47-
},
4840
],
4941
},
5042
{
@@ -85,6 +77,48 @@ const setupAssociationDataSourceModal = ({
8577
return {};
8678
};
8779

80+
const setupAssociationDataSourceModalForCrossClusterSearch = ({
81+
mode,
82+
excludedConnectionIds,
83+
handleAssignDataSourceConnections,
84+
}: Partial<AssociationDataSourceModalProps> = {}) => {
85+
const coreServices = coreMock.createStart();
86+
jest.spyOn(utilsExports, 'getDataSourcesList').mockResolvedValue([]);
87+
jest.spyOn(utilsExports, 'fetchDataSourceConnections').mockResolvedValueOnce([
88+
{
89+
id: 'ds1',
90+
name: 'Data Source 1',
91+
connectionType: DataSourceConnectionType.OpenSearchConnection,
92+
type: 'OpenSearch',
93+
relatedConnections: [
94+
{
95+
id: 'ds1:connection-alias-1',
96+
name: 'ds1:connection-alias-1',
97+
parentId: 'ds1',
98+
connectionType: DataSourceConnectionType.OpenSearchConnection,
99+
type: 'OpenSearch(Cross-cluster search)',
100+
},
101+
],
102+
},
103+
]);
104+
const { logos } = chromeServiceMock.createStartContract();
105+
render(
106+
<IntlProvider locale="en">
107+
<AssociationDataSourceModal
108+
logos={logos}
109+
mode={AssociationDataSourceModalMode.OpenSearchConnections}
110+
http={coreServices.http}
111+
notifications={coreServices.notifications}
112+
savedObjects={coreServices.savedObjects}
113+
closeModal={jest.fn()}
114+
excludedConnectionIds={excludedConnectionIds ?? []}
115+
handleAssignDataSourceConnections={jest.fn()}
116+
/>
117+
</IntlProvider>
118+
);
119+
return {};
120+
};
121+
88122
describe('AssociationDataSourceModal', () => {
89123
const originalOffsetHeight = Object.getOwnPropertyDescriptor(
90124
HTMLElement.prototype,
@@ -127,25 +161,6 @@ describe('AssociationDataSourceModal', () => {
127161
expect(screen.getByRole('option', { name: 'Data Source 1' })).toBeInTheDocument();
128162
expect(screen.getByRole('option', { name: 'Data Source 2' })).toBeInTheDocument();
129163
expect(screen.queryByRole('option', { name: 'Data Connection 1' })).not.toBeInTheDocument();
130-
expect(screen.getByText('+ 1 Cross cluster')).toBeInTheDocument();
131-
});
132-
});
133-
134-
it('should display the cross cluster on clicking on a OpenSearch data sources with cross cluter badge', async () => {
135-
setupAssociationDataSourceModal();
136-
expect(screen.getByText('Associate OpenSearch data sources')).toBeInTheDocument();
137-
expect(
138-
screen.getByText(
139-
'Add data sources that will be available in the workspace. If a selected data source has related Direct Query data sources, they will also be available in the workspace.'
140-
)
141-
).toBeInTheDocument();
142-
await waitFor(() => {
143-
expect(screen.getByRole('option', { name: 'Data Source 1' })).toBeInTheDocument();
144-
expect(screen.getByRole('option', { name: 'Data Source 2' })).toBeInTheDocument();
145-
expect(screen.queryByRole('option', { name: 'Data Connection 1' })).not.toBeInTheDocument();
146-
expect(screen.getByText('+ 1 Cross cluster')).toBeInTheDocument();
147-
fireEvent.click(screen.getByRole('option', { name: 'Data Source 1' }));
148-
expect(screen.getByText('cross-cluster-connection')).toBeInTheDocument();
149164
});
150165
});
151166

@@ -164,7 +179,7 @@ describe('AssociationDataSourceModal', () => {
164179
expect(screen.getByText('Associate OpenSearch data sources')).toBeInTheDocument();
165180
await waitFor(() => {
166181
expect(screen.getByRole('option', { name: 'Data Source 1' })).toBeInTheDocument();
167-
expect(screen.queryByText('+ 1 related')).not.toBeInTheDocument();
182+
expect(screen.queryByText('+ 1 Direct query')).not.toBeInTheDocument();
168183
fireEvent.click(screen.getByRole('option', { name: 'Data Source 1' }));
169184
expect(screen.queryByRole('option', { name: 'dqc1' })).not.toBeInTheDocument();
170185
});
@@ -223,13 +238,6 @@ describe('AssociationDataSourceModal', () => {
223238
connectionType: DataSourceConnectionType.DirectQueryConnection,
224239
type: 'Amazon S3',
225240
},
226-
{
227-
id: 'ds1-cross-cluster-connection',
228-
name: 'cross-cluster-connection',
229-
parentId: 'ds1',
230-
connectionType: DataSourceConnectionType.OpenSearchConnection,
231-
type: DataSourceEngineType.OpenSearchCrossCluster,
232-
},
233241
],
234242
},
235243
]);
@@ -257,3 +265,71 @@ describe('AssociationDataSourceModal', () => {
257265
]);
258266
});
259267
});
268+
269+
describe('Cross-Cluster Search in AssociationDataSourceModal', () => {
270+
const originalOffsetHeight = Object.getOwnPropertyDescriptor(
271+
HTMLElement.prototype,
272+
'offsetHeight'
273+
);
274+
const originalOffsetWidth = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetWidth');
275+
276+
beforeEach(() => {
277+
Object.defineProperty(HTMLElement.prototype, 'offsetHeight', {
278+
configurable: true,
279+
value: 600,
280+
});
281+
Object.defineProperty(HTMLElement.prototype, 'offsetWidth', {
282+
configurable: true,
283+
value: 600,
284+
});
285+
});
286+
287+
afterEach(() => {
288+
Object.defineProperty(
289+
HTMLElement.prototype,
290+
'offsetHeight',
291+
originalOffsetHeight as PropertyDescriptor
292+
);
293+
Object.defineProperty(
294+
HTMLElement.prototype,
295+
'offsetWidth',
296+
originalOffsetWidth as PropertyDescriptor
297+
);
298+
});
299+
300+
it('should display cross-cluster connections when associating OpenSearch data sources', async () => {
301+
await act(async () => {
302+
setupAssociationDataSourceModalForCrossClusterSearch();
303+
});
304+
305+
expect(screen.getByText('Associate OpenSearch data sources')).toBeInTheDocument();
306+
307+
await waitFor(() => {
308+
expect(screen.getByRole('option', { name: 'Data Source 1' })).toBeInTheDocument();
309+
expect(screen.getByText('+ 1 Cross cluster')).toBeInTheDocument();
310+
});
311+
});
312+
313+
it('should display related cross-cluster connections after selecting a data source', async () => {
314+
await act(async () => {
315+
setupAssociationDataSourceModalForCrossClusterSearch();
316+
});
317+
318+
expect(screen.getByText('Associate OpenSearch data sources')).toBeInTheDocument();
319+
320+
await waitFor(() => {
321+
expect(screen.getByText('+ 1 Cross cluster')).toBeInTheDocument();
322+
expect(
323+
screen.queryByRole('option', { name: 'ds1:connection-alias-1' })
324+
).not.toBeInTheDocument();
325+
});
326+
327+
await act(async () => {
328+
fireEvent.click(screen.getByRole('option', { name: 'Data Source 1' }));
329+
});
330+
331+
await waitFor(() => {
332+
expect(screen.getByRole('option', { name: 'ds1:connection-alias-1' })).toBeInTheDocument();
333+
});
334+
});
335+
});

src/plugins/workspace/public/components/data_source_association/association_data_source_modal.tsx

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -89,32 +89,37 @@ const renderOption = (option: DataSourceModalOption) => {
8989

9090
const getOpenSearchRelatedConnectionsBadges = (
9191
relatedCrossClusterConnections: DataSourceConnection[] | undefined,
92-
relatedDirectConnections: DataSourceConnection[] | undefined
92+
relatedDirectConnections: DataSourceConnection[] | undefined,
93+
mode: AssociationDataSourceModalMode
9394
) => {
94-
return relatedCrossClusterConnections && relatedCrossClusterConnections.length > 0 ? (
95+
return (
9596
<EuiBadgeGroup>
96-
{relatedCrossClusterConnections && relatedCrossClusterConnections.length && (
97-
<EuiBadge>
98-
{i18n.translate('workspace.form.selectDataSource.crossClusterOptionBadge', {
99-
defaultMessage: '+ {relatedConnections} Cross cluster',
100-
values: {
101-
relatedConnections: relatedCrossClusterConnections.length,
102-
},
103-
})}
104-
</EuiBadge>
105-
)}
106-
{relatedDirectConnections && relatedDirectConnections.length > 0 && (
107-
<EuiBadge>
108-
{i18n.translate('workspace.form.selectDataSource.directQueryOptionBadge', {
109-
defaultMessage: '+ {relatedConnections} Direct query',
110-
values: {
111-
relatedConnections: relatedDirectConnections.length,
112-
},
113-
})}
114-
</EuiBadge>
115-
)}
97+
{mode !== AssociationDataSourceModalMode.DirectQueryConnections &&
98+
relatedCrossClusterConnections &&
99+
relatedCrossClusterConnections.length > 0 && (
100+
<EuiBadge>
101+
{i18n.translate('workspace.form.selectDataSource.crossClusterOptionBadge', {
102+
defaultMessage: '+ {relatedConnections} Cross cluster',
103+
values: {
104+
relatedConnections: relatedCrossClusterConnections.length,
105+
},
106+
})}
107+
</EuiBadge>
108+
)}
109+
{mode === AssociationDataSourceModalMode.DirectQueryConnections &&
110+
relatedDirectConnections &&
111+
relatedDirectConnections.length > 0 && (
112+
<EuiBadge>
113+
{i18n.translate('workspace.form.selectDataSource.directQueryOptionBadge', {
114+
defaultMessage: '+ {relatedConnections} Direct query',
115+
values: {
116+
relatedConnections: relatedDirectConnections.length,
117+
},
118+
})}
119+
</EuiBadge>
120+
)}
116121
</EuiBadgeGroup>
117-
) : undefined;
122+
);
118123
};
119124

120125
const convertConnectionToOption = ({
@@ -143,7 +148,8 @@ const convertConnectionToOption = ({
143148
description: connection.description,
144149
append: getOpenSearchRelatedConnectionsBadges(
145150
relatedCrossClusterConnections,
146-
relatedDirectConnections
151+
relatedDirectConnections,
152+
mode
147153
),
148154
disabled: !!(
149155
connection.connectionType === DataSourceConnectionType.DirectQueryConnection ||
@@ -198,8 +204,9 @@ const convertConnectionsToOptions = ({
198204
}
199205

200206
if (!connection.relatedConnections || connection.relatedConnections.length === 0) {
201-
return [connection];
207+
return showDirectQueryConnections ? [] : [connection];
202208
}
209+
203210
return [
204211
connection,
205212
...(selectedConnectionIds.includes(connection.id) ? connection.relatedConnections : []),

0 commit comments

Comments
 (0)