diff --git a/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalNodeDetailsDrawer.test.ts b/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalNodeDetailsDrawer.test.ts new file mode 100644 index 0000000000..2a2c34723e --- /dev/null +++ b/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalNodeDetailsDrawer.test.ts @@ -0,0 +1,80 @@ +import { createTestNode } from '@/__tests__/mocks'; +import { createComponentRenderer } from '@/__tests__/render'; +import { cleanupAppModals, createAppModals } from '@/__tests__/utils'; +import { SET_NODE_TYPE } from '@/constants'; +import { useNDVStore } from '@/stores/ndv.store'; +import { useNodeTypesStore } from '@/stores/nodeTypes.store'; +import { useWorkflowsStore } from '@/stores/workflows.store'; +import { createTestingPinia } from '@pinia/testing'; +import ExperimentalNodeDetailsDrawer from './ExperimentalNodeDetailsDrawer.vue'; +import { nextTick } from 'vue'; + +const renderComponent = createComponentRenderer(ExperimentalNodeDetailsDrawer); + +describe('ExperimentalNodeDetailsDrawer', () => { + let pinia: ReturnType; + let workflowsStore: ReturnType; + let nodeTypesStore: ReturnType; + let ndvStore: ReturnType; + + const mockNodes = [ + createTestNode({ + id: 'node1', + name: 'Node 1', + type: SET_NODE_TYPE, + parameters: { p0: 'before update' }, + }), + createTestNode({ id: 'node2', name: 'Node 2', type: SET_NODE_TYPE }), + createTestNode({ id: 'node3', name: 'Node 3', type: SET_NODE_TYPE }), + ]; + + beforeEach(() => { + pinia = createTestingPinia({ + stubActions: false, + }); + + workflowsStore = useWorkflowsStore(pinia); + workflowsStore.setNodes(mockNodes); + nodeTypesStore = useNodeTypesStore(pinia); + nodeTypesStore.setNodeTypes([ + { + name: SET_NODE_TYPE, + properties: [{ name: 'p0', displayName: 'P0', type: 'string', default: '' }], + version: 1, + defaults: {}, + inputs: ['main'], + outputs: ['main'], + displayName: 'T0', + group: [], + description: '', + }, + ]); + ndvStore = useNDVStore(); + createAppModals(); + }); + + afterEach(() => { + cleanupAppModals(); + }); + + it('should show updated parameter after closing NDV', async () => { + const rendered = renderComponent({ + pinia, + props: { + node: mockNodes[0], + nodes: [mockNodes[0]], + }, + }); + + await rendered.findByDisplayValue('before update'); + + // Simulate parameter update in NDV + ndvStore.setActiveNodeName('Node 1', 'other'); + await nextTick(); + workflowsStore.setNodeParameters({ name: 'Node 1', value: { p0: 'after update' } }); + ndvStore.unsetActiveNodeName(); + await nextTick(); + + await rendered.findByDisplayValue('after update'); + }); +}); diff --git a/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalNodeDetailsDrawer.vue b/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalNodeDetailsDrawer.vue index 32e4053726..f1507daf7a 100644 --- a/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalNodeDetailsDrawer.vue +++ b/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalNodeDetailsDrawer.vue @@ -4,14 +4,31 @@ import { ExpressionLocalResolveContextSymbol } from '@/constants'; import { type INodeUi } from '@/Interface'; import { N8nText } from '@n8n/design-system'; import { type GraphNode } from '@vue-flow/core'; -import { computed, provide } from 'vue'; +import { computed, provide, ref, watch } from 'vue'; import ExperimentalCanvasNodeSettings from './ExperimentalCanvasNodeSettings.vue'; +import { useNDVStore } from '@/stores/ndv.store'; const { node, nodes } = defineProps<{ node: INodeUi; nodes: GraphNode[] }>(); const emit = defineEmits<{ openNdv: [] }>(); const expressionResolveCtx = useExpressionResolveCtx(computed(() => node)); +const ndvStore = useNDVStore(); + +const ndvCloseTimes = ref(0); + +// To ensure showing latest parameters, force re-render when NDV is closed +const nodeSettingsViewKey = computed(() => [node.id, ndvCloseTimes.value].join('|')); + +// Track closing NDV +watch( + () => ndvStore.activeNodeName, + (name, oldName) => { + if (name === null && oldName !== null) { + ndvCloseTimes.value += 1; + } + }, +); provide(ExpressionLocalResolveContextSymbol, expressionResolveCtx); @@ -19,7 +36,7 @@ provide(ExpressionLocalResolveContextSymbol, expressionResolveCtx);