Files
don_confiao_frontend/tests/unit/components/graph/VisChart.spec.js

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()
})
})