diff --git a/packages/editor-ui/src/components/ParameterInput.test.ts b/packages/editor-ui/src/components/ParameterInput.test.ts index 4ee22ec0dd..316622508f 100644 --- a/packages/editor-ui/src/components/ParameterInput.test.ts +++ b/packages/editor-ui/src/components/ParameterInput.test.ts @@ -8,6 +8,7 @@ import { waitFor } from '@testing-library/vue'; import userEvent from '@testing-library/user-event'; import type { useNodeTypesStore } from '@/stores/nodeTypes.store'; import { cleanupAppModals, createAppModals } from '@/__tests__/utils'; +import { createEventBus } from 'n8n-design-system'; let mockNdvState: Partial>; let mockNodeTypesState: Partial>; @@ -233,4 +234,88 @@ describe('ParameterInput.vue', () => { expect(emitted('update')).toBeUndefined(); }); + + test('should reset bool on eventBus:removeExpression', async () => { + const eventBus = createEventBus(); + const { emitted } = renderComponent(ParameterInput, { + pinia: createTestingPinia(), + props: { + path: 'aSwitch', + parameter: { + displayName: 'A Switch', + name: 'aSwitch', + type: 'boolean', + default: true, + }, + modelValue: '={{ }}', // note that this makes a syntax error + eventBus, + }, + }); + + eventBus.emit('optionSelected', 'removeExpression'); + expect(emitted('update')).toContainEqual([expect.objectContaining({ value: true })]); + }); + + test('should reset bool with undefined evaluation on eventBus:removeExpression', async () => { + const eventBus = createEventBus(); + const { emitted } = renderComponent(ParameterInput, { + pinia: createTestingPinia(), + props: { + path: 'aSwitch', + parameter: { + displayName: 'A Switch', + name: 'aSwitch', + type: 'boolean', + default: true, + }, + modelValue: undefined, + eventBus, + }, + }); + + eventBus.emit('optionSelected', 'removeExpression'); + expect(emitted('update')).toContainEqual([expect.objectContaining({ value: true })]); + }); + + test('should reset number on eventBus:removeExpression', async () => { + const eventBus = createEventBus(); + const { emitted } = renderComponent(ParameterInput, { + pinia: createTestingPinia(), + props: { + path: 'aNum', + parameter: { + displayName: 'A Num', + name: 'aNum', + type: 'number', + default: 6, + }, + modelValue: '={{ }}', // note that this makes a syntax error + eventBus, + }, + }); + + eventBus.emit('optionSelected', 'removeExpression'); + expect(emitted('update')).toContainEqual([expect.objectContaining({ value: 6 })]); + }); + + test('should reset string on eventBus:removeExpression', async () => { + const eventBus = createEventBus(); + const { emitted } = renderComponent(ParameterInput, { + pinia: createTestingPinia(), + props: { + path: 'aStr', + parameter: { + displayName: 'A Str', + name: 'aStr', + type: 'string', + default: 'some default', + }, + modelValue: '={{ }}', // note that this makes a syntax error + eventBus, + }, + }); + + eventBus.emit('optionSelected', 'removeExpression'); + expect(emitted('update')).toContainEqual([expect.objectContaining({ value: '{{ }}' })]); + }); }); diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index 0730d175e7..a7da5b1a21 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -908,11 +908,16 @@ async function optionSelected(command: string) { if (isResourceLocatorParameter.value && isResourceLocatorValue(props.modelValue)) { valueChanged({ __rl: true, value, mode: props.modelValue.mode }); } else { - let newValue = typeof value !== 'undefined' ? value : null; + let newValue: NodeParameterValueType | {} = typeof value !== 'undefined' ? value : null; if (props.parameter.type === 'string') { // Strip the '=' from the beginning newValue = modelValueString.value ? modelValueString.value.toString().substring(1) : null; + } else if (newValue === null) { + // Invalid expressions land here + if (['number', 'boolean'].includes(props.parameter.type)) { + newValue = props.parameter.default; + } } valueChanged(newValue); }