diff --git a/packages/frontend/editor-ui/src/components/ResourceLocator/ResourceLocator.test.ts b/packages/frontend/editor-ui/src/components/ResourceLocator/ResourceLocator.test.ts index 966093e2b7..77b97db597 100644 --- a/packages/frontend/editor-ui/src/components/ResourceLocator/ResourceLocator.test.ts +++ b/packages/frontend/editor-ui/src/components/ResourceLocator/ResourceLocator.test.ts @@ -229,4 +229,44 @@ describe('ResourceLocator', () => { expect(queryByTestId('permission-error-link')).not.toBeInTheDocument(); }); }); + + it('switches to expression when user enters "{{ "', async () => { + const { getByTestId, emitted } = renderComponent({ + props: { modelValue: { ...TEST_MODEL_VALUE, value: '', mode: 'id' } }, + }); + + const input = getByTestId('rlc-input'); + await userEvent.click(input); + const expression = new DataTransfer(); + // '{' is an escape character: '{{{{' === '{{' + expression.setData('text', '{{ '); + await userEvent.clear(input); + await userEvent.paste(expression); + + expect(emitted('update:modelValue')).toEqual([ + [ + { + __rl: true, + mode: 'id', + value: '={{ }}', + }, + ], + ]); + }); + + it('can switch between modes', async () => { + const { getByTestId, emitted } = renderComponent(); + + await userEvent.click(getByTestId('rlc-mode-selector')); + await userEvent.click(screen.getByTestId('mode-id')); + expect(emitted('update:modelValue')).toEqual([ + [ + { + __rl: true, + mode: 'id', + value: 'test', + }, + ], + ]); + }); }); diff --git a/packages/frontend/editor-ui/src/components/ResourceLocator/ResourceLocator.vue b/packages/frontend/editor-ui/src/components/ResourceLocator/ResourceLocator.vue index 49a228b5e5..1af00c010a 100644 --- a/packages/frontend/editor-ui/src/components/ResourceLocator/ResourceLocator.vue +++ b/packages/frontend/editor-ui/src/components/ResourceLocator/ResourceLocator.vue @@ -54,6 +54,7 @@ import { type FromAIOverride, } from '../../utils/fromAIOverrideUtils'; import { N8nNotice } from '@n8n/design-system'; +import { completeExpressionSyntax } from '@/utils/expressions'; /** * Regular expression to check if the error message contains credential-related phrases. @@ -355,10 +356,12 @@ watch(currentQueryError, (curr, prev) => { watch( () => props.isValueExpression, - (newValue) => { + async (newValue) => { if (newValue) { switchFromListMode(); } + await nextTick(); + inputRef.value?.focus(); }, ); @@ -516,6 +519,8 @@ function onInputChange(value: NodeParameterValue): void { if (resource?.url) { params.cachedResultUrl = resource.url; } + } else { + params.value = completeExpressionSyntax(value); } emit('update:modelValue', params); }