import { beforeEach, describe, expect, it, vi } from 'vitest' import { mount } from '@vue/test-utils' import { nextTick } from 'vue' import ProvenanceDetailModal from '@/components/provenance/ProvenanceDetailModal.vue' import ProvenanceGraph from '@/components/provenance/ProvenanceGraph.vue' import vuetify from '@/plugins/vuetify' vi.mock('@/components/graph/VisChart.vue', () => ({ default: { name: 'VisChart', template: '
', props: ['nodes', 'edges', 'height', 'options', 'minVerticalSpacing'], }, })) const provenance = [ { product: { id: 1, name: 'Panela regional por Kg', catalogue_images: ['http://localhost/media/panela.jpg'], }, suppliers: [ { supplier: { id: 5, name: 'Asociación Agropecuaria La Mesa' }, organization: { id: 3, name: 'Red de Economía Solidaria' }, municipality: { id: 7, name: 'La Mesa' }, department: { id: 2, name: 'Cundinamarca' }, country: { id: 1, name: 'Colombia' }, }, ], }, ] function mountGraph (props = {}) { return mount(ProvenanceGraph, { props: { provenance, ...props }, global: { plugins: [vuetify] }, }) } function visChart (wrapper) { return wrapper.findComponent({ name: 'VisChart' }) } function checkbox (wrapper, label) { return wrapper.findAllComponents({ name: 'VCheckbox' }).find(cb => cb.text().trim() === label) } async function setKinds (wrapper, kinds) { checkbox(wrapper, 'Productos').vm.$emit('update:modelValue', kinds) await nextTick() } describe('ProvenanceGraph', () => { beforeEach(() => { vi.clearAllMocks() }) it('por defecto grafica solo productos y proveedores', () => { const wrapper = mountGraph() const nodeKinds = visChart(wrapper).props('nodes').map(node => node.kind) expect(nodeKinds).toEqual(['product', 'supplier']) const edges = visChart(wrapper).props('edges') expect(edges.find(edge => edge.from === 'product:1' && edge.to === 'supplier:5').dashes).toBe(false) }) it('pide separación vertical mínima equivalente al círculo más una línea de label', () => { const wrapper = mountGraph() expect(visChart(wrapper).props('minVerticalSpacing')).toBe(70) }) it('muestra un checkbox por cada nivel con productos y proveedores activos', () => { const wrapper = mountGraph() const labels = wrapper.findAllComponents({ name: 'VCheckbox' }).map(cb => cb.text().trim()) expect(labels).toEqual(['Productos', 'Proveedores', 'Organizaciones', 'Municipios', 'Departamentos', 'País']) }) it('dibuja un círculo de color junto a cada checkbox como leyenda', () => { const wrapper = mountGraph() const dots = wrapper.findAll('.legend-dot') expect(dots).toHaveLength(6) expect(dots[0].element.style.backgroundColor).toBe('rgb(38, 166, 154)') expect(dots[1].element.style.backgroundColor).toBe('rgb(66, 165, 245)') expect(dots[2].element.style.backgroundColor).toBe('rgb(255, 183, 77)') }) it('al activar municipios agrega nodos de municipio y la arista proveedor→municipio', async () => { const wrapper = mountGraph() await setKinds(wrapper, ['product', 'supplier', 'municipality']) const nodeIds = visChart(wrapper).props('nodes').map(node => node.id) expect(nodeIds).toContain('municipality:7') const edges = visChart(wrapper).props('edges') expect(edges.find(edge => edge.from === 'supplier:5' && edge.to === 'municipality:7').dashes).toBe(false) }) it('con país activo crea el nodo país', async () => { const wrapper = mountGraph() await setKinds(wrapper, ['product', 'supplier', 'country']) expect(visChart(wrapper).props('nodes').map(node => node.id)).toContain('country:1') }) it('al desactivar productos no se crean nodos de producto', async () => { const wrapper = mountGraph() await setKinds(wrapper, ['supplier', 'municipality', 'department']) const nodeKinds = visChart(wrapper).props('nodes').map(node => node.kind) expect(nodeKinds).not.toContain('product') expect(nodeKinds).not.toContain('junction') }) it('avisa cuando no queda ningún nivel seleccionado', async () => { const wrapper = mountGraph() await setKinds(wrapper, []) expect(visChart(wrapper).exists()).toBe(false) expect(wrapper.text()).toContain('Selecciona al menos un elemento') }) it('muestra mensaje de próximamente cuando ningún producto tiene proveedores', () => { const wrapper = mountGraph({ provenance: [{ product: { id: 1, name: 'Panela' }, suppliers: [] }], }) expect(visChart(wrapper).exists()).toBe(false) expect(wrapper.text()).toContain('próximamente') }) it('abre el modal de detalle al seleccionar un proveedor', async () => { const wrapper = mountGraph() await visChart(wrapper).vm.$emit('select', { id: 'supplier:5', kind: 'supplier', label: 'Asociación Agropecuaria La Mesa', entity: { kind: 'supplier' } }) expect(wrapper.findComponent(ProvenanceDetailModal).props('visible')).toBe(true) expect(document.body.textContent).toContain('Asociación Agropecuaria La Mesa') }) it('ignora la selección del punto de disyunción', async () => { const provenanceWithTwoSuppliers = [ { product: { id: 1, name: 'Panela' }, suppliers: [ { supplier: { id: 5, name: 'A' }, municipality: { id: 7, name: 'La Mesa' } }, { supplier: { id: 6, name: 'B' }, municipality: { id: 8, name: 'San Antonio' } }, ], }, ] const wrapper = mountGraph({ provenance: provenanceWithTwoSuppliers }) await visChart(wrapper).vm.$emit('select', { id: 'junction:1', kind: 'junction', label: '' }) expect(wrapper.findComponent(ProvenanceDetailModal).props('visible')).toBe(false) }) })