From 534b186d76a72877e1526e7c17990eeb13c9ac15 Mon Sep 17 00:00:00 2001 From: lana-k Date: Sat, 28 Feb 2026 16:53:43 +0100 Subject: [PATCH] tests for graph editor --- src/components/Graph/GraphEditor.vue | 4 +- src/components/Graph/index.vue | 6 +- tests/components/Graph/Graph.spec.js | 321 +++++++++++++++++++++++++++ 3 files changed, 326 insertions(+), 5 deletions(-) diff --git a/src/components/Graph/GraphEditor.vue b/src/components/Graph/GraphEditor.vue index 0338086..9bb183a 100644 --- a/src/components/Graph/GraphEditor.vue +++ b/src/components/Graph/GraphEditor.vue @@ -288,7 +288,7 @@ export default { initOptions: Object, showViewSettings: Boolean }, - emits: ['update', 'selectItem', 'deselectItem'], + emits: ['update', 'selectItem', 'clearSelection'], data() { return { graph: new Graph({ multi: true, allowSelfLoops: true }), @@ -572,7 +572,7 @@ export default { clearSelection() { this.selectedNodeId = undefined this.selectedEdgeId = undefined - this.$emit('deselectItem') + this.$emit('clearSelection') }, updateHighlightNodeMode(mode) { this.settings.style.highlightMode = mode diff --git a/src/components/Graph/index.vue b/src/components/Graph/index.vue index cf76bca..87211f8 100644 --- a/src/components/Graph/index.vue +++ b/src/components/Graph/index.vue @@ -32,7 +32,7 @@ :showViewSettings="showViewSettings" @update="$emit('update')" @selectItem="selectedItem = $event" - @deselectItem="selectedItem = null" + @clearSelection="selectedItem = null" /> @@ -52,7 +52,7 @@ import 'react-chart-editor/lib/react-chart-editor.css' import GraphEditor from '@/components/Graph/GraphEditor.vue' import { dataSourceIsValid } from '@/lib/graphHelper' -import ValueViewer from '@/components/ValueViewer' +import ValueViewer from '@/components/ValueViewer.vue' import Splitpanes from '@/components/Common/Splitpanes' export default { @@ -78,7 +78,7 @@ export default { data() { return { resizeObserver: null, - selectedItem: {} + selectedItem: null } }, computed: { diff --git a/tests/components/Graph/Graph.spec.js b/tests/components/Graph/Graph.spec.js index 2298921..029c7d4 100644 --- a/tests/components/Graph/Graph.spec.js +++ b/tests/components/Graph/Graph.spec.js @@ -2,6 +2,7 @@ import { expect } from 'chai' import sinon from 'sinon' import { mount, flushPromises } from '@vue/test-utils' import Graph from '@/components/Graph/index.vue' +import { nextTick } from 'vue' function getPixels(canvas) { const context = canvas.getContext('webgl2') @@ -163,6 +164,326 @@ describe('Graph.vue', () => { wrapper.unmount() }) + it('the graph resizes when node viewer visibillity togglles', async () => { + const wrapper = mount(Graph, { + attachTo: document.body, + props: { + dataSources: { + doc: [ + '{"object_type":0,"node_id":"Gryffindor"}', + '{"object_type":0,"node_id":"Hufflepuff"}' + ] + }, + initOptions: { + structure: { + nodeId: 'node_id', + objectType: 'object_type', + edgeSource: 'source', + edgeTarget: 'target' + }, + style: { + backgroundColor: 'white', + nodes: { + size: { + type: 'constant', + value: 10 + }, + color: { + type: 'constant', + value: '#1F77B4' + }, + label: { + source: null, + color: '#444444' + } + }, + edges: { + showDirection: true, + size: { + type: 'constant', + value: 2 + }, + color: { + type: 'constant', + value: '#a2b1c6' + }, + label: { + source: null, + color: '#a2b1c6' + } + } + }, + layout: { + type: 'circular', + options: null + } + }, + showValueViewer: false + }, + global: { + mocks: { $store }, + provide: { + tabLayout: { dataView: 'above' } + } + } + }) + + const canvas = wrapper.find('canvas.sigma-nodes').wrapperElement + const initialCanvasWidth = canvas.scrollWidth + + await wrapper.setProps({ showValueViewer: true }) + await flushPromises() + + expect(canvas.scrollWidth).not.to.equal(initialCanvasWidth) + + await wrapper.setProps({ showValueViewer: false }) + await flushPromises() + + expect(canvas.scrollWidth).to.equal(initialCanvasWidth) + + wrapper.unmount() + }) + + it('the graph resizes when the split pane resizes', async () => { + const wrapper = mount(Graph, { + attachTo: document.body, + props: { + dataSources: { + doc: [ + '{"object_type":0,"node_id":"Gryffindor"}', + '{"object_type":0,"node_id":"Hufflepuff"}' + ] + }, + initOptions: { + structure: { + nodeId: 'node_id', + objectType: 'object_type', + edgeSource: 'source', + edgeTarget: 'target' + }, + style: { + backgroundColor: 'white', + nodes: { + size: { + type: 'constant', + value: 10 + }, + color: { + type: 'constant', + value: '#1F77B4' + }, + label: { + source: null, + color: '#444444' + } + }, + edges: { + showDirection: true, + size: { + type: 'constant', + value: 2 + }, + color: { + type: 'constant', + value: '#a2b1c6' + }, + label: { + source: null, + color: '#a2b1c6' + } + } + }, + layout: { + type: 'circular', + options: null + } + }, + showValueViewer: true + }, + global: { + mocks: { $store }, + provide: { + tabLayout: { dataView: 'above' } + } + } + }) + + const container = + wrapper.find('.graph-container').wrapperElement.parentElement + const canvas = wrapper.find('canvas.sigma-nodes').wrapperElement + + const initialContainerWidth = container.scrollWidth + const initialCanvasWidth = canvas.scrollWidth + await wrapper.find('.splitpanes-splitter').trigger('mousedown') + document.dispatchEvent( + new MouseEvent('mousemove', { + clientX: initialContainerWidth / 2, + clientY: 80 + }) + ) + document.dispatchEvent(new MouseEvent('mouseup')) + await nextTick() + await nextTick() + + await flushPromises() + + expect(canvas.scrollWidth).not.to.equal(initialCanvasWidth) + + wrapper.unmount() + }) + + it('opens and closes node viewer', async () => { + const wrapper = mount(Graph, { + props: { + dataSources: { + doc: [ + '{"object_type":0,"node_id":"Gryffindor"}', + '{"object_type":0,"node_id":"Hufflepuff"}' + ] + }, + initOptions: { + structure: { + nodeId: 'node_id', + objectType: 'object_type', + edgeSource: 'source', + edgeTarget: 'target' + }, + style: { + backgroundColor: 'white', + nodes: { + size: { + type: 'constant', + value: 10 + }, + color: { + type: 'constant', + value: '#1F77B4' + }, + label: { + source: null, + color: '#444444' + } + }, + edges: { + showDirection: true, + size: { + type: 'constant', + value: 2 + }, + color: { + type: 'constant', + value: '#a2b1c6' + }, + label: { + source: null, + color: '#a2b1c6' + } + } + }, + layout: { + type: 'circular', + options: null + } + }, + showValueViewer: false + }, + global: { + mocks: { $store }, + provide: { + tabLayout: { dataView: 'above' } + } + } + }) + + expect(wrapper.text()).not.contain('No node or edge selected to view') + await wrapper.setProps({ showValueViewer: true }) + expect(wrapper.text()).contains('No node or edge selected to view') + }) + + it('passes selected item to node viewer', async () => { + const wrapper = mount(Graph, { + attachTo: document.body, + props: { + dataSources: { + doc: [ + '{"object_type":0,"node_id":"Gryffindor"}', + '{"object_type":0,"node_id":"Hufflepuff"}' + ] + }, + initOptions: { + structure: { + nodeId: 'node_id', + objectType: 'object_type', + edgeSource: 'source', + edgeTarget: 'target' + }, + style: { + backgroundColor: 'white', + nodes: { + size: { + type: 'constant', + value: 10 + }, + color: { + type: 'constant', + value: '#1F77B4' + }, + label: { + source: null, + color: '#444444' + } + }, + edges: { + showDirection: true, + size: { + type: 'constant', + value: 2 + }, + color: { + type: 'constant', + value: '#a2b1c6' + }, + label: { + source: null, + color: '#a2b1c6' + } + } + }, + layout: { + type: 'circular', + options: null + } + }, + showValueViewer: true + }, + global: { + mocks: { $store }, + provide: { + tabLayout: { dataView: 'above' } + } + } + }) + + expect(wrapper.find('.value-viewer .value-body').exists()).to.equal(false) + await wrapper + .findComponent({ ref: 'graphEditor' }) + .vm.$emit('selectItem', { object_type: 0, node_id: 'Gryffindor' }) + + expect(wrapper.find('.value-viewer .value-body').text()).contains( + '"object_type": 0,' + ) + expect(wrapper.find('.value-viewer .value-body').text()).contains( + '"node_id": "Gryffindor"' + ) + + await wrapper + .findComponent({ ref: 'graphEditor' }) + .vm.$emit('clearSelection') + expect(wrapper.find('.value-viewer .value-body').exists()).to.equal(false) + + wrapper.unmount() + }) + it('nodes and edges are rendered', async () => { const wrapper = mount(Graph, { attachTo: document.body,