feat(editor): NDV in focus panel experiment feedback (no-changelog) (#19304)

This commit is contained in:
Suguru Inoue
2025-09-15 12:30:17 +02:00
committed by GitHub
parent 3576443a01
commit c15e9437ee
32 changed files with 543 additions and 127 deletions

View File

@@ -5,12 +5,14 @@ import { BasePage } from './BasePage';
import { ROUTES } from '../config/constants';
import { resolveFromRoot } from '../utils/path-helper';
import { CredentialModal } from './components/CredentialModal';
import { FocusPanel } from './components/FocusPanel';
import { LogsPanel } from './components/LogsPanel';
import { StickyComponent } from './components/StickyComponent';
export class CanvasPage extends BasePage {
readonly sticky = new StickyComponent(this.page);
readonly logsPanel = new LogsPanel(this.page.getByTestId('logs-panel'));
readonly focusPanel = new FocusPanel(this.page.getByTestId('focus-panel'));
readonly credentialModal = new CredentialModal(this.page.getByTestId('editCredential-modal'));
saveWorkflowButton(): Locator {

View File

@@ -0,0 +1,24 @@
import type { Locator } from '@playwright/test';
export class FocusPanel {
constructor(private root: Locator) {}
/**
* Accessors
*/
getHeader(): Locator {
return this.root.locator('header');
}
getParameterInputField(path: string): Locator {
return this.root.locator(
`[data-test-id="parameter-input-field"][title="Parameter: \\"${path}\\""]`,
);
}
getMapper(): Locator {
// find from the entire page because the mapper is rendered as portal
return this.root.page().getByRole('tooltip').getByTestId('ndv-input-panel');
}
}

View File

@@ -109,26 +109,31 @@ test.describe('Canvas Actions', () => {
test.describe('Node hover actions', () => {
test('should execute node', async ({ n8n }) => {
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
await n8n.canvas.deselectAll();
await n8n.canvas.executeNode(MANUAL_TRIGGER_NODE_DISPLAY_NAME);
await expect(
n8n.notifications.getNotificationByTitle('Node executed successfully'),
).toHaveCount(1);
await expect(n8n.canvas.getCanvasNodes()).toHaveCount(1);
await expect(n8n.canvas.selectedNodes()).toHaveCount(0);
});
test('should disable and enable node', async ({ n8n }) => {
await n8n.canvas.addNode(MANUAL_TRIGGER_NODE_NAME);
await n8n.canvas.addNode(CODE_NODE_NAME, { action: 'Code in JavaScript', closeNDV: true });
await n8n.canvas.deselectAll();
const disableButton = n8n.canvas.nodeDisableButton(CODE_NODE_DISPLAY_NAME);
await disableButton.click();
await expect(n8n.canvas.disabledNodes()).toHaveCount(1);
await expect(n8n.canvas.selectedNodes()).toHaveCount(0);
await disableButton.click();
await expect(n8n.canvas.disabledNodes()).toHaveCount(0);
await expect(n8n.canvas.selectedNodes()).toHaveCount(0);
});
test('should delete node', async ({ n8n }) => {

View File

@@ -0,0 +1,40 @@
import { test, expect } from '../../fixtures/base';
import type { TestRequirements } from '../../Types';
test.describe('Focus panel', () => {
test.describe('With experimental NDV in focus panel enabled', () => {
const requirements: TestRequirements = {
storage: {
N8N_EXPERIMENT_OVERRIDES: JSON.stringify({ ndv_in_focus_panel: 'variant' }),
},
};
test('should keep showing selected node when canvas is clicked while mapper popover is shown', async ({
n8n,
setupRequirements,
}) => {
await setupRequirements(requirements);
await n8n.start.fromImportedWorkflow('Test_workflow_3.json');
await n8n.canvas.clickZoomToFitButton();
await n8n.canvas.deselectAll();
await n8n.canvas.toggleFocusPanelButton().click();
await n8n.canvas.nodeByName('Set').click();
await expect(n8n.canvas.focusPanel.getHeader()).toHaveText('Set');
await n8n.canvas.focusPanel.getParameterInputField('assignments.assignments.0.value').focus();
await expect(n8n.canvas.focusPanel.getMapper()).toBeVisible();
// Assert that mapper is closed but the Set node is still selected and shown in
await n8n.canvas.canvasBody().click({ position: { x: 0, y: 0 } });
await expect(n8n.canvas.focusPanel.getMapper()).not.toBeVisible();
await expect(n8n.canvas.focusPanel.getHeader()).toHaveText('Set');
await expect(n8n.canvas.selectedNodes()).toHaveCount(1);
// Assert that another click on canvas does de-select the Set node
await n8n.canvas.canvasBody().click({ position: { x: 0, y: 0 } });
await expect(n8n.canvas.focusPanel.getHeader()).not.toBeVisible();
await expect(n8n.canvas.selectedNodes()).toHaveCount(0);
});
});
});

View File

@@ -2,9 +2,7 @@ import { test, expect } from '../../fixtures/base';
import type { TestRequirements } from '../../Types';
const requirements: TestRequirements = {
workflow: {
'Test_workflow_1.json': 'Test',
},
workflow: 'Test_workflow_1.json',
storage: {
N8N_EXPERIMENT_OVERRIDES: JSON.stringify({ ndv_in_focus_panel: 'variant' }),
},