From 9675fc97fd193c0474b36c084bd3d6e928885fed Mon Sep 17 00:00:00 2001 From: "n8n-cat-bot[bot]" <283985454+n8n-cat-bot[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 12:50:51 +0000 Subject: [PATCH] fix: Align From AI button with parameter inputs (#40152) Co-authored-by: n8n-cat-bot[bot] --- .../components/ParameterInputFull.vue | 9 +++- .../FromAiOverrideButton.vue | 17 +++++-- .../ResourceLocator/ResourceLocator.vue | 5 +- .../playwright/pages/NodeDetailsViewPage.ts | 16 ++++++ .../ado-5599-from-ai-button-alignment.spec.ts | 51 +++++++++++++++++++ 5 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 packages/quality/testing/playwright/tests/e2e/regression/ado-5599-from-ai-button-alignment.spec.ts diff --git a/packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputFull.vue b/packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputFull.vue index 6a17e80c60f..f5611ef0693 100644 --- a/packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputFull.vue +++ b/packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputFull.vue @@ -522,7 +522,14 @@ function removeOverride(clearField = false) { @drop="onDrop" > diff --git a/packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/FromAiOverrideButton.vue b/packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/FromAiOverrideButton.vue index b314a9b15d3..ac57de1577e 100644 --- a/packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/FromAiOverrideButton.vue +++ b/packages/frontend/editor-ui/src/features/ndv/parameters/components/ParameterInputOverrides/FromAiOverrideButton.vue @@ -8,8 +8,9 @@ const i18n = useI18n(); withDefaults( defineProps<{ position?: 'inline' | 'standalone'; + size?: 'small' | 'medium'; }>(), - { position: 'inline' }, + { position: 'inline', size: 'medium' }, ); const emit = defineEmits<{ @@ -24,7 +25,7 @@ const emit = defineEmits<{
@@ -38,8 +39,8 @@ const emit = defineEmits<{ display: flex; align-items: center; justify-content: center; - height: 30px; - width: 30px; + height: var(--from-ai-button-size); + width: var(--from-ai-button-size); background-color: var(--color--foreground); color: var(--color--foreground--shade-2); cursor: pointer; @@ -55,6 +56,14 @@ const emit = defineEmits<{ } } +.small { + --from-ai-button-size: var(--height--sm); +} + +.medium { + --from-ai-button-size: var(--height--md); +} + .inline { border-left: 0; border-top-right-radius: var(--radius); diff --git a/packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceLocator/ResourceLocator.vue b/packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceLocator/ResourceLocator.vue index bbcdd2ef264..6c21c6a0daa 100644 --- a/packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceLocator/ResourceLocator.vue +++ b/packages/frontend/editor-ui/src/features/ndv/parameters/components/ResourceLocator/ResourceLocator.vue @@ -1278,7 +1278,10 @@ function removeOverride() {
- +
diff --git a/packages/quality/testing/playwright/pages/NodeDetailsViewPage.ts b/packages/quality/testing/playwright/pages/NodeDetailsViewPage.ts index 6f1a94235e7..b87bba1f891 100644 --- a/packages/quality/testing/playwright/pages/NodeDetailsViewPage.ts +++ b/packages/quality/testing/playwright/pages/NodeDetailsViewPage.ts @@ -244,6 +244,22 @@ export class NodeDetailsViewPage extends BasePage { return locatorByIndex(this.container.getByTestId(`parameter-input-${parameterName}`), index); } + getParameterInputBorder(parameterName: string) { + return this.getParameterInput(parameterName).locator('.n8n-input__wrapper'); + } + + getParameterNumberBorder(parameterName: string) { + return this.getParameterInput(parameterName).getByTestId('input-number'); + } + + getParameterExpressionBorder(parameterName: string) { + return this.getParameterInput(parameterName).locator('.el-input-group__prepend').locator('..'); + } + + getFromAiOverrideButton(parameterName: string) { + return this.getParameterInput(parameterName).getByTestId('from-ai-override-button'); + } + getParameterInputTextbox(parameterName: string, index?: number) { return this.getParameterInput(parameterName, index).getByRole('textbox'); } diff --git a/packages/quality/testing/playwright/tests/e2e/regression/ado-5599-from-ai-button-alignment.spec.ts b/packages/quality/testing/playwright/tests/e2e/regression/ado-5599-from-ai-button-alignment.spec.ts new file mode 100644 index 00000000000..9cff0148469 --- /dev/null +++ b/packages/quality/testing/playwright/tests/e2e/regression/ado-5599-from-ai-button-alignment.spec.ts @@ -0,0 +1,51 @@ +import { test, expect } from '../../../fixtures/base'; +import type { Locator } from '@playwright/test'; + +async function expectButtonAligned(inputBorder: Locator, fromAiButton: Locator) { + await expect(inputBorder).toBeVisible(); + await expect(fromAiButton).toBeVisible(); + + const inputBounds = await inputBorder.boundingBox(); + const buttonBounds = await fromAiButton.boundingBox(); + expect(inputBounds).not.toBeNull(); + expect(buttonBounds).not.toBeNull(); + + expect(buttonBounds).toMatchObject({ + y: inputBounds!.y, + height: inputBounds!.height, + }); +} + +test.describe( + 'ADO-5599: From AI button alignment', + { annotation: [{ type: 'owner', description: 'Adore' }] }, + () => { + test('aligns the From AI button outline with the tool parameter input border', async ({ + n8n, + }) => { + await n8n.start.fromBlankCanvas(); + await n8n.canvas.addNode('AI Agent', { closeNDV: true }); + await n8n.canvas.getInputPlusEndpointByType('AI Agent', 'ai_tool').click(); + await n8n.canvas.nodeCreator.searchFor('SearXNG'); + await n8n.canvas.nodeCreator.selectItem('SearXNG'); + await n8n.ndv.addParameterOptionByName('Language'); + + await expectButtonAligned( + n8n.ndv.getParameterInputBorder('language'), + n8n.ndv.getFromAiOverrideButton('language'), + ); + + await n8n.ndv.addParameterOptionByName('Number of Results'); + await expectButtonAligned( + n8n.ndv.getParameterNumberBorder('numResults'), + n8n.ndv.getFromAiOverrideButton('numResults'), + ); + + await n8n.ndv.setParameterInput('language', '={{ $json.language }}'); + await expectButtonAligned( + n8n.ndv.getParameterExpressionBorder('language'), + n8n.ndv.getFromAiOverrideButton('language'), + ); + }); + }, +);