11// Copyright 2018-2023 contributors to the Marquez project
22// SPDX-License-Identifier: Apache-2.0
33
4- import React from 'react'
5- import Lineage , { LineageProps , getSelectedPaths , initGraph , buildGraphAll } from '../../components/lineage/Lineage'
6- import { LineageNode } from '../../components/lineage/types'
7- import { render } from '@testing-library/react'
8- import { createBrowserHistory } from 'history'
9- import createSagaMiddleware from 'redux-saga'
10- import { createRouterMiddleware } from '@lagunovsky/redux-react-router'
11- import createRootReducer from '../../store/reducers'
12- import { composeWithDevTools } from '@redux-devtools/extension'
13- import { applyMiddleware , createStore } from 'redux'
14- import { Provider } from 'react-redux'
15- import { MqNode } from '../../components/lineage/types'
4+ import { getSelectedPaths , initGraph , buildGraphAll } from '../../components/lineage/Lineage'
5+ import { LineageNode , MqNode } from '../../components/lineage/types'
166import { graphlib } from 'dagre'
17- import rootSaga from '../../store/sagas'
187
19- const mockGraphWithCycle = [
20- {
21- id : 'job_foo' ,
22- inEdges : [
23- {
24- origin : 'dataset_foo' ,
25- destination : 'job_foo'
26- }
27- ] ,
28- outEdges : [
29- {
30- origin : 'job_foo' ,
31- destination : 'dataset_bar'
32- }
33- ]
34- } ,
35- {
36- id : 'dataset_bar' ,
37- inEdges : [
38- {
39- origin : 'job_foo' ,
40- destination : 'dataset_bar'
41- }
42- ] ,
43- outEdges : [
44- {
45- origin : 'dataset_bar' ,
46- destination : 'job_bar'
47- }
48- ]
49- } ,
50- {
51- id : 'job_bar' ,
52- inEdges : [
53- {
54- origin : 'dataset_bar' ,
55- destination : 'job_bar'
56- }
57- ] ,
58- outEdges : [
59- {
60- origin : 'job_bar' ,
61- destination : 'dataset_foo'
62- }
63- ]
64- } ,
65- {
66- id : 'dataset_foo' ,
67- inEdges : [
68- {
69- origin : 'job_bar' ,
70- destination : 'dataset_foo'
71- }
72- ] ,
73- outEdges : [
74- {
75- origin : 'dataset_foo' ,
76- destination : 'job_foo'
77- }
78- ]
8+ class MockEdge {
9+ origin : string
10+ destination : string
11+
12+ constructor ( origin , destination ) {
13+ this . origin = origin
14+ this . destination = destination
7915 }
80- ]
16+ }
17+
18+ class MockNode implements Partial < LineageNode > {
19+ id : string
20+ inEdges : MockEdge [ ]
21+ outEdges : MockEdge [ ]
22+
23+ constructor ( id , prev : string [ ] , next : string [ ] ) {
24+ this . id = id
25+ this . inEdges = prev ? prev . map ( p => new MockEdge ( p , id ) ) : ( [ ] as MockEdge [ ] )
26+ this . outEdges = next ? next . map ( n => new MockEdge ( id , n ) ) : ( [ ] as MockEdge [ ] )
27+ }
28+ }
29+
30+ const mockGraphWithCycle = [
31+ new MockNode ( '1' , [ '3' ] , [ '2' ] ) ,
32+ new MockNode ( '2' , [ '1' ] , [ '3' ] ) ,
33+ new MockNode ( '3' , [ '2' ] , [ '1' ] )
34+ ] as LineageNode [ ]
35+
36+ const mockGraphWithoutCycle = [
37+ new MockNode ( '1' , [ ] , [ '2' , '4' ] ) ,
38+ new MockNode ( '2' , [ '1' ] , [ '3' ] ) ,
39+ new MockNode ( '3' , [ '2' ] , [ ] ) ,
40+ new MockNode ( '4' , [ '1' ] , [ ] )
41+ ] as LineageNode [ ]
8142
8243describe ( 'Lineage Component' , ( ) => {
83- const selectedNode = 'job_foo '
84- let g : graphlib . Graph < MqNode >
44+ const selectedNode = '1 '
45+ let graphWithCycle : graphlib . Graph < MqNode >
8546
8647 beforeEach ( ( ) => {
87- g = initGraph ( )
88- buildGraphAll ( g , mockGraphWithCycle , ( gResult : graphlib . Graph < MqNode > ) => {
89- g = gResult
90- } )
48+ graphWithCycle = initGraph ( )
49+ buildGraphAll (
50+ graphWithCycle ,
51+ mockGraphWithCycle ,
52+ true ,
53+ selectedNode ,
54+ ( gResult : graphlib . Graph < MqNode > ) => {
55+ graphWithCycle = gResult
56+ }
57+ )
9158 } )
9259
9360 it ( "doesn't follow cycles in the lineage graph" , ( ) => {
94- const paths = getSelectedPaths ( g , selectedNode )
61+ const paths = getSelectedPaths ( graphWithCycle , selectedNode )
9562
9663 const pathCounts = paths . reduce ( ( acc , p ) => {
9764 const pathId = p . join ( ':' )
@@ -103,19 +70,32 @@ describe('Lineage Component', () => {
10370 } )
10471
10572 it ( 'renders a valid cycle' , ( ) => {
106- const actualPaths = getSelectedPaths ( g , selectedNode )
73+ const actualPaths = getSelectedPaths ( graphWithCycle , selectedNode )
10774
10875 const expectedPaths = [
109- [ 'job_foo' , 'dataset_bar' ] ,
110- [ 'dataset_bar' , 'job_bar' ] ,
111- [ 'job_bar' , 'dataset_foo' ] ,
112- [ 'dataset_foo' , 'job_foo' ] ,
113- [ 'dataset_foo' , 'job_foo' ] ,
114- [ 'job_bar' , 'dataset_foo' ] ,
115- [ 'dataset_bar' , 'job_bar' ] ,
116- [ 'job_foo' , 'dataset_bar' ]
76+ [ '1' , '2' ] ,
77+ [ '2' , '3' ] ,
78+ [ '3' , '1' ] ,
79+ [ '3' , '1' ] ,
80+ [ '2' , '3' ] ,
81+ [ '1' , '2' ]
11782 ]
11883
11984 expect ( actualPaths ) . toEqual ( expectedPaths )
12085 } )
86+
87+ it ( 'includes nodes in selected path when fullGraph is true' , ( ) => {
88+ const g = initGraph ( )
89+ buildGraphAll ( g , mockGraphWithoutCycle , true , '3' , ( ) => null )
90+
91+ expect ( g . node ( '4' ) ) . toBeDefined ( )
92+ } )
93+
94+ it ( 'exclude nodes not in selected path when fullGraph is false' , ( ) => {
95+ const g = initGraph ( )
96+
97+ buildGraphAll ( g , mockGraphWithoutCycle , false , '3' , ( ) => null )
98+
99+ expect ( g . node ( '4' ) ) . toBeUndefined ( )
100+ } )
121101} )
0 commit comments