|  | 
 | /* | 
 | * Licensed to the Apache Software Foundation (ASF) under one | 
 | * or more contributor license agreements.  See the NOTICE file | 
 | * distributed with this work for additional information | 
 | * regarding copyright ownership.  The ASF licenses this file | 
 | * to you 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 ComponentModel, { ComponentModelConstructor } from '@/src/model/Component'; | 
 | import { ComponentMainType } from '@/src/util/types'; | 
 |  | 
 | const componentModelConstructor = ComponentModel as ComponentModelConstructor; | 
 |  | 
 | function extendModel(type: string, dependencies?: string[]) { | 
 |     class SubModel extends ComponentModel { | 
 |         static type: string = type; | 
 |         type: string = type; | 
 |         static dependencies = dependencies || []; | 
 |     }; | 
 |     ComponentModel.registerClass(SubModel); | 
 |     return SubModel; | 
 | } | 
 |  | 
 | describe('componentDependency', function () { | 
 |  | 
 |     let idx = 0; | 
 |  | 
 |     function makeTypes(count: number): string[] { | 
 |         const arr = []; | 
 |         for (let i = 0; i < count; i++) { | 
 |             arr.push('type_' + idx++); | 
 |         } | 
 |         return arr; | 
 |     } | 
 |  | 
 |     type TopoResultItem = [ComponentMainType, ComponentMainType[]]; | 
 |  | 
 |     it('topologicalTravel_base', function () { | 
 |         const [m1, a1, a2] = makeTypes(3); | 
 |         extendModel(m1, [a1, a2]); | 
 |         extendModel(a1); | 
 |         extendModel(a2); | 
 |         const result: TopoResultItem[] = []; | 
 |         const allList = componentModelConstructor.getAllClassMainTypes(); | 
 |         componentModelConstructor.topologicalTravel( | 
 |             [m1, a1, a2], | 
 |             allList, | 
 |             function (componentType, dependencies) { | 
 |                 result.push([componentType, dependencies]); | 
 |             } | 
 |         ); | 
 |         expect(result).toEqual([[a2, ['dataset']], [a1, ['dataset']], [m1, ['dataset', a1, a2]]]); | 
 |     }); | 
 |  | 
 |     it('topologicalTravel_a1IsAbsent', function () { | 
 |         const [m1, a1, a2] = makeTypes(3); | 
 |         extendModel(m1, [a1, a2]); | 
 |         extendModel(a2); | 
 |         const allList = componentModelConstructor.getAllClassMainTypes(); | 
 |         const result: TopoResultItem[] = []; | 
 |         componentModelConstructor.topologicalTravel( | 
 |             [m1, a2], | 
 |             allList, | 
 |             function (componentType, dependencies) { | 
 |                 result.push([componentType, dependencies]); | 
 |             } | 
 |         ); | 
 |         expect(result).toEqual([[a2, ['dataset']], [m1, ['dataset', a1, a2]]]); | 
 |     }); | 
 |  | 
 |     it('topologicalTravel_empty', function () { | 
 |         const [m1, a1, a2] = makeTypes(3); | 
 |         extendModel(m1, [a1, a2]); | 
 |         extendModel(a1); | 
 |         extendModel(a2); | 
 |         const allList = componentModelConstructor.getAllClassMainTypes(); | 
 |         const result: TopoResultItem[] = []; | 
 |         componentModelConstructor.topologicalTravel( | 
 |             [], | 
 |             allList, | 
 |             function (componentType, dependencies) { | 
 |                 result.push([componentType, dependencies]); | 
 |             } | 
 |         ); | 
 |         expect(result).toEqual([]); | 
 |     }); | 
 |  | 
 |     it('topologicalTravel_isolate', function () { | 
 |         const [m1, a1, a2] = makeTypes(3); | 
 |         extendModel(a2); | 
 |         extendModel(a1); | 
 |         extendModel(m1, [a2]); | 
 |         const allList = componentModelConstructor.getAllClassMainTypes(); | 
 |         const result: TopoResultItem[] = []; | 
 |         componentModelConstructor.topologicalTravel( | 
 |             [a1, a2, m1], | 
 |             allList, | 
 |             function (componentType, dependencies) { | 
 |                 result.push([componentType, dependencies]); | 
 |             } | 
 |         ); | 
 |         expect(result).toEqual([[a1, ['dataset']], [a2, ['dataset']], [m1, ['dataset', a2]]]); | 
 |     }); | 
 |  | 
 |     it('topologicalTravel_diamond', function () { | 
 |         const [m1, a1, a2, a3] = makeTypes(4); | 
 |         extendModel(a1, []); | 
 |         extendModel(a2, [a1]); | 
 |         extendModel(a3, [a1]); | 
 |         extendModel(m1, [a2, a3]); | 
 |         const allList = componentModelConstructor.getAllClassMainTypes(); | 
 |         const result: TopoResultItem[] = []; | 
 |         componentModelConstructor.topologicalTravel( | 
 |             [m1, a1, a2, a3], | 
 |             allList, | 
 |             function (componentType, dependencies) { | 
 |                 result.push([componentType, dependencies]); | 
 |             } | 
 |         ); | 
 |         expect(result).toEqual( | 
 |             [[a1, ['dataset']], | 
 |             [a3, ['dataset', a1]], | 
 |             [a2, ['dataset', a1]], | 
 |             [m1, ['dataset', a2, a3]] | 
 |         ]); | 
 |     }); | 
 |  | 
 |     it('topologicalTravel_loop', function () { | 
 |         const [m1, m2, a1, a2, a3] = makeTypes(5); | 
 |         extendModel(m1, [a1, a2]); | 
 |         extendModel(m2, [m1, a2]); | 
 |         extendModel(a1, [m2, a2, a3]); | 
 |         extendModel(a2); | 
 |         extendModel(a3); | 
 |         const allList = componentModelConstructor.getAllClassMainTypes(); | 
 |         expect(function () { | 
 |             componentModelConstructor.topologicalTravel( | 
 |                 [m1, m2, a1], | 
 |                 allList, | 
 |                 () => {} | 
 |             ); | 
 |         }).toThrowError(/Circular/); | 
 |     }); | 
 |  | 
 |     it('topologicalTravel_multipleEchartsInstance', function () { | 
 |         const [m1, m2, a1, a2] = makeTypes(4); | 
 |         extendModel(m1, [a1, a2]); | 
 |         extendModel(a1); | 
 |         extendModel(a2); | 
 |         let allList = componentModelConstructor.getAllClassMainTypes(); | 
 |         let result: TopoResultItem[] = []; | 
 |         componentModelConstructor.topologicalTravel( | 
 |             [m1, a1, a2], | 
 |             allList, | 
 |             function (componentType, dependencies) { | 
 |                 result.push([componentType, dependencies]); | 
 |             } | 
 |         ); | 
 |         expect(result).toEqual([[a2, ['dataset']], [a1, ['dataset']], [m1, ['dataset', a1, a2]]]); | 
 |  | 
 |         result = []; | 
 |         extendModel(m2, [a1, m1]); | 
 |         allList = componentModelConstructor.getAllClassMainTypes(); | 
 |         componentModelConstructor.topologicalTravel( | 
 |             [m2, m1, a1, a2], | 
 |             allList, | 
 |             function (componentType, dependencies) { | 
 |                 result.push([componentType, dependencies]); | 
 |             } | 
 |         ); | 
 |         expect(result).toEqual( | 
 |             [[a2, ['dataset']], [a1, ['dataset']], [m1, ['dataset', a1, a2]], [m2, ['dataset', a1, m1]]] | 
 |         ); | 
 |     }); | 
 |  | 
 |     it('topologicalTravel_missingSomeNodeButHasDependencies', function () { | 
 |         const [m1, a1, a2, a3, a4] = makeTypes(5); | 
 |         extendModel(m1, [a1, a2]); | 
 |         extendModel(a2, [a3]); | 
 |         extendModel(a3); | 
 |         extendModel(a4); | 
 |         let result: TopoResultItem[] = []; | 
 |         let allList = componentModelConstructor.getAllClassMainTypes(); | 
 |         componentModelConstructor.topologicalTravel( | 
 |             [a3, m1], | 
 |             allList, | 
 |             function (componentType, dependencies) { | 
 |                 result.push([componentType, dependencies]); | 
 |             } | 
 |         ); | 
 |         expect(result).toEqual([[a3, ['dataset']], [a2, ['dataset', a3]], [m1, ['dataset', a1, a2]]]); | 
 |         result = []; | 
 |         allList = componentModelConstructor.getAllClassMainTypes(); | 
 |         componentModelConstructor.topologicalTravel( | 
 |             [m1, a3], | 
 |             allList, | 
 |             function (componentType, dependencies) { | 
 |                 result.push([componentType, dependencies]); | 
 |             } | 
 |         ); | 
 |         expect(result).toEqual([[a3, ['dataset']], [a2, ['dataset', a3]], [m1, ['dataset', a1, a2]]]); | 
 |     }); | 
 |  | 
 |     it('topologicalTravel_subType', function () { | 
 |         const [m1, a1, a2, a3, a4] = makeTypes(5); | 
 |         extendModel(m1, [a1, a2]); | 
 |         extendModel(a1 + '.aaa', [a2]); | 
 |         extendModel(a1 + '.bbb', [a3, a4]); | 
 |         extendModel(a2); | 
 |         extendModel(a3); | 
 |         extendModel(a4); | 
 |         const result: TopoResultItem[] = []; | 
 |         const allList = componentModelConstructor.getAllClassMainTypes(); | 
 |         componentModelConstructor.topologicalTravel( | 
 |             [m1, a1, a2, a4], | 
 |             allList, | 
 |             function (componentType, dependencies) { | 
 |                 result.push([componentType, dependencies]); | 
 |             } | 
 |         ); | 
 |         expect(result).toEqual( | 
 |             [[a4, ['dataset']], | 
 |             [a2, ['dataset']], | 
 |             [a1, ['dataset', a2, a3, a4]], | 
 |             [m1, ['dataset', a1, a2]] | 
 |         ]); | 
 |     }); | 
 | }); |