mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-27 00:31:42 +00:00
ui: display source of lineage (#15391)
* ui: display lineage source * added locale files * rename dbt source name * test: added unit test case
This commit is contained in:
parent
7424b2f430
commit
ec475bce03
@ -21,8 +21,10 @@ import { Node } from 'reactflow';
|
||||
import { ReactComponent as EditIcon } from '../../../assets/svg/edit-new.svg';
|
||||
import DescriptionV1 from '../../../components/common/EntityDescription/DescriptionV1';
|
||||
import { DE_ACTIVE_COLOR } from '../../../constants/constants';
|
||||
import { LINEAGE_SOURCE } from '../../../constants/Lineage.constants';
|
||||
import { CSMode } from '../../../enums/codemirror.enum';
|
||||
import { EntityType } from '../../../enums/entity.enum';
|
||||
import { Source } from '../../../generated/type/entityLineage';
|
||||
import { getNameFromFQN } from '../../../utils/CommonUtils';
|
||||
import { getLineageDetailsObject } from '../../../utils/EntityLineageUtils';
|
||||
import entityUtilClassBase from '../../../utils/EntityUtilClassBase';
|
||||
@ -266,6 +268,15 @@ const EdgeInfoDrawer = ({
|
||||
</Typography.Paragraph>
|
||||
)}
|
||||
</Col>
|
||||
<Col>
|
||||
<Divider />
|
||||
<Typography.Paragraph className="right-panel-label m-b-sm">
|
||||
{`${t('label.lineage-source')}`}
|
||||
</Typography.Paragraph>
|
||||
<Typography.Text className="m-b-0">
|
||||
{LINEAGE_SOURCE[edgeEntity.source as keyof typeof Source]}
|
||||
</Typography.Text>
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
</Drawer>
|
||||
|
||||
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright 2024 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, fireEvent, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { Edge } from 'reactflow';
|
||||
import { MOCK_NODES_AND_EDGES } from '../../../mocks/Lineage.mock';
|
||||
import EdgeInfoDrawer from './EdgeInfoDrawer.component';
|
||||
|
||||
jest.mock('../../../components/common/EntityDescription/DescriptionV1', () =>
|
||||
jest.fn().mockImplementation(({ onDescriptionUpdate }) => (
|
||||
<div data-testid="description-v1">
|
||||
DescriptionV1
|
||||
<button
|
||||
data-testid="update-description-button"
|
||||
onClick={() => onDescriptionUpdate('updatedHTML')}>
|
||||
Update Description
|
||||
</button>
|
||||
</div>
|
||||
))
|
||||
);
|
||||
|
||||
jest.mock('../../../utils/CommonUtils', () => ({
|
||||
getNameFromFQN: jest.fn().mockReturnValue('getNameFromFQN'),
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils/EntityUtils', () => ({
|
||||
getEntityName: jest.fn().mockReturnValue('username'),
|
||||
}));
|
||||
|
||||
jest.mock('../../common/Loader/Loader', () =>
|
||||
jest.fn().mockImplementation(() => <div>Loader</div>)
|
||||
);
|
||||
|
||||
jest.mock('../../Database/SchemaEditor/SchemaEditor', () => {
|
||||
return jest.fn().mockImplementation(() => <div>SchemaEditor.component</div>);
|
||||
});
|
||||
|
||||
jest.mock('../../Modals/ModalWithQueryEditor/ModalWithQueryEditor', () => {
|
||||
return jest.fn().mockImplementation(() => <div>ModalWithQueryEditor</div>);
|
||||
});
|
||||
|
||||
jest.mock('antd', () => ({
|
||||
...jest.requireActual('antd'),
|
||||
Drawer: jest.fn().mockImplementation(({ children, title }) => (
|
||||
<div data-testid="drawer-component">
|
||||
Drawer
|
||||
<div data-testid="title">{title}</div>
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
)),
|
||||
}));
|
||||
|
||||
const mockOnEdgeDetailsUpdate = jest.fn();
|
||||
const mockEdgeInfoDrawer = {
|
||||
edge: {
|
||||
id: 'edge-5c97531f-d164-4707-842e-af52e0c43e26-5d816d56-40a2-493f-ae9d-012f1cd337dd',
|
||||
source: '5c97531f-d164-4707-842e-af52e0c43e26',
|
||||
target: '5d816d56-40a2-493f-ae9d-012f1cd337dd',
|
||||
type: 'buttonedge',
|
||||
animated: false,
|
||||
style: {
|
||||
strokeWidth: '2px',
|
||||
},
|
||||
markerEnd: {
|
||||
type: 'arrowclosed',
|
||||
},
|
||||
data: {
|
||||
edge: {
|
||||
toEntity: {
|
||||
fqn: 'RedshiftProd.dev.demo_dbt_jaffle.customers',
|
||||
id: '5d816d56-40a2-493f-ae9d-012f1cd337dd',
|
||||
type: 'table',
|
||||
},
|
||||
pipeline: null,
|
||||
fromEntity: {
|
||||
fqn: 'RedshiftProd.dev.demo_dbt_jaffle.stg_orders',
|
||||
id: '5c97531f-d164-4707-842e-af52e0c43e26',
|
||||
type: 'table',
|
||||
},
|
||||
sqlQuery: null,
|
||||
description: null,
|
||||
source: 'DbtLineage',
|
||||
doc_id:
|
||||
'5c97531f-d164-4707-842e-af52e0c43e26-5d816d56-40a2-493f-ae9d-012f1cd337dd',
|
||||
},
|
||||
isColumnLineage: false,
|
||||
isPipelineRootNode: false,
|
||||
},
|
||||
selected: true,
|
||||
} as Edge,
|
||||
nodes: MOCK_NODES_AND_EDGES.nodes,
|
||||
visible: true,
|
||||
hasEditAccess: true,
|
||||
onEdgeDetailsUpdate: mockOnEdgeDetailsUpdate,
|
||||
onClose: jest.fn(),
|
||||
};
|
||||
|
||||
describe('EdgeInfoDrawer Component', () => {
|
||||
it('should render the component', async () => {
|
||||
render(<EdgeInfoDrawer {...mockEdgeInfoDrawer} />);
|
||||
|
||||
expect(await screen.findByTestId('title')).toHaveTextContent(
|
||||
'label.edge-information'
|
||||
);
|
||||
|
||||
expect(await screen.findByTestId('description-v1')).toBeInTheDocument();
|
||||
expect(
|
||||
await screen.findByText('label.sql-uppercase-query')
|
||||
).toBeInTheDocument();
|
||||
expect(await screen.findByTestId('edit-sql')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render no query if no query is present', async () => {
|
||||
render(<EdgeInfoDrawer {...mockEdgeInfoDrawer} />);
|
||||
|
||||
expect(
|
||||
await screen.findByText('server.no-query-available')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render source of lineage', async () => {
|
||||
render(<EdgeInfoDrawer {...mockEdgeInfoDrawer} />);
|
||||
|
||||
expect(await screen.findByText('label.lineage-source')).toBeInTheDocument();
|
||||
expect(await screen.findByText('dbt Lineage')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call onEdgeDetailsUpdate on update description', async () => {
|
||||
render(<EdgeInfoDrawer {...mockEdgeInfoDrawer} />);
|
||||
const updateDescriptionButton = await screen.findByTestId(
|
||||
'update-description-button'
|
||||
);
|
||||
await act(async () => {
|
||||
fireEvent.click(updateDescriptionButton);
|
||||
});
|
||||
|
||||
expect(mockOnEdgeDetailsUpdate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
edge: expect.objectContaining({
|
||||
lineageDetails: expect.objectContaining({
|
||||
description: 'updatedHTML',
|
||||
}),
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should not render edit SQL button if has no edit access', () => {
|
||||
render(<EdgeInfoDrawer {...mockEdgeInfoDrawer} hasEditAccess={false} />);
|
||||
|
||||
expect(screen.queryByTestId('edit-sql')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@ -14,6 +14,7 @@
|
||||
import { t } from 'i18next';
|
||||
import { ElementLoadingState } from '../components/Entity/EntityLineage/EntityLineage.interface';
|
||||
import { SearchIndex } from '../enums/search.enum';
|
||||
import { Source } from '../generated/type/entityLineage';
|
||||
|
||||
export const FOREIGN_OBJECT_SIZE = 40;
|
||||
export const ZOOM_VALUE = 0.75;
|
||||
@ -73,3 +74,13 @@ export const LINEAGE_DEFAULT_QUICK_FILTERS = [
|
||||
'owner.displayName.keyword',
|
||||
'tags.tagFQN',
|
||||
];
|
||||
|
||||
export const LINEAGE_SOURCE: { [key in Source]: string } = {
|
||||
[Source.DashboardLineage]: 'Dashboard Lineage',
|
||||
[Source.DbtLineage]: 'dbt Lineage',
|
||||
[Source.Manual]: 'Manual',
|
||||
[Source.PipelineLineage]: 'Pipeline Lineage',
|
||||
[Source.QueryLineage]: 'Query Lineage',
|
||||
[Source.SparkLineage]: 'Spark Lineage',
|
||||
[Source.ViewLineage]: 'View Lineage',
|
||||
};
|
||||
|
||||
@ -616,6 +616,7 @@
|
||||
"lineage-ingestion": "Abstammungsinjektion",
|
||||
"lineage-lowercase": "Abstammung",
|
||||
"lineage-node-lowercase": "Abstammungsknoten",
|
||||
"lineage-source": "Source of Lineage",
|
||||
"list": "Liste",
|
||||
"list-entity": "{{entity}}-Liste",
|
||||
"live": "Live",
|
||||
|
||||
@ -616,6 +616,7 @@
|
||||
"lineage-ingestion": "Lineage Ingestion",
|
||||
"lineage-lowercase": "lineage",
|
||||
"lineage-node-lowercase": "lineage node",
|
||||
"lineage-source": "Source of Lineage",
|
||||
"list": "List",
|
||||
"list-entity": "List {{entity}}",
|
||||
"live": "Live",
|
||||
|
||||
@ -613,9 +613,10 @@
|
||||
"lineage": "Linaje",
|
||||
"lineage-config": "Configuración del linaje",
|
||||
"lineage-data-lowercase": "lineage data",
|
||||
"lineage-ingestion": "Ingesta de linaje",
|
||||
"lineage-lowercase": "linaje",
|
||||
"lineage-node-lowercase": "nodo de linaje",
|
||||
"lineage-ingestion": "Ingesta de lineaje",
|
||||
"lineage-lowercase": "lineaje",
|
||||
"lineage-node-lowercase": "lineage node",
|
||||
"lineage-source": "Source of Lineage",
|
||||
"list": "Lista",
|
||||
"list-entity": "Lista de {{entity}}",
|
||||
"live": "Vivo",
|
||||
|
||||
@ -616,6 +616,7 @@
|
||||
"lineage-ingestion": "Ingestion de la Traçabilité",
|
||||
"lineage-lowercase": "traçabilité",
|
||||
"lineage-node-lowercase": "Nœud de Traçabilité",
|
||||
"lineage-source": "Source of Lineage",
|
||||
"list": "Liste",
|
||||
"list-entity": "Liste de {{entity}}",
|
||||
"live": "En Direct",
|
||||
|
||||
@ -616,6 +616,7 @@
|
||||
"lineage-ingestion": "כניסת שורשים",
|
||||
"lineage-lowercase": "שורשים",
|
||||
"lineage-node-lowercase": "צומת שורש",
|
||||
"lineage-source": "Source of Lineage",
|
||||
"list": "רשימה",
|
||||
"list-entity": "רשימת {{entity}}",
|
||||
"live": "שידור חי",
|
||||
|
||||
@ -616,6 +616,7 @@
|
||||
"lineage-ingestion": "リネージのインジェスチョン",
|
||||
"lineage-lowercase": "リネージ",
|
||||
"lineage-node-lowercase": "lineage node",
|
||||
"lineage-source": "Source of Lineage",
|
||||
"list": "リスト",
|
||||
"list-entity": "{{entity}}のリスト",
|
||||
"live": "Live",
|
||||
|
||||
@ -616,6 +616,7 @@
|
||||
"lineage-ingestion": "Herkomstingestie",
|
||||
"lineage-lowercase": "herkomst",
|
||||
"lineage-node-lowercase": "herkomstknooppunt",
|
||||
"lineage-source": "Source of Lineage",
|
||||
"list": "Lijst",
|
||||
"list-entity": "Lijst {{entity}}",
|
||||
"live": "Live",
|
||||
|
||||
@ -616,6 +616,7 @@
|
||||
"lineage-ingestion": "Ingestão de Linhagem",
|
||||
"lineage-lowercase": "linhagem",
|
||||
"lineage-node-lowercase": "nó de linhagem",
|
||||
"lineage-source": "Source of Lineage",
|
||||
"list": "Lista",
|
||||
"list-entity": "Listar {{entity}}",
|
||||
"live": "Ao Vivo",
|
||||
|
||||
@ -616,6 +616,7 @@
|
||||
"lineage-ingestion": "Получение проихождения",
|
||||
"lineage-lowercase": "происходение",
|
||||
"lineage-node-lowercase": "узел происхождения",
|
||||
"lineage-source": "Source of Lineage",
|
||||
"list": "Список",
|
||||
"list-entity": "Список {{entity}}",
|
||||
"live": "Процесс",
|
||||
|
||||
@ -616,6 +616,7 @@
|
||||
"lineage-ingestion": "血缘关系提取",
|
||||
"lineage-lowercase": "血缘",
|
||||
"lineage-node-lowercase": "血缘关系节点",
|
||||
"lineage-source": "Source of Lineage",
|
||||
"list": "列表",
|
||||
"list-entity": "列出{{entity}}",
|
||||
"live": "实时",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user