Skip to content

Commit

Permalink
separately fetch dqc
Browse files Browse the repository at this point in the history
Signed-off-by: Qxisylolo <[email protected]>
  • Loading branch information
Qxisylolo committed Dec 11, 2024
1 parent ee0299f commit c506daa
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { fireEvent, render, screen, waitFor, act } from '@testing-library/react';
import React from 'react';
import { IntlProvider } from 'react-intl';

Expand All @@ -15,6 +15,32 @@ import {
AssociationDataSourceModalProps,
} from './association_data_source_modal';
import { AssociationDataSourceModalMode } from 'src/plugins/workspace/common/constants';
import { DataSourceEngineType } from '../../../../data_source/common/data_sources';
const dataSourcesList = [
{
id: 'ds1',
title: 'Data Source 1',
description: 'Description of data source 1',
auth: '',
dataSourceEngineType: '' as DataSourceEngineType,
workspaces: [],
// This is used for mocking saved object function
get: () => {
return 'Data Source 1';
},
},
{
id: 'dqs1',
title: 'Data Connection 1',
description: 'Description of data connection 1',
auth: '',
dataSourceEngineType: '' as DataSourceEngineType,
workspaces: [],
get: () => {
return 'Data Connection 1';
},
},
];

const openSearchAndDataConnectionsMock = {
openSearchConnections: [
Expand All @@ -41,37 +67,18 @@ const setupAssociationDataSourceModal = ({
handleAssignDataSourceConnections,
}: Partial<AssociationDataSourceModalProps> = {}) => {
const coreServices = coreMock.createStart();
jest.spyOn(utilsExports, 'getDataSourcesList').mockResolvedValue([]);
jest.spyOn(utilsExports, 'getDataSourcesList').mockResolvedValue(dataSourcesList);

jest
.spyOn(utilsExports, 'convertDataSourcesToOpenSearchAndDataConnections')
.mockReturnValue(openSearchAndDataConnectionsMock);

jest.spyOn(utilsExports, 'fulfillRelatedConnections').mockReturnValue([
{
id: 'ds1',
name: 'Data Source 1',
type: 'OpenSearch',
connectionType: DataSourceConnectionType.OpenSearchConnection,
relatedConnections: [
{
id: 'ds1-dqc1',
name: 'dqc1',
type: 'Amazon S3',
connectionType: DataSourceConnectionType.DirectQueryConnection,
parentId: 'ds1',
},
],
},
]);

jest.spyOn(utilsExports, 'fetchDirectQueryConnections').mockResolvedValue([
jest.spyOn(utilsExports, 'fetchDirectQueryConnectionsByIDs').mockResolvedValue([
{
id: 'ds1-dqc1',
name: 'dqc1',
type: 'Amazon S3',
connectionType: 1,
description: 'direct_query_connections_1',
parentId: 'ds1',
},
]);
Expand Down Expand Up @@ -165,12 +172,14 @@ describe('AssociationDataSourceModal', () => {
setupAssociationDataSourceModal({
handleAssignDataSourceConnections: handleAssignDataSourceConnectionsMock,
});

await waitFor(() => {
fireEvent.click(screen.getByRole('option', { name: 'Data Source 1' }));
fireEvent.click(screen.getByRole('button', { name: 'Associate data sources' }));
expect(screen.getByText('Data Source 1')).toBeInTheDocument();
expect(screen.getByText('Associate data sources')).toBeInTheDocument();
});

fireEvent.click(screen.getByText('Data Source 1'));
fireEvent.click(screen.getByText('Associate data sources'));

expect(handleAssignDataSourceConnectionsMock).toHaveBeenCalledWith([
{
id: 'ds1',
Expand All @@ -196,11 +205,12 @@ describe('AssociationDataSourceModal', () => {
handleAssignDataSourceConnections: handleAssignDataSourceConnectionsMock,
mode: AssociationDataSourceModalMode.DirectQueryConnections,
});

await waitFor(() => {
fireEvent.click(screen.getByRole('option', { name: 'Data Connection 1' }));
fireEvent.click(screen.getByRole('button', { name: 'Associate data sources' }));
expect(screen.getByText('Data Connection 1')).toBeInTheDocument();
expect(screen.getByText('Associate data sources')).toBeInTheDocument();
});
fireEvent.click(screen.getByText('Data Connection 1'));
fireEvent.click(screen.getByText('Associate data sources'));

expect(handleAssignDataSourceConnectionsMock).toHaveBeenCalledWith([
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ import { i18n } from '@osd/i18n';

import {
getDataSourcesList,
fulfillRelatedConnections,
fetchDirectQueryConnections,
fetchDirectQueryConnectionsByIDs,
convertDataSourcesToOpenSearchAndDataConnections,
} from '../../utils';
import { DataSourceConnection, DataSourceConnectionType } from '../../../common/types';
Expand Down Expand Up @@ -93,18 +92,18 @@ const convertConnectionToOption = ({
connection,
selectedConnectionIds,
logos,
isRelatedConnectionsLoaded,
loadingStatus,
}: {
connection: DataSourceConnection;
selectedConnectionIds: string[];
logos: Logos;
isRelatedConnectionsLoaded: boolean;
loadingStatus: Record<string, boolean>;
}) => {
return {
label: connection.name,
key: connection.id,
description: connection.description,
append: isRelatedConnectionsLoaded ? (
append: !loadingStatus[connection.id] ? (
connection.relatedConnections && connection.relatedConnections.length > 0 ? (
<EuiBadge>
{i18n.translate('workspace.form.selectDataSource.optionBadge', {
Expand Down Expand Up @@ -141,14 +140,14 @@ const convertConnectionsToOptions = ({
selectedConnectionIds,
excludedConnectionIds,
logos,
isRelatedConnectionsLoaded,
loadingStatus,
}: {
connections: DataSourceConnection[];
excludedConnectionIds: string[];
showDirectQueryConnections: boolean;
selectedConnectionIds: string[];
logos: Logos;
isRelatedConnectionsLoaded: boolean;
loadingStatus: Record<string, boolean>;
}) => {
return connections
.flatMap((connection) => {
Expand Down Expand Up @@ -186,7 +185,7 @@ const convertConnectionsToOptions = ({
connection,
selectedConnectionIds,
logos,
isRelatedConnectionsLoaded,
loadingStatus,
})
);
};
Expand Down Expand Up @@ -222,11 +221,11 @@ export const AssociationDataSourceModalContent = ({
}: AssociationDataSourceModalProps) => {
const [allConnections, setAllConnections] = useState<DataSourceConnection[]>([]);
const [selectedConnectionIds, setSelectedConnectionIds] = useState<string[]>([]);
const [isRelatedConnectionsLoaded, setIsRelatedConnectionsLoaded] = useState(false);
const [options, setOptions] = useState<DataSourceModalOption[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [isSaving, setIsSaving] = useState(false);
const mountedRef = useRef(false);
const [loadingStatus, setLoadingStatus] = useState<Record<string, boolean>>({});

useEffect(() => {
mountedRef.current = true;
Expand Down Expand Up @@ -260,21 +259,40 @@ export const AssociationDataSourceModalContent = ({
openSearchConnections,
dataConnections,
} = convertDataSourcesToOpenSearchAndDataConnections(dataSourcesList);

const initialLoadingStatus = dataSourcesList.reduce((acc, ds) => {
acc[ds.id] = true;
return acc;
}, {} as Record<string, boolean>);

setLoadingStatus(initialLoadingStatus);

// display data sources connections first while loading direct query connection
setAllConnections([...openSearchConnections, ...dataConnections]);
return { openSearchConnections, dataConnections, dataSourcesList };
return { openSearchConnections };
})
.then(({ openSearchConnections, dataConnections, dataSourcesList }) => {
fetchDirectQueryConnections(dataSourcesList, http, notifications).then(
(directQueryConnections) => {
const updatedOpenSearchConnections = fulfillRelatedConnections(
openSearchConnections,
directQueryConnections
);

setAllConnections([...updatedOpenSearchConnections, ...dataConnections]);
setIsRelatedConnectionsLoaded(true); // related connections are completely loaded
}
);
.then(({ openSearchConnections }) => {
// Only data source saved object type needs to fetch data source connections, data connection type object not.
openSearchConnections.forEach((ds) => {
// fetch direct query connections for each data source, and set loading status accordingly
fetchDirectQueryConnectionsByIDs([ds.id], http, notifications)
.then((directQueryConnections) => {
setAllConnections((prev) => {
return prev.map((connection) => {
if (connection.id === ds.id) {
return {
...connection,
relatedConnections: directQueryConnections,
};
}
return connection;
});
});
})
.finally(() => {
setLoadingStatus((prev) => ({ ...prev, [ds.id]: false }));
});
});
})
.finally(() => {
setIsLoading(false);
Expand All @@ -291,18 +309,11 @@ export const AssociationDataSourceModalContent = ({
showDirectQueryConnections:
mode === AssociationDataSourceModalMode.DirectQueryConnections,
logos,
isRelatedConnectionsLoaded,
loadingStatus,
})
);
}
}, [
excludedConnectionIds,
selectedConnectionIds,
mode,
allConnections,
logos,
isRelatedConnectionsLoaded,
]);
}, [excludedConnectionIds, selectedConnectionIds, mode, allConnections, logos, loadingStatus]);

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
WorkspaceCreatorProps,
} from './workspace_creator';
import { DataSourceEngineType } from '../../../../data_source/common/data_sources';
import { DataSourceConnectionType, DataSourceConnection } from '../../../common/types';
import { DataSourceConnectionType } from '../../../common/types';
import * as utils from '../../utils';
import * as workspaceUtilsExports from '../utils/workspace';

Expand Down Expand Up @@ -140,7 +140,7 @@ jest.spyOn(utils, 'fulfillRelatedConnections').mockReturnValue([
},
]);

jest.spyOn(utils, 'fetchDirectQueryConnections').mockResolvedValue(directQueryConnectionsMock);
jest.spyOn(utils, 'fetchDirectQueryConnectionsByIDs').mockResolvedValue(directQueryConnectionsMock);

const mockCoreStart = coreMock.createStart();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,25 +63,7 @@ jest
.spyOn(utils, 'convertDataSourcesToOpenSearchAndDataConnections')
.mockReturnValue({ openSearchConnections: [...dataSourceConnectionsMock], dataConnections: [] });

jest.spyOn(utils, 'fetchDirectQueryConnections').mockResolvedValue(directQueryConnectionsMock);

jest.spyOn(utils, 'fulfillRelatedConnections').mockReturnValue([
{
id: 'ds1',
name: 'Data Source 1',
type: 'OpenSearch',
connectionType: DataSourceConnectionType.OpenSearchConnection,
relatedConnections: [
{
id: 'ds1-dqc1',
name: 'dqc1',
type: 'Amazon S3',
connectionType: DataSourceConnectionType.DirectQueryConnection,
parentId: 'ds1',
},
],
},
]);
jest.spyOn(utils, 'fetchDirectQueryConnectionsByIDs').mockResolvedValue(directQueryConnectionsMock);

const mockCoreStart = coreMock.createStart();

Expand Down
6 changes: 3 additions & 3 deletions src/plugins/workspace/public/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -539,15 +539,15 @@ export const fetchDataSourceConnections = async (
}
};

export const fetchDirectQueryConnections = async (
dataSources: DataSource[],
export const fetchDirectQueryConnectionsByIDs = async (
dataSourceIds: string[],
http: HttpSetup | undefined,
notifications: NotificationsStart | undefined
) => {
try {
const directQueryConnections = await fetchDataSourceConnectionsByDataSourceIds(

Check warning on line 548 in src/plugins/workspace/public/utils.ts

View check run for this annotation

Codecov / codecov/patch

src/plugins/workspace/public/utils.ts#L547-L548

Added lines #L547 - L548 were not covered by tests
// Only data source saved object type needs to fetch data source connections, data connection type object not.
dataSources.filter((ds) => ds.type === DATA_SOURCE_SAVED_OBJECT_TYPE).map((ds) => ds.id),
dataSourceIds,
http
);

Expand Down

0 comments on commit c506daa

Please sign in to comment.