Files
lan-manager/web/node_modules/@antv/g6-plugin/tests/unit/minimap-spec.ts
openclaw 0a5f6a8047 Initial commit: Lan-manager project code
- Go backend (server/)
- Frontend (web/, server/static/)
- Database and deployment files
- Scripts and docs

Co-Authored-By: 狸花猫/Claude-Qwen3.6-Plus 🐾
2026-04-20 00:52:58 +08:00

1155 lines
25 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import G6 from '@antv/g6';
import Simulate from 'event-simulate';
import Minimap from '../../src/minimap';
export function mathEqual(a: number, b: number, threshold: number = 1) {
return Math.abs(a - b) < threshold;
}
const cdata = {
nodes: [
{
id: '0',
label: '0',
},
{
id: '1',
label: '1',
},
{
id: '2',
label: '2',
},
{
id: '3',
label: '3',
},
{
id: '4',
label: '4',
},
{
id: '5',
label: '5',
},
{
id: '6',
label: '6',
},
{
id: '7',
label: '7',
},
{
id: '8',
label: '8',
},
{
id: '9',
label: '9',
},
{
id: '10',
label: '10',
},
{
id: '11',
label: '11',
},
{
id: '12',
label: '12',
},
{
id: '13',
label: '13',
},
{
id: '14',
label: '14',
},
{
id: '15',
label: '15',
},
{
id: '16',
label: '16',
},
{
id: '17',
label: '17',
},
{
id: '18',
label: '18',
},
{
id: '19',
label: '19',
},
{
id: '20',
label: '20',
},
{
id: '21',
label: '21',
},
{
id: '22',
label: '22',
},
{
id: '23',
label: '23',
},
{
id: '24',
label: '24',
},
{
id: '25',
label: '25',
},
{
id: '26',
label: '26',
},
{
id: '27',
label: '27',
},
{
id: '28',
label: '28',
},
{
id: '29',
label: '29',
},
{
id: '30',
label: '30',
},
{
id: '31',
label: '31',
},
{
id: '32',
label: '32',
},
{
id: '33',
label: '33',
},
],
edges: [
{
source: '0',
target: '1',
},
{
source: '0',
target: '2',
},
{
source: '0',
target: '3',
},
{
source: '0',
target: '4',
},
{
source: '0',
target: '5',
},
{
source: '0',
target: '7',
},
{
source: '0',
target: '8',
},
{
source: '0',
target: '9',
},
{
source: '0',
target: '10',
},
{
source: '0',
target: '11',
},
{
source: '0',
target: '13',
},
{
source: '0',
target: '14',
},
{
source: '0',
target: '15',
},
{
source: '0',
target: '16',
},
{
source: '2',
target: '3',
},
{
source: '4',
target: '5',
},
{
source: '4',
target: '6',
},
{
source: '5',
target: '6',
},
{
source: '7',
target: '13',
},
{
source: '8',
target: '14',
},
{
source: '9',
target: '10',
},
{
source: '10',
target: '22',
},
{
source: '10',
target: '14',
},
{
source: '10',
target: '12',
},
{
source: '10',
target: '24',
},
{
source: '10',
target: '21',
},
{
source: '10',
target: '20',
},
{
source: '11',
target: '24',
},
{
source: '11',
target: '22',
},
{
source: '11',
target: '14',
},
{
source: '12',
target: '13',
},
{
source: '16',
target: '17',
},
{
source: '16',
target: '18',
},
{
source: '16',
target: '21',
},
{
source: '16',
target: '22',
},
{
source: '17',
target: '18',
},
{
source: '17',
target: '20',
},
{
source: '18',
target: '19',
},
{
source: '19',
target: '20',
},
{
source: '19',
target: '33',
},
{
source: '19',
target: '22',
},
{
source: '19',
target: '23',
},
{
source: '20',
target: '21',
},
{
source: '21',
target: '22',
},
{
source: '22',
target: '24',
},
{
source: '22',
target: '25',
},
{
source: '22',
target: '26',
},
{
source: '22',
target: '23',
},
{
source: '22',
target: '28',
},
{
source: '22',
target: '30',
},
{
source: '22',
target: '31',
},
{
source: '22',
target: '32',
},
{
source: '22',
target: '33',
},
{
source: '23',
target: '28',
},
{
source: '23',
target: '27',
},
{
source: '23',
target: '29',
},
{
source: '23',
target: '30',
},
{
source: '23',
target: '31',
},
{
source: '23',
target: '33',
},
{
source: '32',
target: '33',
},
],
};
const div = document.createElement('div');
div.id = 'minimap';
document.body.appendChild(div);
const container = document.createElement('div');
container.id = 'minimap-container';
div.appendChild(container);
const isFireFox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
const dragEvent = isFireFox ? 'dragover' : 'drag';
describe('minimap', () => {
it('minimap with default settings & destroy', (done) => {
const minimap = new Minimap({ size: [200, 200] });
const graph = new G6.Graph({
container: div,
width: 500,
height: 500,
defaultEdge: {
type: 'line',
style: {
endArrow: {
path: 'M 10,0 L -10,-10 L -10,10 Z',
d: 10,
},
},
},
modes: {
default: [
{
type: 'drag-node',
delegate: false,
},
'zoom-canvas',
'click-select',
'drag-canvas',
],
},
plugins: [minimap],
});
graph.addItem('node', { id: 'node1', label: 'text1', x: 50, y: 50 });
graph.addItem('node', { id: 'node2', label: 'text2', x: 120, y: 150 });
graph.addItem('node', { id: 'node3', label: 'text3', x: 150, y: 190 });
graph.addItem('node', { id: 'node4', label: 'text4', x: 220, y: 250 });
graph.addItem('edge', { id: 'edge1', source: 'node1', target: 'node2' });
const canvas = minimap.getCanvas();
expect(canvas).not.toBe(undefined);
expect(canvas.get('width')).toEqual(200);
expect(canvas.get('height')).toEqual(200);
const viewport = minimap.getViewport();
expect(viewport).not.toBe(undefined);
expect(viewport.className.indexOf('g6-minimap-viewport') >= 0).toBe(true);
// 缩小的时候viewport已经最大了不会更大
graph.zoom(0.5, { x: 250, y: 250 });
expect(viewport.style.left).toEqual('0px');
expect(viewport.style.top).toEqual('0px');
expect(viewport.style.width).toEqual('200px');
expect(viewport.style.height).toEqual('200px');
graph.zoom(2.5, { x: 250, y: 250 });
setTimeout(() => {
const left = parseFloat(viewport.style.left.substr(0, viewport.style.left.length - 2));
const top = parseFloat(viewport.style.top.substr(0, viewport.style.top.length - 2));
const width = parseFloat(viewport.style.width.substr(0, viewport.style.width.length - 2));
const height = parseFloat(viewport.style.height.substr(0, viewport.style.height.length - 2));
expect(mathEqual(left, 47)).toBe(true);
expect(mathEqual(top, 37)).toBe(true);
expect(mathEqual(width, 152, 2)).toBe(true);
expect(mathEqual(height, 162)).toBe(true);
graph.zoom(2.5, { x: 250, y: 250 });
setTimeout(() => {
const left = parseFloat(viewport.style.left.substr(0, viewport.style.left.length - 2));
const top = parseFloat(viewport.style.top.substr(0, viewport.style.top.length - 2));
const width = parseFloat(viewport.style.width.substr(0, viewport.style.width.length - 2));
const height = parseFloat(
viewport.style.height.substr(0, viewport.style.height.length - 2),
);
expect(mathEqual(left, 121, 5)).toBe(true);
expect(mathEqual(top, 112, 5)).toBe(true);
expect(mathEqual(width, 78, 5)).toBe(true);
expect(mathEqual(height, 87, 5)).toBe(true);
minimap.destroyPlugin();
const container: HTMLElement = div.childNodes[0] as HTMLElement;
expect(container.innerHTML).toEqual('');
done();
}, 100);
}, 100);
});
it('move viewport', (done) => {
const minimap = new Minimap({ size: [200, 200] });
const graph = new G6.Graph({
container: div,
width: 500,
height: 500,
plugins: [minimap],
modes: {
default: ['zoom-canvas', 'drag-canvas'],
},
});
const data = {
nodes: [
{
id: '1',
x: 50,
y: 80,
},
{
id: '2',
x: 140,
y: 100,
},
{
id: '3',
x: 250,
y: 250,
},
],
edges: [
{
source: '1',
target: '2',
},
],
};
graph.data(data);
graph.render();
const viewport = minimap.getViewport();
graph.zoom(2, { x: 250, y: 250 });
graph.translate(50, 50);
setTimeout(() => {
expect(viewport.style.left).toEqual('68.8474px');
expect(viewport.style.top).toEqual('59.5016px');
expect(viewport.style.width).toEqual('131.153px');
expect(viewport.style.height).toEqual('140.498px');
// use different events for different browsers
// electron: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_5_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Electron/11.5.0 Safari/537.36
const isFireFox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
const isSafari = navigator.userAgent.toLowerCase().indexOf('safari') > -1;
const dragstartevent = isSafari || isFireFox ? 'mousedown' : 'dragstart';
const dragevent = isSafari || isFireFox ? 'mousemove' : 'drag';
const dragDOM = isSafari || isFireFox ? minimap.get('canvas').get('container') : viewport;
const dragendevent = isSafari || isFireFox ? 'mouseup' : 'dragend';
Simulate.simulate(viewport, dragstartevent, {
clientX: 100,
clientY: 100,
target: viewport,
});
Simulate.simulate(dragDOM, dragevent, {
clientX: 98,
clientY: 91,
});
Simulate.simulate(viewport, dragendevent, {
clientX: 98,
clientY: 91,
});
setTimeout(() => {
expect(viewport.style.left).toEqual('66.8474px');
expect(viewport.style.top).toEqual('50.5016px');
expect(viewport.style.width).toEqual('133.153px');
expect(viewport.style.height).toEqual('149.498px');
const matrix = graph.get('group').getMatrix();
expect(matrix[0]).toEqual(2);
expect(matrix[4]).toEqual(2);
graph.destroy();
done();
}, 300);
}, 300);
});
it('invalid dom event', () => {
const minimap = new Minimap({ size: [200, 200] });
const graph = new G6.Graph({
container: div,
width: 500,
height: 500,
plugins: [minimap],
modes: {
default: ['zoom-canvas'],
},
});
const data = {
nodes: [
{
id: '1',
x: 50,
y: 80,
},
{
id: '2',
x: 140,
y: 100,
},
],
edges: [
{
source: '1',
target: '2',
},
],
};
graph.data(data);
graph.render();
const viewport = minimap.getContainer();
Simulate.simulate(viewport, dragEvent, {
clientX: 100,
clientY: 100,
});
viewport.style.width = '300px';
Simulate.simulate(viewport, 'dragstart', {
clientX: 100,
clientY: 100,
target: null,
});
});
it('delegate type of minimap', (done) => {
const minimap = new Minimap({
size: [200, 200],
type: 'delegate',
delegateStyle: {
fill: '#fff',
},
});
const graph = new G6.Graph({
container: div,
width: 500,
height: 500,
plugins: [minimap],
});
const nodeBBox = graph.addItem('node', { id: 'node', x: 100, y: 100, size: 16 }).getBBox();
const canvas = minimap.getCanvas();
setTimeout(() => {
const delegateShape = canvas.get('children')[0].get('children')[0];
expect(delegateShape.attr('x')).toEqual(nodeBBox.minX);
expect(delegateShape.attr('y')).toEqual(nodeBBox.minY);
expect(delegateShape.attr('width')).toEqual(nodeBBox.width);
expect(delegateShape.attr('height')).toEqual(nodeBBox.height);
expect(delegateShape.attr('fill')).toEqual('#fff');
expect(delegateShape.attr('stroke')).toEqual('#096dd9');
graph.destroy();
done();
}, 110);
});
it('minimap container', () => {
const minimap = new Minimap({
container,
size: [200, 200],
className: 'test-className',
});
const graph = new G6.Graph({
container: div,
width: 500,
height: 500,
plugins: [minimap],
modes: {
default: [
{
type: 'drag-node',
delegate: false,
},
'zoom-canvas',
'click-select',
'drag-canvas',
],
},
});
const minimapContainer: HTMLElement = container.childNodes[0] as HTMLElement;
expect(minimapContainer.childNodes).not.toBe(undefined);
expect(minimapContainer.className).toEqual('test-className');
expect(minimapContainer.style.width).toEqual('200px');
expect(minimapContainer.style.width).toEqual('200px');
const minimapContainerNode = minimapContainer.childNodes[0] as HTMLElement;
expect(minimapContainerNode.tagName).toEqual('DIV');
expect(minimapContainerNode.style.position).toEqual('relative');
expect(minimapContainerNode.childNodes[0]).toEqual(minimap.getCanvas().get('el'));
graph.destroy();
expect(container.innerHTML).toEqual('');
});
it('canvas minX minY < 0', (done) => {
const minimap = new Minimap({
size: [200, 200],
});
const graph = new G6.Graph({
container: div,
width: 500,
height: 500,
plugins: [minimap],
defaultNode: {
size: 60,
},
modes: {
default: ['drag-node', 'drag-canvas', 'zoom-canvas'],
},
});
graph.addItem('node', { id: 'node1', x: -50, y: -50 });
setTimeout(() => {
const canvas = minimap.getCanvas();
const group = canvas.get('children')[0];
const matrix = group.getMatrix();
expect(matrix[6] - 30 < 1).toBe(false);
expect(matrix[7] - 30 < 1).toBe(false);
graph.destroy();
done();
}, 100);
});
it('keyShapeOnly minimap', (done) => {
const minimap = new Minimap({ size: [200, 200], type: 'keyShape' });
const graph = new G6.Graph({
container: div,
width: 500,
height: 500,
plugins: [minimap],
});
graph.addItem('node', { id: 'node1', label: 'text1', x: 50, y: 50 });
graph.addItem('node', { id: 'node2', label: 'text2', x: 120, y: 150 });
graph.addItem('edge', { id: 'edge1', source: 'node1', target: 'node2' });
const canvas = minimap.getCanvas();
setTimeout(() => {
const shapeGroup = canvas.get('children')[0].get('children');
expect(shapeGroup.length).toEqual(3);
expect(shapeGroup[0].attr('path')).not.toBe(undefined);
expect(shapeGroup[1].attr('x')).toEqual(50);
expect(shapeGroup[1].attr('y')).toEqual(50);
expect(shapeGroup[2].attr('x')).toEqual(120);
expect(shapeGroup[2].attr('y')).toEqual(150);
graph.destroy();
done();
}, 100);
});
it('get minimap container', () => {
const minimap = new Minimap({ size: [200, 200], type: 'keyShape' });
const graph = new G6.Graph({
container: div,
width: 500,
height: 500,
plugins: [minimap],
});
const container = minimap.getContainer();
expect(container).not.toBe(undefined);
expect(container.className).toBe('g6-minimap');
graph.destroy();
});
it('minimap beforeanimate afteranimate', () => {
const minimap = new Minimap({ size: [200, 200] });
const graph = new G6.Graph({
container: div,
width: 500,
height: 500,
plugins: [minimap],
});
graph.emit('beforeanimate');
expect(minimap.get('refresh')).toBe(false);
graph.emit('afteranimate');
expect(minimap.get('refresh')).toBe(true);
graph.destroy();
});
});
describe('minimap with hidden shape', () => {
G6.registerNode(
'my-node',
{
drawShape: (cfg, group) => {
const mainGroup = group.addGroup({
id: 'main-group',
});
const rect = mainGroup.addShape('rect', {
attrs: {
fill: '#fff',
},
name: 'main-box',
});
const shape = mainGroup.addShape('rect', {
attrs: {
fill: '#fff',
stroke: '#FA8C16',
radius: 4,
},
name: 'main-shape',
});
if (cfg.open) {
mainGroup.addShape('rect', {
attrs: {
x: 0,
y: -4,
width: 266,
height: 4,
fill: '#FA8C16',
stroke: '#FA8C16',
radius: [6, 6, 0, 0],
},
name: 'css-rect',
});
} else {
mainGroup.addShape('rect', {
attrs: {
x: 0,
y: 0,
width: 4,
height: 40,
fill: '#FA8C16',
stroke: '#FA8C16',
radius: [6, 0, 0, 6],
},
name: 'css-rect',
});
}
const text = mainGroup.addShape('text', {
attrs: {
text: '文本0',
x: 14,
y: 20,
textAlign: 'left',
textBaseline: 'middle',
fill: '#666',
fontSize: 14,
},
name: 'rect-shape',
zIndex: 0,
});
const detailGroup = group.addGroup({
id: 'detail-group',
});
detailGroup.addShape('text', {
attrs: {
text: '文本1',
x: 14,
y: 46,
textAlign: 'left',
textBaseline: 'middle',
fill: '#666',
},
name: 'desc',
});
detailGroup.addShape('text', {
attrs: {
text: '文本2',
x: 14,
y: 66,
textAlign: 'left',
textBaseline: 'middle',
fill: '#666',
},
name: 'dbName',
});
detailGroup.addShape('text', {
attrs: {
text: '文本3',
x: 134,
y: 66,
textAlign: 'left',
textBaseline: 'middle',
fill: '#666',
},
name: 'dbType',
});
detailGroup.addShape('image', {
attrs: {
x: 0,
y: 60,
width: 16,
height: 16,
img:
'https://g.alicdn.com/cm-design/arms-trace/1.0.155/styles/armsTrace/images/TAIR.png',
},
// must be assigned in G6 3.3 and later versions. it can be any value you want
name: 'btn',
data: cfg.detail,
});
if (cfg.open) {
detailGroup.show();
rect.attr({
x: 0,
y: 0,
width: 280,
height: 134,
});
shape.attr({
x: 0,
y: 0,
width: 266,
height: 134,
});
} else {
detailGroup.hide();
rect.attr({
x: 0,
y: 0,
width: 280,
height: 40,
});
shape.attr({
x: 0,
y: 0,
width: 266,
height: 40,
});
}
return rect;
},
update: undefined,
},
'single-node',
);
it('svg renderer, minimap with hidden shape in custom node', (done) => {
const minimap = new Minimap({ size: [200, 200] });
const graph = new G6.Graph({
container: div,
width: 500,
height: 500,
plugins: [minimap],
renderer: 'svg',
defaultNode: {
type: 'my-node',
},
});
graph.addItem('node', { id: 'node1', label: 'text1', x: 50, y: 50, open: true });
graph.addItem('node', { id: 'node2', label: 'text2', x: 120, y: 150, open: true });
graph.addItem('node', { id: 'node3', label: 'text3', x: 150, y: 190 });
graph.addItem('node', { id: 'node4', label: 'text4', x: 220, y: 250 });
setTimeout(() => {
const minimapCanvas = minimap.getCanvas();
const minimapRootGroup = minimapCanvas.get('children')[0];
expect(
minimapRootGroup.get('children')[2].get('children')[3].get('children')[1].get('visible'),
).toBe(false);
done();
}, 100);
});
});
describe('minimap with combo', () => {
const combodata = {
nodes: [
{
id: "5930",
label: "NODE1",
comboId: "CHILD-93-5-1",
x: 440,
y: 0
},
{
id: "3830",
label: "NODE2",
comboId: "CHILD-83-3-1",
x: 320,
y: 0
},
{
id: "5920",
label: "NODE3",
comboId: "CHILD-92-5-1",
x: 440,
y: 40
},
{
id: "2400",
label: "NODE4",
comboId: "CHILD-40-2-1",
x: 260,
y: 0
},
{
id: "41010",
label: "NODE5",
comboId: "CHILD-101-4-1",
x: 380,
y: 0
},
{
id: "41280",
label: "NODE6",
comboId: "CHILD-128-4-1",
x: 380,
y: 80
}
],
edges: [
{ source: "5920", target: "41280" },
{ source: "5930", target: "41010" },
{ source: "41010", target: "5920" },
{ source: "41010", target: "3830" },
{ source: "3830", target: "2400" }
],
combos: [
{
id: "ROOT-1",
label: " ROOT1",
collapsed: false
},
{
id: "PARENT-5-1",
label: "CMB5",
parentId: "ROOT-1",
collapsed: false,
style: { fill: "#AD9D9A", stroke: "#AD9D9A" }
},
{
id: "CHILD-93-5-1",
label: " COMBTKT5",
parentId: "PARENT-5-1",
collapsed: true,
},
{
id: "PARENT-3-1",
label: "CMB9",
parentId: "ROOT-1",
collapsed: true,
style: { fill: "#DE6295", stroke: "#DDDDDD" }
},
{
id: "CHILD-83-3-1",
label: " COMBTUH4",
parentId: "PARENT-3-1",
collapsed: true,
},
{
id: "CHILD-92-5-1",
label: " COMBTUH3",
parentId: "PARENT-5-1",
collapsed: true,
},
{
id: "PARENT-2-1",
label: "CMB4",
parentId: "ROOT-1",
collapsed: true,
style: { fill: "#9E7FCB", stroke: "#CDCDCD" }
},
{
id: "CHILD-40-2-1",
label: " COMBQGL3",
parentId: "PARENT-2-1",
collapsed: true,
},
{
id: "PARENT-4-1",
label: "CMB0",
parentId: "ROOT-1",
collapsed: true,
style: { fill: "#8FB9C2", stroke: "#8FB9C2" }
},
{
id: "CHILD-101-4-1",
label: " COMBQISB",
parentId: "PARENT-4-1",
collapsed: false,
},
{
id: "CHILD-128-4-1",
label: " COMBTTIT",
parentId: "PARENT-4-1",
collapsed: true,
}
]
};
it('keyShape minimap with combo', (done) => {
const minimap = new Minimap({
size: [200, 200],
type: 'keyShape'
});
const graph = new G6.Graph({
container: div,
width: 500,
height: 500,
modes: {
default: [
'drag-node',
'zoom-canvas',
'collapse-expand-combo',
'drag-canvas',
],
},
plugins: [minimap],
defaultCombo: {
type: 'rect'
},
});
graph.read(combodata);
setTimeout(() => {
const canvas = minimap.get('canvas');
expect(canvas.get('children').length).toBe(1);
const comboGroup = canvas.find(ele => ele.get('name') === 'comboGroup');
expect(comboGroup.get('children').length).toBe(11);
expect(comboGroup.get('children').filter(e => e.get('visible')).length).toBe(7);
graph.destroy();
done();
}, 600);
});
it('delegate minimap with combo', (done) => {
const minimap = new Minimap({
size: [500, 500],
type: 'delegate'
});
const graph = new G6.Graph({
container: div,
width: 500,
height: 500,
modes: {
default: [
'drag-node',
'zoom-canvas',
'collapse-expand-combo',
'drag-canvas',
],
},
plugins: [minimap],
defaultCombo: {
type: 'rect'
},
});
graph.read(combodata)
setTimeout(() => {
const canvas = minimap.get('canvas');
expect(canvas.get('children').length).toBe(1);
const comboGroup = canvas.find(ele => ele.get('name') === 'comboGroup');
expect(comboGroup.get('children').length).toBe(11);
expect(comboGroup.get('children').filter(e => e.get('visible')).length).toBe(7);
graph.destroy();
done();
}, 600);
});
});