mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-21 22:02:37 +00:00
minor fix
This commit is contained in:
parent
e51fc7afe6
commit
f16e5f2bf2
@ -262,10 +262,10 @@ const CustomControls: FC<{
|
||||
);
|
||||
|
||||
const handleExportClick = useCallback(() => {
|
||||
if (activeTab === 'lineage') {
|
||||
onExportClick([ExportTypes.CSV, ExportTypes.PNG]);
|
||||
} else {
|
||||
if (activeTab === 'impact_analysis') {
|
||||
onExportClick([ExportTypes.CSV], handleImpactAnalysisExport);
|
||||
} else {
|
||||
onExportClick([ExportTypes.CSV, ExportTypes.PNG]);
|
||||
}
|
||||
}, [activeTab, onExportClick]);
|
||||
|
||||
@ -354,7 +354,7 @@ const CustomControls: FC<{
|
||||
arrow
|
||||
placement="top"
|
||||
title={t('label.export-as-type', { type: t('label.csv') })}>
|
||||
<StyledIconButton size="large" onClick={() => handleExportClick}>
|
||||
<StyledIconButton size="large" onClick={handleExportClick}>
|
||||
<DownloadIcon />
|
||||
</StyledIconButton>
|
||||
</Tooltip>
|
||||
|
@ -10,66 +10,328 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { render } from '@testing-library/react';
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { LINEAGE_TAB_VIEW } from '../../../constants/Lineage.constants';
|
||||
import { LineageLayer } from '../../../generated/settings/settings';
|
||||
import { EntityType } from '../../../enums/entity.enum';
|
||||
import CustomControlsComponent from './CustomControls.component';
|
||||
|
||||
const mockOnEditLineageClick = jest.fn();
|
||||
const mockOnExportClick = jest.fn();
|
||||
const mockHandleActiveViewTabChange = jest.fn();
|
||||
const mockOnLineageConfigUpdate = jest.fn();
|
||||
const mockSetSelectedQuickFilters = jest.fn();
|
||||
const mockOnSearchValueChange = jest.fn();
|
||||
|
||||
const mockLineageConfig = {
|
||||
upstreamDepth: 3,
|
||||
downstreamDepth: 3,
|
||||
nodesPerLayer: 50,
|
||||
};
|
||||
|
||||
const mockNavigate = jest.fn();
|
||||
const mockLocation = {
|
||||
search: '?mode=lineage&depth=3&dir=downstream',
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
nodeDepthOptions: [1, 2, 3, 4, 5],
|
||||
onSearchValueChange: mockOnSearchValueChange,
|
||||
searchValue: '',
|
||||
};
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useNavigate: () => mockNavigate,
|
||||
useLocation: () => mockLocation,
|
||||
}));
|
||||
|
||||
jest.mock('./LineageSearchSelect/LineageSearchSelect', () =>
|
||||
jest.fn().mockReturnValue(<p>LineageSearchSelect</p>)
|
||||
jest
|
||||
.fn()
|
||||
.mockReturnValue(
|
||||
<div data-testid="lineage-search-select">LineageSearchSelect</div>
|
||||
)
|
||||
);
|
||||
|
||||
jest.mock('../../Explore/ExploreQuickFilters', () =>
|
||||
jest.fn().mockReturnValue(<p>ExploreQuickFilters</p>)
|
||||
jest
|
||||
.fn()
|
||||
.mockReturnValue(
|
||||
<div data-testid="explore-quick-filters">ExploreQuickFilters</div>
|
||||
)
|
||||
);
|
||||
|
||||
jest.mock('reactflow', () => ({
|
||||
Position: () => ({
|
||||
Left: 'left',
|
||||
Top: 'top',
|
||||
Right: 'right',
|
||||
Bottom: 'bottom',
|
||||
}),
|
||||
MarkerType: () => ({
|
||||
Arrow: 'arrow',
|
||||
ArrowClosed: 'arrowclosed',
|
||||
}),
|
||||
}));
|
||||
jest.mock('./LineageConfigModal', () =>
|
||||
jest.fn(({ visible, onCancel, onSave }) =>
|
||||
visible ? (
|
||||
<div data-testid="lineage-config-modal">
|
||||
<button onClick={onCancel}>Cancel</button>
|
||||
<button onClick={() => onSave(mockLineageConfig)}>Save</button>
|
||||
</div>
|
||||
) : null
|
||||
)
|
||||
);
|
||||
|
||||
jest.mock('../../common/SearchBarComponent/SearchBar.component', () =>
|
||||
jest.fn(({ onSearch, searchValue, placeholder }) => (
|
||||
<input
|
||||
data-testid="search-bar"
|
||||
placeholder={placeholder}
|
||||
value={searchValue}
|
||||
onChange={(e) => onSearch(e.target.value)}
|
||||
/>
|
||||
))
|
||||
);
|
||||
|
||||
jest.mock('../../../context/LineageProvider/LineageProvider', () => ({
|
||||
useLineageProvider: jest.fn().mockImplementation(() => ({
|
||||
onLineageEditClick: mockOnEditLineageClick,
|
||||
onExportClick: mockOnExportClick,
|
||||
activeLayer: [LineageLayer.ColumnLevelLineage],
|
||||
onLineageConfigUpdate: mockOnLineageConfigUpdate,
|
||||
selectedQuickFilters: [],
|
||||
setSelectedQuickFilters: jest.fn(),
|
||||
setSelectedQuickFilters: mockSetSelectedQuickFilters,
|
||||
lineageConfig: mockLineageConfig,
|
||||
nodes: [],
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('../../../hooks/useFqn', () => ({
|
||||
useFqn: jest.fn().mockReturnValue({ fqn: 'test.table' }),
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils/useRequiredParams', () => ({
|
||||
useRequiredParams: jest
|
||||
.fn()
|
||||
.mockReturnValue({ entityType: EntityType.TABLE }),
|
||||
}));
|
||||
|
||||
jest.mock('../../../rest/lineageAPI', () => ({
|
||||
exportLineageByEntityCountAsync: jest.fn(),
|
||||
}));
|
||||
|
||||
// Mock window.location
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
search: '?mode=lineage&depth=3&dir=downstream',
|
||||
},
|
||||
writable: true,
|
||||
});
|
||||
|
||||
describe('CustomControls', () => {
|
||||
afterEach(() => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('calls onEditLinageClick on Edit Lineage button click', () => {
|
||||
const { getByText } = render(
|
||||
<CustomControlsComponent
|
||||
activeViewTab={LINEAGE_TAB_VIEW.DIAGRAM_VIEW}
|
||||
handleActiveViewTabChange={mockHandleActiveViewTabChange}
|
||||
onlyShowTabSwitch={false}
|
||||
/>,
|
||||
{ wrapper: MemoryRouter }
|
||||
it('renders all main control buttons', () => {
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
expect(screen.getByLabelText('label.filter-plural')).toBeInTheDocument();
|
||||
expect(screen.getByText('label.lineage')).toBeInTheDocument();
|
||||
expect(screen.getByText('label.impact-analysis')).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('label.export-as-type')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByLabelText('label.lineage-configuration')
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByLabelText('label.full-screen-view')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows LineageSearchSelect by default in lineage mode', () => {
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('lineage-search-select')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows SearchBar when in impact analysis mode', () => {
|
||||
window.location.search = '?mode=impact_analysis&depth=3&dir=downstream';
|
||||
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('search-bar')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('toggles filter selection when filter button is clicked', () => {
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const filterButton = screen.getByLabelText('label.filter-plural');
|
||||
fireEvent.click(filterButton);
|
||||
|
||||
expect(screen.getByTestId('explore-quick-filters')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('navigates to lineage mode when lineage button is clicked', () => {
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const lineageButton = screen.getByText('label.lineage');
|
||||
fireEvent.click(lineageButton);
|
||||
|
||||
expect(mockNavigate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('navigates to impact analysis mode when impact analysis button is clicked', () => {
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const impactAnalysisButton = screen.getByText('label.impact-analysis');
|
||||
fireEvent.click(impactAnalysisButton);
|
||||
|
||||
expect(mockNavigate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls onExportClick when export button is clicked', () => {
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const exportButton = screen.getByLabelText('label.export-as-type');
|
||||
fireEvent.click(exportButton);
|
||||
|
||||
expect(mockOnExportClick).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('opens lineage config modal when settings button is clicked', () => {
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const settingsButton = screen.getByLabelText('label.lineage-configuration');
|
||||
fireEvent.click(settingsButton);
|
||||
|
||||
expect(screen.getByTestId('lineage-config-modal')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls onLineageConfigUpdate when modal is saved', async () => {
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const settingsButton = screen.getByLabelText('label.lineage-configuration');
|
||||
fireEvent.click(settingsButton);
|
||||
|
||||
const saveButton = screen.getByText('Save');
|
||||
fireEvent.click(saveButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockOnLineageConfigUpdate).toHaveBeenCalledWith(mockLineageConfig);
|
||||
});
|
||||
});
|
||||
|
||||
it('toggles fullscreen mode when fullscreen button is clicked', () => {
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const fullscreenButton = screen.getByLabelText('label.full-screen-view');
|
||||
fireEvent.click(fullscreenButton);
|
||||
|
||||
expect(mockNavigate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('shows node depth selector in impact analysis mode with filters active', () => {
|
||||
window.location.search = '?mode=impact_analysis&depth=3&dir=downstream';
|
||||
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const filterButton = screen.getByLabelText('label.filter-plural');
|
||||
fireEvent.click(filterButton);
|
||||
|
||||
// Node depth should be visible in the filter section
|
||||
expect(
|
||||
screen.getByText(
|
||||
(content) =>
|
||||
content?.includes('label.node-depth') && content?.includes(':')
|
||||
)
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByText('3')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('opens node depth menu and selects new depth', () => {
|
||||
window.location.search = '?mode=impact_analysis&depth=3&dir=downstream';
|
||||
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const filterButton = screen.getByLabelText('label.filter-plural');
|
||||
fireEvent.click(filterButton);
|
||||
|
||||
const nodeDepthButton = screen.getByText(
|
||||
(content) =>
|
||||
content?.includes('label.node-depth') && content?.includes(':')
|
||||
);
|
||||
fireEvent.click(nodeDepthButton);
|
||||
|
||||
// check LineageSearchSelect is visible
|
||||
expect(getByText('LineageSearchSelect')).toBeInTheDocument();
|
||||
// The menu items would be rendered by Material-UI Menu component
|
||||
// This test verifies the click handler is set up correctly
|
||||
expect(nodeDepthButton).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// check ExploreQuickFilters is visible
|
||||
expect(getByText('ExploreQuickFilters')).toBeInTheDocument();
|
||||
it('calls onSearchValueChange when search value changes in impact analysis mode', () => {
|
||||
window.location.search = '?mode=impact_analysis&depth=3&dir=downstream';
|
||||
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const searchInput = screen.getByTestId('search-bar');
|
||||
fireEvent.change(searchInput, { target: { value: 'test search' } });
|
||||
|
||||
expect(mockOnSearchValueChange).toHaveBeenCalledWith('test search');
|
||||
});
|
||||
|
||||
it('shows clear filters button when filters are applied', () => {
|
||||
const mockSetSelectedQuickFilters = jest.fn();
|
||||
|
||||
jest.doMock('../../../context/LineageProvider/LineageProvider', () => ({
|
||||
useLineageProvider: jest.fn().mockImplementation(() => ({
|
||||
onExportClick: mockOnExportClick,
|
||||
onLineageConfigUpdate: mockOnLineageConfigUpdate,
|
||||
selectedQuickFilters: [{ key: 'service', value: ['test-service'] }],
|
||||
setSelectedQuickFilters: mockSetSelectedQuickFilters,
|
||||
lineageConfig: mockLineageConfig,
|
||||
nodes: [],
|
||||
})),
|
||||
}));
|
||||
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const filterButton = screen.getByLabelText('label.filter-plural');
|
||||
fireEvent.click(filterButton);
|
||||
|
||||
expect(screen.getByText('label.clear-entity')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('parses query parameters correctly for upstream direction', () => {
|
||||
window.location.search = '?mode=lineage&depth=2&dir=upstream';
|
||||
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
// Component should render correctly with upstream direction
|
||||
expect(screen.getByText('label.lineage')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('handles missing query parameters with defaults', () => {
|
||||
window.location.search = '';
|
||||
|
||||
render(<CustomControlsComponent {...defaultProps} />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
// Component should render with default values
|
||||
expect(screen.getByText('label.lineage')).toBeInTheDocument();
|
||||
expect(screen.getByText('label.impact-analysis')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -14,7 +14,6 @@
|
||||
import { IconButton, Menu, ToggleButtonGroup } from '@mui/material';
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { ExportTypes } from '../../constants/Export.constants';
|
||||
import { useLineageProvider } from '../../context/LineageProvider/LineageProvider';
|
||||
import { LineageContextType } from '../../context/LineageProvider/LineageProvider.interface';
|
||||
import { EntityType } from '../../enums/entity.enum';
|
||||
@ -26,6 +25,7 @@ import {
|
||||
getLineagePagingData,
|
||||
} from '../../rest/lineageAPI';
|
||||
import { useRequiredParams } from '../../utils/useRequiredParams';
|
||||
import CustomControlsComponent from '../Entity/EntityLineage/CustomControls.component';
|
||||
import { LineageConfig } from '../Entity/EntityLineage/EntityLineage.interface';
|
||||
import LineageTable from './LineageTable';
|
||||
import { EImpactLevel } from './LineageTable.interface';
|
||||
@ -66,6 +66,9 @@ jest.mock('lodash', () => {
|
||||
|
||||
return module;
|
||||
});
|
||||
jest.mock('../Entity/EntityLineage/CustomControls.component', () => {
|
||||
return jest.fn().mockReturnValue(<div>CustomControls</div>);
|
||||
});
|
||||
|
||||
const mockUseLineageProvider = useLineageProvider as jest.MockedFunction<
|
||||
typeof useLineageProvider
|
||||
@ -163,8 +166,6 @@ const mockEntity = {
|
||||
domain: null,
|
||||
};
|
||||
|
||||
// Remove the custom renderWithRouter function since our test utils handle this
|
||||
|
||||
describe('LineageTable', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
@ -176,6 +177,7 @@ describe('LineageTable', () => {
|
||||
downstreamDepth: 2,
|
||||
upstreamDepth: 2,
|
||||
} as LineageConfig,
|
||||
updateEntityData: jest.fn(),
|
||||
onExportClick: jest.fn(),
|
||||
onLineageConfigUpdate: jest.fn(),
|
||||
} as unknown as LineageContextType);
|
||||
@ -230,20 +232,10 @@ describe('LineageTable', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should render the component', () => {
|
||||
it('should render the CustomControls component', () => {
|
||||
render(<LineageTable entity={mockEntity} />, { wrapper: MemoryRouter });
|
||||
|
||||
// expect(screen.getByRole('searchbox')).toBeInTheDocument();
|
||||
expect(screen.getByText('label.lineage')).toBeInTheDocument();
|
||||
expect(screen.getByText('label.impact-analysis')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display search bar with correct placeholder', () => {
|
||||
render(<LineageTable entity={mockEntity} />, { wrapper: MemoryRouter });
|
||||
|
||||
const searchInput = screen.getByPlaceholderText('label.search-for-type');
|
||||
|
||||
expect(searchInput).toHaveAttribute('placeholder', 'label.search-for-type');
|
||||
expect(screen.getByText('CustomControls')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render toggle buttons for upstream and downstream', () => {
|
||||
@ -263,36 +255,6 @@ describe('LineageTable', () => {
|
||||
expect(impactButton).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle search input changes', async () => {
|
||||
const setSearchValue = jest.fn();
|
||||
mockUseLineageTableState.mockReturnValue({
|
||||
...defaultMockState,
|
||||
setSearchValue,
|
||||
});
|
||||
|
||||
render(<LineageTable entity={mockEntity} />, { wrapper: MemoryRouter });
|
||||
|
||||
const searchInput = screen.getByPlaceholderText('label.search-for-type');
|
||||
fireEvent.change(searchInput, { target: { value: 'test search' } });
|
||||
|
||||
expect(setSearchValue).toHaveBeenCalledWith('test search');
|
||||
});
|
||||
|
||||
it('should toggle filter selection when filter button is clicked', async () => {
|
||||
const toggleFilterSelection = jest.fn();
|
||||
mockUseLineageTableState.mockReturnValue({
|
||||
...defaultMockState,
|
||||
toggleFilterSelection,
|
||||
});
|
||||
|
||||
render(<LineageTable entity={mockEntity} />, { wrapper: MemoryRouter });
|
||||
|
||||
const filterButton = screen.getByTitle('label.filter-plural');
|
||||
fireEvent.click(filterButton);
|
||||
|
||||
expect(toggleFilterSelection).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should open impact level menu when clicked', async () => {
|
||||
render(<LineageTable entity={mockEntity} />, { wrapper: MemoryRouter });
|
||||
|
||||
@ -337,44 +299,6 @@ describe('LineageTable', () => {
|
||||
expect(screen.getByText(/label.node-depth/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call export function when export button is clicked', async () => {
|
||||
const onExportClick = jest.fn();
|
||||
mockUseLineageProvider.mockReturnValue({
|
||||
selectedQuickFilters: [],
|
||||
setSelectedQuickFilters: jest.fn(),
|
||||
lineageConfig: {},
|
||||
onExportClick,
|
||||
onLineageConfigUpdate: jest.fn(),
|
||||
} as unknown as LineageContextType);
|
||||
|
||||
render(<LineageTable entity={mockEntity} />, { wrapper: MemoryRouter });
|
||||
|
||||
const exportButton = screen.getByRole('button', { name: 'Export as CSV' });
|
||||
fireEvent.click(exportButton);
|
||||
|
||||
expect(onExportClick).toHaveBeenCalledWith(
|
||||
[ExportTypes.CSV],
|
||||
expect.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it('should open lineage config dialog when settings button is clicked', async () => {
|
||||
const setDialogVisible = jest.fn();
|
||||
mockUseLineageTableState.mockReturnValue({
|
||||
...defaultMockState,
|
||||
setDialogVisible,
|
||||
});
|
||||
|
||||
render(<LineageTable entity={mockEntity} />, { wrapper: MemoryRouter });
|
||||
|
||||
const settingsButton = screen.getByRole('button', {
|
||||
name: 'label.lineage-configuration',
|
||||
});
|
||||
fireEvent.click(settingsButton);
|
||||
|
||||
expect(setDialogVisible).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it('should render table with correct data source for table level', () => {
|
||||
mockUseLineageTableState.mockReturnValue({
|
||||
...defaultMockState,
|
||||
@ -405,8 +329,8 @@ describe('LineageTable', () => {
|
||||
|
||||
render(<LineageTable entity={mockEntity} />, { wrapper: MemoryRouter });
|
||||
|
||||
expect(screen.getByText('Source Table')).toBeInTheDocument();
|
||||
expect(screen.getByText('Impacted Table')).toBeInTheDocument();
|
||||
expect(screen.getByText('label.source')).toBeInTheDocument();
|
||||
expect(screen.getByText('label.impacted')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should fetch nodes on component mount', async () => {
|
||||
@ -503,24 +427,6 @@ describe('LineageTable', () => {
|
||||
expect(table).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should handle node depth selection', async () => {
|
||||
mockUseLineageTableState.mockReturnValue({
|
||||
...defaultMockState,
|
||||
filterSelectionActive: true,
|
||||
});
|
||||
|
||||
render(<LineageTable entity={mockEntity} />, { wrapper: MemoryRouter });
|
||||
|
||||
const nodeDepthButton = screen.getByRole('button', {
|
||||
name: /label.node-depth/,
|
||||
});
|
||||
fireEvent.click(nodeDepthButton);
|
||||
|
||||
const depthOption = await screen.findByRole('menuitem', { name: '1' });
|
||||
|
||||
expect(depthOption).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('LineageTable Hooks Integration', () => {
|
||||
it('should integrate with useLineageTableState correctly', () => {
|
||||
const mockState = {
|
||||
@ -532,7 +438,12 @@ describe('LineageTable', () => {
|
||||
|
||||
render(<LineageTable entity={mockEntity} />, { wrapper: MemoryRouter });
|
||||
|
||||
expect(screen.getByDisplayValue('test search')).toBeInTheDocument();
|
||||
expect(CustomControlsComponent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
searchValue: 'test search',
|
||||
}),
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should integrate with usePaging correctly', () => {
|
||||
|
@ -48,7 +48,6 @@ import { useFqn } from '../../hooks/useFqn';
|
||||
import { SearchSourceAlias } from '../../interface/search.interface';
|
||||
import { QueryFieldInterface } from '../../pages/ExplorePage/ExplorePage.interface';
|
||||
import {
|
||||
exportLineageByEntityCountAsync,
|
||||
getLineageByEntityCount,
|
||||
getLineagePagingData,
|
||||
} from '../../rest/lineageAPI';
|
||||
@ -306,27 +305,6 @@ const LineageTable: FC<{ entity: SourceType }> = ({ entity }) => {
|
||||
return JSON.stringify(query);
|
||||
}, [selectedQuickFilters, searchValue]);
|
||||
|
||||
// Function to handle export click
|
||||
const handleExportClick = useCallback(
|
||||
() =>
|
||||
exportLineageByEntityCountAsync({
|
||||
fqn: fqn ?? '',
|
||||
type: entityType ?? '',
|
||||
direction: lineageDirection,
|
||||
nodeDepth: nodeDepth,
|
||||
query_filter: queryFilter,
|
||||
}),
|
||||
[
|
||||
fqn,
|
||||
entityType,
|
||||
lineageDirection,
|
||||
nodeDepth,
|
||||
currentPage,
|
||||
pageSize,
|
||||
queryFilter,
|
||||
]
|
||||
);
|
||||
|
||||
// Define table columns
|
||||
const extraTableFilters = useMemo(() => {
|
||||
return (
|
||||
@ -375,7 +353,7 @@ const LineageTable: FC<{ entity: SourceType }> = ({ entity }) => {
|
||||
</StyledMenu>
|
||||
</div>
|
||||
);
|
||||
}, [navigate, streamButtonGroup, impactOnEl, impactLevel, handleExportClick]);
|
||||
}, [navigate, streamButtonGroup, impactOnEl, impactLevel]);
|
||||
|
||||
// Function to fetch nodes based on current filters and pagination
|
||||
const fetchNodes = useCallback(async () => {
|
||||
@ -662,7 +640,7 @@ const LineageTable: FC<{ entity: SourceType }> = ({ entity }) => {
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t('label.source-column'),
|
||||
title: t('label.source-column-plural'),
|
||||
dataIndex:
|
||||
lineageDirection === LineageDirection.Downstream
|
||||
? ['column', 'fromColumns']
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "Quelle",
|
||||
"source-aligned": "Source-aligned",
|
||||
"source-column": "Quellenspalte",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Quelle:",
|
||||
"source-match": "Quellenübereinstimmung",
|
||||
"source-plural": "Quellen",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "Source",
|
||||
"source-aligned": "Source-aligned",
|
||||
"source-column": "Source Column",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "Match By Event Source",
|
||||
"source-plural": "Sources",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "Fuente",
|
||||
"source-aligned": "Alineado con el Origen",
|
||||
"source-column": "Columna de Origen",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Fuente:",
|
||||
"source-match": "Coincidir por Fuente de Eventos",
|
||||
"source-plural": "Fuentes",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "Source",
|
||||
"source-aligned": "Source-aligned",
|
||||
"source-column": "Colonne Source",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "Correspondance par Source d'Événement",
|
||||
"source-plural": "Sources",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "Fonte",
|
||||
"source-aligned": "Aliñado coa fonte",
|
||||
"source-column": "Columna de orixe",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "Coincidencia por fonte de evento",
|
||||
"source-plural": "Fontes",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "מקור",
|
||||
"source-aligned": "מקור מתואם",
|
||||
"source-column": "עמודת מקור",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "התאמה לפי מקור אירוע",
|
||||
"source-plural": "מקורות",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "ソース",
|
||||
"source-aligned": "ソース整列",
|
||||
"source-column": "ソースカラム",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "ソース:",
|
||||
"source-match": "イベントソースで一致",
|
||||
"source-plural": "ソース",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "소스",
|
||||
"source-aligned": "소스 정렬",
|
||||
"source-column": "소스 열",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "이벤트 소스로 매칭",
|
||||
"source-plural": "소스들",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "स्रोत",
|
||||
"source-aligned": "स्रोत-संरेखित",
|
||||
"source-column": "स्रोत स्तंभ",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "इव्हेंट स्रोताद्वारे जुळवा",
|
||||
"source-plural": "स्रोत",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "Bron",
|
||||
"source-aligned": "Bron-georiënteerd",
|
||||
"source-column": "Bronkolom",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "Overeenkomst op eventbron",
|
||||
"source-plural": "Bronnen",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "منبع",
|
||||
"source-aligned": "همراستا با منبع",
|
||||
"source-column": "ستون منبع",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "مطابقت بر اساس منبع رویداد",
|
||||
"source-plural": "منابع",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "Fonte",
|
||||
"source-aligned": "Alinhado à Fonte",
|
||||
"source-column": "Coluna de Fonte",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "Correspondência por Fonte de Evento",
|
||||
"source-plural": "Fontes",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "Fonte",
|
||||
"source-aligned": "Alinhado à Fonte",
|
||||
"source-column": "Coluna de Fonte",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "Correspondência por Fonte de Evento",
|
||||
"source-plural": "Fontes",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "Источник",
|
||||
"source-aligned": "Выровненный по источнику",
|
||||
"source-column": "Источник столбца",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "Сопоставление по источнику события",
|
||||
"source-plural": "Источники",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "แหล่งที่มา",
|
||||
"source-aligned": "ตรงตามแหล่งที่มา",
|
||||
"source-column": "คอลัมน์แหล่งที่มา",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "จับคู่ตามแหล่งที่มาของเหตุการณ์",
|
||||
"source-plural": "แหล่งที่มาหลายรายการ",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "Kaynak",
|
||||
"source-aligned": "Kaynak Odaklı",
|
||||
"source-column": "Kaynak Sütun",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "Olay Kaynağına Göre Eşleştir",
|
||||
"source-plural": "Kaynaklar",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "源",
|
||||
"source-aligned": "Source-aligned",
|
||||
"source-column": "源列",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "Source:",
|
||||
"source-match": "根据事件源匹配",
|
||||
"source-plural": "来源",
|
||||
|
@ -1554,6 +1554,7 @@
|
||||
"source": "來源",
|
||||
"source-aligned": "來源導向",
|
||||
"source-column": "來源欄位",
|
||||
"source-column-plural": "Source Columns",
|
||||
"source-label": "來源:",
|
||||
"source-match": "依事件來源比對",
|
||||
"source-plural": "來源",
|
||||
|
Loading…
x
Reference in New Issue
Block a user