Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: cypress failure #319

Merged
merged 7 commits into from
Apr 7, 2024
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [BUG] Remove duplicate sample data as id 90943e30-9a47-11e8-b64d-95841ca0b247 ([5668](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5668))
- [BUG][Multiple Datasource] Fix datasource testing connection unexpectedly passed with wrong endpoint [#5663](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5663)
- [Table Visualization] Fix filter action buttons for split table aggregations ([#5619](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5619))
- [BUG][Discover] Allow saved sort from search embeddable to load in Dashboard ([#5934](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5934))

### 🚞 Infrastructure

Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@
"@types/react-router-dom": "^5.3.2",
"@types/react-virtualized": "^9.18.7",
"@types/recompose": "^0.30.6",
"@types/redux-mock-store": "^1.0.6",
"@types/selenium-webdriver": "^4.0.9",
"@types/semver": "^7.5.0",
"@types/sinon": "^7.0.13",
Expand Down Expand Up @@ -446,6 +447,7 @@
"react-test-renderer": "^16.12.0",
"reactcss": "1.2.3",
"redux": "^4.0.5",
"redux-mock-store": "^1.5.4",
"regenerate": "^1.4.0",
"reselect": "^4.0.0",
"resize-observer-polyfill": "^1.5.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,17 @@ import { DataSourceGroup, DataSourceSelectableProps } from './types';
type DataSourceTypeKey = 'DEFAULT_INDEX_PATTERNS' | 's3glue' | 'spark';

// Mapping between datasource type and its display name.
// Temporary solution, will be removed along with refactoring of data source APIs
const DATASOURCE_TYPE_DISPLAY_NAME_MAP: Record<DataSourceTypeKey, string> = {
DEFAULT_INDEX_PATTERNS: 'Index patterns',
s3glue: 'Amazon S3',
spark: 'Spark',
DEFAULT_INDEX_PATTERNS: i18n.translate('dataExplorer.dataSourceSelector.indexPatternGroupTitle', {
defaultMessage: 'Index patterns',
}),
s3glue: i18n.translate('dataExplorer.dataSourceSelector.amazonS3GroupTitle', {
defaultMessage: 'Amazon S3',
}),
spark: i18n.translate('dataExplorer.dataSourceSelector.sparkGroupTitle', {
defaultMessage: 'Spark',
}),
};

type DataSetType = ISourceDataSet['data_sets'][number];
Expand Down Expand Up @@ -66,7 +73,19 @@ const getSourceList = (allDataSets: ISourceDataSet[]) => {
const finalList = [] as DataSourceGroup[];
allDataSets.forEach((curDataSet) => {
const typeKey = curDataSet.ds.getType() as DataSourceTypeKey;
const groupName = DATASOURCE_TYPE_DISPLAY_NAME_MAP[typeKey] || 'Default Group';
let groupName =
DATASOURCE_TYPE_DISPLAY_NAME_MAP[typeKey] ||
i18n.translate('dataExplorer.dataSourceSelector.defaultGroupTitle', {
defaultMessage: 'Default Group',
});

// add '- Opens in Log Explorer' to hint user that selecting these types of data sources
// will lead to redirection to log explorer
if (typeKey !== 'DEFAULT_INDEX_PATTERNS') {
groupName = `${groupName}${i18n.translate('dataExplorer.dataSourceSelector.redirectionHint', {
defaultMessage: ' - Opens in Log Explorer',
})}`;
}

const existingGroup = finalList.find((item) => item.label === groupName);
const mappedOptions = curDataSet.data_sets.map((dataSet) =>
Expand Down
110 changes: 110 additions & 0 deletions src/plugins/data_explorer/public/components/sidebar/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react';
import { Sidebar } from './index'; // Adjust the import path as necessary
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import { MockS3DataSource } from '../../../../discover/public/__mock__/index.test.mock';
import { createMemoryHistory } from 'history';
import { Router } from 'react-router-dom';

const mockStore = configureMockStore();
const initialState = {
metadata: { indexPattern: 'some-index-pattern-id' },
};
const store = mockStore(initialState);

jest.mock('../../../../opensearch_dashboards_react/public', () => {
return {
toMountPoint: jest.fn().mockImplementation((component) => () => component),
useOpenSearchDashboards: jest.fn().mockReturnValue({
services: {
data: {
indexPatterns: {},
dataSources: {
dataSourceService: {
dataSources$: {
subscribe: jest.fn((callback) => {
callback({
's3-prod-mock': new MockS3DataSource({
name: 's3-prod-mock',
type: 's3glue',
metadata: {},
}),
});
return { unsubscribe: jest.fn() };
}),
},
},
},
},
notifications: {
toasts: {
addError: jest.fn(),
},
},
application: {
navigateToUrl: jest.fn(),
},
overlays: {
openConfirm: jest.fn(),
},
},
}),
withOpenSearchDashboards: () => (Component: React.ComponentClass) => (props: any) => (
<Component {...props} />
),
};
});

jest.mock('../../../../data_explorer/public', () => ({
useTypedSelector: jest.fn(),
useTypedDispatch: jest.fn(),
}));

describe('Sidebar Component', () => {
it('renders without crashing', () => {
const { container, getByTestId } = render(
<Provider store={store}>
<Sidebar />
</Provider>
);
expect(container).toBeInTheDocument();
expect(getByTestId('dataExplorerDSSelect')).toBeInTheDocument();
});

it('shows title extensions on the non-index pattern data source', () => {
const { getByText, getByTestId } = render(
<Provider store={store}>
<Sidebar />
</Provider>
);

fireEvent.click(getByTestId('comboBoxToggleListButton'));
waitFor(() => {
expect(getByText('Open in Log Explorer')).toBeInTheDocument();
});
});

it('redirects to log explorer when clicking open-in-log-explorer button', () => {
const history = createMemoryHistory();
const { getByText, getByTestId } = render(
<Provider store={store}>
<Router history={history}>
<Sidebar />
</Router>
</Provider>
);

fireEvent.click(getByTestId('comboBoxToggleListButton'));
waitFor(() => {
expect(getByText('s3-prod-mock')).toBeInTheDocument();
fireEvent.click(getByText('s3-prod-mock'));
expect(history.location.pathname).toContain('observability-logs#/explorer');
});
});
});
20 changes: 14 additions & 6 deletions src/plugins/data_explorer/public/components/sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,31 @@ export const Sidebar: FC = ({ children }) => {
}
}, [indexPatternId, activeDataSources, dataSourceOptionList]);

const redirectToLogExplorer = useCallback(
(dsName: string, dsType: string) => {
return application.navigateToUrl(
`../observability-logs#/explorer?datasourceName=${dsName}&datasourceType=${dsType}`
);
},
[application]
);

const handleSourceSelection = useCallback(
(selectedDataSources: DataSourceOption[]) => {
if (selectedDataSources.length === 0) {
setSelectedSources(selectedDataSources);
return;
}
// Temporary redirection solution for 2.11, where clicking non-index-pattern datasource
// will redirect user to Observability event explorer
// Temporary redirection solution for 2.11, where clicking non-index-pattern data sources
// will prompt users with modal explaining they are being redirected to Observability log explorer
if (selectedDataSources[0]?.ds?.getType() !== 'DEFAULT_INDEX_PATTERNS') {
return application.navigateToUrl(
`../observability-logs#/explorer?datasourceName=${selectedDataSources[0].label}&datasourceType=${selectedDataSources[0].type}`
);
redirectToLogExplorer(selectedDataSources[0].label, selectedDataSources[0].type);
return;
}
setSelectedSources(selectedDataSources);
dispatch(setIndexPattern(selectedDataSources[0].value));
},
[application, dispatch]
[dispatch, redirectToLogExplorer, setSelectedSources]
);

const handleGetDataSetError = useCallback(
Expand Down
28 changes: 28 additions & 0 deletions src/plugins/discover/public/__mock__/index.test.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export class MockS3DataSource {
protected name: string;
protected type: string;
protected metadata: any;

constructor({ name, type, metadata }: { name: string; type: string; metadata: any }) {
this.name = name;
this.type = type;
this.metadata = metadata;
}

async getDataSet(dataSetParams?: any) {
return [this.name];
}

getName() {
return this.name;
}

getType() {
return this.type;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface DataGridTableProps {
isContextView?: boolean;
isLoading?: boolean;
showPagination?: boolean;
scrollToTop?: () => void;
}

export const DataGridTable = ({
Expand All @@ -67,6 +68,7 @@ export const DataGridTable = ({
isContextView = false,
isLoading = false,
showPagination,
scrollToTop,
}: DataGridTableProps) => {
const services = getServices();
const [inspectedHit, setInspectedHit] = useState<OpenSearchSearchHit | undefined>();
Expand Down Expand Up @@ -179,6 +181,7 @@ export const DataGridTable = ({
isShortDots={isShortDots}
hideTimeColumn={hideTimeColumn}
defaultSortOrder={defaultSortOrder}
scrollToTop={scrollToTop}
/>
),
[
Expand All @@ -197,6 +200,7 @@ export const DataGridTable = ({
defaultSortOrder,
hideTimeColumn,
isShortDots,
scrollToTop,
]
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@

.osdDocTableCell__source {
.truncate-by-height {
transform: translateY(-1.5px);
margin-bottom: -1.5px;
margin-top: -1.5px;
margin-bottom: -3.5px;
}

dd,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import './_doc_table.scss';

import React, { useEffect, useRef, useState } from 'react';
import React, { useEffect, useRef, useState, useCallback } from 'react';
import { EuiButtonEmpty, EuiCallOut, EuiProgress } from '@elastic/eui';
import { FormattedMessage } from '@osd/i18n/react';
import { TableHeader } from './table_header';
Expand Down Expand Up @@ -33,6 +33,7 @@ export interface DefaultDiscoverTableProps {
hideTimeColumn: boolean;
defaultSortOrder: SortDirection;
showPagination?: boolean;
scrollToTop?: () => void;
}

export const LegacyDiscoverTable = ({
Expand All @@ -52,6 +53,7 @@ export const LegacyDiscoverTable = ({
hideTimeColumn,
defaultSortOrder,
showPagination,
scrollToTop,
}: DefaultDiscoverTableProps) => {
const displayedColumns = getLegacyDisplayedColumns(
columns,
Expand All @@ -68,33 +70,34 @@ export const LegacyDiscoverTable = ({
endRow: rows.length < pageSize ? rows.length : pageSize,
});
const observerRef = useRef<IntersectionObserver | null>(null);
const sentinelRef = useRef<HTMLDivElement | null>(null);

const loadMoreRows = () => {
setRenderedRowCount((prevRowCount) => prevRowCount + 50); // Load 50 more rows
};
const [sentinelEle, setSentinelEle] = useState<HTMLDivElement>();
// Need a callback ref since the element isnt set on the first render.
const sentinelRef = useCallback((node: HTMLDivElement | null) => {
if (node !== null) {
setSentinelEle(node);
}
}, []);

useEffect(() => {
const sentinel = sentinelRef.current;
observerRef.current = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
loadMoreRows();
}
},
{ threshold: 1.0 }
);
if (sentinelEle) {
observerRef.current = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
setRenderedRowCount((prevRowCount) => prevRowCount + 50); // Load 50 more rows
}
},
{ threshold: 1.0 }
);

if (sentinelRef.current) {
observerRef.current.observe(sentinelRef.current);
observerRef.current.observe(sentinelEle);
}

return () => {
if (observerRef.current && sentinel) {
observerRef.current.unobserve(sentinel);
if (observerRef.current && sentinelEle) {
observerRef.current.unobserve(sentinelEle);
}
};
}, []);
}, [sentinelEle]);

const [activePage, setActivePage] = useState(0);
const pageCount = Math.ceil(rows.length / pageSize);
Expand Down Expand Up @@ -173,7 +176,7 @@ export const LegacyDiscoverTable = ({
values={{ sampleSize }}
/>

<EuiButtonEmpty onClick={() => window.scrollTo(0, 0)}>
<EuiButtonEmpty onClick={scrollToTop}>
<FormattedMessage id="discover.backToTopLinkText" defaultMessage="Back to top." />
</EuiButtonEmpty>
</EuiCallOut>
Expand Down
Loading
Loading