mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-28 09:13:58 +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 { ReactComponent as EditIcon } from '../../../assets/svg/edit-new.svg';
|
||||||
import DescriptionV1 from '../../../components/common/EntityDescription/DescriptionV1';
|
import DescriptionV1 from '../../../components/common/EntityDescription/DescriptionV1';
|
||||||
import { DE_ACTIVE_COLOR } from '../../../constants/constants';
|
import { DE_ACTIVE_COLOR } from '../../../constants/constants';
|
||||||
|
import { LINEAGE_SOURCE } from '../../../constants/Lineage.constants';
|
||||||
import { CSMode } from '../../../enums/codemirror.enum';
|
import { CSMode } from '../../../enums/codemirror.enum';
|
||||||
import { EntityType } from '../../../enums/entity.enum';
|
import { EntityType } from '../../../enums/entity.enum';
|
||||||
|
import { Source } from '../../../generated/type/entityLineage';
|
||||||
import { getNameFromFQN } from '../../../utils/CommonUtils';
|
import { getNameFromFQN } from '../../../utils/CommonUtils';
|
||||||
import { getLineageDetailsObject } from '../../../utils/EntityLineageUtils';
|
import { getLineageDetailsObject } from '../../../utils/EntityLineageUtils';
|
||||||
import entityUtilClassBase from '../../../utils/EntityUtilClassBase';
|
import entityUtilClassBase from '../../../utils/EntityUtilClassBase';
|
||||||
@ -266,6 +268,15 @@ const EdgeInfoDrawer = ({
|
|||||||
</Typography.Paragraph>
|
</Typography.Paragraph>
|
||||||
)}
|
)}
|
||||||
</Col>
|
</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>
|
</Row>
|
||||||
)}
|
)}
|
||||||
</Drawer>
|
</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 { t } from 'i18next';
|
||||||
import { ElementLoadingState } from '../components/Entity/EntityLineage/EntityLineage.interface';
|
import { ElementLoadingState } from '../components/Entity/EntityLineage/EntityLineage.interface';
|
||||||
import { SearchIndex } from '../enums/search.enum';
|
import { SearchIndex } from '../enums/search.enum';
|
||||||
|
import { Source } from '../generated/type/entityLineage';
|
||||||
|
|
||||||
export const FOREIGN_OBJECT_SIZE = 40;
|
export const FOREIGN_OBJECT_SIZE = 40;
|
||||||
export const ZOOM_VALUE = 0.75;
|
export const ZOOM_VALUE = 0.75;
|
||||||
@ -73,3 +74,13 @@ export const LINEAGE_DEFAULT_QUICK_FILTERS = [
|
|||||||
'owner.displayName.keyword',
|
'owner.displayName.keyword',
|
||||||
'tags.tagFQN',
|
'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-ingestion": "Abstammungsinjektion",
|
||||||
"lineage-lowercase": "Abstammung",
|
"lineage-lowercase": "Abstammung",
|
||||||
"lineage-node-lowercase": "Abstammungsknoten",
|
"lineage-node-lowercase": "Abstammungsknoten",
|
||||||
|
"lineage-source": "Source of Lineage",
|
||||||
"list": "Liste",
|
"list": "Liste",
|
||||||
"list-entity": "{{entity}}-Liste",
|
"list-entity": "{{entity}}-Liste",
|
||||||
"live": "Live",
|
"live": "Live",
|
||||||
|
|||||||
@ -616,6 +616,7 @@
|
|||||||
"lineage-ingestion": "Lineage Ingestion",
|
"lineage-ingestion": "Lineage Ingestion",
|
||||||
"lineage-lowercase": "lineage",
|
"lineage-lowercase": "lineage",
|
||||||
"lineage-node-lowercase": "lineage node",
|
"lineage-node-lowercase": "lineage node",
|
||||||
|
"lineage-source": "Source of Lineage",
|
||||||
"list": "List",
|
"list": "List",
|
||||||
"list-entity": "List {{entity}}",
|
"list-entity": "List {{entity}}",
|
||||||
"live": "Live",
|
"live": "Live",
|
||||||
|
|||||||
@ -613,9 +613,10 @@
|
|||||||
"lineage": "Linaje",
|
"lineage": "Linaje",
|
||||||
"lineage-config": "Configuración del linaje",
|
"lineage-config": "Configuración del linaje",
|
||||||
"lineage-data-lowercase": "lineage data",
|
"lineage-data-lowercase": "lineage data",
|
||||||
"lineage-ingestion": "Ingesta de linaje",
|
"lineage-ingestion": "Ingesta de lineaje",
|
||||||
"lineage-lowercase": "linaje",
|
"lineage-lowercase": "lineaje",
|
||||||
"lineage-node-lowercase": "nodo de linaje",
|
"lineage-node-lowercase": "lineage node",
|
||||||
|
"lineage-source": "Source of Lineage",
|
||||||
"list": "Lista",
|
"list": "Lista",
|
||||||
"list-entity": "Lista de {{entity}}",
|
"list-entity": "Lista de {{entity}}",
|
||||||
"live": "Vivo",
|
"live": "Vivo",
|
||||||
|
|||||||
@ -616,6 +616,7 @@
|
|||||||
"lineage-ingestion": "Ingestion de la Traçabilité",
|
"lineage-ingestion": "Ingestion de la Traçabilité",
|
||||||
"lineage-lowercase": "traçabilité",
|
"lineage-lowercase": "traçabilité",
|
||||||
"lineage-node-lowercase": "Nœud de Traçabilité",
|
"lineage-node-lowercase": "Nœud de Traçabilité",
|
||||||
|
"lineage-source": "Source of Lineage",
|
||||||
"list": "Liste",
|
"list": "Liste",
|
||||||
"list-entity": "Liste de {{entity}}",
|
"list-entity": "Liste de {{entity}}",
|
||||||
"live": "En Direct",
|
"live": "En Direct",
|
||||||
|
|||||||
@ -616,6 +616,7 @@
|
|||||||
"lineage-ingestion": "כניסת שורשים",
|
"lineage-ingestion": "כניסת שורשים",
|
||||||
"lineage-lowercase": "שורשים",
|
"lineage-lowercase": "שורשים",
|
||||||
"lineage-node-lowercase": "צומת שורש",
|
"lineage-node-lowercase": "צומת שורש",
|
||||||
|
"lineage-source": "Source of Lineage",
|
||||||
"list": "רשימה",
|
"list": "רשימה",
|
||||||
"list-entity": "רשימת {{entity}}",
|
"list-entity": "רשימת {{entity}}",
|
||||||
"live": "שידור חי",
|
"live": "שידור חי",
|
||||||
|
|||||||
@ -616,6 +616,7 @@
|
|||||||
"lineage-ingestion": "リネージのインジェスチョン",
|
"lineage-ingestion": "リネージのインジェスチョン",
|
||||||
"lineage-lowercase": "リネージ",
|
"lineage-lowercase": "リネージ",
|
||||||
"lineage-node-lowercase": "lineage node",
|
"lineage-node-lowercase": "lineage node",
|
||||||
|
"lineage-source": "Source of Lineage",
|
||||||
"list": "リスト",
|
"list": "リスト",
|
||||||
"list-entity": "{{entity}}のリスト",
|
"list-entity": "{{entity}}のリスト",
|
||||||
"live": "Live",
|
"live": "Live",
|
||||||
|
|||||||
@ -616,6 +616,7 @@
|
|||||||
"lineage-ingestion": "Herkomstingestie",
|
"lineage-ingestion": "Herkomstingestie",
|
||||||
"lineage-lowercase": "herkomst",
|
"lineage-lowercase": "herkomst",
|
||||||
"lineage-node-lowercase": "herkomstknooppunt",
|
"lineage-node-lowercase": "herkomstknooppunt",
|
||||||
|
"lineage-source": "Source of Lineage",
|
||||||
"list": "Lijst",
|
"list": "Lijst",
|
||||||
"list-entity": "Lijst {{entity}}",
|
"list-entity": "Lijst {{entity}}",
|
||||||
"live": "Live",
|
"live": "Live",
|
||||||
|
|||||||
@ -616,6 +616,7 @@
|
|||||||
"lineage-ingestion": "Ingestão de Linhagem",
|
"lineage-ingestion": "Ingestão de Linhagem",
|
||||||
"lineage-lowercase": "linhagem",
|
"lineage-lowercase": "linhagem",
|
||||||
"lineage-node-lowercase": "nó de linhagem",
|
"lineage-node-lowercase": "nó de linhagem",
|
||||||
|
"lineage-source": "Source of Lineage",
|
||||||
"list": "Lista",
|
"list": "Lista",
|
||||||
"list-entity": "Listar {{entity}}",
|
"list-entity": "Listar {{entity}}",
|
||||||
"live": "Ao Vivo",
|
"live": "Ao Vivo",
|
||||||
|
|||||||
@ -616,6 +616,7 @@
|
|||||||
"lineage-ingestion": "Получение проихождения",
|
"lineage-ingestion": "Получение проихождения",
|
||||||
"lineage-lowercase": "происходение",
|
"lineage-lowercase": "происходение",
|
||||||
"lineage-node-lowercase": "узел происхождения",
|
"lineage-node-lowercase": "узел происхождения",
|
||||||
|
"lineage-source": "Source of Lineage",
|
||||||
"list": "Список",
|
"list": "Список",
|
||||||
"list-entity": "Список {{entity}}",
|
"list-entity": "Список {{entity}}",
|
||||||
"live": "Процесс",
|
"live": "Процесс",
|
||||||
|
|||||||
@ -616,6 +616,7 @@
|
|||||||
"lineage-ingestion": "血缘关系提取",
|
"lineage-ingestion": "血缘关系提取",
|
||||||
"lineage-lowercase": "血缘",
|
"lineage-lowercase": "血缘",
|
||||||
"lineage-node-lowercase": "血缘关系节点",
|
"lineage-node-lowercase": "血缘关系节点",
|
||||||
|
"lineage-source": "Source of Lineage",
|
||||||
"list": "列表",
|
"list": "列表",
|
||||||
"list-entity": "列出{{entity}}",
|
"list-entity": "列出{{entity}}",
|
||||||
"live": "实时",
|
"live": "实时",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user