/* * 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]] ]); }); });