diff --git a/packages/frontend/@n8n/design-system/src/components/N8nInlineTextEdit/InlineTextEdit.test.ts b/packages/frontend/@n8n/design-system/src/components/N8nInlineTextEdit/InlineTextEdit.test.ts index 94aef2b650..cc178f81ec 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nInlineTextEdit/InlineTextEdit.test.ts +++ b/packages/frontend/@n8n/design-system/src/components/N8nInlineTextEdit/InlineTextEdit.test.ts @@ -23,14 +23,21 @@ describe('N8nInlineTextEdit', () => { modelValue: 'Test Value', }, }); - const input = wrapper.getByTestId('inline-edit-input'); const preview = wrapper.getByTestId('inline-edit-preview'); - await wrapper.rerender({ modelValue: 'New Value' }); + await userEvent.click(preview); + + const input = wrapper.getByTestId('inline-edit-input'); + + await userEvent.clear(input); await userEvent.type(input, 'Updated Value'); await userEvent.keyboard('{Enter}'); expect(preview).toHaveTextContent('Updated Value'); + + const emittedEvents = wrapper.emitted('update:model-value'); + expect(emittedEvents).toBeDefined(); + expect(emittedEvents?.[0]).toEqual(['Updated Value']); }); it('should not update value on blur if input is empty', async () => { @@ -39,9 +46,11 @@ describe('N8nInlineTextEdit', () => { modelValue: 'Test Value', }, }); - const input = wrapper.getByTestId('inline-edit-input'); const preview = wrapper.getByTestId('inline-edit-preview'); + await userEvent.click(preview); + const input = wrapper.getByTestId('inline-edit-input'); + await userEvent.clear(input); await userEvent.tab(); // Simulate blur @@ -54,12 +63,31 @@ describe('N8nInlineTextEdit', () => { modelValue: 'Test Value', }, }); - const input = wrapper.getByTestId('inline-edit-input'); const preview = wrapper.getByTestId('inline-edit-preview'); + await userEvent.click(preview); + const input = wrapper.getByTestId('inline-edit-input'); + + await userEvent.clear(input); await userEvent.type(input, 'Updated Value'); await userEvent.keyboard('{Escape}'); expect(preview).toHaveTextContent('Test Value'); }); + + it('should not emit update:model-value on blur when value unchanged', async () => { + const wrapper = renderComponent({ + props: { + modelValue: 'Test Value', + }, + }); + const preview = wrapper.getByTestId('inline-edit-preview'); + + await userEvent.click(preview); + + await userEvent.tab(); + + const emittedEvents = wrapper.emitted('update:model-value'); + expect(emittedEvents).toBeUndefined(); + }); }); diff --git a/packages/frontend/@n8n/design-system/src/components/N8nInlineTextEdit/InlineTextEdit.vue b/packages/frontend/@n8n/design-system/src/components/N8nInlineTextEdit/InlineTextEdit.vue index 2fd2fecd71..7b33d50b0a 100644 --- a/packages/frontend/@n8n/design-system/src/components/N8nInlineTextEdit/InlineTextEdit.vue +++ b/packages/frontend/@n8n/design-system/src/components/N8nInlineTextEdit/InlineTextEdit.vue @@ -25,6 +25,8 @@ const emit = defineEmits<{ 'update:model-value': [value: string]; }>(); +const newValue = ref(props.modelValue); +const temp = ref(props.modelValue || props.placeholder); const editableRoot = useTemplateRef('editableRoot'); function forceFocus() { @@ -40,15 +42,15 @@ function forceCancel() { } } -defineExpose({ forceFocus, forceCancel }); - function onSubmit() { if (newValue.value === '') { newValue.value = props.modelValue; temp.value = props.modelValue; return; } - emit('update:model-value', newValue.value); + if (newValue.value !== props.modelValue) { + emit('update:model-value', newValue.value); + } } function onInput(value: string) { @@ -62,9 +64,6 @@ function onStateChange(state: string) { } // Resize logic -const newValue = ref(props.modelValue); -const temp = ref(props.modelValue || props.placeholder); - const measureSpan = useTemplateRef('measureSpan'); const { width: measuredWidth } = useElementSize(measureSpan); @@ -85,6 +84,8 @@ const computedInlineStyles = computed(() => { zIndex: 1, }; }); + +defineExpose({ forceFocus, forceCancel });