diff --git a/packages/frontend/editor-ui/src/components/ParameterInput.test.ts b/packages/frontend/editor-ui/src/components/ParameterInput.test.ts index eafc83542cd..29a298f058e 100644 --- a/packages/frontend/editor-ui/src/components/ParameterInput.test.ts +++ b/packages/frontend/editor-ui/src/components/ParameterInput.test.ts @@ -224,39 +224,65 @@ describe('ParameterInput.vue', () => { expect(emitted('update')).toContainEqual([expect.objectContaining({ value: 'foo' })]); }); - test('should correctly handle paste events', async () => { - const { container, emitted } = renderComponent({ - props: { - path: 'tag', - parameter: { - displayName: 'Tag', - name: 'tag', - type: 'string', - }, - modelValue: '', - }, - }); - const input = container.querySelector('input') as HTMLInputElement; - expect(input).toBeInTheDocument(); - await userEvent.click(input); - - async function paste(text: string) { + describe('paste events', () => { + async function paste(input: HTMLInputElement, text: string) { const expression = new DataTransfer(); expression.setData('text', text); await userEvent.clear(input); await userEvent.paste(expression); } - await paste('foo'); - expect(emitted('update')).toContainEqual([expect.objectContaining({ value: 'foo' })]); + test('should handle pasting into a string parameter', async () => { + const { container, emitted } = renderComponent({ + props: { + path: 'tag', + parameter: { + displayName: 'Tag', + name: 'tag', + type: 'string', + }, + modelValue: '', + }, + }); + const input = container.querySelector('input') as HTMLInputElement; + expect(input).toBeInTheDocument(); + await userEvent.click(input); - await paste('={{ $json.foo }}'); - expect(emitted('update')).toContainEqual([ - expect.objectContaining({ value: '={{ $json.foo }}' }), - ]); + await paste(input, 'foo'); + expect(emitted('update')).toContainEqual([expect.objectContaining({ value: 'foo' })]); - await paste('=flDvzj%y1nP'); - expect(emitted('update')).toContainEqual([expect.objectContaining({ value: '==flDvzj%y1nP' })]); + await paste(input, '={{ $json.foo }}'); + expect(emitted('update')).toContainEqual([ + expect.objectContaining({ value: '={{ $json.foo }}' }), + ]); + + await paste(input, '=flDvzj%y1nP'); + expect(emitted('update')).toContainEqual([ + expect.objectContaining({ value: '==flDvzj%y1nP' }), + ]); + }); + + test('should handle pasting an expression into a number parameter', async () => { + const { container, emitted } = renderComponent({ + props: { + path: 'percentage', + parameter: { + displayName: 'Percentage', + name: 'percentage', + type: 'number', + }, + modelValue: 1, + }, + }); + const input = container.querySelector('input') as HTMLInputElement; + expect(input).toBeInTheDocument(); + await userEvent.click(input); + + await paste(input, '{{ $json.foo }}'); + expect(emitted('update')).toContainEqual([ + expect.objectContaining({ value: '={{ $json.foo }}' }), + ]); + }); }); test('should not reset the value of a multi-select with loadOptionsMethod on load', async () => { diff --git a/packages/frontend/editor-ui/src/components/ParameterInput.vue b/packages/frontend/editor-ui/src/components/ParameterInput.vue index fe76f65dd46..32cfafcbcb0 100644 --- a/packages/frontend/editor-ui/src/components/ParameterInput.vue +++ b/packages/frontend/editor-ui/src/components/ParameterInput.vue @@ -786,6 +786,16 @@ function onPaste(event: ClipboardEvent) { } } +function onPasteNumber(event: ClipboardEvent) { + const pastedText = event.clipboardData?.getData('text'); + + if (shouldConvertToExpression(pastedText)) { + event.preventDefault(); + valueChanged('=' + pastedText); + return; + } +} + function onResourceLocatorDrop(data: string) { emit('drop', data); } @@ -1596,7 +1606,7 @@ onUpdated(async () => { @update:model-value="onUpdateTextInput" @focus="setFocus" @blur="onBlur" - @keydown.stop + @paste="onPasteNumber" />