fix(editor): Fix copy button hover state in MCP settings (#39888)

Co-authored-by: n8n-cat-bot[bot] <n8n-cat-bot[bot]@users.noreply.github.com>
Co-authored-by: Svetoslav Dekov <svetoslav.dekov@n8n.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
n8n-cat-bot[bot] 2026-09-29 14:34:38 +00:00 committed by GitHub
parent 1153702d1a
commit f0b70134a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 70 additions and 1 deletions

View File

@ -170,6 +170,7 @@ const handleCopy = async (value: string) => {
}
button {
height: auto;
border: none;
border-radius: 0;
box-shadow: none;
@ -196,8 +197,13 @@ const handleCopy = async (value: string) => {
.copy-button-wrapper {
display: flex;
align-items: center;
align-items: stretch;
border-left: var(--border);
// Tooltip triggers wrap each button in a span, which must stretch it too.
> span {
display: flex;
}
}
.copy-button {

View File

@ -0,0 +1,23 @@
import { BasePage } from './BasePage';
export class SettingsMcpPage extends BasePage {
async goto() {
await this.page.goto('/settings/mcp');
}
getConnectButton() {
return this.page.getByTestId('mcp-connect-client-button');
}
getCopyButton() {
return this.page
.getByRole('dialog')
.getByTestId('connection-parameter-value')
.first()
.getByRole('button');
}
getCopyButtonContainer() {
return this.page.getByRole('dialog').getByTestId('connection-parameter-value').first();
}
}

View File

@ -39,6 +39,7 @@ import { SecretsProviderSettingsPage } from './SecretsProviderSettingsPage';
import { SecuritySettingsPage } from './SecuritySettingsPage';
import { SettingsEnvironmentPage } from './SettingsEnvironmentPage';
import { SettingsLogStreamingPage } from './SettingsLogStreamingPage';
import { SettingsMcpPage } from './SettingsMcpPage';
import { SettingsPersonalPage } from './SettingsPersonalPage';
import { SettingsSsoPage } from './SettingsSsoPage';
import { SettingsUsersPage } from './SettingsUsersPage';
@ -100,6 +101,7 @@ export class n8nPage {
readonly oauthConsent: OAuthConsentPage;
readonly projectSettings: ProjectSettingsPage;
readonly settingsPersonal: SettingsPersonalPage;
readonly settingsMcp: SettingsMcpPage;
readonly settingsLogStreaming: SettingsLogStreamingPage;
readonly templateCredentialSetup: TemplateCredentialSetupPage;
readonly templates: TemplatesPage;
@ -191,6 +193,7 @@ export class n8nPage {
this.oauthConsent = new OAuthConsentPage(page);
this.projectSettings = new ProjectSettingsPage(page);
this.settingsPersonal = new SettingsPersonalPage(page);
this.settingsMcp = new SettingsMcpPage(page);
this.settingsLogStreaming = new SettingsLogStreamingPage(page);
this.templateCredentialSetup = new TemplateCredentialSetupPage(page);
this.templates = new TemplatesPage(page);

View File

@ -0,0 +1,37 @@
import { test, expect } from '../../../fixtures/base';
test.describe(
'MCP connection parameter copy button',
{ annotation: [{ type: 'owner', description: 'AI' }] },
() => {
test('fills the copy control height on hover', async ({ n8n, api }) => {
// ADO-5385: The hover background must reach both edges of the copy control.
await api.setMcpAccess(true);
await n8n.start.fromHome();
await n8n.settingsMcp.goto();
await n8n.settingsMcp.getConnectButton().click();
const button = n8n.settingsMcp.getCopyButton();
await expect(button).toBeVisible();
const backgroundBeforeHover = await button.evaluate(
(element) => getComputedStyle(element).backgroundColor,
);
await button.hover();
const backgroundOnHover = await button.evaluate(
(element) => getComputedStyle(element).backgroundColor,
);
expect(backgroundOnHover).not.toBe(backgroundBeforeHover);
const buttonBox = await button.boundingBox();
const containerBox = await n8n.settingsMcp.getCopyButtonContainer().boundingBox();
expect(buttonBox).not.toBeNull();
expect(containerBox).not.toBeNull();
// The input container has a one-pixel border on each edge.
expect.soft(Math.abs(buttonBox!.y - containerBox!.y)).toBeLessThanOrEqual(1);
expect(
Math.abs(buttonBox!.y + buttonBox!.height - containerBox!.y - containerBox!.height),
).toBeLessThanOrEqual(1);
});
},
);