diff --git a/package.json b/package.json index 00c9d81b9d..701b3244e3 100644 --- a/package.json +++ b/package.json @@ -77,9 +77,9 @@ "@antv/path-util": "^2.0.3", "@antv/scale": "^0.2.0", "@antv/util": "~2.0.5", - "lodash": "^4.17.15", "d3-force": "^2.0.1", "dagre": "^0.8.5", + "lodash": "^4.17.15", "numericjs": "^1.2.6", "tslib": "^1.10.0", "webpack": "^4.41.4" diff --git a/src/graph/controller/item.ts b/src/graph/controller/item.ts index acd27ae165..23c9ed0c37 100644 --- a/src/graph/controller/item.ts +++ b/src/graph/controller/item.ts @@ -271,7 +271,7 @@ export default class ItemController { * @param {string[]} states 状态名称集合 * @memberof ItemController */ - public clearItemStates(item: Item | string, states: string[]): void { + public clearItemStates(item: Item | string, states: string | string[]): void { const graph = this.graph; if (isString(item)) { diff --git a/src/graph/controller/state.ts b/src/graph/controller/state.ts index 5b32521d0f..dcea6776b9 100644 --- a/src/graph/controller/state.ts +++ b/src/graph/controller/state.ts @@ -133,7 +133,6 @@ export default class StateController { */ public updateGraphStates() { const states = this.graph.get('states') - const cachedStates = this.cachedStates; each(cachedStates.disabled, (val, key) => { @@ -148,6 +147,8 @@ export default class StateController { if (!states[key]) { states[key] = val; } else { + // TODO 需要测试是否能够走到这个分支 + console.log('走到这里没有', states) const map = {}; states[key].forEach(item => { if (!item.destroyed) { diff --git a/src/graph/graph.ts b/src/graph/graph.ts index fbfa3ba1e1..69b6e28393 100644 --- a/src/graph/graph.ts +++ b/src/graph/graph.ts @@ -378,7 +378,7 @@ export default class Graph extends EventEmitter implements IGraph { * @param {string|Item} item 元素id或元素实例 * @param {string[]} states 状态 */ - public clearItemStates(item: Item | string, states?: string[]): void { + public clearItemStates(item: Item | string, states?: string[] | string): void { if(isString(item)) { item = this.findById(item) } @@ -725,9 +725,11 @@ export default class Graph extends EventEmitter implements IGraph { } if (!nodeItem && isString(item)) { - this.get('customGroupControll').remove(item); + const customGroupControll: CustomGroup = this.get('customGroupControll') + customGroupControll.remove(item); } else { - this.get('itemController').removeItem(item); + const itemController: ItemController = this.get('itemController') + itemController.removeItem(item); } } @@ -783,7 +785,7 @@ export default class Graph extends EventEmitter implements IGraph { * @param {string} state 状态 * @param {boolean} enabled 是否启用状态 */ - public setItemState(item: Item | string | string, state: string, enabled: boolean): void { + public setItemState(item: Item | string, state: string, enabled: boolean): void { if (isString(item)) { item = this.findById(item); } @@ -1380,7 +1382,6 @@ export default class Graph extends EventEmitter implements IGraph { customGroupControll.expandGroup(groupId); } - // TODO plugin 机制完善后再补充类型 /** * 添加插件 * @param {object} plugin 插件实例 diff --git a/src/interface/graph.ts b/src/interface/graph.ts index 9e9f74b8e6..9442485cfe 100644 --- a/src/interface/graph.ts +++ b/src/interface/graph.ts @@ -386,9 +386,9 @@ export interface IGraph extends EventEmitter { /** * 清理元素多个状态 * @param {string|Item} item 元素id或元素实例 - * @param {String[]} states 状态 + * @param {string | string[]} states 状态 */ - clearItemStates(item: Item | string, states?: string[]): void; + clearItemStates(item: Item | string, states?: string | string[]): void; /** * 设置各个节点样式,以及在各种状态下节点 keyShape 的样式。 diff --git a/src/plugins/bundling/index.ts b/src/plugins/bundling/index.ts index b225c6f03f..19563b01b5 100644 --- a/src/plugins/bundling/index.ts +++ b/src/plugins/bundling/index.ts @@ -4,7 +4,7 @@ import Graph from '@g6/graph/graph'; import { GraphData, NodeConfig, NodeMapConfig, EdgeConfig } from '@g6/types'; import { Point } from '@antv/g-base/lib/types'; -interface IBundlingConfig extends IPluginBaseConfig { +interface BundlingConfig extends IPluginBaseConfig { edgeBundles?: Edge[]; edgePoints?: NodeConfig[]; K?: number; @@ -47,10 +47,10 @@ function projectPointToEdge(p: Point, e): Point { } export default class Bundling extends Base { - constructor(cfg?: IBundlingConfig) { + constructor(cfg?: BundlingConfig) { super(cfg) } - public getDefaultCfgs(): IBundlingConfig { + public getDefaultCfgs(): BundlingConfig { return { edgeBundles: [], // |edges| arrays, each one stores the related edges' id edgePoints: [], // |edges| * divisions edge points diff --git a/src/plugins/menu/index.ts b/src/plugins/menu/index.ts index 0c305940fa..3966f8eb1e 100644 --- a/src/plugins/menu/index.ts +++ b/src/plugins/menu/index.ts @@ -5,12 +5,17 @@ import Base, { IPluginBaseConfig } from '../base' interface MenuConfig extends IPluginBaseConfig { createDOM?: boolean; - getContent: (evt?: IG6GraphEvent) => string; + menu?: HTMLDivElement; + getContent?: (evt?: IG6GraphEvent) => string; onShow: (evt?: IG6GraphEvent) => boolean; onHide: (evt?: IG6GraphEvent) => boolean; } export default class Menu extends Base { + constructor(cfg: MenuConfig) { + super(cfg) + } + public getDefaultCfgs(): MenuConfig { return { createDOM: true, // 是否渲染 dom diff --git a/src/plugins/minimap/index.ts b/src/plugins/minimap/index.ts index 97a820175c..88582c80e6 100644 --- a/src/plugins/minimap/index.ts +++ b/src/plugins/minimap/index.ts @@ -17,7 +17,7 @@ const DEFAULT_MODE = 'default'; const KEYSHAPE_MODE = 'keyShape'; const DELEGATE_MODE = 'delegate'; -interface IMiniMapConfig extends IPluginBaseConfig { +interface MiniMapConfig extends IPluginBaseConfig { viewportClassName?: string; type?: 'default' | 'keyShape' | 'delegate'; size: number[]; @@ -26,11 +26,11 @@ interface IMiniMapConfig extends IPluginBaseConfig { } export default class MiniMap extends Base { - constructor(cfg: IMiniMapConfig) { + constructor(cfg: MiniMapConfig) { super(cfg) } - public getDefaultCfgs(): IMiniMapConfig { + public getDefaultCfgs(): MiniMapConfig { return { container: null, className: 'g6-minimap', @@ -70,7 +70,7 @@ export default class MiniMap extends Base { } private initViewport() { - const cfgs:IMiniMapConfig = this._cfgs as IMiniMapConfig; + const cfgs:MiniMapConfig = this._cfgs as MiniMapConfig; const size = cfgs.size; const graph = cfgs.graph; const canvas = this.get('canvas'); diff --git a/src/util/math.ts b/src/util/math.ts index 635274ef96..daa4449bff 100644 --- a/src/util/math.ts +++ b/src/util/math.ts @@ -289,6 +289,9 @@ export const getAdjMatrix = (data: GraphData, directed: boolean): Matrix[] => { // map node with index in data.nodes const nodeMap = {}; + if(!nodes) { + throw new Error('invalid nodes data!') + } if (nodes) { nodes.forEach((node, i) => { nodeMap[node.id] = i; diff --git a/src/util/path.ts b/src/util/path.ts index 79f4ae810b..5b8ea39d03 100644 --- a/src/util/path.ts +++ b/src/util/path.ts @@ -28,7 +28,7 @@ export const getSpline = (points: IPoint[]) => { const data: number[] = []; if (points.length < 2) { - console.warn(`point length must largn than 2, now it's ${points.length}`); + throw new Error(`point length must largn than 2, now it's ${points.length}`); } for (const point of points) { const { x, y } = point; diff --git a/tests/unit/graph/controller/customGroup-spec.ts b/tests/unit/graph/controller/customGroup-spec.ts index 53e2428338..40a3b8400d 100644 --- a/tests/unit/graph/controller/customGroup-spec.ts +++ b/tests/unit/graph/controller/customGroup-spec.ts @@ -28,7 +28,7 @@ G6.registerNode('circleNode', { } }, 'circle'); -describe.only('signle layer group', () => { +describe('signle layer group', () => { it('render signle group test', () => { const graph = new G6.Graph({ @@ -605,8 +605,8 @@ describe.only('signle layer group', () => { expect(groups.length).toBe(4); // 删除group1 - const customGroup = graph.get('customGroupControll'); - customGroup.remove('group1'); + // const customGroup = graph.get('customGroupControll'); + graph.remove('group1'); const groupNodes1 = graph.get('groupNodes'); const keys1 = Object.keys(groupNodes1); @@ -625,7 +625,7 @@ describe.only('signle layer group', () => { }); -describe.only('nesting layer group', () => { +describe('nesting layer group', () => { it('render nesting layer group', () => { const data = { nodes: [ @@ -924,7 +924,7 @@ describe.only('nesting layer group', () => { }); // 手动创建分子 -describe.only('create node group', () => { +describe('create node group', () => { it('use addItem create group', () => { const data = { nodes: [ diff --git a/tests/unit/graph/controller/state-spec.ts b/tests/unit/graph/controller/state-spec.ts index 0ca47cfc9a..58c4a8f207 100644 --- a/tests/unit/graph/controller/state-spec.ts +++ b/tests/unit/graph/controller/state-spec.ts @@ -1,15 +1,10 @@ import G6 from '../../../../src' +import { timerOut } from '../../util/timeOut' const div = document.createElement('div'); div.id = 'state-controller'; document.body.appendChild(div); -function timerGame(callback, time = 50) { - setTimeout(() => { - callback(); - }, time); -} - describe('graph state controller', () => { const graph = new G6.Graph({ container: div, @@ -18,7 +13,7 @@ describe('graph state controller', () => { }); const data = { nodes: [ - { id: 'node1', x: 100, y: 100 }, + { id: 'node1', x: 100, y: 100, label: 'node1' }, { id: 'node2', x: 120, y: 80 }, { id: 'node3', x: 150, y: 150 } ], @@ -44,7 +39,7 @@ describe('graph state controller', () => { graph.setItemState('node1', 'selected', true); - timerGame(() => { + timerOut(() => { expect(itemCount).toBe(1); expect(graphCount).toBe(0); @@ -52,7 +47,7 @@ describe('graph state controller', () => { expect(graph.get('states').selected.length).toBe(1); expect(graph.get('states').selected[0]).toEqual(graph.findById('node1')); - timerGame(() => { + timerOut(() => { graph.setItemState('node1', 'selected', false); graph.setItemState('node1', 'selected', true); graph.setItemState('node2', 'selected', true); @@ -65,7 +60,7 @@ describe('graph state controller', () => { graph.setItemState('node2', 'selected', false); graph.setItemState('node3', 'selected', false); - timerGame(() => { + timerOut(() => { expect(graph.get('states').selected.length).toBe(0); }, 90) }, 70) @@ -86,4 +81,21 @@ describe('graph state controller', () => { expect(Object.keys(modes)).toEqual(['default']) expect(modes.default).toEqual([]) }); + + it('updateGraphStates', () => { + const node1 = graph.findById('node1') + graph.setItemState(node1, 'selected', true) + graph.setItemState(node1, 'hover', true) + graph.setItemState('node2', 'hover', true) + graph.on('node:mouseenter', () => { + const states = graph.get('states') + expect(states).not.toBe(undefined) + expect(states.selected.length).toBe(1) + expect(states.hover.length).toBe(2) + }) + + timerOut(() => { + graph.emit('node:mouseenter', { item: node1 }) + }, 20) + }) }); diff --git a/tests/unit/graph/graph-spec.ts b/tests/unit/graph/graph-spec.ts index 6a4a2bd582..0a32d20aef 100644 --- a/tests/unit/graph/graph-spec.ts +++ b/tests/unit/graph/graph-spec.ts @@ -4,6 +4,7 @@ import '../../../src/behavior' import { scale, translate } from '../../../src/util/math' import { GraphData, Item } from '../../../types'; import Plugin from '../../../src/plugins' +import { timerOut } from '../util/timeOut' const div = document.createElement('div'); div.id = 'global-spec'; @@ -619,16 +620,20 @@ describe('all node link center', () => { expect(graph.findAllByState('node', 'a').length).toBe(1); graph.clearItemStates(node); - + expect(graph.findAllByState('node', 'a').length).toBe(0); expect(graph.findAllByState('node', 'b').length).toBe(0); - + graph.setItemState(node, 'a', true); graph.setItemState(node, 'b', true); - + + debugger graph.clearItemStates('a', ['a']); expect(graph.findAllByState('node', 'a').length).toBe(0); expect(graph.findAllByState('node', 'b').length).toBe(1); + + graph.clearItemStates(node, 'b') + expect(graph.findAllByState('node', 'b').length).toBe(0) }); it('default node & edge style', () => { @@ -1004,4 +1009,57 @@ describe('plugins & layout', () => { graph.destroy() expect(graph.destroyed).toBe(true) }) + + it('graph animate', () => { + const graph = new G6.Graph({ + container: div, + height: 500, + width: 500 + }) + + const data = { + nodes: [ + { + id: 'node', + label: 'node', + groupId: 'g1' + },{ + id: 'node1', + groupId: 'g2' + } + ], + groups: [ + { + id: 'g1', + title: 'cokkdl' + }, + { + id: 'g2' + } + ] + } + + graph.data(data) + graph.render() + + graph.stopAnimate() + const isAnimating = graph.isAnimating() + expect(isAnimating).toBe(false) + + graph.collapseGroup('g1') + + let gnode = graph.findById('node') + + expect(gnode.get('visible')).toBe(false) + + const g2Node = graph.findById('node1') + expect(g2Node.get('visible')).toBe(true) + + graph.expandGroup('g1') + + timerOut(() => { + gnode = graph.findById('node') + expect(gnode.get('visible')).toBe(true) + }, 500) + }) }) \ No newline at end of file diff --git a/tests/unit/graph/tree-graph-spec.ts b/tests/unit/graph/tree-graph-spec.ts index 8c5358aa0e..51fb4182af 100644 --- a/tests/unit/graph/tree-graph-spec.ts +++ b/tests/unit/graph/tree-graph-spec.ts @@ -1,16 +1,10 @@ -import Hierarchy from '@antv/hierarchy'; import G6 from '../../../src'; +import { timerOut } from '../util/timeOut' const div = document.createElement('div'); div.id = 'tree-spec'; document.body.appendChild(div); -function timerGame(callback, time = 50) { - setTimeout(() => { - callback(); - }, time); -} - describe('tree graph without animate', () => { let graph = new G6.TreeGraph({ container: div, @@ -166,7 +160,7 @@ describe('tree graph without animate', () => { }); graph.addBehaviors('collapse-expand', 'default'); graph.emit('node:click', { item: parent }); - timerGame(() => { + timerOut(() => { collapsed = false; graph.emit('node:click', { item: parent }); }, 600); @@ -232,7 +226,7 @@ describe('tree graph without animate', () => { } }); graph.emit('node:dblclick', { item: parent }); - timerGame(() => { + timerOut(() => { collapsed = false; graph.emit('node:dblclick', { item: parent }); }, 600); @@ -446,7 +440,7 @@ describe('tree graph with animate', () => { graph.addBehaviors('collapse-expand', 'default'); graph.emit('node:click', { item: parent }); - timerGame(() => { + timerOut(() => { collapsed = false; graph.emit('node:click', { item: parent }); }, 600); @@ -478,7 +472,7 @@ describe('tree graph with animate', () => { graph.emit('node:dblclick', { item: parent }); - timerGame(() => { + timerOut(() => { collapsed = false; graph.emit('node:dblclick', { item: parent }); }, 600); diff --git a/tests/unit/layout/circular-spec.ts b/tests/unit/layout/circular-spec.ts index 4aef2e04ae..819f403870 100644 --- a/tests/unit/layout/circular-spec.ts +++ b/tests/unit/layout/circular-spec.ts @@ -6,7 +6,7 @@ const div = document.createElement('div'); div.id = 'circular-layout'; document.body.appendChild(div); -describe.only('circular layout', () => { +describe('circular layout', () => { it('circular layout with default configs', () => { const graph = new G6.Graph({ container: div, diff --git a/tests/unit/layout/circular-web-worker-spec.ts b/tests/unit/layout/circular-web-worker-spec.ts index 01f8584db3..07ccff9cb2 100644 --- a/tests/unit/layout/circular-web-worker-spec.ts +++ b/tests/unit/layout/circular-web-worker-spec.ts @@ -7,7 +7,7 @@ const div = document.createElement('div'); div.id = 'circular-layout-web-worker'; document.body.appendChild(div); -describe.only('circular layout(web worker)', () => { +describe('circular layout(web worker)', () => { it('circular layout(web worker) with default configs', (done) => { const graph = new G6.Graph({ container: div, diff --git a/tests/unit/layout/force-web-worker-spec.ts b/tests/unit/layout/force-web-worker-spec.ts index 0de81f31b6..c329f98a16 100644 --- a/tests/unit/layout/force-web-worker-spec.ts +++ b/tests/unit/layout/force-web-worker-spec.ts @@ -6,7 +6,7 @@ const div = document.createElement('div'); div.id = 'force-layout-web-worker'; document.body.appendChild(div); -describe.only('force layout(web worker)', function() { +describe('force layout(web worker)', function() { // this.timeout(10000); it('force layout(web worker) with default configs', done => { diff --git a/tests/unit/layout/grid-spec.ts b/tests/unit/layout/grid-spec.ts index 5472effa91..6bb1fe95cb 100644 --- a/tests/unit/layout/grid-spec.ts +++ b/tests/unit/layout/grid-spec.ts @@ -24,7 +24,7 @@ const div = document.createElement('div'); div.id = 'grid-layout'; document.body.appendChild(div); -describe.only('grid layout', () => { +describe('grid layout', () => { it('grid layout with default configs', () => { const graph = new G6.Graph({ container: div, diff --git a/tests/unit/layout/mds-spec.ts b/tests/unit/layout/mds-spec.ts index 8548e4729b..3fe73860af 100644 --- a/tests/unit/layout/mds-spec.ts +++ b/tests/unit/layout/mds-spec.ts @@ -5,7 +5,7 @@ const div = document.createElement('div'); div.id = 'mds-layout'; document.body.appendChild(div); -describe.only('mds', () => { +describe('mds', () => { it('mds layout with default configs', () => { const graph = new G6.Graph({ container: div, diff --git a/tests/unit/layout/preset-spec.ts b/tests/unit/layout/preset-spec.ts index bd9c4d0b61..c41e6bd121 100644 --- a/tests/unit/layout/preset-spec.ts +++ b/tests/unit/layout/preset-spec.ts @@ -86,7 +86,7 @@ const data2 = { ], }; -describe.only('preset layout', () => { +describe('preset layout', () => { it('new graph without layout, part of the data has position infor', () => { const graph = new G6.Graph({ container: div, diff --git a/tests/unit/layout/random-spec.ts b/tests/unit/layout/random-spec.ts index b5b04951c1..c61c2f957c 100644 --- a/tests/unit/layout/random-spec.ts +++ b/tests/unit/layout/random-spec.ts @@ -16,7 +16,7 @@ const data: {nodes: object, edges: object} = { edges: [], }; -describe.only('random', () => { +describe('random', () => { it('new graph without layout, random by default', () => { const graph = new G6.Graph({ container: div, diff --git a/tests/unit/layout/web-worker-spec.ts b/tests/unit/layout/web-worker-spec.ts index 576cbe48e3..9990a4a112 100644 --- a/tests/unit/layout/web-worker-spec.ts +++ b/tests/unit/layout/web-worker-spec.ts @@ -9,7 +9,7 @@ document.body.appendChild(div); // jest.setTimeout(10000) -describe.only('layout using web worker', function() { +describe('layout using web worker', function() { it('change layout', function(done) { const node = data.nodes[0]; const graph = new G6.Graph({ diff --git a/tests/unit/plugins/bundling-spec.ts b/tests/unit/plugins/bundling-spec.ts index 2565d5a840..f3d8940d54 100644 --- a/tests/unit/plugins/bundling-spec.ts +++ b/tests/unit/plugins/bundling-spec.ts @@ -7,8 +7,7 @@ const div = document.createElement('div'); div.id = 'force-layout'; document.body.appendChild(div); -describe.skip('edge bundling', () => { - // TODO Wait for layout +describe('edge bundling', () => { const graph = new G6.Graph({ container: div, width: 500, @@ -31,6 +30,7 @@ describe.skip('edge bundling', () => { expect(graphData.edges[0].shape).toEqual('polyline'); expect(graphData.edges[0].controlPoints.length > 2).toEqual(true); + bundle.destroy() }); it('bundling on circular with fixed bundleThreshold and iterations', () => { @@ -45,6 +45,7 @@ describe.skip('edge bundling', () => { expect(graphData.edges[0].shape).toEqual('polyline'); expect(graphData.edges[0].controlPoints.length > 2).toEqual(true); + bundle.destroy() }); it('bundling update', () => { @@ -80,16 +81,27 @@ describe.skip('edge bundling', () => { expect(data2.edges[0].shape).toEqual('polyline'); expect(data2.edges[0].controlPoints.length > 2).toEqual(true); + bundle.destroy() }); it('bundling no position info, throw error', () => { const bundle = new Bundling(); bundle.initPlugin(graph); + const data2: GraphData = { + nodes: [ + { id: 'n0' }, { id: 'n1' } + ], + edges: [ + { source: 'n0', target: 'n1' } + ] + }; + function fn() { - bundle.bundling(data); + bundle.bundling(data2); } expect(fn).toThrowError('please layout the graph or assign x and y for nodes first'); + bundle.destroy() graph.destroy(); }); }); diff --git a/tests/unit/plugins/menu-spec.ts b/tests/unit/plugins/menu-spec.ts index 9c8037f02a..fadfc2f211 100644 --- a/tests/unit/plugins/menu-spec.ts +++ b/tests/unit/plugins/menu-spec.ts @@ -18,6 +18,7 @@ describe('menu', () => { onShow(e) { expect(isNaN(e.canvasX)).toBe(false); expect(isNaN(e.canvasY)).toBe(false); + return true }, onHide() { count++; @@ -80,13 +81,19 @@ describe('menu', () => { const menu = new Menu({ createDOM: false, menu: outDiv, + getContent(e) { + expect(e).not.toBe(undefined); + return 'test menu'; + }, onShow(e) { outDiv.style.left = e.canvasX + 'px'; outDiv.style.top = e.canvasY + 'px'; outDiv.style.visibility = 'visible'; + return true }, onHide() { outDiv.style.visibility = 'hidden'; + return false } }); diff --git a/tests/unit/plugins/minimap-spec.ts b/tests/unit/plugins/minimap-spec.ts index 631ca2dcbf..d705a1fcaf 100644 --- a/tests/unit/plugins/minimap-spec.ts +++ b/tests/unit/plugins/minimap-spec.ts @@ -1,6 +1,7 @@ import G6 from '../../../src' import Minimap from '../../../src/plugins/minimap' import Simulate from 'event-simulate' +import { timerOut } from '../util/timeOut' const div = document.createElement('div'); div.id = 'minimap'; @@ -8,12 +9,6 @@ document.body.appendChild(div); const container = document.createElement('div'); div.appendChild(container); -function timerGame(callback, time = 50) { - setTimeout(() => { - callback(); - }, time); -} - describe('minimap', () => { const minimap = new Minimap({ size: [ 200, 200 ] }); const graph = new G6.Graph({ @@ -111,7 +106,7 @@ describe('minimap', () => { clientY: 120 }); - timerGame(() => { + timerOut(() => { expect(viewport.style.left).toEqual('20px'); expect(viewport.style.top).toEqual('20px'); expect(viewport.style.width).toEqual('0px'); @@ -134,7 +129,7 @@ describe('minimap', () => { clientY: 0 }); - timerGame(() => { + timerOut(() => { expect(viewport.style.left).toEqual('0px'); expect(viewport.style.top).toEqual('0px'); expect(viewport.style.width).toEqual('100px'); diff --git a/tests/unit/util/base-spec.ts b/tests/unit/util/base-spec.ts new file mode 100644 index 0000000000..7d077ab487 --- /dev/null +++ b/tests/unit/util/base-spec.ts @@ -0,0 +1,34 @@ +import { formatPadding, isViewportChanged } from '../../../src/util/base' + +describe('base util', () => { + it('formatPadding', () => { + let padding = formatPadding(5) + expect(padding).toEqual([5, 5, 5, 5]) + + padding = formatPadding('10') + expect(padding).toEqual([10, 10, 10, 10]) + + padding = formatPadding([5]) + expect(padding).toEqual([5, 5, 5, 5]) + + padding = formatPadding([5, 10]) + expect(padding).toEqual([5, 10, 5, 10]) + + padding = formatPadding([5, 10, 15]) + expect(padding).toEqual([5, 10, 15, 10]) + + padding = formatPadding([5, 10, 15, 20]) + expect(padding).toEqual([5, 10, 15, 20]) + }) + + it('isViewportChanged', () => { + let isChanged = isViewportChanged(null) + expect(isChanged).toBe(false) + + isChanged = isViewportChanged([1, 0, 0, 0, 1, 0, 0, 0, 1]) + expect(isChanged).toBe(false) + + isChanged = isViewportChanged([1, 0, 0, 0.5, 1, 0, 0, 0, 1]) + expect(isChanged).toBe(true) + }) +}) \ No newline at end of file diff --git a/tests/unit/util/math-spec.ts b/tests/unit/util/math-spec.ts index 4493cb31a6..7fe5c97929 100644 --- a/tests/unit/util/math-spec.ts +++ b/tests/unit/util/math-spec.ts @@ -227,6 +227,42 @@ describe('math util test', () => { expect(directedMatrix[1]).toEqual([]) }) + it('getAdjMatrix without nodes', () => { + const data = { + edges: [ + { + source: 'node1', + target: 'node2' + }, + { + source: 'node1', + target: 'node1' + } + ] + } + + expect(() => {getAdjMatrix(data, false)}).toThrowError('invalid nodes data!') + }) + + it('getAdjMatrix without edges', () => { + const data1 = { + nodes: [ + { + id: 'node1', + label: 'node1' + }, + { + id: 'node2', + label: 'node2' + } + ] + } + + const directedMatrix = getAdjMatrix(data1, true) + expect(directedMatrix[0]).toEqual([]) + expect(directedMatrix[1]).toEqual([]) + }) + it('floydWarshall', () => { const matrix = [ [1, 1, 2], diff --git a/tests/unit/util/path-spec.ts b/tests/unit/util/path-spec.ts index 745d374701..cfe662b919 100644 --- a/tests/unit/util/path-spec.ts +++ b/tests/unit/util/path-spec.ts @@ -39,6 +39,17 @@ describe('Path Util Test', () => { expect(three[6]).toEqual(7) }) + it('getSpline thorw new error', () => { + const points = [ + { + x: 10, + y: 12 + } + ] + + expect(() => getSpline(points)).toThrowError(`point length must largn than 2, now it's ${points.length}`) + }) + it('getControlPoint horizontal', () => { const start = { x: 0, y: 0 }; const end = { x: 100, y: 0 }; @@ -81,6 +92,19 @@ describe('Path Util Test', () => { expect(point.y).toEqual(50 - sqrt2 * 10 / 2); }) + it('getControlPoint percent is 0', () => { + const start = { x: 100, y: 100 }; + const end = { x: 50, y: 20 }; + const point = getControlPoint(start, end); + expect(point.x).toEqual(100); + expect(point.y).toEqual(100); + }) + + it('pointsToPolygon points.length = 0', () => { + const polygonPoint = pointsToPolygon([]) + expect(polygonPoint).toEqual('') + }) + it('pointsToPolygon z = false', () => { const points = [ { @@ -112,4 +136,17 @@ describe('Path Util Test', () => { const polygonPoint = pointsToPolygon(points, true) expect(polygonPoint).toEqual('M1 2L5 5Z') }) + + it('pointsToPolygon substitute', () => { + const points = [ + { + x: 1, + y: 2 + }, + '' + ] + + const polygonPoint = pointsToPolygon(points, true) + expect(polygonPoint).toEqual('M1 2L{x} {y}Z') + }) }) \ No newline at end of file diff --git a/tests/unit/util/timeOut.ts b/tests/unit/util/timeOut.ts new file mode 100644 index 0000000000..3f32002068 --- /dev/null +++ b/tests/unit/util/timeOut.ts @@ -0,0 +1,10 @@ +/** + * 在 jest 中使用 setTimeout 功能 + * @param callback 回调函数 + * @param time 延迟的时间 + */ +export const timerOut = (callback, time = 50) => { + setTimeout(() => { + callback(); + }, time); +} \ No newline at end of file diff --git a/types/index.ts b/types/index.ts index a252d623da..a3b38b65b1 100644 --- a/types/index.ts +++ b/types/index.ts @@ -201,8 +201,8 @@ export interface NodeConfig extends ModelConfig { export interface EdgeConfig extends ModelConfig { id?: string; - source: string; - target: string; + source?: string; + target?: string; label?: string; labelCfg?: { style?: object;