158 lines
5.5 KiB
JavaScript
158 lines
5.5 KiB
JavaScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { mount } from '@vue/test-utils'
|
|
import VisChart from '@/components/graph/VisChart.vue'
|
|
|
|
const vis = vi.hoisted(() => {
|
|
const networkInstance = {
|
|
on: vi.fn(),
|
|
once: vi.fn(),
|
|
setData: vi.fn(),
|
|
setOptions: vi.fn(),
|
|
fit: vi.fn(),
|
|
destroy: vi.fn(),
|
|
getPositions: vi.fn(() => ({})),
|
|
moveNode: vi.fn(),
|
|
}
|
|
const dataSetInstance = {
|
|
get: vi.fn(),
|
|
}
|
|
return {
|
|
networkInstance,
|
|
dataSetInstance,
|
|
Network: vi.fn(() => networkInstance),
|
|
DataSet: vi.fn(() => dataSetInstance),
|
|
}
|
|
})
|
|
|
|
vi.mock('vis-network/standalone', () => ({
|
|
Network: vis.Network,
|
|
DataSet: vis.DataSet,
|
|
}))
|
|
|
|
function handlerFor (mock, eventName) {
|
|
const call = mock.mock.calls.find(args => args[0] === eventName)
|
|
return call ? call[1] : null
|
|
}
|
|
|
|
describe('VisChart', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
it('crea la red con los nodos y aristas recibidos', () => {
|
|
const nodes = [{ id: 'product:1', label: 'Panela' }]
|
|
const edges = [{ from: 'product:1', to: 'supplier:5', dashes: true }]
|
|
mount(VisChart, { props: { nodes, edges } })
|
|
|
|
expect(vis.Network).toHaveBeenCalledTimes(1)
|
|
const [container, , options] = vis.Network.mock.calls[0]
|
|
expect(container).toBeInstanceOf(HTMLElement)
|
|
expect(options.physics.stabilization.enabled).toBe(true)
|
|
expect(vis.dataSetInstance.get).toBeDefined()
|
|
const data = vis.networkInstance.setData.mock.calls[0][0]
|
|
expect(data.nodes).toBe(vis.dataSetInstance)
|
|
expect(data.edges).toBe(vis.dataSetInstance)
|
|
})
|
|
|
|
it('mezcla las opciones base con las recibidas', () => {
|
|
mount(VisChart, {
|
|
props: {
|
|
nodes: [],
|
|
edges: [],
|
|
options: { nodes: { font: { size: 16 } }, physics: { stabilization: { iterations: 100 } } },
|
|
},
|
|
})
|
|
|
|
const options = vis.Network.mock.calls[0][2]
|
|
expect(options.nodes.font.size).toBe(16)
|
|
expect(options.nodes.shape).toBe('dot')
|
|
expect(options.physics.stabilization.iterations).toBe(100)
|
|
expect(options.physics.barnesHut.springLength).toBe(140)
|
|
})
|
|
|
|
it('emite select con el nodo al hacer click', () => {
|
|
const wrapper = mount(VisChart, { props: { nodes: [{ id: 'supplier:5', kind: 'supplier' }], edges: [] } })
|
|
|
|
vis.dataSetInstance.get.mockReturnValue({ id: 'supplier:5', kind: 'supplier', label: 'La Mesa' })
|
|
handlerFor(vis.networkInstance.on, 'click')({ nodes: ['supplier:5'] })
|
|
|
|
expect(wrapper.emitted('select')[0][0]).toEqual({ id: 'supplier:5', kind: 'supplier', label: 'La Mesa' })
|
|
})
|
|
|
|
it('no emite select cuando el click no cae sobre un nodo', () => {
|
|
const wrapper = mount(VisChart, { props: { nodes: [], edges: [] } })
|
|
|
|
handlerFor(vis.networkInstance.on, 'click')({ nodes: [] })
|
|
|
|
expect(wrapper.emitted('select')).toBeUndefined()
|
|
})
|
|
|
|
it('desactiva la física y ajusta la vista cuando la estabilización termina', () => {
|
|
mount(VisChart, { props: { nodes: [], edges: [] } })
|
|
|
|
const onStabilized = handlerFor(vis.networkInstance.once, 'stabilizationIterationsDone')
|
|
expect(onStabilized).toBeDefined()
|
|
onStabilized()
|
|
|
|
expect(vis.networkInstance.setOptions).toHaveBeenCalledWith({ physics: { enabled: false } })
|
|
expect(vis.networkInstance.fit).toHaveBeenCalled()
|
|
})
|
|
|
|
it('separa verticalmente los nodos de una misma columna tras estabilizar', () => {
|
|
vis.networkInstance.getPositions.mockReturnValue({
|
|
'supplier:5': { x: 0, y: 100 },
|
|
'supplier:6': { x: 0, y: 112 },
|
|
'municipality:7': { x: 240, y: 100 },
|
|
'product:1': { x: -240, y: 60 },
|
|
})
|
|
mount(VisChart, { props: { nodes: [], edges: [], minVerticalSpacing: 70 } })
|
|
|
|
const onStabilized = handlerFor(vis.networkInstance.once, 'stabilizationIterationsDone')
|
|
onStabilized()
|
|
|
|
expect(vis.networkInstance.moveNode).toHaveBeenCalledWith('supplier:6', 0, 170)
|
|
expect(vis.networkInstance.moveNode).not.toHaveBeenCalledWith('supplier:5', 0, expect.anything())
|
|
expect(vis.networkInstance.moveNode).not.toHaveBeenCalledWith('municipality:7', 240, expect.anything())
|
|
expect(vis.networkInstance.moveNode).not.toHaveBeenCalledWith('product:1', -240, expect.anything())
|
|
})
|
|
|
|
it('no separa nodos cuando no se indica espaciado vertical mínimo', () => {
|
|
vis.networkInstance.getPositions.mockReturnValue({
|
|
'supplier:5': { x: 0, y: 100 },
|
|
'supplier:6': { x: 0, y: 112 },
|
|
})
|
|
mount(VisChart, { props: { nodes: [], edges: [] } })
|
|
|
|
const onStabilized = handlerFor(vis.networkInstance.once, 'stabilizationIterationsDone')
|
|
onStabilized()
|
|
|
|
expect(vis.networkInstance.moveNode).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('vuelve a estabilizar el grafo cuando cambian los nodos o aristas', async () => {
|
|
const wrapper = mount(VisChart, { props: { nodes: [{ id: 'product:1' }], edges: [] } })
|
|
expect(vis.Network).toHaveBeenCalledTimes(1)
|
|
expect(vis.networkInstance.destroy).not.toHaveBeenCalled()
|
|
|
|
await wrapper.setProps({ nodes: [{ id: 'product:2' }], edges: [{ from: 'product:2', to: 'supplier:5' }] })
|
|
|
|
expect(vis.networkInstance.destroy).toHaveBeenCalled()
|
|
expect(vis.Network).toHaveBeenCalledTimes(2)
|
|
expect(vis.networkInstance.setData).toHaveBeenCalledTimes(2)
|
|
})
|
|
|
|
it('aplica la altura recibida al contenedor', () => {
|
|
const wrapper = mount(VisChart, { props: { height: 340 } })
|
|
|
|
expect(wrapper.element.style.height).toBe('340px')
|
|
})
|
|
|
|
it('destruye la red al desmontar', () => {
|
|
const wrapper = mount(VisChart, { props: { nodes: [], edges: [] } })
|
|
|
|
wrapper.unmount()
|
|
|
|
expect(vis.networkInstance.destroy).toHaveBeenCalled()
|
|
})
|
|
})
|