import cytoscape from 'cytoscape' import { beforeEach, describe, expect, it, vi } from 'vitest' import { mount } from '@vue/test-utils' import CytoscapeChart from '@/components/graph/CytoscapeChart.vue' const tapHandler = { current: null } const cy = { on: vi.fn((event, selector, handler) => { if (event === 'tap') tapHandler.current = handler }), elements: vi.fn(() => ({ remove: vi.fn() })), add: vi.fn(), layout: vi.fn(() => ({ run: vi.fn() })), destroy: vi.fn(), } vi.mock('cytoscape', () => ({ default: vi.fn(() => cy), })) const elements = [ { data: { id: 'product:1', kind: 'product', label: 'Panela' }, position: { x: 100, y: 100 } }, { data: { id: 'supplier:5', kind: 'supplier', label: 'La Mesa' }, position: { x: 320, y: 100 } }, { data: { id: 'e1', source: 'product:1', target: 'supplier:5' } }, ] const styles = [{ selector: 'node', style: { 'background-color': '#eee' } }] beforeEach(() => { vi.clearAllMocks() tapHandler.current = null }) function mountChart (props = {}) { return mount(CytoscapeChart, { props: { elements, styles, ...props }, }) } describe('CytoscapeChart', () => { it('crea la instancia de cytoscape con elements, styles y layout', () => { mountChart() expect(cytoscape).toHaveBeenCalledTimes(1) expect(cytoscape).toHaveBeenCalledWith( expect.objectContaining({ elements, style: styles, layout: { name: 'preset' }, }) ) }) it('permite sobreescribir el layout con el prop layout', () => { mountChart({ layout: { name: 'breadthfirst' } }) expect(cytoscape).toHaveBeenCalledWith( expect.objectContaining({ layout: { name: 'breadthfirst' } }) ) }) it('emite select con los datos del nodo al hacer tap', () => { const wrapper = mountChart() tapHandler.current({ target: { data: () => elements[0].data } }) expect(wrapper.emitted('select')).toEqual([[elements[0].data]]) }) it('actualiza la instancia cuando cambian los elements', async () => { const wrapper = mountChart() const next = [{ data: { id: 'organization:3', kind: 'organization', label: 'Red' } }] await wrapper.setProps({ elements: next }) expect(cy.elements).toHaveBeenCalled() expect(cy.add).toHaveBeenCalledWith(next) expect(cy.layout).toHaveBeenCalled() }) it('destruye la instancia al desmontarse', () => { const wrapper = mountChart() wrapper.unmount() expect(cy.destroy).toHaveBeenCalledTimes(1) }) it('no escucha eventos mientras no exista la instancia', () => { mountChart() expect(cy.on).toHaveBeenCalledWith('tap', 'node', expect.any(Function)) }) })